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