Coverage Report - org.apache.shiro.util.ClassUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassUtils
72%
40/55
76%
20/26
2.833
ClassUtils$1
100%
2/2
N/A
2.833
ClassUtils$2
100%
2/2
N/A
2.833
ClassUtils$3
100%
2/2
N/A
2.833
ClassUtils$ClassLoaderAccessor
N/A
N/A
2.833
ClassUtils$ExceptionIgnoringAccessor
80%
16/20
37%
3/8
2.833
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.shiro.util;
 20  
 
 21  
 import org.slf4j.Logger;
 22  
 import org.slf4j.LoggerFactory;
 23  
 
 24  
 import java.io.InputStream;
 25  
 import java.lang.reflect.Constructor;
 26  
 
 27  
 
 28  
 /**
 29  
  * Utility method library used to conveniently interact with <code>Class</code>es, such as acquiring them from the
 30  
  * application <code>ClassLoader</code>s and instantiating Objects from them.
 31  
  *
 32  
  * @since 0.1
 33  
  */
 34  102
 public class ClassUtils {
 35  
 
 36  
     //TODO - complete JavaDoc
 37  
 
 38  
     /**
 39  
      * Private internal log instance.
 40  
      */
 41  1
     private static final Logger log = LoggerFactory.getLogger(ClassUtils.class);
 42  
 
 43  
     /**
 44  
      * @since 1.0
 45  
      */
 46  1
     private static final ClassLoaderAccessor THREAD_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
 47  
         @Override
 48  
         protected ClassLoader doGetClassLoader() throws Throwable {
 49  94
             return Thread.currentThread().getContextClassLoader();
 50  
         }
 51  
     };
 52  
 
 53  
     /**
 54  
      * @since 1.0
 55  
      */
 56  1
     private static final ClassLoaderAccessor CLASS_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
 57  
         @Override
 58  
         protected ClassLoader doGetClassLoader() throws Throwable {
 59  19
             return ClassUtils.class.getClassLoader();
 60  
         }
 61  
     };
 62  
 
 63  
     /**
 64  
      * @since 1.0
 65  
      */
 66  1
     private static final ClassLoaderAccessor SYSTEM_CL_ACCESSOR = new ExceptionIgnoringAccessor() {
 67  
         @Override
 68  
         protected ClassLoader doGetClassLoader() throws Throwable {
 69  19
             return ClassLoader.getSystemClassLoader();
 70  
         }
 71  
     };
 72  
 
 73  
     /**
 74  
      * Returns the specified resource by checking the current thread's
 75  
      * {@link Thread#getContextClassLoader() context class loader}, then the
 76  
      * current ClassLoader (<code>ClassUtils.class.getClassLoader()</code>), then the system/application
 77  
      * ClassLoader (<code>ClassLoader.getSystemClassLoader()</code>, in that order, using
 78  
      * {@link ClassLoader#getResourceAsStream(String) getResourceAsStream(name)}.
 79  
      *
 80  
      * @param name the name of the resource to acquire from the classloader(s).
 81  
      * @return the InputStream of the resource found, or <code>null</code> if the resource cannot be found from any
 82  
      *         of the three mentioned ClassLoaders.
 83  
      * @since 0.9
 84  
      */
 85  
     public static InputStream getResourceAsStream(String name) {
 86  
 
 87  7
         InputStream is = THREAD_CL_ACCESSOR.getResourceStream(name);
 88  
 
 89  7
         if (is == null) {
 90  2
             if (log.isTraceEnabled()) {
 91  2
                 log.trace("Resource [" + name + "] was not found via the thread context ClassLoader.  Trying the " +
 92  
                         "current ClassLoader...");
 93  
             }
 94  2
             is = CLASS_CL_ACCESSOR.getResourceStream(name);
 95  
         }
 96  
 
 97  7
         if (is == null) {
 98  2
             if (log.isTraceEnabled()) {
 99  2
                 log.trace("Resource [" + name + "] was not found via the current class loader.  Trying the " +
 100  
                         "system/application ClassLoader...");
 101  
             }
 102  2
             is = SYSTEM_CL_ACCESSOR.getResourceStream(name);
 103  
         }
 104  
 
 105  7
         if (is == null && log.isTraceEnabled()) {
 106  2
             log.trace("Resource [" + name + "] was not found via the thread context, current, or " +
 107  
                     "system/application ClassLoaders.  All heuristics have been exhausted.  Returning null.");
 108  
         }
 109  
 
 110  7
         return is;
 111  
     }
 112  
 
 113  
     /**
 114  
      * Attempts to load the specified class name from the current thread's
 115  
      * {@link Thread#getContextClassLoader() context class loader}, then the
 116  
      * current ClassLoader (<code>ClassUtils.class.getClassLoader()</code>), then the system/application
 117  
      * ClassLoader (<code>ClassLoader.getSystemClassLoader()</code>, in that order.  If any of them cannot locate
 118  
      * the specified class, an <code>UnknownClassException</code> is thrown (our RuntimeException equivalent of
 119  
      * the JRE's <code>ClassNotFoundException</code>.
 120  
      *
 121  
      * @param fqcn the fully qualified class name to load
 122  
      * @return the located class
 123  
      * @throws UnknownClassException if the class cannot be found.
 124  
      */
 125  
     public static Class forName(String fqcn) throws UnknownClassException {
 126  
 
 127  87
         Class clazz = THREAD_CL_ACCESSOR.loadClass(fqcn);
 128  
 
 129  87
         if (clazz == null) {
 130  17
             if (log.isTraceEnabled()) {
 131  17
                 log.trace("Unable to load class named [" + fqcn +
 132  
                         "] from the thread context ClassLoader.  Trying the current ClassLoader...");
 133  
             }
 134  17
             clazz = CLASS_CL_ACCESSOR.loadClass(fqcn);
 135  
         }
 136  
 
 137  87
         if (clazz == null) {
 138  17
             if (log.isTraceEnabled()) {
 139  17
                 log.trace("Unable to load class named [" + fqcn + "] from the current ClassLoader.  " +
 140  
                         "Trying the system/application ClassLoader...");
 141  
             }
 142  17
             clazz = SYSTEM_CL_ACCESSOR.loadClass(fqcn);
 143  
         }
 144  
 
 145  87
         if (clazz == null) {
 146  17
             String msg = "Unable to load class named [" + fqcn + "] from the thread context, current, or " +
 147  
                     "system/application ClassLoaders.  All heuristics have been exhausted.  Class could not be found.";
 148  17
             throw new UnknownClassException(msg);
 149  
         }
 150  
 
 151  70
         return clazz;
 152  
     }
 153  
 
 154  
     public static boolean isAvailable(String fullyQualifiedClassName) {
 155  
         try {
 156  0
             forName(fullyQualifiedClassName);
 157  0
             return true;
 158  0
         } catch (UnknownClassException e) {
 159  0
             return false;
 160  
         }
 161  
     }
 162  
 
 163  
     public static Object newInstance(String fqcn) {
 164  66
         return newInstance(forName(fqcn));
 165  
     }
 166  
 
 167  
     public static Object newInstance(String fqcn, Object... args) {
 168  0
         return newInstance(forName(fqcn), args);
 169  
     }
 170  
 
 171  
     public static Object newInstance(Class clazz) {
 172  92
         if (clazz == null) {
 173  0
             String msg = "Class method parameter cannot be null.";
 174  0
             throw new IllegalArgumentException(msg);
 175  
         }
 176  
         try {
 177  92
             return clazz.newInstance();
 178  0
         } catch (Exception e) {
 179  0
             throw new InstantiationException("Unable to instantiate class [" + clazz.getName() + "]", e);
 180  
         }
 181  
     }
 182  
 
 183  
     public static Object newInstance(Class clazz, Object... args) {
 184  33
         Class[] argTypes = new Class[args.length];
 185  77
         for (int i = 0; i < args.length; i++) {
 186  44
             argTypes[i] = args[i].getClass();
 187  
         }
 188  33
         Constructor ctor = getConstructor(clazz, argTypes);
 189  33
         return instantiate(ctor, args);
 190  
     }
 191  
 
 192  
     public static Constructor getConstructor(Class clazz, Class... argTypes) {
 193  
         try {
 194  33
             return clazz.getConstructor(argTypes);
 195  0
         } catch (NoSuchMethodException e) {
 196  0
             throw new IllegalStateException(e);
 197  
         }
 198  
 
 199  
     }
 200  
 
 201  
     public static Object instantiate(Constructor ctor, Object... args) {
 202  
         try {
 203  33
             return ctor.newInstance(args);
 204  0
         } catch (Exception e) {
 205  0
             String msg = "Unable to instantiate Permission instance with constructor [" + ctor + "]";
 206  0
             throw new InstantiationException(msg, e);
 207  
         }
 208  
     }
 209  
 
 210  
     /**
 211  
      * @since 1.0
 212  
      */
 213  
     private static interface ClassLoaderAccessor {
 214  
         Class loadClass(String fqcn);
 215  
         InputStream getResourceStream(String name);
 216  
     }
 217  
 
 218  
     /**
 219  
      * @since 1.0
 220  
      */
 221  6
     private static abstract class ExceptionIgnoringAccessor implements ClassLoaderAccessor {
 222  
 
 223  
         public Class loadClass(String fqcn) {
 224  121
             Class clazz = null;
 225  121
             ClassLoader cl = getClassLoader();
 226  121
             if (cl != null) {
 227  
                 try {
 228  121
                     clazz = cl.loadClass(fqcn);
 229  51
                 } catch (ClassNotFoundException e) {
 230  51
                     if (log.isTraceEnabled()) {
 231  51
                         log.trace("Unable to load clazz named [" + fqcn + "] from class loader [" + cl + "]");
 232  
                     }
 233  70
                 }
 234  
             }
 235  121
             return clazz;
 236  
         }
 237  
 
 238  
         public InputStream getResourceStream(String name) {
 239  11
             InputStream is = null;
 240  11
             ClassLoader cl = getClassLoader();
 241  11
             if (cl != null) {
 242  11
                 is = cl.getResourceAsStream(name);
 243  
             }
 244  11
             return is;
 245  
         }
 246  
 
 247  
         protected final ClassLoader getClassLoader() {
 248  
             try {
 249  132
                 return doGetClassLoader();
 250  0
             } catch (Throwable t) {
 251  0
                 if (log.isDebugEnabled()) {
 252  0
                     log.debug("Unable to acquire ClassLoader.", t);
 253  
                 }
 254  
             }
 255  0
             return null;
 256  
         }
 257  
 
 258  
         protected abstract ClassLoader doGetClassLoader() throws Throwable;
 259  
     }
 260  
 }