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.camel.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 class IntrospectionSupport { 035 036 /** 037 * Utility classes should not have a public constructor. 038 */ 039 private IntrospectionSupport() { 040 } 041 042 public static boolean getProperties(Object target, Map props, String optionPrefix) { 043 044 boolean rc = false; 045 if (target == null) { 046 throw new IllegalArgumentException("target was null."); 047 } 048 if (props == null) { 049 throw new IllegalArgumentException("props was null."); 050 } 051 if (optionPrefix == null) { 052 optionPrefix = ""; 053 } 054 055 Class clazz = target.getClass(); 056 Method[] methods = clazz.getMethods(); 057 for (int i = 0; i < methods.length; i++) { 058 Method method = methods[i]; 059 String name = method.getName(); 060 Class type = method.getReturnType(); 061 Class params[] = method.getParameterTypes(); 062 if (name.startsWith("get") && params.length == 0 && type != null && isSettableType(type)) { 063 064 try { 065 066 Object value = method.invoke(target, new Object[] {}); 067 if (value == null) { 068 continue; 069 } 070 071 String strValue = convertToString(value, type); 072 if (strValue == null) { 073 continue; 074 } 075 076 name = name.substring(3, 4).toLowerCase() + name.substring(4); 077 props.put(optionPrefix + name, strValue); 078 rc = true; 079 080 } catch (Throwable ignore) { 081 } 082 083 } 084 } 085 086 return rc; 087 } 088 089 public static boolean setProperties(Object target, Map props, String optionPrefix) { 090 boolean rc = false; 091 if (target == null) { 092 throw new IllegalArgumentException("target was null."); 093 } 094 if (props == null) { 095 throw new IllegalArgumentException("props was null."); 096 } 097 098 for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { 099 String name = (String)iter.next(); 100 if (name.startsWith(optionPrefix)) { 101 Object value = props.get(name); 102 name = name.substring(optionPrefix.length()); 103 if (setProperty(target, name, value)) { 104 iter.remove(); 105 rc = true; 106 } 107 } 108 } 109 return rc; 110 } 111 112 public static Map extractProperties(Map props, String optionPrefix) { 113 if (props == null) { 114 throw new IllegalArgumentException("props was null."); 115 } 116 117 HashMap rc = new HashMap(props.size()); 118 119 for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { 120 String name = (String)iter.next(); 121 if (name.startsWith(optionPrefix)) { 122 Object value = props.get(name); 123 name = name.substring(optionPrefix.length()); 124 rc.put(name, value); 125 iter.remove(); 126 } 127 } 128 129 return rc; 130 } 131 132 public static boolean setProperties(Object target, Map props) { 133 boolean rc = false; 134 135 if (target == null) { 136 throw new IllegalArgumentException("target was null."); 137 } 138 if (props == null) { 139 throw new IllegalArgumentException("props was null."); 140 } 141 142 for (Iterator iter = props.entrySet().iterator(); iter.hasNext();) { 143 Map.Entry entry = (Entry)iter.next(); 144 if (setProperty(target, (String)entry.getKey(), entry.getValue())) { 145 iter.remove(); 146 rc = true; 147 } 148 } 149 150 return rc; 151 } 152 153 public static boolean setProperty(Object target, String name, Object value) { 154 try { 155 Class clazz = target.getClass(); 156 Method setter = findSetterMethod(clazz, name); 157 if (setter == null) { 158 return false; 159 } 160 161 // If the type is null or it matches the needed type, just use the 162 // value directly 163 if (value == null || value.getClass() == setter.getParameterTypes()[0]) { 164 setter.invoke(target, new Object[] {value}); 165 } else { 166 // We need to convert it 167 setter.invoke(target, new Object[] {convert(value, setter.getParameterTypes()[0])}); 168 } 169 return true; 170 } catch (Throwable ignore) { 171 return false; 172 } 173 } 174 175 private static Object convert(Object value, Class type) throws URISyntaxException { 176 PropertyEditor editor = PropertyEditorManager.findEditor(type); 177 if (editor != null) { 178 editor.setAsText(value.toString()); 179 return editor.getValue(); 180 } 181 if (type == URI.class) { 182 return new URI(value.toString()); 183 } 184 return null; 185 } 186 187 private static String convertToString(Object value, Class type) throws URISyntaxException { 188 PropertyEditor editor = PropertyEditorManager.findEditor(type); 189 if (editor != null) { 190 editor.setValue(value); 191 return editor.getAsText(); 192 } 193 if (type == URI.class) { 194 return ((URI)value).toString(); 195 } 196 return null; 197 } 198 199 private static Method findSetterMethod(Class clazz, String name) { 200 // Build the method name. 201 name = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); 202 Method[] methods = clazz.getMethods(); 203 for (int i = 0; i < methods.length; i++) { 204 Method method = methods[i]; 205 Class params[] = method.getParameterTypes(); 206 if (method.getName().equals(name) && params.length == 1 && isSettableType(params[0])) { 207 return method; 208 } 209 } 210 return null; 211 } 212 213 private static boolean isSettableType(Class clazz) { 214 if (PropertyEditorManager.findEditor(clazz) != null) { 215 return true; 216 } 217 if (clazz == URI.class) { 218 return true; 219 } 220 if (clazz == Boolean.class) { 221 return true; 222 } 223 return false; 224 } 225 226 public static String toString(Object target) { 227 return toString(target, Object.class); 228 } 229 230 public static String toString(Object target, Class stopClass) { 231 LinkedHashMap map = new LinkedHashMap(); 232 addFields(target, target.getClass(), stopClass, map); 233 StringBuffer buffer = new StringBuffer(simpleName(target.getClass())); 234 buffer.append(" {"); 235 Set entrySet = map.entrySet(); 236 boolean first = true; 237 for (Iterator iter = entrySet.iterator(); iter.hasNext();) { 238 Map.Entry entry = (Map.Entry)iter.next(); 239 if (first) { 240 first = false; 241 } else { 242 buffer.append(", "); 243 } 244 buffer.append(entry.getKey()); 245 buffer.append(" = "); 246 appendToString(buffer, entry.getValue()); 247 } 248 buffer.append("}"); 249 return buffer.toString(); 250 } 251 252 protected static void appendToString(StringBuffer buffer, Object value) { 253 // if (value instanceof ActiveMQDestination) { 254 // ActiveMQDestination destination = (ActiveMQDestination) value; 255 // buffer.append(destination.getQualifiedName()); 256 // } 257 // else { 258 buffer.append(value); 259 // } 260 } 261 262 public static String simpleName(Class clazz) { 263 String name = clazz.getName(); 264 int p = name.lastIndexOf("."); 265 if (p >= 0) { 266 name = name.substring(p + 1); 267 } 268 return name; 269 } 270 271 private static void addFields(Object target, Class startClass, Class stopClass, LinkedHashMap map) { 272 273 if (startClass != stopClass) { 274 addFields(target, startClass.getSuperclass(), stopClass, map); 275 } 276 277 Field[] fields = startClass.getDeclaredFields(); 278 for (int i = 0; i < fields.length; i++) { 279 Field field = fields[i]; 280 if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers()) || Modifier.isPrivate(field.getModifiers())) { 281 continue; 282 } 283 284 try { 285 field.setAccessible(true); 286 Object o = field.get(target); 287 if (o != null && o.getClass().isArray()) { 288 try { 289 o = Arrays.asList((Object[])o); 290 } catch (Throwable e) { 291 } 292 } 293 map.put(field.getName(), o); 294 } catch (Throwable e) { 295 e.printStackTrace(); 296 } 297 } 298 299 } 300 301 }