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