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