1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.joran.util.beans;
16  
17  import java.lang.reflect.Method;
18  import java.util.HashMap;
19  import java.util.Map;
20  
21  import ch.qos.logback.core.Context;
22  import ch.qos.logback.core.spi.ContextAwareBase;
23  
24  /**
25   * Encapsulates creation of {@link BeanDescription} instances. This factory is
26   * kind of a lightweight Introspector as described in the Java Beans API
27   * specification. The given class is only analyzed for its public getters,
28   * setters and adders methods. Implementations of the BeanInfo interface are not
29   * taken into account for analysis. Therefore this class is only partially
30   * compatible with the Java Beans API specification.
31   *
32   *
33   * @author urechm
34   */
35  public class BeanDescriptionFactory extends ContextAwareBase {
36  
37      BeanDescriptionFactory(Context context) {
38          setContext(context);
39      }
40  
41      /**
42       *
43       * @param clazz to create a {@link BeanDescription} for.
44       * @return a {@link BeanDescription} for the given class.
45       */
46      public BeanDescription create(Class<?> clazz) {
47          Map<String, Method> propertyNameToGetter = new HashMap<String, Method>();
48          Map<String, Method> propertyNameToSetter = new HashMap<String, Method>();
49          Map<String, Method> propertyNameToAdder = new HashMap<String, Method>();
50          Method[] methods = clazz.getMethods();
51          for (Method method : methods) {
52              if (method.isBridge()) {
53                  // we can safely ignore bridge methods
54                  continue;
55              }
56              if (BeanUtil.isGetter(method)) {
57                  String propertyName = BeanUtil.getPropertyName(method);
58                  Method oldGetter = propertyNameToGetter.put(propertyName, method);
59                  if (oldGetter != null) {
60                      if (oldGetter.getName().startsWith(BeanUtil.PREFIX_GETTER_IS)) {
61                          propertyNameToGetter.put(propertyName, oldGetter);
62                      }
63                      String message = String.format("Class '%s' contains multiple getters for the same property '%s'.",
64                              clazz.getCanonicalName(), propertyName);
65                      addWarn(message);
66                  }
67              } else if (BeanUtil.isSetter(method)) {
68                  String propertyName = BeanUtil.getPropertyName(method);
69                  Method oldSetter = propertyNameToSetter.put(propertyName, method);
70                  if (oldSetter != null) {
71                      String message = String.format("Class '%s' contains multiple setters for the same property '%s'.",
72                              clazz.getCanonicalName(), propertyName);
73                      addWarn(message);
74                  }
75              } else if (BeanUtil.isAdder(method)) {
76                  String propertyName = BeanUtil.getPropertyName(method);
77                  Method oldAdder = propertyNameToAdder.put(propertyName, method);
78                  if (oldAdder != null) {
79                      String message = String.format("Class '%s' contains multiple adders for the same property '%s'.",
80                              clazz.getCanonicalName(), propertyName);
81                      addWarn(message);
82                  }
83              }
84          }
85          return new BeanDescription(clazz, propertyNameToGetter, propertyNameToSetter, propertyNameToAdder);
86      }
87  }