View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  /*
17    Copyright (c) 2004-2011 QOS.ch
18    All rights reserved.
19  
20    Permission is hereby granted, free  of charge, to any person obtaining
21    a  copy  of this  software  and  associated  documentation files  (the
22    "Software"), to  deal in  the Software without  restriction, including
23    without limitation  the rights to  use, copy, modify,  merge, publish,
24    distribute,  sublicense, and/or sell  copies of  the Software,  and to
25    permit persons to whom the Software  is furnished to do so, subject to
26    the following conditions:
27  
28    The  above  copyright  notice  and  this permission  notice  shall  be
29    included in all copies or substantial portions of the Software.
30  
31    THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
32    EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
33    MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
34    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36    OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
37    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  
39   */
40  package io.netty5.util.internal.logging;
41  
42  import java.util.logging.Level;
43  import java.util.logging.LogRecord;
44  import java.util.logging.Logger;
45  
46  /**
47   * <a href="https://java.sun.com/javase/6/docs/technotes/guides/logging/index.html">java.util.logging</a>
48   * logger.
49   */
50  class JdkLogger extends AbstractInternalLogger {
51  
52      private static final long serialVersionUID = -1767272577989225979L;
53  
54      final transient Logger logger;
55  
56      JdkLogger(Logger logger) {
57          super(logger.getName());
58          this.logger = logger;
59      }
60  
61      /**
62       * Is this logger instance enabled for the FINEST level?
63       *
64       * @return True if this Logger is enabled for level FINEST, false otherwise.
65       */
66      @Override
67      public boolean isTraceEnabled() {
68          return logger.isLoggable(Level.FINEST);
69      }
70  
71      /**
72       * Log a message object at level FINEST.
73       *
74       * @param msg
75       *          - the message object to be logged
76       */
77      @Override
78      public void trace(String msg) {
79          if (logger.isLoggable(Level.FINEST)) {
80              log(SELF, Level.FINEST, msg, null);
81          }
82      }
83  
84      /**
85       * Log a message at level FINEST according to the specified format and
86       * argument.
87       *
88       * <p>
89       * This form avoids superfluous object creation when the logger is disabled
90       * for level FINEST.
91       * </p>
92       *
93       * @param format
94       *          the format string
95       * @param arg
96       *          the argument
97       */
98      @Override
99      public void trace(String format, Object arg) {
100         if (logger.isLoggable(Level.FINEST)) {
101             FormattingTuple ft = MessageFormatter.format(format, arg);
102             log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable());
103         }
104     }
105 
106     /**
107      * Log a message at level FINEST according to the specified format and
108      * arguments.
109      *
110      * <p>
111      * This form avoids superfluous object creation when the logger is disabled
112      * for the FINEST level.
113      * </p>
114      *
115      * @param format
116      *          the format string
117      * @param argA
118      *          the first argument
119      * @param argB
120      *          the second argument
121      */
122     @Override
123     public void trace(String format, Object argA, Object argB) {
124         if (logger.isLoggable(Level.FINEST)) {
125             FormattingTuple ft = MessageFormatter.format(format, argA, argB);
126             log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable());
127         }
128     }
129 
130     /**
131      * Log a message at level FINEST according to the specified format and
132      * arguments.
133      *
134      * <p>
135      * This form avoids superfluous object creation when the logger is disabled
136      * for the FINEST level.
137      * </p>
138      *
139      * @param format
140      *          the format string
141      * @param argArray
142      *          an array of arguments
143      */
144     @Override
145     public void trace(String format, Object... argArray) {
146         if (logger.isLoggable(Level.FINEST)) {
147             FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
148             log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable());
149         }
150     }
151 
152     /**
153      * Log an exception (throwable) at level FINEST with an accompanying message.
154      *
155      * @param msg
156      *          the message accompanying the exception
157      * @param t
158      *          the exception (throwable) to log
159      */
160     @Override
161     public void trace(String msg, Throwable t) {
162         if (logger.isLoggable(Level.FINEST)) {
163             log(SELF, Level.FINEST, msg, t);
164         }
165     }
166 
167     /**
168      * Is this logger instance enabled for the FINE level?
169      *
170      * @return True if this Logger is enabled for level FINE, false otherwise.
171      */
172     @Override
173     public boolean isDebugEnabled() {
174         return logger.isLoggable(Level.FINE);
175     }
176 
177     /**
178      * Log a message object at level FINE.
179      *
180      * @param msg
181      *          - the message object to be logged
182      */
183     @Override
184     public void debug(String msg) {
185         if (logger.isLoggable(Level.FINE)) {
186             log(SELF, Level.FINE, msg, null);
187         }
188     }
189 
190     /**
191      * Log a message at level FINE according to the specified format and argument.
192      *
193      * <p>
194      * This form avoids superfluous object creation when the logger is disabled
195      * for level FINE.
196      * </p>
197      *
198      * @param format
199      *          the format string
200      * @param arg
201      *          the argument
202      */
203     @Override
204     public void debug(String format, Object arg) {
205         if (logger.isLoggable(Level.FINE)) {
206             FormattingTuple ft = MessageFormatter.format(format, arg);
207             log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
208         }
209     }
210 
211     /**
212      * Log a message at level FINE according to the specified format and
213      * arguments.
214      *
215      * <p>
216      * This form avoids superfluous object creation when the logger is disabled
217      * for the FINE level.
218      * </p>
219      *
220      * @param format
221      *          the format string
222      * @param argA
223      *          the first argument
224      * @param argB
225      *          the second argument
226      */
227     @Override
228     public void debug(String format, Object argA, Object argB) {
229         if (logger.isLoggable(Level.FINE)) {
230             FormattingTuple ft = MessageFormatter.format(format, argA, argB);
231             log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
232         }
233     }
234 
235     /**
236      * Log a message at level FINE according to the specified format and
237      * arguments.
238      *
239      * <p>
240      * This form avoids superfluous object creation when the logger is disabled
241      * for the FINE level.
242      * </p>
243      *
244      * @param format
245      *          the format string
246      * @param argArray
247      *          an array of arguments
248      */
249     @Override
250     public void debug(String format, Object... argArray) {
251         if (logger.isLoggable(Level.FINE)) {
252             FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
253             log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
254         }
255     }
256 
257     /**
258      * Log an exception (throwable) at level FINE with an accompanying message.
259      *
260      * @param msg
261      *          the message accompanying the exception
262      * @param t
263      *          the exception (throwable) to log
264      */
265     @Override
266     public void debug(String msg, Throwable t) {
267         if (logger.isLoggable(Level.FINE)) {
268             log(SELF, Level.FINE, msg, t);
269         }
270     }
271 
272     /**
273      * Is this logger instance enabled for the INFO level?
274      *
275      * @return True if this Logger is enabled for the INFO level, false otherwise.
276      */
277     @Override
278     public boolean isInfoEnabled() {
279         return logger.isLoggable(Level.INFO);
280     }
281 
282     /**
283      * Log a message object at the INFO level.
284      *
285      * @param msg
286      *          - the message object to be logged
287      */
288     @Override
289     public void info(String msg) {
290         if (logger.isLoggable(Level.INFO)) {
291             log(SELF, Level.INFO, msg, null);
292         }
293     }
294 
295     /**
296      * Log a message at level INFO according to the specified format and argument.
297      *
298      * <p>
299      * This form avoids superfluous object creation when the logger is disabled
300      * for the INFO level.
301      * </p>
302      *
303      * @param format
304      *          the format string
305      * @param arg
306      *          the argument
307      */
308     @Override
309     public void info(String format, Object arg) {
310         if (logger.isLoggable(Level.INFO)) {
311             FormattingTuple ft = MessageFormatter.format(format, arg);
312             log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable());
313         }
314     }
315 
316     /**
317      * Log a message at the INFO level according to the specified format and
318      * arguments.
319      *
320      * <p>
321      * This form avoids superfluous object creation when the logger is disabled
322      * for the INFO level.
323      * </p>
324      *
325      * @param format
326      *          the format string
327      * @param argA
328      *          the first argument
329      * @param argB
330      *          the second argument
331      */
332     @Override
333     public void info(String format, Object argA, Object argB) {
334         if (logger.isLoggable(Level.INFO)) {
335             FormattingTuple ft = MessageFormatter.format(format, argA, argB);
336             log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable());
337         }
338     }
339 
340     /**
341      * Log a message at level INFO according to the specified format and
342      * arguments.
343      *
344      * <p>
345      * This form avoids superfluous object creation when the logger is disabled
346      * for the INFO level.
347      * </p>
348      *
349      * @param format
350      *          the format string
351      * @param argArray
352      *          an array of arguments
353      */
354     @Override
355     public void info(String format, Object... argArray) {
356         if (logger.isLoggable(Level.INFO)) {
357             FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
358             log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable());
359         }
360     }
361 
362     /**
363      * Log an exception (throwable) at the INFO level with an accompanying
364      * message.
365      *
366      * @param msg
367      *          the message accompanying the exception
368      * @param t
369      *          the exception (throwable) to log
370      */
371     @Override
372     public void info(String msg, Throwable t) {
373         if (logger.isLoggable(Level.INFO)) {
374             log(SELF, Level.INFO, msg, t);
375         }
376     }
377 
378     /**
379      * Is this logger instance enabled for the WARNING level?
380      *
381      * @return True if this Logger is enabled for the WARNING level, false
382      *         otherwise.
383      */
384     @Override
385     public boolean isWarnEnabled() {
386         return logger.isLoggable(Level.WARNING);
387     }
388 
389     /**
390      * Log a message object at the WARNING level.
391      *
392      * @param msg
393      *          - the message object to be logged
394      */
395     @Override
396     public void warn(String msg) {
397         if (logger.isLoggable(Level.WARNING)) {
398             log(SELF, Level.WARNING, msg, null);
399         }
400     }
401 
402     /**
403      * Log a message at the WARNING level according to the specified format and
404      * argument.
405      *
406      * <p>
407      * This form avoids superfluous object creation when the logger is disabled
408      * for the WARNING level.
409      * </p>
410      *
411      * @param format
412      *          the format string
413      * @param arg
414      *          the argument
415      */
416     @Override
417     public void warn(String format, Object arg) {
418         if (logger.isLoggable(Level.WARNING)) {
419             FormattingTuple ft = MessageFormatter.format(format, arg);
420             log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable());
421         }
422     }
423 
424     /**
425      * Log a message at the WARNING level according to the specified format and
426      * arguments.
427      *
428      * <p>
429      * This form avoids superfluous object creation when the logger is disabled
430      * for the WARNING level.
431      * </p>
432      *
433      * @param format
434      *          the format string
435      * @param argA
436      *          the first argument
437      * @param argB
438      *          the second argument
439      */
440     @Override
441     public void warn(String format, Object argA, Object argB) {
442         if (logger.isLoggable(Level.WARNING)) {
443             FormattingTuple ft = MessageFormatter.format(format, argA, argB);
444             log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable());
445         }
446     }
447 
448     /**
449      * Log a message at level WARNING according to the specified format and
450      * arguments.
451      *
452      * <p>
453      * This form avoids superfluous object creation when the logger is disabled
454      * for the WARNING level.
455      * </p>
456      *
457      * @param format
458      *          the format string
459      * @param argArray
460      *          an array of arguments
461      */
462     @Override
463     public void warn(String format, Object... argArray) {
464         if (logger.isLoggable(Level.WARNING)) {
465             FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
466             log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable());
467         }
468     }
469 
470     /**
471      * Log an exception (throwable) at the WARNING level with an accompanying
472      * message.
473      *
474      * @param msg
475      *          the message accompanying the exception
476      * @param t
477      *          the exception (throwable) to log
478      */
479     @Override
480     public void warn(String msg, Throwable t) {
481         if (logger.isLoggable(Level.WARNING)) {
482             log(SELF, Level.WARNING, msg, t);
483         }
484     }
485 
486     /**
487      * Is this logger instance enabled for level SEVERE?
488      *
489      * @return True if this Logger is enabled for level SEVERE, false otherwise.
490      */
491     @Override
492     public boolean isErrorEnabled() {
493         return logger.isLoggable(Level.SEVERE);
494     }
495 
496     /**
497      * Log a message object at the SEVERE level.
498      *
499      * @param msg
500      *          - the message object to be logged
501      */
502     @Override
503     public void error(String msg) {
504         if (logger.isLoggable(Level.SEVERE)) {
505             log(SELF, Level.SEVERE, msg, null);
506         }
507     }
508 
509     /**
510      * Log a message at the SEVERE level according to the specified format and
511      * argument.
512      *
513      * <p>
514      * This form avoids superfluous object creation when the logger is disabled
515      * for the SEVERE level.
516      * </p>
517      *
518      * @param format
519      *          the format string
520      * @param arg
521      *          the argument
522      */
523     @Override
524     public void error(String format, Object arg) {
525         if (logger.isLoggable(Level.SEVERE)) {
526             FormattingTuple ft = MessageFormatter.format(format, arg);
527             log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable());
528         }
529     }
530 
531     /**
532      * Log a message at the SEVERE level according to the specified format and
533      * arguments.
534      *
535      * <p>
536      * This form avoids superfluous object creation when the logger is disabled
537      * for the SEVERE level.
538      * </p>
539      *
540      * @param format
541      *          the format string
542      * @param argA
543      *          the first argument
544      * @param argB
545      *          the second argument
546      */
547     @Override
548     public void error(String format, Object argA, Object argB) {
549         if (logger.isLoggable(Level.SEVERE)) {
550             FormattingTuple ft = MessageFormatter.format(format, argA, argB);
551             log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable());
552         }
553     }
554 
555     /**
556      * Log a message at level SEVERE according to the specified format and
557      * arguments.
558      *
559      * <p>
560      * This form avoids superfluous object creation when the logger is disabled
561      * for the SEVERE level.
562      * </p>
563      *
564      * @param format
565      *          the format string
566      * @param arguments
567      *          an array of arguments
568      */
569     @Override
570     public void error(String format, Object... arguments) {
571         if (logger.isLoggable(Level.SEVERE)) {
572             FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
573             log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable());
574         }
575     }
576 
577     /**
578      * Log an exception (throwable) at the SEVERE level with an accompanying
579      * message.
580      *
581      * @param msg
582      *          the message accompanying the exception
583      * @param t
584      *          the exception (throwable) to log
585      */
586     @Override
587     public void error(String msg, Throwable t) {
588         if (logger.isLoggable(Level.SEVERE)) {
589             log(SELF, Level.SEVERE, msg, t);
590         }
591     }
592 
593     /**
594      * Log the message at the specified level with the specified throwable if any.
595      * This method creates a LogRecord and fills in caller date before calling
596      * this instance's JDK14 logger.
597      *
598      * See bug report #13 for more details.
599      */
600     private void log(String callerFQCN, Level level, String msg, Throwable t) {
601         // millis and thread are filled by the constructor
602         LogRecord record = new LogRecord(level, msg);
603         record.setLoggerName(name());
604         record.setThrown(t);
605         fillCallerData(callerFQCN, record);
606         logger.log(record);
607     }
608 
609     static final String SELF = JdkLogger.class.getName();
610     static final String SUPER = AbstractInternalLogger.class.getName();
611 
612     /**
613      * Fill in caller data if possible.
614      *
615      * @param record
616      *          The record to update
617      */
618     private static void fillCallerData(String callerFQCN, LogRecord record) {
619         StackTraceElement[] steArray = new Throwable().getStackTrace();
620 
621         int selfIndex = -1;
622         for (int i = 0; i < steArray.length; i++) {
623             final String className = steArray[i].getClassName();
624             if (className.equals(callerFQCN) || className.equals(SUPER)) {
625                 selfIndex = i;
626                 break;
627             }
628         }
629 
630         int found = -1;
631         for (int i = selfIndex + 1; i < steArray.length; i++) {
632             final String className = steArray[i].getClassName();
633             if (!(className.equals(callerFQCN) || className.equals(SUPER))) {
634                 found = i;
635                 break;
636             }
637         }
638 
639         if (found != -1) {
640             StackTraceElement ste = steArray[found];
641             // setting the class name has the side effect of setting
642             // the needToInferCaller variable to false.
643             record.setSourceClassName(ste.getClassName());
644             record.setSourceMethodName(ste.getMethodName());
645         }
646     }
647 }