001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.jbi.util;
018    
019    import java.beans.PropertyEditor;
020    import java.beans.PropertyEditorManager;
021    import java.lang.reflect.Field;
022    import java.lang.reflect.Method;
023    import java.lang.reflect.Modifier;
024    import java.net.URI;
025    import java.net.URISyntaxException;
026    import java.util.Arrays;
027    import java.util.HashMap;
028    import java.util.Iterator;
029    import java.util.LinkedHashMap;
030    import java.util.Map;
031    import java.util.Map.Entry;
032    import java.util.Set;
033    
034    public final class IntrospectionSupport {
035        
036        private IntrospectionSupport() {
037        }
038    
039        public static boolean setProperties(Object target, Map props, String optionPrefix) {
040            boolean rc = false;
041            if (target == null) {
042                throw new IllegalArgumentException("target was null.");
043            }
044            if (props == null) {
045                throw new IllegalArgumentException("props was null.");
046            }
047            for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
048                String name = (String) iter.next();
049                if (name.startsWith(optionPrefix)) {
050                    Object value = props.get(name);
051                    name = name.substring(optionPrefix.length());
052                    if (setProperty(target, name, value)) {
053                        iter.remove();
054                        rc = true;
055                    }
056                }
057            }
058            return rc;
059        }
060    
061        public static Map extractProperties(Map props, String optionPrefix) {
062            if (props == null) {
063                throw new IllegalArgumentException("props was null.");
064            }
065            Map rc = new HashMap(props.size());
066            for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
067                String name = (String) iter.next();
068                if (name.startsWith(optionPrefix)) {
069                    Object value = props.get(name);
070                    name = name.substring(optionPrefix.length());
071                    rc.put(name, value);
072                    iter.remove();
073                }
074            }
075            return rc;
076        }
077    
078        public static void setProperties(Object target, Map props) {
079            if (target == null) {
080                throw new IllegalArgumentException("target was null.");
081            }
082            if (props == null) {
083                throw new IllegalArgumentException("props was null.");
084            }
085            for (Iterator iter = props.entrySet().iterator(); iter.hasNext();) {
086                Map.Entry entry = (Entry) iter.next();
087                if (setProperty(target, (String) entry.getKey(), entry.getValue())) {
088                    iter.remove();
089                }
090            }
091        }
092    
093        private static boolean setProperty(Object target, String name, Object value) {
094            try {
095                Class clazz = target.getClass();
096                Method setter = findSetterMethod(clazz, name);
097                if (setter == null) {
098                    return false;
099                }
100                // If the type is null or it matches the needed type, just use the
101                // value directly
102                if (value == null || value.getClass() == setter.getParameterTypes()[0]) {
103                    setter.invoke(target, new Object[] {value });
104                } else {
105                    // We need to convert it
106                    setter.invoke(target, new Object[] {convert(value, setter.getParameterTypes()[0]) });
107                }
108                return true;
109            } catch (Throwable ignore) {
110                return false;
111            }
112        }
113    
114        private static Object convert(Object value, Class type) throws URISyntaxException {
115            PropertyEditor editor = PropertyEditorManager.findEditor(type);
116            if (editor != null) {
117                editor.setAsText(value.toString());
118                return editor.getValue();
119            }
120            if (type == URI.class) {
121                return new URI(value.toString());
122            }
123            return null;
124        }
125    
126        private static Method findSetterMethod(Class clazz, String name) {
127            // Build the method name.
128            name = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
129            Method[] methods = clazz.getMethods();
130            for (int i = 0; i < methods.length; i++) {
131                Method method = methods[i];
132                Class params[] = method.getParameterTypes();
133                if (method.getName().equals(name) && params.length == 1 && isSettableType(params[0])) {
134                    return method;
135                }
136            }
137            return null;
138        }
139    
140        private static boolean isSettableType(Class clazz) {
141            if (PropertyEditorManager.findEditor(clazz) != null) {
142                return true;
143            }
144            if (clazz == URI.class) {
145                return true;
146            }
147            return false;
148        }
149    
150        public static String toString(Object target) {
151            return toString(target, Object.class);
152        }
153    
154        public static String toString(Object target, Class stopClass) {
155            Map map = new LinkedHashMap();
156            addFields(target, target.getClass(), stopClass, map);
157            StringBuffer buffer = new StringBuffer(simpleName(target.getClass()));
158            buffer.append(" {");
159            Set entrySet = map.entrySet();
160            boolean first = true;
161            for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
162                Map.Entry entry = (Map.Entry) iter.next();
163                if (first) {
164                    first = false;
165                } else {
166                    buffer.append(", ");
167                }
168                buffer.append(entry.getKey());
169                buffer.append(" = ");
170                buffer.append(entry.getValue());
171            }
172            buffer.append("}");
173            return buffer.toString();
174        }
175    
176        public static String simpleName(Class clazz) {
177            String name = clazz.getName();
178            int p = name.lastIndexOf(".");
179            if (p >= 0) {
180                name = name.substring(p + 1);
181            }
182            return name;
183        }
184    
185        private static void addFields(Object target, Class startClass, Class stopClass, Map map) {
186            if (startClass != stopClass) {
187                addFields(target, startClass.getSuperclass(), stopClass, map);
188            }
189            Field[] fields = startClass.getDeclaredFields();
190            for (int i = 0; i < fields.length; i++) {
191                Field field = fields[i];
192                if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())
193                                || Modifier.isPrivate(field.getModifiers())) {
194                    continue;
195                }
196                try {
197                    field.setAccessible(true);
198                    Object o = field.get(target);
199                    if (o != null && o.getClass().isArray()) {
200                        try {
201                            o = Arrays.asList((Object[]) o);
202                        } catch (Throwable e) {
203                            // Ignore
204                        }
205                    }
206                    map.put(field.getName(), o);
207                } catch (Throwable e) {
208                    e.printStackTrace();
209                }
210            }
211    
212        }
213    
214    }