jaulib v1.3.0
Jau Support Library (C++, Java, ..)
ReflectionUtil.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24package org.jau.lang;
25
26import java.lang.reflect.InaccessibleObjectException;
27import java.lang.reflect.InvocationTargetException;
28import java.lang.reflect.Method;
29
30import org.jau.sys.Debug;
31
32/**
33 * Utility methods to simplify reflection access
34 */
35public class ReflectionUtil {
36 static final boolean DEBUG = Debug.debug("Reflection");
37
38 private static final String asString(final Class<?>[] argTypes) {
39 final StringBuilder args = new StringBuilder();
40 if(null != argTypes) {
41 for (int i = 0; i < argTypes.length; i++) {
42 if(i > 0) {
43 args.append(", ");
44 }
45 args.append(argTypes[i].getName());
46 }
47 }
48 return args.toString();
49 }
50
51 private ReflectionUtil() {}
52
53 /**
54 * Returns true only if the class could be loaded but w/o class initialization.
55 */
56 public static boolean isClassAvailable(final String clazzName, final ClassLoader cl) {
57 try {
58 return null != Class.forName(clazzName, false /* initializeClazz */, cl);
59 /**
60 } catch( final ClassNotFoundException cnfe ) {
61 return false;
62 } catch( final ExceptionInInitializerError eiie ) {
63 return false;
64 } catch( final LinkageError le ) {
65 return false;
66 */
67 } catch( final Throwable t ) {
68 return false;
69 }
70 }
71
72 /**
73 * Loads and returns the class or null.
74 * @see Class#forName(java.lang.String, boolean, java.lang.ClassLoader)
75 */
76 public static final Class<?> getClass(final String clazzName, final boolean initializeClazz, final ClassLoader cl)
77 throws RuntimeException {
78 try {
79 return Class.forName(clazzName, initializeClazz, cl);
80 } catch( final Throwable t ) {
81 throw new RuntimeException(clazzName + " not available", t);
82 }
83 }
84
85 /**
86 * @throws RuntimeException if the Method can not be found.
87 */
88 public static final Method getMethod(final Class<?> clazz, final String methodName, final Class<?> ... argTypes)
89 throws RuntimeException
90 {
91 try {
92 return clazz.getDeclaredMethod(methodName, argTypes);
93 } catch (final Throwable t) {
94 throw new RuntimeException("Method: '" + clazz + "." + methodName + "(" + asString(argTypes) + ")' not found", t);
95 }
96 }
97
98 /**
99 * @throws RuntimeException if the Method can not be found.
100 */
101 public static final Method getMethod(final String clazzName, final boolean initializeClazz, final String methodName, final Class<?>[] argTypes, final ClassLoader cl)
102 throws RuntimeException
103 {
104 try {
105 return getMethod(Class.forName(clazzName, initializeClazz, cl), methodName, argTypes);
106 } catch (final Throwable t) {
107 throw new RuntimeException("Method: '" + clazzName + "." + methodName + "(" + asString(argTypes) + ")' not found", t);
108 }
109 }
110
111 /**
112 * @param instance may be null in case of a static method
113 * @param method the method to be called
114 * @param args the method arguments
115 * @return the methods result, maybe null if void
116 * @throws RuntimeException if call fails
117 */
118 @SuppressWarnings("unchecked")
119 public static final <R> R callMethod(final Object instance, final Method method, final Object ... args)
120 throws RuntimeException
121 {
122 try {
123 return (R)method.invoke(instance, args);
124 } catch (final Exception e) {
125 Throwable t = e;
126 if (t instanceof InvocationTargetException) {
127 t = ((InvocationTargetException) t).getTargetException();
128 }
129 if (t instanceof Error) {
130 throw (Error) t;
131 }
132 if (t instanceof RuntimeException) {
133 throw (RuntimeException) t;
134 }
135 throw new RuntimeException("calling "+method+" failed", t);
136 }
137 }
138
139 /**
140 * @param method the method to be called
141 * @param args the method arguments
142 * @return the methods result, maybe null if void
143 * @throws RuntimeException if call fails
144 */
145 public static final <R> R callStaticMethod(final Method method, final Object ... args)
146 throws RuntimeException
147 {
148 return callMethod(null, method, args);
149 }
150
151 /**
152 * @throws RuntimeException if the instance can not be created.
153 */
154 public static final <R> R callStaticMethod(final String clazzName, final String methodName, final Class<?>[] argTypes, final Object[] args, final ClassLoader cl)
155 throws RuntimeException
156 {
157 return callStaticMethod(getMethod(clazzName, true /* initializeClazz */, methodName, argTypes, cl), args);
158 }
159
160 /** Convenient Method access class */
161 public static class MethodAccessor {
162 Method m = null;
163
164 /** Check {@link #available()} before using instance. */
165 public MethodAccessor(final Class<?> clazz, final String methodName, final Class<?> ... argTypes) {
166 try {
167 m = ReflectionUtil.getMethod(clazz, methodName, argTypes);
168 } catch (final RuntimeException jre) { /* method n/a */ }
169 }
170
171 /** Returns true if method is available, otherwise false. */
172 public boolean available() {
173 return null != m;
174 }
175
176 /**
177 * See {@link Method#setAccessible(boolean)}.
178 * @param flag new accessible flag value
179 * @throws InaccessibleObjectException
180 * @throws SecurityException
181 */
182 public void setAccessible(final boolean flag)
183 throws InaccessibleObjectException, SecurityException
184 {
185 m.setAccessible(flag);
186 }
187
188 /**
189 * See {@link #setAccessible(boolean)}.
190 * @param flag new accessible flag value
191 * @return true if successful, otherwise false in case {@link Method#setAccessible(boolean)} threw an exception.
192 */
193 public boolean setAccessibleSafe(final boolean flag) {
194 try {
195 m.setAccessible(flag);
196 return true;
197 } catch( final Throwable t ) {
198 return false;
199 }
200 }
201
202 /**
203 * Check {@link #available()} before calling to avoid throwing a RuntimeException.
204 * @param instance may be null in case of a static method
205 * @param args the method arguments
206 * @return the methods result, maybe null if void
207 * @throws RuntimeException if call fails or method not {@link #available()}.
208 */
209 public <R> R callMethod(final Object instance, final Object ... args) {
210 if(null == m) {
211 throw new RuntimeException("Method not available. Instance: "+instance);
212 }
213 return ReflectionUtil.callMethod(instance, m, args);
214 }
215
216 /**
217 * Check {@link #available()} before calling to avoid throwing a RuntimeException.
218 * @param args the method arguments
219 * @return the methods result, maybe null if void
220 * @throws RuntimeException if call fails or method not {@link #available()}.
221 */
222 public <R> R callStaticMethod(final Object ... args) {
223 if(null == m) {
224 throw new RuntimeException("Method not available.");
225 }
226 return ReflectionUtil.callStaticMethod(m, args);
227 }
228 }
229
230}
void setAccessible(final boolean flag)
See Method#setAccessible(boolean).
boolean setAccessibleSafe(final boolean flag)
See setAccessible(boolean).
MethodAccessor(final Class<?> clazz, final String methodName, final Class<?> ... argTypes)
Check available() before using instance.
boolean available()
Returns true if method is available, otherwise false.
Utility methods to simplify reflection access.
static final< R > R callStaticMethod(final Method method, final Object ... args)
static final Class<?> getClass(final String clazzName, final boolean initializeClazz, final ClassLoader cl)
Loads and returns the class or null.
static final< R > R callStaticMethod(final String clazzName, final String methodName, final Class<?>[] argTypes, final Object[] args, final ClassLoader cl)
static final Method getMethod(final String clazzName, final boolean initializeClazz, final String methodName, final Class<?>[] argTypes, final ClassLoader cl)
static final< R > R callMethod(final Object instance, final Method method, final Object ... args)
static final Method getMethod(final Class<?> clazz, final String methodName, final Class<?> ... argTypes)
static boolean isClassAvailable(final String clazzName, final ClassLoader cl)
Returns true only if the class could be loaded but w/o class initialization.
Helper routines for logging and debugging.
Definition: Debug.java:35
static final boolean debug(final String subcomponent)
Definition: Debug.java:63