Home » tiles-2.2.1-src » org.apache.tiles.reflect » [javadoc | source]

    1   /*
    2    * $Id: ClassUtil.java 791161 2009-07-04 18:53:36Z apetrelli $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
   10    * with the License.  You may obtain a copy of the License at
   11    *
   12    * http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing,
   15    * software distributed under the License is distributed on an
   16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   17    * KIND, either express or implied.  See the License for the
   18    * specific language governing permissions and limitations
   19    * under the License.
   20    */
   21   package org.apache.tiles.reflect;
   22   
   23   import java.beans.BeanInfo;
   24   import java.beans.Introspector;
   25   import java.beans.PropertyDescriptor;
   26   import java.lang.reflect.InvocationTargetException;
   27   import java.lang.reflect.Method;
   28   import java.util.Map;
   29   
   30   import org.slf4j.Logger;
   31   import org.slf4j.LoggerFactory;
   32   
   33   
   34   /**
   35    * Utilities to work with dynamic class loading and instantiation.
   36    *
   37    * @version $Rev: 791161 $ $Date: 2009-07-04 20:53:36 +0200 (sab, 04 lug 2009) $
   38    * @since 2.0.7
   39    */
   40   public final class ClassUtil {
   41   
   42       /**
   43        * Constructor, private to avoid instantiation.
   44        */
   45       private ClassUtil() {
   46       }
   47   
   48       /**
   49        * Returns the class and casts it to the correct subclass.<br>
   50        * It tries to use the thread's current classloader first and, if it does
   51        * not succeed, uses the classloader of ClassUtil.
   52        *
   53        * @param <T> The subclass to use.
   54        * @param className The name of the class to load.
   55        * @param baseClass The base class to subclass to.
   56        * @return The loaded class.
   57        * @throws ClassNotFoundException If the class has not been found.
   58        * @since 2.1.3
   59        */
   60       public static <T> Class<? extends T> getClass(String className,
   61               Class<T> baseClass) throws ClassNotFoundException {
   62           ClassLoader classLoader = Thread.currentThread()
   63                   .getContextClassLoader();
   64           if (classLoader == null) {
   65               classLoader = ClassUtil.class.getClassLoader();
   66           }
   67           return Class.forName(className, true, classLoader)
   68                   .asSubclass(baseClass);
   69       }
   70   
   71       /**
   72        * Returns an instance of the given class name, by calling the default
   73        * constructor.
   74        *
   75        * @param className The class name to load and to instantiate.
   76        * @return The new instance of the class name.
   77        * @throws CannotInstantiateObjectException If something goes wrong during
   78        * instantiation.
   79        * @since 2.0.7
   80        */
   81       public static Object instantiate(String className) {
   82           return instantiate(className, false);
   83       }
   84   
   85       /**
   86        * Returns an instance of the given class name, by calling the default
   87        * constructor.
   88        *
   89        * @param className The class name to load and to instantiate.
   90        * @param returnNull If <code>true</code>, if the class is not found it
   91        * returns <code>true</code>, otherwise it throws a
   92        * <code>TilesException</code>.
   93        * @return The new instance of the class name.
   94        * @throws CannotInstantiateObjectException If something goes wrong during instantiation.
   95        * @since 2.0.7
   96        */
   97       public static Object instantiate(String className, boolean returnNull) {
   98           ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
   99           if (classLoader == null) {
  100               classLoader = ClassUtil.class.getClassLoader();
  101           }
  102           try {
  103               Class<? extends Object> namedClass = getClass(className, Object.class);
  104               return namedClass.newInstance();
  105           } catch (ClassNotFoundException e) {
  106               if (returnNull) {
  107                   return null;
  108               }
  109               throw new CannotInstantiateObjectException(
  110                       "Unable to resolve factory class: '" + className + "'", e);
  111           } catch (IllegalAccessException e) {
  112               throw new CannotInstantiateObjectException(
  113                       "Unable to access factory class: '" + className + "'", e);
  114           } catch (InstantiationException e) {
  115               throw new CannotInstantiateObjectException(
  116                       "Unable to instantiate factory class: '"
  117                               + className
  118                               + "'. Make sure that this class has a default constructor",
  119                       e);
  120           }
  121       }
  122   
  123       /**
  124        * Gets a method and forces it to be accessible, even if it is not.
  125        *
  126        * @param clazz The class from which the method will be got.
  127        * @param methodName The name of the method.
  128        * @param parameterTypes The parameter types that the method must match.
  129        * @return The method, if it is found.
  130        * @since 2.0.7
  131        */
  132       public static Method getForcedAccessibleMethod(Class<?> clazz,
  133               String methodName, Class<?>... parameterTypes) {
  134           Method method;
  135           try {
  136               method = clazz.getMethod(methodName, parameterTypes);
  137           } catch (SecurityException e) {
  138               throw new CannotAccessMethodException("Cannot access method '"
  139                       + methodName + "' in class '" + clazz.getName()
  140                       + "' for security reasons", e);
  141           } catch (NoSuchMethodException e) {
  142               throw new CannotAccessMethodException("The method '"
  143                       + methodName + "' in class '" + clazz.getName()
  144                       + "' does not exist", e);
  145           }
  146           if (!method.isAccessible()) {
  147               method.setAccessible(true);
  148           }
  149           return method;
  150       }
  151   
  152       /**
  153        * Invokes a method, masking with a runtime exception all the exceptions.
  154        *
  155        * @param obj The object from which a method will be called.
  156        * @param method The method to call.
  157        * @param args The arguments of the method.
  158        * @return The object returned, if the method is not "void".
  159        * @since 2.0.7
  160        */
  161       public static Object invokeMethod(Object obj, Method method, Object... args) {
  162           try {
  163               return method.invoke(obj, args);
  164           } catch (IllegalArgumentException e) {
  165               throw new CannotAccessMethodException("The arguments for '"
  166                       + method.getName() + "' in class '"
  167                       + obj.getClass().getName() + "' are not valid", e);
  168           } catch (IllegalAccessException e) {
  169               throw new CannotAccessMethodException("Cannot access '"
  170                       + method.getName() + "' in class '"
  171                       + obj.getClass().getName() + "'", e);
  172           } catch (InvocationTargetException e) {
  173               throw new CannotAccessMethodException(
  174                       "An exception has been thrown inside '" + method.getName()
  175                       + "' in class '" + obj.getClass().getName() + "'", e);
  176           }
  177       }
  178   
  179       /**
  180        * Collects bean infos from a class and filling a list.
  181        *
  182        * @param clazz The class to be inspected.
  183        * @param name2descriptor The map in the form: name of the property ->
  184        * descriptor.
  185        * @since 2.2.0
  186        */
  187       public static void collectBeanInfo(Class<?> clazz,
  188               Map<String, PropertyDescriptor> name2descriptor) {
  189           Logger log = LoggerFactory.getLogger(ClassUtil.class);
  190           BeanInfo info = null;
  191           try {
  192               info = Introspector.getBeanInfo(clazz);
  193           } catch (Exception ex) {
  194               if (log.isDebugEnabled()) {
  195                   log.debug("Cannot inspect class " + clazz, ex);
  196               }
  197           }
  198           if (info == null) {
  199               return;
  200           }
  201           for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
  202               pd.setValue("type", pd.getPropertyType());
  203               pd.setValue("resolvableAtDesignTime", Boolean.TRUE);
  204               name2descriptor.put(pd.getName(), pd);
  205           }
  206       }
  207   }

Home » tiles-2.2.1-src » org.apache.tiles.reflect » [javadoc | source]