View Javadoc
1   package ch.qos.logback.core.joran.util.beans;
2   
3   import java.lang.reflect.Method;
4   import java.util.HashMap;
5   import java.util.Map;
6   
7   import ch.qos.logback.core.Context;
8   import ch.qos.logback.core.spi.ContextAwareBase;
9   
10  /**
11   * Encapsulates creation of {@link BeanDescription} instances.
12   * This factory is kind of a lightweight Introspector as described in the Java Beans API specification.
13   * The given class is only analyzed for its public getters, setters and adders methods.
14   * Implementations of the BeanInfo interface are not taken into account for analysis.
15   * Therefore this class is only partially compatible with the Java Beans API specification.
16   *
17   *
18   * @author urechm
19   */
20  public class BeanDescriptionFactory extends ContextAwareBase {
21  
22      BeanDescriptionFactory(Context context) {
23          setContext(context);
24      }
25  
26      /**
27       *
28       * @param clazz to create a {@link BeanDescription} for.
29       * @return a {@link BeanDescription} for the given class.
30       */
31      public BeanDescription create(Class<?> clazz) {
32          Map<String, Method> propertyNameToGetter = new HashMap<String, Method>();
33          Map<String, Method> propertyNameToSetter = new HashMap<String, Method>();
34          Map<String, Method> propertyNameToAdder = new HashMap<String, Method>();
35          Method[] methods = clazz.getMethods();
36          for (Method method : methods) {
37              if(method.isBridge()) {
38                  // we can safely ignore bridge methods
39                  continue;
40              }
41              if (BeanUtil.isGetter(method)) {
42                  String propertyName = BeanUtil.getPropertyName(method);
43                  Method oldGetter = propertyNameToGetter.put(propertyName, method);
44                  if (oldGetter != null) {
45                      if (oldGetter.getName().startsWith(BeanUtil.PREFIX_GETTER_IS)) {
46                          propertyNameToGetter.put(propertyName, oldGetter);
47                      }
48                      String message = String.format("Class '%s' contains multiple getters for the same property '%s'.", clazz.getCanonicalName(), propertyName);
49                      addWarn(message);
50                  }
51              } else if (BeanUtil.isSetter(method)) {
52                  String propertyName = BeanUtil.getPropertyName(method);
53                  Method oldSetter = propertyNameToSetter.put(propertyName, method);
54                  if (oldSetter != null) {
55                      String message = String.format("Class '%s' contains multiple setters for the same property '%s'.", clazz.getCanonicalName(), propertyName);
56                      addWarn(message);
57                  }
58              } else if (BeanUtil.isAdder(method)) {
59                  String propertyName = BeanUtil.getPropertyName(method);
60                  Method oldAdder = propertyNameToAdder.put(propertyName, method);
61                  if (oldAdder != null) {
62                      String message = String.format("Class '%s' contains multiple adders for the same property '%s'.", clazz.getCanonicalName(), propertyName);
63                      addWarn(message);
64                  }
65              }
66          }
67          return new BeanDescription(clazz, propertyNameToGetter, propertyNameToSetter, propertyNameToAdder);
68      }
69  }