001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2011, Michael Meyling <mime@qedeq.org>.
004 *
005 * "Hilbert II" is free software; you can redistribute
006 * it and/or modify it under the terms of the GNU General Public
007 * License as published by the Free Software Foundation; either
008 * version 2 of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 */
015
016 package org.qedeq.base.utility;
017
018 import java.lang.reflect.Field;
019 import java.lang.reflect.InvocationTargetException;
020 import java.lang.reflect.Method;
021
022
023 /**
024 * We learned so much from the great Jedi master. Using the force we can get and set private
025 * fields of arbitrary objects. We can even execute private methods...
026 *
027 * @author Michael Meyling
028 */
029 public abstract class YodaUtility {
030
031 /**
032 * Constructor, should never be called.
033 */
034 private YodaUtility() {
035 // don't call me
036 }
037
038 /**
039 * Analyze if a class or one of its super classes contains a given method.
040 * <p>
041 * Example: you can test with <code>YodaUtility.existsMethod("java.net.URLConnection",
042 * "setConnectTimeout", new Class[] {Integer.TYPE}</code> with JDK 1.4.2 and if you run it
043 * with a 1.5 JRE or higher then it will be successfully executed.
044 *
045 * @param clazz Class to analyze.
046 * @param name Method name.
047 * @param parameterTypes Parameter types.
048 * @return Does the class (or one of its super classes) have such a method?
049 */
050 public static boolean existsMethod(final String clazz, final String name,
051 final Class[] parameterTypes) {
052 Class c;
053 try {
054 c = Class.forName(clazz);
055 } catch (ClassNotFoundException e) {
056 return false;
057 }
058 if (c == null) {
059 return false;
060 }
061 return existsMethod(c, name, parameterTypes);
062 }
063
064 /**
065 * Analyze if a class or one of its super classes contains a given method.
066 * <p>
067 * Example: you can test with <code>YodaUtility.existsMethod(URLConnection.class,
068 * "setConnectTimeout", new Class[] {Integer.TYPE}</code> with JDK 1.4.2 and if you run it
069 * with a 1.5 JRE or higher then it will be successfully executed.
070 *
071 * @param clazz Class to analyze.
072 * @param name Method name.
073 * @param parameterTypes Parameter types.
074 * @return Does the class (or one of its super classes) have such a method?
075 */
076 public static boolean existsMethod(final Class clazz, final String name,
077 final Class[] parameterTypes) {
078 Method method = null;
079 Class cl = clazz;
080 try {
081 while (!Object.class.equals(cl)) {
082 try {
083 method = cl.getDeclaredMethod(name, parameterTypes);
084 break;
085 } catch (NoSuchMethodException ex) {
086 cl = cl.getSuperclass();
087 }
088 }
089 if (method == null) {
090 return false;
091 }
092 return true;
093 } catch (SecurityException e) {
094 throw new RuntimeException(e);
095 }
096 }
097
098 /**
099 * This method executes a method on an object or one of its super instances (even if it is
100 * private).
101 * <p>
102 * Example: you can compile <code>YodaUtility.executeMethod((URLConnection) httpConnection,
103 * "setConnectTimeout", new Class[] {Integer.TYPE}, new Object[] { new Integer(100)});</code>
104 * with JDK 1.4.2 and if you run it with a 1.5 JRE or higher then it will be successfully
105 * executed.
106 *
107 * @param obj Object.
108 * @param name Method name.
109 * @param parameterTypes Parameter types.
110 * @param parameter Parameter values.
111 * @return Execution result.
112 * @throws NoSuchMethodException Method not found.
113 * @throws InvocationTargetException Wrapped exception.
114 */
115 public static Object executeMethod(final Object obj, final String name,
116 final Class[] parameterTypes, final Object[] parameter) throws NoSuchMethodException,
117 InvocationTargetException {
118 Method method = null;
119 try {
120 Class cl = obj.getClass();
121 while (!Object.class.equals(cl)) {
122 try {
123 method = cl.getDeclaredMethod(name, parameterTypes);
124 break;
125 } catch (NoSuchMethodException ex) {
126 cl = cl.getSuperclass();
127 }
128 }
129 if (method == null) {
130 throw new NoSuchMethodException(name);
131 }
132 method.setAccessible(true);
133 } catch (SecurityException e) {
134 throw new RuntimeException(e);
135 }
136 try {
137 return method.invoke(obj, parameter);
138 } catch (IllegalArgumentException e) {
139 throw new RuntimeException(e);
140 } catch (IllegalAccessException e) {
141 throw new RuntimeException(e);
142 }
143 }
144
145 /**
146 * This method executes a static class method (even if it is private).
147 * <p>
148 * Example: you can compile <code>YodaUtility.executeMethod(
149 * "java.util.concurrent.locks.LockSupport",
150 * "park", new Class[0], new Object[0]);</code>
151 * with JDK 1.4.2 and if you run it with a 1.5 JRE or higher then it will be successfully
152 * executed.
153 *
154 * @param clazzName Name of class.
155 * @param name Name of static method to execute.
156 * @param parameterTypes Parameter types.
157 * @param parameter Parameter values.
158 * @return Execution result.
159 * @throws NoSuchMethodException Method not found.
160 * @throws InvocationTargetException Wrapped exception.
161 */
162 public static Object executeMethod(final String clazzName, final String name,
163 final Class[] parameterTypes, final Object[] parameter) throws NoSuchMethodException,
164 InvocationTargetException {
165 Method method = null;
166 try {
167 Class cl = Class.forName(clazzName);
168 method = cl.getDeclaredMethod(name, parameterTypes);
169 if (method == null) {
170 throw new NoSuchMethodException(name);
171 }
172 method.setAccessible(true);
173 return method.invoke(cl, parameter);
174 } catch (SecurityException e) {
175 throw new RuntimeException(e);
176 } catch (ClassNotFoundException e) {
177 throw new RuntimeException(e);
178 } catch (IllegalAccessException e) {
179 throw new RuntimeException(e);
180 }
181 }
182
183 /**
184 * This method returns the contents of an object variable .The class hierarchy is recursively
185 * searched to find such a field (even if it is private).
186 *
187 * @param obj Object.
188 * @param name Variable name.
189 * @return Contents of variable.
190 * @throws NoSuchFieldException Variable of given name was not found.
191 */
192 public static Object getFieldValue(final Object obj, final String name) throws NoSuchFieldException {
193 final Field field = getField(obj, name);
194 try {
195 return field.get(obj);
196 } catch (IllegalArgumentException e) {
197 throw new RuntimeException(e);
198 } catch (IllegalAccessException e) {
199 throw new RuntimeException(e);
200 }
201 }
202
203 /**
204 * This method sets the contents of an object variable. The class hierarchy is recursively
205 * searched to find such a field (even if it is private).
206 *
207 * @param obj Object.
208 * @param name Variable name.
209 * @param value Value to set.
210 * @throws NoSuchFieldException Variable of given name was not found.
211 */
212 public static void setFieldContent(final Object obj, final String name, final Object value)
213 throws NoSuchFieldException {
214 final Field field = getField(obj, name);
215 try {
216 field.set(obj, value);
217 } catch (IllegalArgumentException e) {
218 throw new RuntimeException(e);
219 } catch (IllegalAccessException e) {
220 throw new RuntimeException(e);
221 }
222 }
223
224 /**
225 * Get field of given name in given object. The class hierarchy is recursively searched
226 * to find such a field (even if it is private).
227 *
228 * @param obj Object to work on.
229 * @param name Search this field.
230 * @return Found field.
231 * @throws NoSuchFieldException Field with name <code>name</code> was not found.
232 */
233 public static Field getField(final Object obj, final String name) throws NoSuchFieldException {
234 Field field = null;
235 try {
236 Class cl = obj.getClass();
237 while (!Object.class.equals(cl)) {
238 try {
239 field = cl.getDeclaredField(name);
240 break;
241 } catch (NoSuchFieldException ex) {
242 cl = cl.getSuperclass();
243 }
244 }
245 if (field == null) {
246 throw (new NoSuchFieldException(name + " within " + obj.getClass()));
247 }
248 field.setAccessible(true);
249 } catch (SecurityException e) {
250 throw new RuntimeException(e);
251 }
252 return field;
253 }
254
255 }
|