001package ch.qos.logback.core.joran.util.beans; 002 003import java.lang.reflect.Method; 004import java.util.HashMap; 005import java.util.Map; 006 007import ch.qos.logback.core.Context; 008import ch.qos.logback.core.spi.ContextAwareBase; 009 010/** 011 * Encapsulates creation of {@link BeanDescription} instances. This factory is 012 * kind of a lightweight Introspector as described in the Java Beans API 013 * specification. The given class is only analyzed for its public getters, 014 * setters and adders methods. Implementations of the BeanInfo interface are not 015 * taken into account for analysis. Therefore this class is only partially 016 * compatible with the Java Beans API specification. 017 * 018 * 019 * @author urechm 020 */ 021public class BeanDescriptionFactory extends ContextAwareBase { 022 023 BeanDescriptionFactory(Context context) { 024 setContext(context); 025 } 026 027 /** 028 * 029 * @param clazz to create a {@link BeanDescription} for. 030 * @return a {@link BeanDescription} for the given class. 031 */ 032 public BeanDescription create(Class<?> clazz) { 033 Map<String, Method> propertyNameToGetter = new HashMap<String, Method>(); 034 Map<String, Method> propertyNameToSetter = new HashMap<String, Method>(); 035 Map<String, Method> propertyNameToAdder = new HashMap<String, Method>(); 036 Method[] methods = clazz.getMethods(); 037 for (Method method : methods) { 038 if (method.isBridge()) { 039 // we can safely ignore bridge methods 040 continue; 041 } 042 if (BeanUtil.isGetter(method)) { 043 String propertyName = BeanUtil.getPropertyName(method); 044 Method oldGetter = propertyNameToGetter.put(propertyName, method); 045 if (oldGetter != null) { 046 if (oldGetter.getName().startsWith(BeanUtil.PREFIX_GETTER_IS)) { 047 propertyNameToGetter.put(propertyName, oldGetter); 048 } 049 String message = String.format("Class '%s' contains multiple getters for the same property '%s'.", 050 clazz.getCanonicalName(), propertyName); 051 addWarn(message); 052 } 053 } else if (BeanUtil.isSetter(method)) { 054 String propertyName = BeanUtil.getPropertyName(method); 055 Method oldSetter = propertyNameToSetter.put(propertyName, method); 056 if (oldSetter != null) { 057 String message = String.format("Class '%s' contains multiple setters for the same property '%s'.", 058 clazz.getCanonicalName(), propertyName); 059 addWarn(message); 060 } 061 } else if (BeanUtil.isAdder(method)) { 062 String propertyName = BeanUtil.getPropertyName(method); 063 Method oldAdder = propertyNameToAdder.put(propertyName, method); 064 if (oldAdder != null) { 065 String message = String.format("Class '%s' contains multiple adders for the same property '%s'.", 066 clazz.getCanonicalName(), propertyName); 067 addWarn(message); 068 } 069 } 070 } 071 return new BeanDescription(clazz, propertyNameToGetter, propertyNameToSetter, propertyNameToAdder); 072 } 073}