All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.faces.util.ReflectionUtils Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.faces.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.beans.PropertyDescriptor;
import java.beans.Introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;

/**
 * 

A set of utility methods to make working with * Classes and Reflection a little easier.

*/ public final class ReflectionUtils { private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); /** *

Cache

*/ private static final Map> REFLECTION_CACHE = new WeakHashMap>(); // ------------------------------------------------------------ Constructors private ReflectionUtils() { } // ---------------------------------------------------------- Public Methods /** *

Clears the cache for the specified ClassLoader.

*

This method MUST be called when ConfigureListener * .contextDestroyed() is called.

* @param loader the ClassLoader whose associated cache * should be cleared */ public static synchronized void clearCache(ClassLoader loader) { REFLECTION_CACHE.remove(loader); } public static synchronized void initCache(ClassLoader loader) { if (REFLECTION_CACHE.get(loader) == null) { REFLECTION_CACHE.put(loader, new ConcurrentHashMap()); } } /** *

Returns the Constructor appropriate to the specified * Class and parameters.

* @param clazz the Class of interest * @param params the parameters for the constructor of the provided Class * @return a Constructor that can be invoked with the specified parameters */ public static Constructor lookupConstructor( Class clazz, Class... params) { ClassLoader loader = Util.getCurrentLoader(clazz); if (loader == null) { return null; } return getMetaData(loader, clazz).lookupConstructor(params); } /** *

Returns the Method appropriate to the specified * Class, method name, and parameters.

* @param clazz the Class of interest * @param methodName the name of the method * @param params the parameters for the specified method * @return a Method that can be invoked with the specified parameters */ public static Method lookupMethod( Class clazz, String methodName, Class... params) { ClassLoader loader = Util.getCurrentLoader(clazz); if (loader == null) { return null; } return getMetaData(loader, clazz).lookupMethod(methodName, params); } /** *

Constructs a new object instance based off the * provided class name.

* @param className the class of the object to instantiate * @return a new instances of said class * @throws InstantiationException if the class cannot be instantiated * @throws IllegalAccessException if there is a security violation */ public static Object newInstance(String className) throws InstantiationException, IllegalAccessException { ClassLoader loader = Util.getCurrentLoader(null); if (loader == null) { return null; } return getMetaData(loader, className).lookupClass().newInstance(); } /** *

Obtain a Class instance based on the provided * String name.

* @param className the class to look up * @return the Class corresponding to className */ public static Class lookupClass(String className) { ClassLoader loader = Util.getCurrentLoader(null); if (loader == null) { return null; } return getMetaData(loader, className).lookupClass(); } /** * @param className the fully qualified class name * @param propertyName a JavaBeans property name * @return a method suitable for setting a JavaBeans property, or * null if the property doesn't exist or is readonly. */ public static Method lookupWriteMethod(String className, String propertyName) { ClassLoader loader = Util.getCurrentLoader(null); if (loader == null) { return null; } return getMetaData(loader, className).lookupWriteMethod(propertyName); } /** * @param className the fully qualified class name * @param propertyName a JavaBeans property name * @return a method suitable for obtaining the value of a JavaBeans property, * or null if the property doesn't exist or can't be read. */ public static Method lookupReadMethod(String className, String propertyName) { ClassLoader loader = Util.getCurrentLoader(null); if (loader == null) { return null; } return getMetaData(loader, className).lookupReadMethod(propertyName); } // --------------------------------------------------------- Private Methods /** *

Return the MetaData for the specified Class.

* *

