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 }