001/* 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2026, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v2.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014 015package ch.qos.logback.core.joran.util.beans; 016 017import java.lang.reflect.Method; 018import java.util.HashMap; 019import java.util.Map; 020 021import ch.qos.logback.core.Context; 022import ch.qos.logback.core.spi.ContextAwareBase; 023 024/** 025 * Encapsulates creation of {@link BeanDescription} instances. This factory is 026 * kind of a lightweight Introspector as described in the Java Beans API 027 * specification. The given class is only analyzed for its public getters, 028 * setters and adders methods. Implementations of the BeanInfo interface are not 029 * taken into account for analysis. Therefore this class is only partially 030 * compatible with the Java Beans API specification. 031 * 032 * 033 * @author urechm 034 */ 035public class BeanDescriptionFactory extends ContextAwareBase { 036 037 BeanDescriptionFactory(Context context) { 038 setContext(context); 039 } 040 041 /** 042 * 043 * @param clazz to create a {@link BeanDescription} for. 044 * @return a {@link BeanDescription} for the given class. 045 */ 046 public BeanDescription create(Class<?> clazz) { 047 Map<String, Method> propertyNameToGetter = new HashMap<String, Method>(); 048 Map<String, Method> propertyNameToSetter = new HashMap<String, Method>(); 049 Map<String, Method> propertyNameToAdder = new HashMap<String, Method>(); 050 Method[] methods = clazz.getMethods(); 051 for (Method method : methods) { 052 if (method.isBridge()) { 053 // we can safely ignore bridge methods 054 continue; 055 } 056 if (BeanUtil.isGetter(method)) { 057 String propertyName = BeanUtil.getPropertyName(method); 058 Method oldGetter = propertyNameToGetter.put(propertyName, method); 059 if (oldGetter != null) { 060 if (oldGetter.getName().startsWith(BeanUtil.PREFIX_GETTER_IS)) { 061 propertyNameToGetter.put(propertyName, oldGetter); 062 } 063 String message = String.format("Class '%s' contains multiple getters for the same property '%s'.", 064 clazz.getCanonicalName(), propertyName); 065 addWarn(message); 066 } 067 } else if (BeanUtil.isSetter(method)) { 068 String propertyName = BeanUtil.getPropertyName(method); 069 Method oldSetter = propertyNameToSetter.put(propertyName, method); 070 if (oldSetter != null) { 071 String message = String.format("Class '%s' contains multiple setters for the same property '%s'.", 072 clazz.getCanonicalName(), propertyName); 073 addWarn(message); 074 } 075 } else if (BeanUtil.isAdder(method)) { 076 String propertyName = BeanUtil.getPropertyName(method); 077 Method oldAdder = propertyNameToAdder.put(propertyName, method); 078 if (oldAdder != null) { 079 String message = String.format("Class '%s' contains multiple adders for the same property '%s'.", 080 clazz.getCanonicalName(), propertyName); 081 addWarn(message); 082 } 083 } 084 } 085 return new BeanDescription(clazz, propertyNameToGetter, propertyNameToSetter, propertyNameToAdder); 086 } 087}