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