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.logback;
12  
13  import com.google.common.collect.Iterators;
14  
15  import java.util.ArrayList;
16  import java.util.Collection;
17  import java.util.Collections;
18  import java.util.Iterator;
19  import java.util.List;
20  
21  import org.apache.commons.lang3.reflect.MethodUtils;
22  
23  import psiprobe.tools.logging.DefaultAccessor;
24  
25  /**
26   * A wrapper for a Logback logger.
27   */
28  public class LogbackLoggerAccessor extends DefaultAccessor {
29  
30    /**
31     * Returns all appenders of this logger.
32     *
33     * @return a list of {@link LogbackAppenderAccessor}s
34     */
35    @SuppressWarnings("unchecked")
36    public List<LogbackAppenderAccessor> getAppenders() {
37      List<LogbackAppenderAccessor> appenders = new ArrayList<>();
38      try {
39        for (Object appender : Collections.list(Iterators.asEnumeration(
40            (Iterator<Object>) MethodUtils.invokeMethod(getTarget(), "iteratorForAppenders")))) {
41          List<Object> siftedAppenders = getSiftedAppenders(appender);
42          if (!siftedAppenders.isEmpty()) {
43            for (Object siftedAppender : siftedAppenders) {
44              wrapAndAddAppender(siftedAppender, appenders);
45            }
46          } else {
47            wrapAndAddAppender(appender, appenders);
48          }
49        }
50      } catch (NoClassDefFoundError e) {
51        logger.error("{}#getAppenders() failed, To see this logger, upgrade slf4j to 1.7.21+",
52            getTarget().getClass().getName(), e);
53      } catch (Exception e) {
54        logger.error("{}#getAppenders() failed", getTarget().getClass().getName(), e);
55      }
56      return appenders;
57    }
58  
59    /**
60     * Returns the appender of this logger with the given name.
61     *
62     * @param name the name of the appender to return
63     *
64     * @return the appender with the given name, or null if no such appender exists for this logger
65     */
66    public LogbackAppenderAccessor getAppender(String name) {
67      try {
68        Object appender = MethodUtils.invokeMethod(getTarget(), "getAppender", name);
69        if (appender == null) {
70          List<LogbackAppenderAccessor> appenders = getAppenders();
71          for (LogbackAppenderAccessor wrappedAppender : appenders) {
72            if (wrappedAppender.getIndex().equals(name)) {
73              return wrappedAppender;
74            }
75          }
76        }
77        return wrapAppender(appender);
78      } catch (Exception e) {
79        logger.error("{}#getAppender() failed", getTarget().getClass().getName(), e);
80      }
81      return null;
82    }
83  
84    /**
85     * Checks if is context.
86     *
87     * @return true, if is context
88     */
89    public boolean isContext() {
90      return false;
91    }
92  
93    /**
94     * Checks if is root.
95     *
96     * @return true, if is root
97     */
98    public boolean isRoot() {
99      return "ROOT".equals(getName());
100   }
101 
102   /**
103    * Gets the name.
104    *
105    * @return the name
106    */
107   public String getName() {
108     return (String) getProperty(getTarget(), "name", null);
109   }
110 
111   /**
112    * Gets the log level of this logger.
113    *
114    * @return the level of this logger
115    */
116   public String getLevel() {
117     try {
118       Object level = MethodUtils.invokeMethod(getTarget(), "getLevel");
119       return (String) MethodUtils.invokeMethod(level, "toString");
120     } catch (Exception e) {
121       logger.error("{}#getLevel() failed", getTarget().getClass().getName(), e);
122     }
123     return null;
124   }
125 
126   /**
127    * Sets the log level of this logger.
128    *
129    * @param newLevelStr the name of the new level
130    */
131   public void setLevel(String newLevelStr) {
132     try {
133       Object level = MethodUtils.invokeMethod(getTarget(), "getLevel");
134       Object newLevel = MethodUtils.invokeMethod(level, "toLevel", newLevelStr);
135       MethodUtils.invokeMethod(getTarget(), "setLevel", newLevel);
136     } catch (Exception e) {
137       logger.error("{}#setLevel('{}') failed", getTarget().getClass().getName(), newLevelStr, e);
138     }
139   }
140 
141   /**
142    * Gets the sifted appenders.
143    *
144    * @param appender the appender
145    *
146    * @return the sifted appenders
147    *
148    * @throws Exception the exception
149    */
150   @SuppressWarnings("unchecked")
151   private List<Object> getSiftedAppenders(Object appender) throws Exception {
152     if ("ch.qos.logback.classic.sift.SiftingAppender".equals(appender.getClass().getName())) {
153       Object tracker = MethodUtils.invokeMethod(appender, "getAppenderTracker");
154       if (tracker != null) {
155         return (List<Object>) MethodUtils.invokeMethod(tracker, "allComponents");
156       }
157     }
158     return Collections.emptyList();
159   }
160 
161   /**
162    * Wrap and add appender.
163    *
164    * @param appender the appender
165    * @param appenders the appenders
166    */
167   private void wrapAndAddAppender(Object appender, Collection<LogbackAppenderAccessor> appenders) {
168     LogbackAppenderAccessor appenderAccessor = wrapAppender(appender);
169     if (appenderAccessor != null) {
170       appenders.add(appenderAccessor);
171     }
172   }
173 
174   /**
175    * Wrap appender.
176    *
177    * @param appender the appender
178    *
179    * @return the logback appender accessor
180    */
181   private LogbackAppenderAccessor wrapAppender(Object appender) {
182     try {
183       if (appender == null) {
184         throw new IllegalArgumentException("appender is null");
185       }
186       LogbackAppenderAccessor appenderAccessor = new LogbackAppenderAccessor();
187       appenderAccessor.setTarget(appender);
188       appenderAccessor.setLoggerAccessor(this);
189       appenderAccessor.setApplication(getApplication());
190       return appenderAccessor;
191     } catch (Exception e) {
192       logger.error("Could not wrap appender: '{}'", appender, e);
193     }
194     return null;
195   }
196 
197 }