001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2013, 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 return existsMethod(c, name, parameterTypes);
059 }
060
061 /**
062 * Analyze if a class or one of its super classes contains a given method.
063 * <p>
064 * Example: you can test with <code>YodaUtility.existsMethod(URLConnection.class,
065 * "setConnectTimeout", new Class[] {Integer.TYPE}</code> with JDK 1.4.2 and if you run it
066 * with a 1.5 JRE or higher then it will be successfully executed.
067 *
068 * @param clazz Class to analyze.
069 * @param name Method name.
070 * @param parameterTypes Parameter types.
071 * @return Does the class (or one of its super classes) have such a method?
072 */
073 public static boolean existsMethod(final Class clazz, final String name,
074 final Class[] parameterTypes) {
075 Method method = null;
076 Class cl = clazz;
077 try {
078 while (!Object.class.equals(cl)) {
079 try {
080 method = cl.getDeclaredMethod(name, parameterTypes);
081 break;
082 } catch (NoSuchMethodException ex) {
083 cl = cl.getSuperclass();
084 }
085 }
086 if (method == null) {
087 return false;
088 }
089 return true;
090 } catch (SecurityException e) {
091 throw new RuntimeException(e);
092 }
093 }
094
095 /**
096 * This method executes a method on an object or one of its super instances (even if it is
097 * private).
098 * <p>
099 * Example: you can compile <code>YodaUtility.executeMethod((URLConnection) httpConnection,
100 * "setConnectTimeout", new Class[] {Integer.TYPE}, new Object[] { new Integer(100)});</code>
101 * with JDK 1.4.2 and if you run it with a 1.5 JRE or higher then it will be successfully
102 * executed.
103 *
104 * @param obj Object.
105 * @param name Method name.
106 * @param parameterTypes Parameter types.
107 * @param parameter Parameter values.
108 * @return Execution result.
109 * @throws NoSuchMethodException Method not found.
110 * @throws InvocationTargetException Wrapped exception.
111 */
112 public static Object executeMethod(final Object obj, final String name,
113 final Class[] parameterTypes, final Object[] parameter) throws NoSuchMethodException,
114 InvocationTargetException {
115 Method method = null;
116 try {
117 Class cl = obj.getClass();
118 while (!Object.class.equals(cl)) {
119 try {
120 method = cl.getDeclaredMethod(name, parameterTypes);
121 break;
122 } catch (NoSuchMethodException ex) {
123 cl = cl.getSuperclass();
124 }
125 }
126 if (method == null) {
127 throw new NoSuchMethodException(name);
128 }
129 method.setAccessible(true);
130 } catch (SecurityException e) {
131 throw new RuntimeException(e);
132 }
133 try {
134 return method.invoke(obj, parameter);
135 } catch (IllegalArgumentException e) {
136 throw new RuntimeException(e);
137 } catch (IllegalAccessException e) {
138 throw new RuntimeException(e);
139 }
140 }
141
142 /**
143 * This method executes a static class method (even if it is private).
144 * <p>
145 * Example: you can compile <code>YodaUtility.executeMethod(
146 * "java.util.concurrent.locks.LockSupport",
147 * "park", new Class[0], new Object[0]);</code>
148 * with JDK 1.4.2 and if you run it with a 1.5 JRE or higher then it will be successfully
149 * executed.
150 *
151 * @param clazzName Name of class.
152 * @param name Name of static method to execute.
153 * @param parameterTypes Parameter types.
154 * @param parameter Parameter values.
155 * @return Execution result.
156 * @throws NoSuchMethodException Method not found.
157 * @throws InvocationTargetException Wrapped exception.
158 */
159 public static Object executeMethod(final String clazzName, final String name,
160 final Class[] parameterTypes, final Object[] parameter) throws NoSuchMethodException,
161 InvocationTargetException {
162 Method method = null;
163 try {
164 Class cl = Class.forName(clazzName);
165 method = cl.getDeclaredMethod(name, parameterTypes);
166 if (method == null) {
167 throw new NoSuchMethodException(name);
168 }
169 method.setAccessible(true);
170 return method.invoke(cl, parameter);
171 } catch (SecurityException e) {
172 throw new RuntimeException(e);
173 } catch (ClassNotFoundException e) {
174 throw new RuntimeException(e);
175 } catch (IllegalAccessException e) {
176 throw new RuntimeException(e);
177 }
178 }
179
180 /**
181 * This method returns the contents of an object variable .The class hierarchy is recursively
182 * searched to find such a field (even if it is private).
183 *
184 * @param obj Object.
185 * @param name Variable name.
186 * @return Contents of variable.
187 * @throws NoSuchFieldException Variable of given name was not found.
188 */
189 public static Object getFieldValue(final Object obj, final String name) throws NoSuchFieldException {
190 final Field field = getField(obj, name);
191 try {
192 return field.get(obj);
193 } catch (IllegalArgumentException e) {
194 throw new RuntimeException(e);
195 } catch (IllegalAccessException e) {
196 throw new RuntimeException(e);
197 }
198 }
199
200 /**
201 * This method sets the contents of an object variable. The class hierarchy is recursively
202 * searched to find such a field (even if it is private).
203 *
204 * @param obj Object.
205 * @param name Variable name.
206 * @param value Value to set.
207 * @throws NoSuchFieldException Variable of given name was not found.
208 */
209 public static void setFieldContent(final Object obj, final String name, final Object value)
210 throws NoSuchFieldException {
211 final Field field = getField(obj, name);
212 try {
213 field.set(obj, value);
214 } catch (IllegalArgumentException e) {
215 throw new RuntimeException(e);
216 } catch (IllegalAccessException e) {
217 throw new RuntimeException(e);
218 }
219 }
220
221 /**
222 * Get field of given name in given object. The class hierarchy is recursively searched
223 * to find such a field (even if it is private).
224 *
225 * @param obj Object to work on.
226 * @param name Search this field.
227 * @return Found field.
228 * @throws NoSuchFieldException Field with name <code>name</code> was not found.
229 */
230 public static Field getField(final Object obj, final String name) throws NoSuchFieldException {
231 Field field = null;
232 try {
233 Class cl = obj.getClass();
234 while (!Object.class.equals(cl)) {
235 try {
236 field = cl.getDeclaredField(name);
237 break;
238 } catch (NoSuchFieldException ex) {
239 cl = cl.getSuperclass();
240 }
241 }
242 if (field == null) {
243 throw (new NoSuchFieldException(name + " within " + obj.getClass()));
244 }
245 field.setAccessible(true);
246 } catch (SecurityException e) {
247 throw new RuntimeException(e);
248 }
249 return field;
250 }
251
252 }
|