View Javadoc
1   /*
2    * Copyright 2018 SPF4J.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.slf4j.impl;
17  
18  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19  import java.util.concurrent.LinkedBlockingQueue;
20  import org.spf4j.test.log.TestLoggers;
21  import org.slf4j.ILoggerFactory;
22  import org.slf4j.event.Level;
23  import org.slf4j.event.SubstituteLoggingEvent;
24  import org.slf4j.helpers.SubstituteLogger;
25  import org.slf4j.helpers.SubstituteLoggerFactory;
26  import org.slf4j.spi.LoggerFactoryBinder;
27  
28  /**
29   * @author Zoltan Farkas
30   */
31  @SuppressFBWarnings("MS_SHOULD_BE_FINAL")
32  public final class StaticLoggerBinder implements LoggerFactoryBinder {
33  
34      private static final SubstituteLoggerFactory SUBSTITUTE = new SubstituteLoggerFactory();
35      /**
36       * The unique instance of this class.
37       *
38       */
39      private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
40  
41  
42      private static final String LOGGER_FACTORY_CLASS_STR = TestLoggers.class.getName();
43  
44      static {
45        SINGLETON.init();
46      }
47      /**
48       * The ILoggerFactory instance returned by the {@link #getLoggerFactory}
49       * method should always be the same object
50       */
51      private volatile ILoggerFactory loggerFactory;
52  
53      private StaticLoggerBinder() {
54        this.loggerFactory = SUBSTITUTE;
55      }
56  
57      private void init() {
58        Thread currentThread = Thread.currentThread();
59        ClassLoader contextClassLoader = currentThread.getContextClassLoader();
60        currentThread.setContextClassLoader(ClassLoader.getSystemClassLoader());
61        try {
62          TestLoggers newLoggers = TestLoggers.sys();
63          this.loggerFactory = newLoggers;
64          // init complete, now delegate to test loggers.
65          for (SubstituteLogger logger : SUBSTITUTE.getLoggers()) {
66            logger.setDelegate(newLoggers.getLogger(logger.getName()));
67          }
68          LinkedBlockingQueue<SubstituteLoggingEvent> eventQueue = SUBSTITUTE.getEventQueue();
69          // drain the collected log events.
70          for (SubstituteLoggingEvent event: eventQueue) {
71            Throwable t = event.getThrowable();
72            Level level = event.getLevel();
73            switch (level) {
74              case TRACE:
75                if (t == null) {
76                  newLoggers.getLogger(event.getLoggerName()).trace(event.getMarker(), event.getMessage(),
77                        event.getArgumentArray());
78                } else {
79                  newLoggers.getLogger(event.getLoggerName()).trace(event.getMarker(), event.getMessage(),
80                        org.spf4j.base.Arrays.append(event.getArgumentArray(), t));
81                }
82                break;
83              case DEBUG:
84                if (t == null) {
85                  newLoggers.getLogger(event.getLoggerName()).debug(event.getMarker(), event.getMessage(),
86                        event.getArgumentArray());
87                } else {
88                  newLoggers.getLogger(event.getLoggerName()).debug(event.getMarker(), event.getMessage(),
89                        org.spf4j.base.Arrays.append(event.getArgumentArray(), t));
90                }
91                break;
92              case INFO:
93                if (t == null) {
94                  newLoggers.getLogger(event.getLoggerName()).info(event.getMarker(), event.getMessage(),
95                        event.getArgumentArray());
96                } else {
97                  newLoggers.getLogger(event.getLoggerName()).info(event.getMarker(), event.getMessage(),
98                        org.spf4j.base.Arrays.append(event.getArgumentArray(), t));
99                }
100               break;
101             case WARN:
102               if (t == null) {
103                 newLoggers.getLogger(event.getLoggerName()).warn(event.getMarker(), event.getMessage(),
104                       event.getArgumentArray());
105               } else {
106                 newLoggers.getLogger(event.getLoggerName()).warn(event.getMarker(), event.getMessage(),
107                       org.spf4j.base.Arrays.append(event.getArgumentArray(), t));
108               }
109               break;
110             case ERROR:
111               if (t == null) {
112                 newLoggers.getLogger(event.getLoggerName()).error(event.getMarker(), event.getMessage(),
113                       event.getArgumentArray());
114               } else {
115                 newLoggers.getLogger(event.getLoggerName()).error(event.getMarker(), event.getMessage(),
116                       org.spf4j.base.Arrays.append(event.getArgumentArray(), t));
117               }
118               break;
119             default:
120               throw new UnsupportedOperationException("Unsupported log level " + level);
121           }
122         }
123         eventQueue.clear();
124       } finally {
125          currentThread.setContextClassLoader(contextClassLoader);
126       }
127     }
128 
129     /**
130      * Return the singleton of this class.
131      *
132      * @return the StaticLoggerBinder singleton
133      */
134     public static StaticLoggerBinder getSingleton() {
135         return SINGLETON;
136     }
137 
138     public ILoggerFactory getLoggerFactory() {
139         return loggerFactory;
140     }
141 
142     public String getLoggerFactoryClassStr() {
143         return LOGGER_FACTORY_CLASS_STR;
144     }
145 
146   @Override
147   public String toString() {
148     return "StaticLoggerBinder{" + "loggerFactory=" + loggerFactory + '}';
149   }
150 
151 }
152