View Javadoc
1   /*
2    * Licensed under the GPL License. You may not use this file except in compliance with the License.
3    * You may obtain a copy of the License at
4    *
5    *   https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
6    *
7    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
8    * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
9    * PURPOSE.
10   */
11  package psiprobe.tools.logging.log4j2;
12  
13  import com.google.common.base.Strings;
14  
15  import java.util.ArrayList;
16  import java.util.Collection;
17  import java.util.List;
18  import java.util.Map;
19  
20  import org.apache.commons.lang3.reflect.MethodUtils;
21  
22  import psiprobe.tools.logging.DefaultAccessor;
23  
24  /**
25   * The Class Log4JLoggerAccessor.
26   */
27  public class Log4J2LoggerConfigAccessor extends DefaultAccessor {
28  
29    /** The context. */
30    private boolean context;
31  
32    /** The LoggerContext. */
33    private Log4J2LoggerContextAccessor loggerContext;
34  
35    /** The loggers Map of appenders. **/
36    private Map<String, Object> appenderMap;
37  
38    /**
39     * Sets the target.
40     *
41     * @param target the new target
42     */
43    @Override
44    @SuppressWarnings("unchecked")
45    public void setTarget(Object target) {
46      super.setTarget(target);
47  
48      try {
49        this.appenderMap = (Map<String, Object>) invokeMethod(target, "getAppenders", null, null);
50      } catch (Exception e) {
51        logger.error("{}#getAppenders() failed", target.getClass().getName(), e);
52      }
53    }
54  
55    /**
56     * Returns all appenders of this logger.
57     *
58     * @return a list of {@link Log4J2AppenderAccessor}s
59     */
60    public List<Log4J2AppenderAccessor> getAppenders() {
61      List<Log4J2AppenderAccessor> appenders = new ArrayList<>();
62      if (appenderMap != null) {
63        try {
64          for (Object appender : appenderMap.values()) {
65            List<Object> asyncedAppenders = getAsyncedAppenders(appender);
66            if (!asyncedAppenders.isEmpty()) {
67              for (Object asyncedAppender : asyncedAppenders) {
68                wrapAndAddAppender(asyncedAppender, appenders);
69              }
70            } else {
71              wrapAndAddAppender(appender, appenders);
72            }
73          }
74        } catch (NoClassDefFoundError e) {
75          logger.error("{}#getAppenders() failed, To see this logger, upgrade slf4j to 1.7.21+",
76              getTarget().getClass().getName(), e);
77        } catch (Exception e) {
78          logger.error("{}#getAppenders() failed", getTarget().getClass().getName(), e);
79        }
80      }
81      return appenders;
82    }
83  
84    /**
85     * Returns the appender of this logger with the given name.
86     *
87     * @param name the name of the appender to return
88     *
89     * @return the appender with the given name, or null if no such appender exists for this logger
90     */
91    public Log4J2AppenderAccessor getAppender(String name) {
92      if (this.appenderMap != null) {
93        try {
94          Object appender = appenderMap.get(name);
95          if (appender == null) {
96            List<Log4J2AppenderAccessor> appenders = getAppenders();
97            for (Log4J2AppenderAccessor wrappedAppender : appenders) {
98              if (wrappedAppender.getIndex().equals(name)) {
99                return wrappedAppender;
100             }
101           }
102         }
103         return wrapAppender(appender);
104       } catch (Exception e) {
105         logger.error("{}#getAppender() failed", getTarget().getClass().getName(), e);
106       }
107     }
108     return null;
109   }
110 
111   /**
112    * Checks if is context.
113    *
114    * @return true, if is context
115    */
116   public boolean isContext() {
117     return context;
118   }
119 
120   /**
121    * Sets the context.
122    *
123    * @param context the new context
124    */
125   public void setContext(boolean context) {
126     this.context = context;
127   }
128 
129   /**
130    * Sets the logger context.
131    *
132    * @param loggerContext the new logger context
133    */
134   public void setLoggerContext(Log4J2LoggerContextAccessor loggerContext) {
135     this.loggerContext = loggerContext;
136   }
137 
138   /**
139    * Checks if is root.
140    *
141    * @return true, if is root
142    */
143   public boolean isRoot() {
144     return Strings.isNullOrEmpty(getName());
145   }
146 
147   /**
148    * Gets the name.
149    *
150    * @return the name
151    */
152   public String getName() {
153     return (String) getProperty(getTarget(), "name", null);
154   }
155 
156   /**
157    * Gets the level.
158    *
159    * @return the level
160    */
161   public String getLevel() {
162     try {
163       Object level = MethodUtils.invokeMethod(getTarget(), "getLevel");
164       return (String) MethodUtils.invokeMethod(level, "toString");
165     } catch (Exception e) {
166       logger.error("{}#getLevel() failed", getTarget().getClass().getName(), e);
167     }
168     return null;
169   }
170 
171   /**
172    * Sets the level.
173    *
174    * @param newLevelStr the new level
175    */
176   public void setLevel(String newLevelStr) {
177     try {
178       Object level = MethodUtils.invokeMethod(getTarget(), "getLevel");
179       Object newLevel = MethodUtils.invokeMethod(level, "toLevel", newLevelStr);
180       MethodUtils.invokeMethod(getTarget(), "setLevel", newLevel);
181       loggerContext.updateLoggers();
182     } catch (Exception e) {
183       logger.error("{}#setLevel('{}') failed", getTarget().getClass().getName(), newLevelStr, e);
184     }
185   }
186 
187 
188   /**
189    * Gets the Asynced appenders.
190    *
191    * @param appender the appender
192    *
193    * @return the Asynced appenders
194    *
195    * @throws Exception the exception
196    */
197   @SuppressWarnings("unchecked")
198   private List<Object> getAsyncedAppenders(Object appender) throws Exception {
199     if ("org.apache.logging.log4j.core.appender.AsyncAppender"
200         .equals(appender.getClass().getName())) {
201       Object appenders = MethodUtils.invokeMethod(appender, "getAppenders");
202       if (appenders != null) {
203         return (List<Object>) appenders;
204       }
205     }
206     return List.of();
207   }
208 
209   /**
210    * Wrap and add appender.
211    *
212    * @param appender the appender
213    * @param appenders the appenders
214    */
215   private void wrapAndAddAppender(Object appender, Collection<Log4J2AppenderAccessor> appenders) {
216     Log4J2AppenderAccessor appenderAccessor = wrapAppender(appender);
217     if (appenderAccessor != null) {
218       appenders.add(appenderAccessor);
219     }
220   }
221 
222   /**
223    * Wrap appender.
224    *
225    * @param appender the appender
226    *
227    * @return the log4 j appender accessor
228    */
229   protected Log4J2AppenderAccessor wrapAppender(Object appender) {
230     try {
231       if (appender == null) {
232         throw new IllegalArgumentException("appender is null");
233       }
234       Log4J2AppenderAccessor appenderAccessor = new Log4J2AppenderAccessor();
235       appenderAccessor.setTarget(appender);
236       appenderAccessor.setLoggerAccessor(this);
237       appenderAccessor.setApplication(getApplication());
238       return appenderAccessor;
239     } catch (Exception e) {
240       logger.error("Could not wrap appender: {}", appender, e);
241     }
242     return null;
243   }
244 
245 }