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 }