1472 |
17 Oct 05 |
nicklas |
1 |
/* |
1472 |
17 Oct 05 |
nicklas |
$Id$ |
1472 |
17 Oct 05 |
nicklas |
3 |
|
3675 |
16 Aug 07 |
jari |
Copyright (C) 2005 Nicklas Nordborg |
4889 |
06 Apr 09 |
nicklas |
Copyright (C) 2006 Jari Häkkinen |
3675 |
16 Aug 07 |
jari |
Copyright (C) 2007 Nicklas Nordborg |
1472 |
17 Oct 05 |
nicklas |
7 |
|
2304 |
22 May 06 |
jari |
This file is part of BASE - BioArray Software Environment. |
2304 |
22 May 06 |
jari |
Available at http://base.thep.lu.se/ |
1472 |
17 Oct 05 |
nicklas |
10 |
|
1472 |
17 Oct 05 |
nicklas |
BASE is free software; you can redistribute it and/or |
1472 |
17 Oct 05 |
nicklas |
modify it under the terms of the GNU General Public License |
4479 |
05 Sep 08 |
jari |
as published by the Free Software Foundation; either version 3 |
1472 |
17 Oct 05 |
nicklas |
of the License, or (at your option) any later version. |
1472 |
17 Oct 05 |
nicklas |
15 |
|
1472 |
17 Oct 05 |
nicklas |
BASE is distributed in the hope that it will be useful, |
1472 |
17 Oct 05 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
1472 |
17 Oct 05 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1472 |
17 Oct 05 |
nicklas |
GNU General Public License for more details. |
1472 |
17 Oct 05 |
nicklas |
20 |
|
1472 |
17 Oct 05 |
nicklas |
You should have received a copy of the GNU General Public License |
4515 |
11 Sep 08 |
jari |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
1472 |
17 Oct 05 |
nicklas |
23 |
*/ |
1472 |
17 Oct 05 |
nicklas |
24 |
package net.sf.basedb.util; |
1472 |
17 Oct 05 |
nicklas |
25 |
|
1472 |
17 Oct 05 |
nicklas |
26 |
import java.lang.reflect.Constructor; |
7513 |
02 Nov 18 |
nicklas |
27 |
import java.lang.reflect.InvocationTargetException; |
4233 |
17 Apr 08 |
nicklas |
28 |
import java.lang.reflect.Method; |
1617 |
16 Nov 05 |
nicklas |
29 |
import java.util.Set; |
7513 |
02 Nov 18 |
nicklas |
30 |
|
7513 |
02 Nov 18 |
nicklas |
31 |
import net.sf.basedb.core.BaseException; |
7513 |
02 Nov 18 |
nicklas |
32 |
|
1617 |
16 Nov 05 |
nicklas |
33 |
import java.util.HashSet; |
1617 |
16 Nov 05 |
nicklas |
34 |
import java.util.Collections; |
1472 |
17 Oct 05 |
nicklas |
35 |
|
1472 |
17 Oct 05 |
nicklas |
36 |
/** |
1584 |
10 Nov 05 |
nicklas |
Utility class for {@link Class} objects. |
1472 |
17 Oct 05 |
nicklas |
38 |
|
1472 |
17 Oct 05 |
nicklas |
39 |
|
1472 |
17 Oct 05 |
nicklas |
@author Nicklas |
1472 |
17 Oct 05 |
nicklas |
@version 2.0 |
1472 |
17 Oct 05 |
nicklas |
@base.modified $Date$ |
1472 |
17 Oct 05 |
nicklas |
43 |
*/ |
1472 |
17 Oct 05 |
nicklas |
44 |
public class ClassUtil |
1472 |
17 Oct 05 |
nicklas |
45 |
{ |
1472 |
17 Oct 05 |
nicklas |
46 |
|
1472 |
17 Oct 05 |
nicklas |
47 |
/** |
7513 |
02 Nov 18 |
nicklas |
Utility method for creating a new instance from a class with a default |
7513 |
02 Nov 18 |
nicklas |
no-argument constructor. Exceptions are wrapped in BaseExceptions. |
7513 |
02 Nov 18 |
nicklas |
@since 3.14 |
7513 |
02 Nov 18 |
nicklas |
51 |
*/ |
7513 |
02 Nov 18 |
nicklas |
52 |
public static <I> I newInstance(Class<I> clazz) |
7513 |
02 Nov 18 |
nicklas |
53 |
{ |
7513 |
02 Nov 18 |
nicklas |
54 |
try |
7513 |
02 Nov 18 |
nicklas |
55 |
{ |
7513 |
02 Nov 18 |
nicklas |
56 |
return clazz.getDeclaredConstructor().newInstance(); |
7513 |
02 Nov 18 |
nicklas |
57 |
} |
7513 |
02 Nov 18 |
nicklas |
58 |
catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) |
7513 |
02 Nov 18 |
nicklas |
59 |
{ |
7513 |
02 Nov 18 |
nicklas |
60 |
throw new BaseException(ex); |
7513 |
02 Nov 18 |
nicklas |
61 |
} |
7513 |
02 Nov 18 |
nicklas |
62 |
} |
7513 |
02 Nov 18 |
nicklas |
63 |
|
7513 |
02 Nov 18 |
nicklas |
64 |
/** |
7729 |
14 Jun 19 |
nicklas |
Utility method for creating a new instance from a class (given by name) |
7729 |
14 Jun 19 |
nicklas |
with a default no-argument constructor. Exceptions are wrapped in BaseExceptions. |
7729 |
14 Jun 19 |
nicklas |
@since 3.16 |
7729 |
14 Jun 19 |
nicklas |
@see #checkAndLoadClass(ClassLoader, String, boolean, Class, Class...) |
7729 |
14 Jun 19 |
nicklas |
69 |
*/ |
7729 |
14 Jun 19 |
nicklas |
70 |
public static <I> I newInstance(ClassLoader classLoader, String name, Class<I> iface, Class<?>... interfaces) |
7729 |
14 Jun 19 |
nicklas |
71 |
{ |
7729 |
14 Jun 19 |
nicklas |
72 |
try |
7729 |
14 Jun 19 |
nicklas |
73 |
{ |
7729 |
14 Jun 19 |
nicklas |
74 |
Class<? extends I> clazz = checkAndLoadClass(classLoader, name, true, iface, interfaces); |
7729 |
14 Jun 19 |
nicklas |
75 |
return clazz.getDeclaredConstructor().newInstance(); |
7729 |
14 Jun 19 |
nicklas |
76 |
} |
7729 |
14 Jun 19 |
nicklas |
77 |
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) |
7729 |
14 Jun 19 |
nicklas |
78 |
{ |
7729 |
14 Jun 19 |
nicklas |
79 |
throw new BaseException(ex); |
7729 |
14 Jun 19 |
nicklas |
80 |
} |
7729 |
14 Jun 19 |
nicklas |
81 |
} |
7729 |
14 Jun 19 |
nicklas |
82 |
|
7729 |
14 Jun 19 |
nicklas |
83 |
/** |
1472 |
17 Oct 05 |
nicklas |
Find a constructor for the specified class which takes parameters of |
1472 |
17 Oct 05 |
nicklas |
the specified types taking superclasses and interfaces into |
1472 |
17 Oct 05 |
nicklas |
account. This method finds the first declared constructor which can |
1472 |
17 Oct 05 |
nicklas |
accept parameters of the specified type. |
1472 |
17 Oct 05 |
nicklas |
88 |
|
1472 |
17 Oct 05 |
nicklas |
@param clazz The class to find a constructor for |
1472 |
17 Oct 05 |
nicklas |
@param parameters The parameters that are going to be sent to the |
1584 |
10 Nov 05 |
nicklas |
constructor's {@link Constructor#newInstance(Object[])} method |
1472 |
17 Oct 05 |
nicklas |
@return A constructor object or null if no constructor was found |
1472 |
17 Oct 05 |
nicklas |
93 |
*/ |
1472 |
17 Oct 05 |
nicklas |
94 |
@SuppressWarnings({"unchecked"}) |
1472 |
17 Oct 05 |
nicklas |
95 |
public static <I> Constructor<I> findConstructor(Class<I> clazz, Object[] parameters) |
1472 |
17 Oct 05 |
nicklas |
96 |
{ |
3459 |
07 Jun 07 |
nicklas |
97 |
Constructor<I>[] all = (Constructor<I>[])clazz.getDeclaredConstructors(); |
1472 |
17 Oct 05 |
nicklas |
98 |
for (Constructor<I> c : all) |
1472 |
17 Oct 05 |
nicklas |
99 |
{ |
1472 |
17 Oct 05 |
nicklas |
100 |
if (isAssignable(c.getParameterTypes(), parameters)) |
1472 |
17 Oct 05 |
nicklas |
101 |
{ |
1472 |
17 Oct 05 |
nicklas |
102 |
return c; |
1472 |
17 Oct 05 |
nicklas |
103 |
} |
1472 |
17 Oct 05 |
nicklas |
104 |
} |
1472 |
17 Oct 05 |
nicklas |
105 |
return null; |
1472 |
17 Oct 05 |
nicklas |
106 |
} |
1472 |
17 Oct 05 |
nicklas |
107 |
|
1472 |
17 Oct 05 |
nicklas |
108 |
/** |
1472 |
17 Oct 05 |
nicklas |
Check if one array of class objects is assignment compatible with values in |
1472 |
17 Oct 05 |
nicklas |
another array. Ie. the {@link Class#isAssignableFrom(Class)} method returns |
1472 |
17 Oct 05 |
nicklas |
true for each element in the <code>classes</code> array with respect to the class |
1472 |
17 Oct 05 |
nicklas |
of the corresponding value in the <code>values</code> array. |
1472 |
17 Oct 05 |
nicklas |
Null elements in the <code>values</code> array are ignored. |
1472 |
17 Oct 05 |
nicklas |
@param classes The class objects representing the parameters we want to assign values to |
1472 |
17 Oct 05 |
nicklas |
@param values The parameter values to assign |
1472 |
17 Oct 05 |
nicklas |
@return TRUE if all parameters are assignable |
1472 |
17 Oct 05 |
nicklas |
117 |
*/ |
1472 |
17 Oct 05 |
nicklas |
118 |
public static boolean isAssignable(Class<?>[] classes, Object[] values) |
1472 |
17 Oct 05 |
nicklas |
119 |
{ |
1472 |
17 Oct 05 |
nicklas |
120 |
if (classes.length != values.length) return false; |
1472 |
17 Oct 05 |
nicklas |
121 |
for (int i = 0; i < classes.length; ++i) |
1472 |
17 Oct 05 |
nicklas |
122 |
{ |
1472 |
17 Oct 05 |
nicklas |
123 |
if (values[i] != null && !classes[i].isAssignableFrom(values[i].getClass())) return false; |
1472 |
17 Oct 05 |
nicklas |
124 |
} |
1472 |
17 Oct 05 |
nicklas |
125 |
return true; |
1472 |
17 Oct 05 |
nicklas |
126 |
} |
1617 |
16 Nov 05 |
nicklas |
127 |
|
1617 |
16 Nov 05 |
nicklas |
128 |
/** |
1617 |
16 Nov 05 |
nicklas |
Get all interfaces a class implements, including those implemented |
1617 |
16 Nov 05 |
nicklas |
by superclasses. |
1472 |
17 Oct 05 |
nicklas |
131 |
|
1617 |
16 Nov 05 |
nicklas |
@param clazz The <code>Class</code> to check |
1617 |
16 Nov 05 |
nicklas |
@return A <code>Set</code> containing the <code>Class</code> objects |
1617 |
16 Nov 05 |
nicklas |
for the interfaces |
1617 |
16 Nov 05 |
nicklas |
135 |
*/ |
6875 |
20 Apr 15 |
nicklas |
136 |
public static Set<Class<?>> getInterfaces(Class<?> clazz) |
1617 |
16 Nov 05 |
nicklas |
137 |
{ |
6875 |
20 Apr 15 |
nicklas |
138 |
Set<Class<?>> interfaces = new HashSet<Class<?>>(); |
1617 |
16 Nov 05 |
nicklas |
139 |
while (clazz != null) |
1617 |
16 Nov 05 |
nicklas |
140 |
{ |
1617 |
16 Nov 05 |
nicklas |
141 |
Collections.addAll(interfaces, clazz.getInterfaces()); |
1617 |
16 Nov 05 |
nicklas |
142 |
clazz = clazz.getSuperclass(); |
1617 |
16 Nov 05 |
nicklas |
143 |
} |
1617 |
16 Nov 05 |
nicklas |
144 |
return interfaces; |
1617 |
16 Nov 05 |
nicklas |
145 |
} |
1472 |
17 Oct 05 |
nicklas |
146 |
|
6875 |
20 Apr 15 |
nicklas |
147 |
|
3820 |
12 Oct 07 |
nicklas |
148 |
/** |
3820 |
12 Oct 07 |
nicklas |
Check if a specified class exists and, optionally, if it has public no-argument |
3820 |
12 Oct 07 |
nicklas |
constructor and implements a set of specific interfaces or superclasses. |
3820 |
12 Oct 07 |
nicklas |
151 |
|
3820 |
12 Oct 07 |
nicklas |
@param loader The classloader used to load the class, or null |
3820 |
12 Oct 07 |
nicklas |
to use the default classloader |
3820 |
12 Oct 07 |
nicklas |
@param name The fully qualified name of class to check |
3820 |
12 Oct 07 |
nicklas |
@param publicNoArgConstructor TRUE to check if a public no-argument constructor exists |
3820 |
12 Oct 07 |
nicklas |
@param interfaces An array of class objects representing interfaces or superclasses |
3820 |
12 Oct 07 |
nicklas |
that the class to check must implement or extend |
3820 |
12 Oct 07 |
nicklas |
@return The <code>Class</code> object for the named class |
3820 |
12 Oct 07 |
nicklas |
@throws ClassNotFoundException If a class with the specified name isn't found |
3820 |
12 Oct 07 |
nicklas |
@throws NoSuchMethodException If a public no-argument constructor isn't found |
3820 |
12 Oct 07 |
nicklas |
@throws ClassCastException If the class doesn't implement or extend all of |
3820 |
12 Oct 07 |
nicklas |
the interfaces/superclasses |
3820 |
12 Oct 07 |
nicklas |
@since 2.5 |
3820 |
12 Oct 07 |
nicklas |
164 |
*/ |
7401 |
28 Aug 17 |
nicklas |
165 |
@SuppressWarnings("unchecked") |
7401 |
28 Aug 17 |
nicklas |
166 |
public static <C> Class<? extends C> checkAndLoadClass(ClassLoader loader, String name, |
7401 |
28 Aug 17 |
nicklas |
167 |
boolean publicNoArgConstructor, Class<C> iface, Class<?>... interfaces) |
3820 |
12 Oct 07 |
nicklas |
168 |
throws ClassNotFoundException, NoSuchMethodException, ClassCastException |
3820 |
12 Oct 07 |
nicklas |
169 |
{ |
3820 |
12 Oct 07 |
nicklas |
170 |
if (loader == null) loader = ClassUtil.class.getClassLoader(); |
3820 |
12 Oct 07 |
nicklas |
171 |
Class<?> clazz = loader.loadClass(name); |
7401 |
28 Aug 17 |
nicklas |
172 |
checkClass(clazz, publicNoArgConstructor, iface); |
7401 |
28 Aug 17 |
nicklas |
173 |
if (interfaces != null && interfaces.length > 0) |
7401 |
28 Aug 17 |
nicklas |
174 |
{ |
7401 |
28 Aug 17 |
nicklas |
175 |
checkClass(clazz, publicNoArgConstructor, interfaces); |
7401 |
28 Aug 17 |
nicklas |
176 |
} |
7401 |
28 Aug 17 |
nicklas |
177 |
return (Class<? extends C>)clazz; |
4740 |
05 Feb 09 |
nicklas |
178 |
} |
4740 |
05 Feb 09 |
nicklas |
179 |
|
7401 |
28 Aug 17 |
nicklas |
180 |
|
4740 |
05 Feb 09 |
nicklas |
181 |
/** |
4740 |
05 Feb 09 |
nicklas |
Check if a specified class has public no-argument |
4740 |
05 Feb 09 |
nicklas |
constructor and implements a set of specific interfaces or superclasses. |
4740 |
05 Feb 09 |
nicklas |
184 |
|
4740 |
05 Feb 09 |
nicklas |
@param clazz The clazz to check |
4740 |
05 Feb 09 |
nicklas |
@param publicNoArgConstructor TRUE to check if a public no-argument constructor exists |
4740 |
05 Feb 09 |
nicklas |
@param interfaces An array of class objects representing interfaces or superclasses |
4740 |
05 Feb 09 |
nicklas |
that the class to check must implement or extend |
4740 |
05 Feb 09 |
nicklas |
@throws NoSuchMethodException If a public no-argument constructor isn't found |
4740 |
05 Feb 09 |
nicklas |
@throws ClassCastException If the class doesn't implement or extend all of |
4740 |
05 Feb 09 |
nicklas |
the interfaces/superclasses |
4740 |
05 Feb 09 |
nicklas |
@since 2.10 |
4740 |
05 Feb 09 |
nicklas |
193 |
*/ |
4740 |
05 Feb 09 |
nicklas |
194 |
public static void checkClass(Class<?> clazz, |
4740 |
05 Feb 09 |
nicklas |
195 |
boolean publicNoArgConstructor, Class<?>... interfaces) |
4740 |
05 Feb 09 |
nicklas |
196 |
throws NoSuchMethodException, ClassCastException |
4740 |
05 Feb 09 |
nicklas |
197 |
{ |
3820 |
12 Oct 07 |
nicklas |
198 |
if (publicNoArgConstructor) |
3820 |
12 Oct 07 |
nicklas |
199 |
{ |
3820 |
12 Oct 07 |
nicklas |
200 |
clazz.getConstructor((Class<?>[])null); |
3820 |
12 Oct 07 |
nicklas |
201 |
} |
3820 |
12 Oct 07 |
nicklas |
202 |
if (interfaces != null) |
3820 |
12 Oct 07 |
nicklas |
203 |
{ |
3820 |
12 Oct 07 |
nicklas |
204 |
for (Class<?> iFace : interfaces) |
3820 |
12 Oct 07 |
nicklas |
205 |
{ |
3820 |
12 Oct 07 |
nicklas |
206 |
if (iFace != null && !iFace.isAssignableFrom(clazz)) |
3820 |
12 Oct 07 |
nicklas |
207 |
{ |
4740 |
05 Feb 09 |
nicklas |
208 |
throw new ClassCastException("Class '" + clazz.getName() + "' is not a '" + iFace.getName() + "'"); |
3820 |
12 Oct 07 |
nicklas |
209 |
} |
3820 |
12 Oct 07 |
nicklas |
210 |
} |
3820 |
12 Oct 07 |
nicklas |
211 |
} |
3820 |
12 Oct 07 |
nicklas |
212 |
} |
4233 |
17 Apr 08 |
nicklas |
213 |
|
4233 |
17 Apr 08 |
nicklas |
214 |
/** |
4233 |
17 Apr 08 |
nicklas |
Find a method in a <code>clazz</code> with the given <code>name</code> |
4233 |
17 Apr 08 |
nicklas |
that takes the given list of <code>arguments</code>. This method is |
4233 |
17 Apr 08 |
nicklas |
just calling {@link Class#getMethod(String, Class...)} but returns |
4233 |
17 Apr 08 |
nicklas |
null instead of throwing an exception in case the method is not found. |
1617 |
16 Nov 05 |
nicklas |
219 |
|
4233 |
17 Apr 08 |
nicklas |
@param clazz The class to look for the method in |
4233 |
17 Apr 08 |
nicklas |
@param name The name of the method |
4233 |
17 Apr 08 |
nicklas |
@param arguments The class types of the arguments |
4233 |
17 Apr 08 |
nicklas |
@return The method or null if not found |
4233 |
17 Apr 08 |
nicklas |
@since 2.7 |
4233 |
17 Apr 08 |
nicklas |
225 |
*/ |
4233 |
17 Apr 08 |
nicklas |
226 |
public static Method findMethod(Class<?> clazz, String name, Class<?>... arguments) |
4233 |
17 Apr 08 |
nicklas |
227 |
{ |
4233 |
17 Apr 08 |
nicklas |
228 |
Method m = null; |
4233 |
17 Apr 08 |
nicklas |
229 |
try |
4233 |
17 Apr 08 |
nicklas |
230 |
{ |
4233 |
17 Apr 08 |
nicklas |
231 |
m = clazz.getMethod(name, arguments); |
4233 |
17 Apr 08 |
nicklas |
232 |
} |
4233 |
17 Apr 08 |
nicklas |
233 |
catch (NoSuchMethodException ex) |
4233 |
17 Apr 08 |
nicklas |
234 |
{} |
4233 |
17 Apr 08 |
nicklas |
235 |
return m; |
4233 |
17 Apr 08 |
nicklas |
236 |
} |
4233 |
17 Apr 08 |
nicklas |
237 |
|
1472 |
17 Oct 05 |
nicklas |
238 |
} |