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.lang.reflect.Field;
020 import java.lang.reflect.Method;
021 import java.lang.reflect.Modifier;
022
023 /**
024 * Helper for working with reflection on classes.
025 * <p/>
026 * This code is based on org.apache.camel.spring.util.ReflectionUtils class.
027 */
028 public final class ReflectionHelper {
029
030 private ReflectionHelper() {
031 // utility class
032 }
033
034 /**
035 * Callback interface invoked on each field in the hierarchy.
036 */
037 public interface FieldCallback {
038
039 /**
040 * Perform an operation using the given field.
041 *
042 * @param field the field to operate on
043 */
044 void doWith(Field field) throws IllegalArgumentException, IllegalAccessException;
045 }
046
047 /**
048 * Action to take on each method.
049 */
050 public interface MethodCallback {
051
052 /**
053 * Perform an operation using the given method.
054 *
055 * @param method the method to operate on
056 */
057 void doWith(Method method) throws IllegalArgumentException, IllegalAccessException;
058 }
059
060 /**
061 * Invoke the given callback on all fields in the target class, going up the
062 * class hierarchy to get all declared fields.
063 * @param clazz the target class to analyze
064 * @param fc the callback to invoke for each field
065 */
066 public static void doWithFields(Class<?> clazz, FieldCallback fc) throws IllegalArgumentException {
067 // Keep backing up the inheritance hierarchy.
068 Class<?> targetClass = clazz;
069 do {
070 Field[] fields = targetClass.getDeclaredFields();
071 for (Field field : fields) {
072 try {
073 fc.doWith(field);
074 } catch (IllegalAccessException ex) {
075 throw new IllegalStateException("Shouldn't be illegal to access field '" + field.getName() + "': " + ex);
076 }
077 }
078 targetClass = targetClass.getSuperclass();
079 }
080 while (targetClass != null && targetClass != Object.class);
081 }
082
083 /**
084 * Perform the given callback operation on all matching methods of the given
085 * class and superclasses (or given interface and super-interfaces).
086 *
087 * @param clazz class to start looking at
088 * @param mc the callback to invoke for each method
089 */
090 public static void doWithMethods(Class<?> clazz, MethodCallback mc) throws IllegalArgumentException {
091 // Keep backing up the inheritance hierarchy.
092 Method[] methods = clazz.getDeclaredMethods();
093 for (Method method : methods) {
094 try {
095 mc.doWith(method);
096 } catch (IllegalAccessException ex) {
097 throw new IllegalStateException("Shouldn't be illegal to access method '" + method.getName() + "': " + ex);
098 }
099 }
100 if (clazz.getSuperclass() != null) {
101 doWithMethods(clazz.getSuperclass(), mc);
102 } else if (clazz.isInterface()) {
103 for (Class<?> superIfc : clazz.getInterfaces()) {
104 doWithMethods(superIfc, mc);
105 }
106 }
107 }
108
109 public static void setField(Field f, Object instance, Object value) {
110 try {
111 boolean oldAccessible = f.isAccessible();
112 boolean shouldSetAccessible = !Modifier.isPublic(f.getModifiers()) && !oldAccessible;
113 if (shouldSetAccessible) {
114 f.setAccessible(true);
115 }
116 f.set(instance, value);
117 if (shouldSetAccessible) {
118 f.setAccessible(oldAccessible);
119 }
120 } catch (Exception ex) {
121 throw new UnsupportedOperationException("Cannot inject value of class: " + value.getClass() + " into: " + f);
122 }
123 }
124
125 }