src/core/net/sf/basedb/util/ClassUtil.java

Code
Comments
Other
Rev Date Author Line
1472 17 Oct 05 nicklas 1 /*
1472 17 Oct 05 nicklas 2   $Id$
1472 17 Oct 05 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2005 Nicklas Nordborg
4889 06 Apr 09 nicklas 5   Copyright (C) 2006 Jari Häkkinen
3675 16 Aug 07 jari 6   Copyright (C) 2007 Nicklas Nordborg
1472 17 Oct 05 nicklas 7
2304 22 May 06 jari 8   This file is part of BASE - BioArray Software Environment.
2304 22 May 06 jari 9   Available at http://base.thep.lu.se/
1472 17 Oct 05 nicklas 10
1472 17 Oct 05 nicklas 11   BASE is free software; you can redistribute it and/or
1472 17 Oct 05 nicklas 12   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 13   as published by the Free Software Foundation; either version 3
1472 17 Oct 05 nicklas 14   of the License, or (at your option) any later version.
1472 17 Oct 05 nicklas 15
1472 17 Oct 05 nicklas 16   BASE is distributed in the hope that it will be useful,
1472 17 Oct 05 nicklas 17   but WITHOUT ANY WARRANTY; without even the implied warranty of
1472 17 Oct 05 nicklas 18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1472 17 Oct 05 nicklas 19   GNU General Public License for more details.
1472 17 Oct 05 nicklas 20
1472 17 Oct 05 nicklas 21   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 22   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 37   Utility class for {@link Class} objects.
1472 17 Oct 05 nicklas 38
1472 17 Oct 05 nicklas 39
1472 17 Oct 05 nicklas 40   @author Nicklas
1472 17 Oct 05 nicklas 41   @version 2.0
1472 17 Oct 05 nicklas 42   @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 48     Utility method for creating a new instance from a class with a default 
7513 02 Nov 18 nicklas 49     no-argument constructor. Exceptions are wrapped in BaseExceptions.
7513 02 Nov 18 nicklas 50     @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 65     Utility method for creating a new instance from a class (given by name) 
7729 14 Jun 19 nicklas 66     with a default no-argument constructor. Exceptions are wrapped in BaseExceptions.
7729 14 Jun 19 nicklas 67     @since 3.16
7729 14 Jun 19 nicklas 68     @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 84     Find a constructor for the specified class which takes parameters of
1472 17 Oct 05 nicklas 85     the specified types taking superclasses and interfaces into
1472 17 Oct 05 nicklas 86     account. This method finds the first declared constructor which can
1472 17 Oct 05 nicklas 87     accept parameters of the specified type.
1472 17 Oct 05 nicklas 88     
1472 17 Oct 05 nicklas 89     @param clazz The class to find a constructor for
1472 17 Oct 05 nicklas 90     @param parameters The parameters that are going to be sent to the 
1584 10 Nov 05 nicklas 91       constructor's {@link Constructor#newInstance(Object[])} method
1472 17 Oct 05 nicklas 92     @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 109     Check if one array of class objects is assignment compatible with values in
1472 17 Oct 05 nicklas 110     another array. Ie. the {@link Class#isAssignableFrom(Class)} method returns
1472 17 Oct 05 nicklas 111     true for each element in the <code>classes</code> array with respect to the class
1472 17 Oct 05 nicklas 112     of the corresponding value in the <code>values</code> array. 
1472 17 Oct 05 nicklas 113     Null elements in the <code>values</code> array are ignored.
1472 17 Oct 05 nicklas 114     @param classes The class objects representing the parameters we want to assign values to
1472 17 Oct 05 nicklas 115     @param values The parameter values to assign
1472 17 Oct 05 nicklas 116     @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 129     Get all interfaces a class implements, including those implemented
1617 16 Nov 05 nicklas 130     by superclasses.
1472 17 Oct 05 nicklas 131
1617 16 Nov 05 nicklas 132     @param clazz The <code>Class</code> to check
1617 16 Nov 05 nicklas 133     @return A <code>Set</code> containing the <code>Class</code> objects 
1617 16 Nov 05 nicklas 134       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 149     Check if a specified class exists and, optionally, if it has public no-argument
3820 12 Oct 07 nicklas 150     constructor and implements a set of specific interfaces or superclasses.
3820 12 Oct 07 nicklas 151     
3820 12 Oct 07 nicklas 152     @param loader The classloader used to load the class, or null
3820 12 Oct 07 nicklas 153       to use the default classloader
3820 12 Oct 07 nicklas 154     @param name The fully qualified name of class to check
3820 12 Oct 07 nicklas 155     @param publicNoArgConstructor TRUE to check if a public no-argument constructor exists
3820 12 Oct 07 nicklas 156     @param interfaces An array of class objects representing interfaces or superclasses
3820 12 Oct 07 nicklas 157       that the class to check must implement or extend
3820 12 Oct 07 nicklas 158     @return The <code>Class</code> object for the named class
3820 12 Oct 07 nicklas 159     @throws ClassNotFoundException If a class with the specified name isn't found
3820 12 Oct 07 nicklas 160     @throws NoSuchMethodException If a public no-argument constructor isn't found
3820 12 Oct 07 nicklas 161     @throws ClassCastException If the class doesn't implement or extend all of
3820 12 Oct 07 nicklas 162       the interfaces/superclasses
3820 12 Oct 07 nicklas 163     @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 182     Check if a specified class has public no-argument
4740 05 Feb 09 nicklas 183     constructor and implements a set of specific interfaces or superclasses.
4740 05 Feb 09 nicklas 184     
4740 05 Feb 09 nicklas 185     @param clazz The clazz to check
4740 05 Feb 09 nicklas 186     @param publicNoArgConstructor TRUE to check if a public no-argument constructor exists
4740 05 Feb 09 nicklas 187     @param interfaces An array of class objects representing interfaces or superclasses
4740 05 Feb 09 nicklas 188       that the class to check must implement or extend
4740 05 Feb 09 nicklas 189     @throws NoSuchMethodException If a public no-argument constructor isn't found
4740 05 Feb 09 nicklas 190     @throws ClassCastException If the class doesn't implement or extend all of
4740 05 Feb 09 nicklas 191       the interfaces/superclasses
4740 05 Feb 09 nicklas 192     @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 215     Find a method in a <code>clazz</code> with the given <code>name</code>
4233 17 Apr 08 nicklas 216     that takes the given list of <code>arguments</code>. This method is
4233 17 Apr 08 nicklas 217     just calling {@link Class#getMethod(String, Class...)} but returns
4233 17 Apr 08 nicklas 218     null instead of throwing an exception in case the method is not found.
1617 16 Nov 05 nicklas 219
4233 17 Apr 08 nicklas 220     @param clazz The class to look for the method in
4233 17 Apr 08 nicklas 221     @param name The name of the method
4233 17 Apr 08 nicklas 222     @param arguments The class types of the arguments
4233 17 Apr 08 nicklas 223     @return The method or null if not found
4233 17 Apr 08 nicklas 224     @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 }