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