This will check the cache associated with the specified * ClassLoader. If there is no cache hit, then a new * MetaData instance will be created and stored. * * @param loader ClassLoader * @param clazz the Class of interest * @return a MetaData object for the specified Class */ private static MetaData getMetaData(ClassLoader loader, Class clazz) { ConcurrentMap cache = REFLECTION_CACHE.get(loader); if (cache == null) { initCache(loader); cache = REFLECTION_CACHE.get(loader); } MetaData meta = cache.get(clazz.getName()); if (meta == null) { meta = new MetaData(clazz); cache.put(clazz.getName(), meta); } return meta; } /** *

Return the MetaData for the specified className.

* *

This will check the cache associated with the specified * ClassLoader. If there is no cache hit, then a new * MetaData instance will be created and stored. * * @param loader ClassLoader * @param className the class of interest * @return a MetaData object for the specified Class */ private static MetaData getMetaData(ClassLoader loader, String className) { ConcurrentMap cache = REFLECTION_CACHE.get(loader); if (cache == null) { initCache(loader); cache = REFLECTION_CACHE.get(loader); } MetaData meta = cache.get(className); if (meta == null) { try { Class clazz = Util.loadClass(className, cache); meta = new MetaData(clazz); cache.put(className, meta); } catch (ClassNotFoundException cnfe) { return null; } } return meta; } /** *

MetaData contains lookup methods for Constructors and * Methods of a particular Class. */ private static final class MetaData { Map constructors; Map> methods; Map> declaredMethods; Map propertyDescriptors; Class clazz; // ------------------------------------------------------------ Constructors /** *

Constructs a new MetaData instance for the specified * class.

* @param clazz class to construct a new MetaData instance from. */ public MetaData(Class clazz) { String name; this.clazz = clazz; Constructor[] ctors = clazz.getConstructors(); constructors = new HashMap(ctors.length, 1.0f); for (int i = 0, len = ctors.length; i < len; i++) { constructors.put(getKey(ctors[i].getParameterTypes()), ctors[i]); } Method[] meths = clazz.getMethods(); methods = new HashMap>(meths.length, 1.0f); for (int i = 0, len = meths.length; i < len; i++) { name = meths[i].getName(); HashMap methodsMap = methods.get(name); if (methodsMap == null) { methodsMap = new HashMap(4, 1.0f); methods.put(name, methodsMap); } methodsMap.put(getKey(meths[i].getParameterTypes()), meths[i]); } meths = clazz.getDeclaredMethods(); declaredMethods = new HashMap>(meths.length, 1.0f); for (int i = 0, len = meths.length; i < len; i++) { name = meths[i].getName(); HashMap declaredMethodsMap = declaredMethods.get(name); if (declaredMethodsMap == null) { declaredMethodsMap = new HashMap(4, 1.0f); declaredMethods.put(name, declaredMethodsMap); } declaredMethodsMap.put(getKey(meths[i].getParameterTypes()), meths[i]); } try { BeanInfo info = Introspector.getBeanInfo(clazz); PropertyDescriptor[] pds = info.getPropertyDescriptors(); if (pds != null) { if (propertyDescriptors == null) { propertyDescriptors = new HashMap(pds.length, 1.0f); } for (PropertyDescriptor pd : pds) { propertyDescriptors.put(pd.getName(), pd); } } } catch (IntrospectionException ie) { if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, ie.toString(), ie); } } } // ---------------------------------------------------------- Public Methods /** *

Looks up a Constructor based off the specified * params.

* @param params constructor parameters * @return the Constructor appropriate to the specified * parameters or null */ public Constructor lookupConstructor(Class... params) { return constructors.get(getKey(params)); } /** *

Looks up a Method based off the specified method * name and params.

* @param name the name of the Method
* @param params the Method parameters * @return the Method appropriate to the specified * name and parameters or null */ public Method lookupMethod(String name, Class... params) { Map map = methods.get(name); Integer key = getKey(params); Method result = null; if ((null == map) || null == (result = map.get(key))) { map = declaredMethods.get(name); if (null != map) { result = map.get(key); } } return result; } /** *

Looks up the class for this MetaData instance.

* @return the Class for this MetaData instance */ public Class lookupClass() { return clazz; } /** * @param propName a JavaBeans property name * @return a method suitable for setting a JavaBeans property, or * null if the property doesn't exist or is readonly. */ public Method lookupWriteMethod(String propName) { if (propertyDescriptors == null) { return null; } PropertyDescriptor pd = propertyDescriptors.get(propName); if (pd != null) { return pd.getWriteMethod(); } return null; } /** * @param propName a JavaBeans property name * @return a method suitable for obtaining the value of a JavaBeans property, * or null if the property doesn't exist or can't be read. */ public Method lookupReadMethod(String propName) { if (propertyDescriptors == null) { return null; } PropertyDescriptor pd = propertyDescriptors.get(propName); if (pd != null) { return pd.getReadMethod(); } return null; } // --------------------------------------------------------- Private Methods /** * Return a hashcode of all the class parameters. * @param params the parameters to a Constructor or * a Method instance * @return the result of Arrays.deepHashCode */ private static Integer getKey(Class... params) { return Arrays.deepHashCode(params); } } } // END ReflectionUtils




© 2015 - 2024 Weber Informatics LLC | Privacy Policy