Clover coverage report - brownies library - 1.0-beta-1
Coverage timestamp: 月 8 16 2004 17:14:42 GMT+09:00
file stats: LOC: 316   Methods: 17
NCLOC: 192   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ClassUtils.java 20.2% 26.6% 47.1% 25.8%
coverage coverage
 1   
 /*
 2   
  * Joey and its relative products are published under the terms
 3   
  * of the Apache Software License.
 4   
  */
 5   
 package org.asyrinx.brownie.core.lang;
 6   
 
 7   
 import java.lang.reflect.Constructor;
 8   
 import java.lang.reflect.InvocationTargetException;
 9   
 import java.lang.reflect.Modifier;
 10   
 import java.util.ArrayList;
 11   
 import java.util.List;
 12   
 
 13   
 /**
 14   
  * 
 15   
  * クラスに関するユーティリティです。 <br>
 16   
  * クラス名を指定した生成、基底クラスのチェック付の生成などが 主な責務です。 <br>
 17   
  * インスタンス生成のメソッドnewObjectのほとんどは、引数にbaseClassという
 18   
  * Class変数を持ち、この引数によって生成するインスタンスのクラスが
 19   
  * 意図しているクラス(あるいはインタフェース)を継承(実装)するものなのかをチェックします。 <br>
 20   
  * これらのメソッドは例外InstantiationExceptionをthrowsしています。 これは以下の場合にthrowされます。 <br>
 21   
  * ・引数baseClassによるチェックがパスしなかった。 <br>
 22   
  * ・クラス名が指定されていない。 <br>
 23   
  * ・クラスが見つからない。 <br>
 24   
  * ・コンストラクタが見つからない。 <br>
 25   
  * ・コンストラクタの引数が異なる。 <br>
 26   
  * ・クラスへのアクセス権に問題がある。 <br>
 27   
  * ・その他インスタンス生成の例外が発生した場合。 <br>
 28   
  * <br>
 29   
  * 
 30   
  * @author Akima
 31   
  */
 32   
 public class ClassUtils {
 33   
 
 34   
     public static final char PACKAGE_DELIM_CHAR = '.';
 35   
 
 36   
     public static final String PACKAGE_DELIM = ".";
 37   
 
 38   
     /**
 39   
      * クラス名によって指定されたクラスのインスタンスを生成します。 <br>
 40   
      * 
 41   
      * @param className
 42   
      *            生成されるクラスの名前
 43   
      * @param classLoader
 44   
      *            クラスを名前で検索する際のクラスローダ
 45   
      *            nullを指定した場合には、カレントスレッドのコンテキストクラスローダが使用されます。
 46   
      * @param baseClass
 47   
      *            生成されるクラスの基底クラス nullを指定した場合には、Objectクラスのclass変数が使用されます。
 48   
      * @return 生成されたインスタンス
 49   
      * @throws InstantiationException
 50   
      */
 51  0
     public static Object newObject(String className, ClassLoader classLoader,
 52   
             Class baseClass) throws InstantiationException {
 53  0
         if (classLoader == null)
 54  0
             classLoader = Thread.currentThread().getContextClassLoader();
 55  0
         if (className == null)
 56  0
             throw new InstantiationException("className is null !");
 57  0
         try {
 58  0
             Class resultClass = classLoader.loadClass(className);
 59  0
             return newObject(resultClass, baseClass);
 60   
         } catch (ClassNotFoundException e) {
 61  0
             throw new InstantiationException(e.toString());
 62   
         }
 63   
     }
 64   
 
 65   
     /**
 66   
      * クラス名によって指定されたクラスのインスタンスを生成します。 <br>
 67   
      * 
 68   
      * @param className
 69   
      *            生成されるクラスの名前
 70   
      * @param baseClass
 71   
      *            生成されるクラスの基底クラス nullを指定した場合には、Objectクラスのclass変数が使用されます。
 72   
      * @return 生成されたインスタンス
 73   
      * @throws InstantiationException
 74   
      */
 75  3
     public static Object newObject(String className, Class baseClass)
 76   
             throws InstantiationException {
 77  3
         if (className == null)
 78  0
             throw new InstantiationException("className is null !");
 79  3
         try {
 80  3
             Class resultClass = Class.forName(className);
 81  3
             return newObject(resultClass, baseClass);
 82   
         } catch (ClassNotFoundException e) {
 83  0
             throw new InstantiationException(e.toString());
 84   
         }
 85   
     }
 86   
 
 87   
     /**
 88   
      * 指定されたクラスのインスタンスを生成します。 <br>
 89   
      * 
 90   
      * @param instanciateClass
 91   
      *            生成されるクラス
 92   
      * @param baseClass
 93   
      *            生成されるクラスの基底クラス nullを指定した場合には、Objectクラスのclass変数が使用されます。
 94   
      * @return 生成されたインスタンス
 95   
      * @throws InstantiationException
 96   
      */
 97  3
     public static Object newObject(Class instanciateClass, Class baseClass)
 98   
             throws InstantiationException {
 99  3
         checkByBaseClass(instanciateClass, baseClass);
 100  3
         try {
 101  3
             return instanciateClass.newInstance();
 102   
         } catch (IllegalAccessException e) {
 103  0
             throw new InstantiationException(e.toString());
 104   
         }
 105   
     }
 106   
 
 107   
     /**
 108   
      * コンストラクタを検索しインスタンスを生成します。 <br>
 109   
      * 
 110   
      * @param instanciateClass
 111   
      *            生成されるインスタンスのクラス。
 112   
      * @param baseClass
 113   
      *            生成されるインスタンスのクラスの基底クラス nullを指定した場合には、Objectクラスのclass変数が使用されます。
 114   
      * @param params
 115   
      *            コンストラクタに渡される引数。
 116   
      * @return 生成されたインスタンス
 117   
      * @throws InstantiationException
 118   
      */
 119  1
     public static Object newObject(Class instanciateClass, Class baseClass,
 120   
             Object[] params) throws InstantiationException {
 121  1
         checkByBaseClass(instanciateClass, baseClass);
 122  1
         Constructor constructor = findConstructor(instanciateClass, params);
 123  1
         if (constructor == null)
 124  0
             throw new InstantiationException("該当するコンストラクタが見つかりませんでした");
 125  1
         try {
 126  1
             return constructor.newInstance(params);
 127   
         } catch (InstantiationException e) {
 128  0
             throw new InstantiationException(e.toString());
 129   
         } catch (IllegalAccessException e) {
 130  0
             throw new InstantiationException(e.toString());
 131   
         } catch (InvocationTargetException e) {
 132  0
             throw new InstantiationException(e.toString());
 133   
         }
 134   
     }
 135   
 
 136   
     /**
 137   
      * コンストラクタを検索しインスタンスを生成します。 <br>
 138   
      * 
 139   
      * @param className
 140   
      *            生成されるクラスの名前
 141   
      * @param classLoader
 142   
      *            クラスを名前で検索する際のクラスローダ
 143   
      *            nullを指定した場合には、カレントスレッドのコンテキストクラスローダが使用されます。
 144   
      * @param baseClass
 145   
      *            生成されるインスタンスのクラスの基底クラス nullを指定した場合には、Objectクラスのclass変数が使用されます。
 146   
      * @param params
 147   
      *            コンストラクタに渡される引数。
 148   
      * @return 生成されたインスタンス
 149   
      * @throws InstantiationException
 150   
      */
 151  0
     public static Object newObject(String className, ClassLoader classLoader,
 152   
             Class baseClass, Object[] params) throws InstantiationException {
 153  0
         if (classLoader == null)
 154  0
             classLoader = Thread.currentThread().getContextClassLoader();
 155  0
         if (className == null)
 156  0
             throw new InstantiationException("className is null !");
 157  0
         try {
 158  0
             Class resultClass = classLoader.loadClass(className);
 159  0
             return newObject(resultClass, baseClass, params);
 160   
         } catch (ClassNotFoundException e) {
 161  0
             throw new InstantiationException(e.toString());
 162   
         }
 163   
     }
 164   
 
 165   
     /**
 166   
      * クラスと引数からコンストラクタを検索します。 <br>
 167   
      */
 168  1
     public static Constructor findConstructor(Class targetClass, Object[] params) {
 169  1
         Constructor[] constructors = targetClass.getConstructors();
 170  1
         for (int i = 0; i < constructors.length; i++) {
 171  1
             if (matchTypes(params, constructors[i].getParameterTypes()))
 172  1
                 return constructors[i];
 173   
         }
 174  0
         return null;
 175   
     }
 176   
 
 177   
     /**
 178   
      * 引数valuesの各要素が、引数valueTypesの各要素(Classクラスのインスタンス)の
 179   
      * インスタンスとして対応するるかどうかを判断します。 <br>
 180   
      * 
 181   
      * @return 全てのvalueのクラスがvalueTypesと合致すればtrue、一つでも合致しないものがあればfalse。
 182   
      */
 183  1
     public static boolean matchTypes(Object[] values, Class[] valueTypes) {
 184  1
         if (values == null)
 185  0
             return (valueTypes == null) || (valueTypes.length == 0);
 186  1
         if (valueTypes == null)
 187  0
             return false;
 188  1
         if (values.length != valueTypes.length)
 189  0
             return false;
 190  1
         for (int i = 0; i < values.length; i++) {
 191  1
             if (!valueTypes[i].isInstance(values[i]))
 192  0
                 return false;
 193   
         }
 194  1
         return true;
 195   
     }
 196   
 
 197  0
     public static List modifierToString(int value) {
 198  0
         List result = new ArrayList();
 199  0
         if (Modifier.isAbstract(value))
 200  0
             result.add("abstract");
 201  0
         if (Modifier.isFinal(value))
 202  0
             result.add("final");
 203  0
         if (Modifier.isInterface(value))
 204  0
             result.add("interface");
 205  0
         if (Modifier.isNative(value))
 206  0
             result.add("native");
 207  0
         if (Modifier.isPrivate(value))
 208  0
             result.add("private");
 209  0
         if (Modifier.isProtected(value))
 210  0
             result.add("protected");
 211  0
         if (Modifier.isPublic(value))
 212  0
             result.add("public");
 213  0
         if (Modifier.isStatic(value))
 214  0
             result.add("static");
 215  0
         if (Modifier.isStrict(value))
 216  0
             result.add("strict");
 217  0
         if (Modifier.isSynchronized(value))
 218  0
             result.add("synchronized");
 219  0
         if (Modifier.isTransient(value))
 220  0
             result.add("transient");
 221  0
         if (Modifier.isVolatile(value))
 222  0
             result.add("volatile");
 223  0
         return result;
 224   
     }
 225   
 
 226  4
     static private void checkByBaseClass(Class targetClass, Class baseClass)
 227   
             throws InstantiationException {
 228  4
         if (baseClass == null)
 229  4
             baseClass = Object.class;
 230  4
         if (!baseClass.isAssignableFrom(targetClass))
 231  0
             throw new InstantiationException(targetClass.getName() + "クラスは"
 232   
                     + baseClass.getName() + "クラスと互換性がありません");
 233   
     }
 234   
 
 235   
     /**
 236   
      * 指定したtargetクラスが、classNameで表されるクラス名のクラスかどうかを返す。
 237   
      * もし、クラス名でなかった場合はtargetクラスのスーパークラスのクラス名と比較する。
 238   
      * 
 239   
      * @param target
 240   
      *            対象となるClassクラスのインスタンス
 241   
      * @param className
 242   
      *            照合するクラス名。
 243   
      * @return 継承ツリーをさかのぼった結果、クラス名がclassNameと照合するクラスがあればtrueなければfalse
 244   
      */
 245  0
     static public boolean isAssignableFrom(Class target, final String className) {
 246  0
         if (className == null)
 247  0
             return false;
 248  0
         if (target == null)
 249  0
             return false;
 250  0
         if (className.equals(target.getName()))
 251  0
             return true;
 252  0
         Class[] intf = target.getInterfaces();
 253  0
         for (int idx = 0; idx < intf.length; idx++) {
 254  0
             if (isAssignableFrom(intf[idx], className))
 255  0
                 return true;
 256   
         }
 257  0
         return isAssignableFrom(target.getSuperclass(), className);
 258   
     }
 259   
 
 260  0
     static public void showClassLoaders() {
 261  0
         showClassLoaders(Thread.currentThread().getContextClassLoader());
 262   
     }
 263   
 
 264  0
     static public void showClassLoaders(Class clazz) {
 265  0
         showClassLoaders(clazz.getClassLoader());
 266   
     }
 267   
 
 268  0
     static public void showClassLoaders(ClassLoader loader) {
 269  0
         if (loader == null) {
 270  0
             return;
 271   
         }
 272  0
         int depth = getClassLoaderDepth(loader);
 273  0
         ClassLoader target = loader;
 274  0
         while (target != null) {
 275  0
             System.out.println(depth + ": " + target);
 276  0
             depth--;
 277  0
             target = target.getParent();
 278   
         }
 279   
     }
 280   
 
 281  0
     public static int getClassLoaderDepth(ClassLoader loader) {
 282  0
         int result = 0;
 283  0
         while (loader != null) {
 284  0
             result++;
 285  0
             loader = loader.getParent();
 286   
         }
 287  0
         return result;
 288   
     }
 289   
 
 290  0
     public static boolean isAncestor(ClassLoader ancestor, ClassLoader target) {
 291  0
         if (target == null && ancestor == null)
 292  0
             return true;
 293  0
         if (target == null)
 294  0
             return false;
 295  0
         if (target == ancestor)
 296  0
             return true;
 297  0
         return isAncestor(ancestor, target.getParent());
 298   
     }
 299   
 
 300  1
     public static String toShortClassName(Class class1) {
 301  1
         if (class1 == null)
 302  1
             return null;
 303  0
         return toShortClassName(class1.getName());
 304   
     }
 305   
 
 306  4
     public static String toShortClassName(String className) {
 307  4
         if (StringUtils.isEmpty(className))
 308  2
             return null;
 309  2
         final List elements = StringUtils.tokenize(className, PACKAGE_DELIM);
 310  2
         if (elements == null)
 311  0
             return null;
 312  2
         if (elements.isEmpty())
 313  0
             return null;
 314  2
         return String.valueOf(elements.get(elements.size() - 1));
 315   
     }
 316   
 }