/** * Copyright 2005-2014 Restlet * * The contents of this file are subject to the terms of one of the following * open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can * select the license that you prefer but you may not use this file except in * compliance with one of these Licenses. * * You can obtain a copy of the Apache 2.0 license at * http://www.opensource.org/licenses/apache-2.0 * * You can obtain a copy of the EPL 1.0 license at * http://www.opensource.org/licenses/eclipse-1.0 * * See the Licenses for the specific language governing permissions and * limitations under the Licenses. * * Alternatively, you can obtain a royalty free commercial license with less * limitations, transferable or non-transferable, directly at * http://restlet.com/products/restlet-framework * * Restlet is a registered trademark of Restlet S.A.S. */ package org.restlet.engine.util; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Utilities to get the {@link BeanInfo} of a class. * * @author Manuel Boillod */ public class BeanInfoUtils { /** BeanInfo cache. */ private static final ConcurrentMap<Class<?>, BeanInfo> cache = new ConcurrentHashMap<Class<?>, BeanInfo>(); /** * Get a BeanInfo from cache or create it. Stop introspection to * {@link Object} or {@link Throwable} if the class is a subtype of * {@link Throwable} * * @param clazz * The class * @return BeanInfo of the class */ public static BeanInfo getBeanInfo(Class<?> clazz) { BeanInfo result = cache.get(clazz); if (result == null) { // Inspect the class itself for annotations Class<?> stopClass = Throwable.class.isAssignableFrom(clazz) ? Throwable.class : Object.class; try { result = Introspector.getBeanInfo(clazz, stopClass, Introspector.IGNORE_ALL_BEANINFO); } catch (IntrospectionException e) { throw new RuntimeException("Could not get BeanInfo of class " + clazz.getName(), e); } // Put the list in the cache if no one was previously present BeanInfo prev = cache.putIfAbsent(clazz, result); if (prev != null) { // Reuse the previous entry result = prev; } } return result; } }