1/*2 * $Id: ClassUtil.java 1306435 2012-03-28 15:39:11Z nlebas $3 *4 * Licensed to the Apache Software Foundation (ASF) under one5 * or more contributor license agreements. See the NOTICE file6 * distributed with this work for additional information7 * regarding copyright ownership. The ASF licenses this file8 * to you under the Apache License, Version 2.0 (the9 * "License"); you may not use this file except in compliance10 * with the License. You may obtain a copy of the License at11 *12 * http://www.apache.org/licenses/LICENSE-2.013 *14 * Unless required by applicable law or agreed to in writing,15 * software distributed under the License is distributed on an16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY17 * KIND, either express or implied. See the License for the18 * specific language governing permissions and limitations19 * under the License.20 */21package org.apache.tiles.request.reflect;
2223import java.beans.BeanInfo;
24import java.beans.Introspector;
25import java.beans.PropertyDescriptor;
26import java.util.Map;
2728import org.slf4j.Logger;
29import org.slf4j.LoggerFactory;
303132/**33 * Utilities to work with dynamic class loading and instantiation.34 *35 * @version $Rev: 1306435 $ $Date: 2012-03-29 02:39:11 +1100 (Thu, 29 Mar 2012) $36 */37publicfinalclassClassUtil {
3839/**40 * Constructor, private to avoid instantiation.41 */42privateClassUtil() {
43 }
4445/**46 * Returns the class and casts it to the correct subclass.<br>47 * It tries to use the thread's current classloader first and, if it does48 * not succeed, uses the classloader of ClassUtil.49 *50 * @param <T> The subclass to use.51 * @param className The name of the class to load.52 * @param baseClass The base class to subclass to.53 * @return The loaded class.54 * @throws ClassNotFoundException If the class has not been found.55 */56publicstatic <T> Class<? extends T> getClass(String className,
57 Class<T> baseClass) throws ClassNotFoundException {
58 ClassLoader classLoader = Thread.currentThread()
59 .getContextClassLoader();
60if (classLoader == null) {
61 classLoader = ClassUtil.class.getClassLoader();
62 }
63return Class.forName(className, true, classLoader)
64 .asSubclass(baseClass);
65 }
6667/**68 * Returns an instance of the given class name, by calling the default69 * constructor.70 *71 * @param className The class name to load and to instantiate.72 * @return The new instance of the class name.73 * @throws CannotInstantiateObjectException If something goes wrong during74 * instantiation.75 */76publicstatic Object instantiate(String className) {
77return instantiate(className, false);
78 }
7980/**81 * Returns an instance of the given class name, by calling the default82 * constructor.83 *84 * @param className The class name to load and to instantiate.85 * @param returnNull If <code>true</code>, if the class is not found it86 * returns <code>true</code>, otherwise it throws a87 * <code>TilesException</code>.88 * @return The new instance of the class name.89 * @throws CannotInstantiateObjectException If something goes wrong during instantiation.90 */91publicstatic Object instantiate(String className, boolean returnNull) {
92 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
93if (classLoader == null) {
94 classLoader = ClassUtil.class.getClassLoader();
95 }
96try {
97 Class<? extends Object> namedClass = getClass(className, Object.class);
98return namedClass.newInstance();
99 } catch (ClassNotFoundException e) {
100if (returnNull) {
101returnnull;
102 }
103thrownewCannotInstantiateObjectException(
104"Unable to resolve factory class: '" + className + "'", e);
105 } catch (IllegalAccessException e) {
106thrownewCannotInstantiateObjectException(
107"Unable to access factory class: '" + className + "'", e);
108 } catch (InstantiationException e) {
109thrownewCannotInstantiateObjectException(
110"Unable to instantiate factory class: '"111 + className
112 + "'. Make sure that this class has a default constructor",
113 e);
114 }
115 }
116117/**118 * Collects bean infos from a class and filling a list.119 *120 * @param clazz The class to be inspected.121 * @param name2descriptor The map in the form: name of the property ->122 * descriptor.123 */124publicstaticvoid collectBeanInfo(Class<?> clazz,
125 Map<String, PropertyDescriptor> name2descriptor) {
126 Logger log = LoggerFactory.getLogger(ClassUtil.class);
127 BeanInfo info = null;
128try {
129 info = Introspector.getBeanInfo(clazz);
130 } catch (Exception ex) {
131if (log.isDebugEnabled()) {
132 log.debug("Cannot inspect class " + clazz, ex);
133 }
134 }
135if (info == null) {
136return;
137 }
138for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
139 pd.setValue("type", pd.getPropertyType());
140 pd.setValue("resolvableAtDesignTime", Boolean.TRUE);
141 name2descriptor.put(pd.getName(), pd);
142 }
143 }
144 }