1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 package org.slf4j.impl;
46
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.logging.LogRecord;
54 import java.util.logging.Logger;
55
56 import org.bukkit.Bukkit;
57 import org.bukkit.plugin.Plugin;
58 import org.slf4j.event.Level;
59 import org.slf4j.helpers.FormattingTuple;
60 import org.slf4j.helpers.MarkerIgnoringBase;
61 import org.slf4j.helpers.MessageFormatter;
62 import org.yaml.snakeyaml.Yaml;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public final class BukkitPluginLoggerAdapter extends MarkerIgnoringBase {
164
165
166 private static transient Plugin BUKKIT_PLUGIN;
167 private static transient String BUKKIT_PLUGIN_NAME;
168
169 private static final String CLASS_SELF = BukkitPluginLoggerAdapter.class.getName();
170 private static final String CLASS_SUPER = MarkerIgnoringBase.class.getName();
171
172 private static final String CONFIG_FALLBACK_DEFAULT_LOG_LEVEL = "info";
173 private static final boolean CONFIG_FALLBACK_SHOW_HEADER = false;
174 private static final boolean CONFIG_FALLBACK_SHOW_LOG_NAME = false;
175 private static final boolean CONFIG_FALLBACK_SHOW_SHORT_LOG_NAME = true;
176 private static final boolean CONFIG_FALLBACK_SHOW_THREAD_NAME = false;
177 private static final String CONFIG_KEY_DEFAULT_LOG_LEVEL = "slf4j.defaultLogLevel";
178 private static final String CONFIG_KEY_PREFIX_LOG = "slf4j.log.";
179 private static final String CONFIG_KEY_SHOW_HEADER = "slf4j.showHeader";
180 private static final String CONFIG_KEY_SHOW_LOG_NAME = "slf4j.showLogName";
181 private static final String CONFIG_KEY_SHOW_SHORT_LOG_NAME = "slf4j.showShortLogName";
182 private static final String CONFIG_KEY_SHOW_THREAD_NAME = "slf4j.showThreadName";
183 private static Level CONFIG_VALUE_DEFAULT_LOG_LEVEL;
184 private static boolean CONFIG_VALUE_SHOW_HEADER;
185 private static boolean CONFIG_VALUE_SHOW_LOG_NAME;
186 private static boolean CONFIG_VALUE_SHOW_SHORT_LOG_NAME;
187 private static boolean CONFIG_VALUE_SHOW_THREAD_NAME;
188
189 private static final Object INITIALIZATION_LOCK = new Object();
190
191 private static final long serialVersionUID = -2270127287235697381L;
192
193 private transient String shortLogName = null;
194
195
196
197 BukkitPluginLoggerAdapter(final String name) {
198 this.name = name;
199 }
200
201
202
203
204
205
206
207
208
209 public static void init(final boolean reinitialize) {
210 synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
211
212 if (reinitialize) {
213 BukkitPluginLoggerAdapter.BUKKIT_PLUGIN = null;
214 BukkitPluginLoggerAdapter.BUKKIT_PLUGIN_NAME = null;
215 } else if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN != null) { return; }
216
217 if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN_NAME == null) {
218 InputStream pluginYmlFile = null;
219 try {
220 pluginYmlFile = BukkitPluginLoggerAdapter.class.getClassLoader()
221 .getResource("plugin.yml")
222 .openStream();
223 final Yaml yaml = new Yaml();
224 @SuppressWarnings("rawtypes")
225 final Map pluginYml = (Map) yaml.load(pluginYmlFile);
226 BukkitPluginLoggerAdapter.BUKKIT_PLUGIN_NAME = (String) pluginYml.get("name");
227 } catch (final IOException e) {
228 throw new IllegalStateException(e);
229 } finally {
230 if (pluginYmlFile != null) {
231 try {
232 pluginYmlFile.close();
233 } catch (final IOException e) {
234 e.printStackTrace();
235 }
236 }
237 }
238 }
239
240
241
242
243 BukkitPluginLoggerAdapter.BUKKIT_PLUGIN = Bukkit.getPluginManager()
244 .getPlugin(BukkitPluginLoggerAdapter.BUKKIT_PLUGIN_NAME);
245
246
247
248
249
250 BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL = BukkitPluginLoggerAdapter.stringToLevel(BukkitPluginLoggerAdapter.getStringProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_DEFAULT_LOG_LEVEL,
251 BukkitPluginLoggerAdapter.CONFIG_FALLBACK_DEFAULT_LOG_LEVEL));
252 BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_HEADER = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_HEADER,
253 BukkitPluginLoggerAdapter.CONFIG_FALLBACK_SHOW_HEADER);
254 BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_LOG_NAME = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_LOG_NAME,
255 BukkitPluginLoggerAdapter.CONFIG_FALLBACK_SHOW_LOG_NAME);
256 BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_SHORT_LOG_NAME = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_SHORT_LOG_NAME,
257 BukkitPluginLoggerAdapter.CONFIG_FALLBACK_SHOW_SHORT_LOG_NAME);
258 BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_THREAD_NAME = BukkitPluginLoggerAdapter.getBooleanProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_SHOW_THREAD_NAME,
259 BukkitPluginLoggerAdapter.CONFIG_FALLBACK_SHOW_THREAD_NAME);
260 }
261 }
262
263 private static boolean getBooleanProperty(final String name,
264 final boolean defaultValue) {
265 synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
266 if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null) { return defaultValue; }
267 final String prop = BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getConfig()
268 .getString(name);
269 return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
270 }
271 }
272
273
274
275
276
277
278
279 private static Logger getBukkitLogger() {
280 synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
281 return BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null ? Bukkit.getLogger()
282 : BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getLogger();
283 }
284 }
285
286 private static String getStringProperty(final String name,
287 final String defaultValue) {
288 synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
289 if (BukkitPluginLoggerAdapter.BUKKIT_PLUGIN == null) { return defaultValue; }
290 final String prop = BukkitPluginLoggerAdapter.BUKKIT_PLUGIN.getConfig()
291 .getString(name);
292 return (prop == null) ? defaultValue : prop;
293 }
294 }
295
296 private static java.util.logging.Level
297 slf4jLevelIntToBukkitJULLevel(final Level slf4jLevel) {
298 java.util.logging.Level julLevel;
299 switch (slf4jLevel) {
300
301
302 case TRACE:
303 case DEBUG:
304 case INFO:
305 julLevel = java.util.logging.Level.INFO;
306 break;
307 case WARN:
308 julLevel = java.util.logging.Level.WARNING;
309 break;
310 case ERROR:
311 julLevel = java.util.logging.Level.SEVERE;
312 break;
313 default:
314 throw new IllegalStateException("Level " + slf4jLevel
315 + " is not recognized.");
316 }
317 return julLevel;
318 }
319
320
321
322
323
324 private static Level stringToLevel(final String levelStr) {
325 if ("trace".equalsIgnoreCase(levelStr)) {
326 return Level.TRACE;
327 } else if ("debug".equalsIgnoreCase(levelStr)) {
328 return Level.DEBUG;
329 } else if ("info".equalsIgnoreCase(levelStr)) {
330 return Level.INFO;
331 } else if ("warn".equalsIgnoreCase(levelStr)) {
332 return Level.WARN;
333 } else if ("error".equalsIgnoreCase(levelStr)) {
334 return Level.ERROR;
335 } else {
336 return Level.INFO;
337 }
338 }
339
340
341
342
343
344 @Override
345 public void debug(final String msg) {
346 if (!this.isDebugEnabled()) { return; }
347 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.DEBUG, msg, null);
348 }
349
350
351
352
353
354 @Override
355 public void debug(final String format, final Object param1) {
356 if (!this.isDebugEnabled()) { return; }
357 this.formatAndLog(Level.DEBUG, format, param1, null);
358 }
359
360
361
362
363
364 @Override
365 public void debug(final String format, final Object... argArray) {
366 if (!this.isDebugEnabled()) { return; }
367 this.formatAndLog(Level.DEBUG, format, argArray);
368 }
369
370
371
372
373
374 @Override
375 public void debug(final String format, final Object param1,
376 final Object param2) {
377 if (!this.isDebugEnabled()) { return; }
378 this.formatAndLog(Level.DEBUG, format, param1, param2);
379 }
380
381
382 @Override
383 public void debug(final String msg, final Throwable t) {
384 if (!this.isDebugEnabled()) { return; }
385 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.DEBUG, msg, t);
386 }
387
388
389
390
391
392 @Override
393 public void error(final String msg) {
394 if (!this.isErrorEnabled()) { return; }
395 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.ERROR, msg, null);
396 }
397
398
399
400
401
402 @Override
403 public void error(final String format, final Object arg) {
404 if (!this.isErrorEnabled()) { return; }
405 this.formatAndLog(Level.ERROR, format, arg, null);
406 }
407
408
409
410
411
412 @Override
413 public void error(final String format, final Object... argArray) {
414 if (!this.isErrorEnabled()) { return; }
415 this.formatAndLog(Level.ERROR, format, argArray);
416 }
417
418
419
420
421
422 @Override
423 public void error(final String format, final Object arg1, final Object arg2) {
424 if (!this.isErrorEnabled()) { return; }
425 this.formatAndLog(Level.ERROR, format, arg1, arg2);
426 }
427
428
429 @Override
430 public void error(final String msg, final Throwable t) {
431 if (!this.isErrorEnabled()) { return; }
432 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.ERROR, msg, t);
433 }
434
435
436
437
438
439 @Override
440 public void info(final String msg) {
441 if (!this.isInfoEnabled()) { return; }
442 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.INFO, msg, null);
443 }
444
445
446
447
448
449 @Override
450 public void info(final String format, final Object arg) {
451 if (!this.isInfoEnabled()) { return; }
452 this.formatAndLog(Level.INFO, format, arg, null);
453 }
454
455
456
457
458
459 @Override
460 public void info(final String format, final Object... argArray) {
461 if (!this.isInfoEnabled()) { return; }
462 this.formatAndLog(Level.INFO, format, argArray);
463 }
464
465
466
467
468
469 @Override
470 public void info(final String format, final Object arg1, final Object arg2) {
471 if (!this.isInfoEnabled()) { return; }
472 this.formatAndLog(Level.INFO, format, arg1, arg2);
473 }
474
475
476 @Override
477 public void info(final String msg, final Throwable t) {
478 if (!this.isInfoEnabled()) { return; }
479 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.INFO, msg, t);
480 }
481
482
483 @Override
484 public boolean isDebugEnabled() {
485 return this.isLevelEnabled(Level.DEBUG);
486 }
487
488
489 @Override
490 public boolean isErrorEnabled() {
491 return this.isLevelEnabled(Level.ERROR);
492 }
493
494
495 @Override
496 public boolean isInfoEnabled() {
497 return this.isLevelEnabled(Level.INFO);
498 }
499
500
501 @Override
502 public boolean isTraceEnabled() {
503 return this.isLevelEnabled(Level.TRACE);
504 }
505
506
507 @Override
508 public boolean isWarnEnabled() {
509 return this.isLevelEnabled(Level.WARN);
510 }
511
512
513
514
515
516 @Override
517 public void trace(final String msg) {
518 if (!this.isTraceEnabled()) { return; }
519 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.TRACE, msg, null);
520 }
521
522
523
524
525
526 @Override
527 public void trace(final String format, final Object param1) {
528 if (!this.isTraceEnabled()) { return; }
529 this.formatAndLog(Level.TRACE, format, param1, null);
530 }
531
532
533
534
535
536 @Override
537 public void trace(final String format, final Object... argArray) {
538 if (!this.isTraceEnabled()) { return; }
539 this.formatAndLog(Level.TRACE, format, argArray);
540 }
541
542
543
544
545
546 @Override
547 public void trace(final String format, final Object param1,
548 final Object param2) {
549 if (!this.isTraceEnabled()) { return; }
550 this.formatAndLog(Level.TRACE, format, param1, param2);
551 }
552
553
554 @Override
555 public void trace(final String msg, final Throwable t) {
556 if (!this.isTraceEnabled()) { return; }
557 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.TRACE, msg, t);
558 }
559
560
561
562
563
564 @Override
565 public void warn(final String msg) {
566 if (!this.isWarnEnabled()) { return; }
567 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.WARN, msg, null);
568 }
569
570
571
572
573
574 @Override
575 public void warn(final String format, final Object arg) {
576 if (!this.isWarnEnabled()) { return; }
577 this.formatAndLog(Level.WARN, format, arg, null);
578 }
579
580
581
582
583
584 @Override
585 public void warn(final String format, final Object... argArray) {
586 if (!this.isWarnEnabled()) { return; }
587 this.formatAndLog(Level.WARN, format, argArray);
588 }
589
590
591
592
593
594 @Override
595 public void warn(final String format, final Object arg1, final Object arg2) {
596 if (!this.isWarnEnabled()) { return; }
597 this.formatAndLog(Level.WARN, format, arg1, arg2);
598 }
599
600
601
602
603
604
605 @Override
606 public void warn(final String msg, final Throwable t) {
607 if (!this.isWarnEnabled()) { return; }
608 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, Level.WARN, msg, t);
609 }
610
611 private String computeShortName() {
612 final List<String> splitName = new ArrayList<String>();
613 splitName.addAll(Arrays.asList(this.name.split("\\.")));
614 final int shortNameLength = ((splitName.size() - 1) * 2)
615 + splitName.get(splitName.size() - 1).length();
616 final String finalName = splitName.remove(splitName.size() - 1);
617 final StringBuffer shortName = new StringBuffer(shortNameLength);
618 for (final String part : splitName) {
619 shortName.append(part.charAt(0)).append('.');
620 }
621 shortName.append(finalName);
622 return shortName.toString();
623 }
624
625 private Level determineCurrentLevel() {
626 final String levelString = this.recursivelyComputeLevelString();
627 if (levelString != null) {
628 return BukkitPluginLoggerAdapter.stringToLevel(levelString);
629 } else {
630 return BukkitPluginLoggerAdapter.CONFIG_VALUE_DEFAULT_LOG_LEVEL;
631 }
632 }
633
634
635
636
637
638
639
640
641
642 private void formatAndLog(final Level level, final String format,
643 final Object... arguments) {
644 if (!this.isLevelEnabled(level)) { return; }
645 final FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments);
646 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, level, tp.getMessage(),
647 tp.getThrowable());
648 }
649
650
651
652
653
654
655
656
657
658 private void formatAndLog(final Level level, final String format,
659 final Object arg1, final Object arg2) {
660 if (!this.isLevelEnabled(level)) { return; }
661 final FormattingTuple tp = MessageFormatter.format(format, arg1, arg2);
662 this.log(BukkitPluginLoggerAdapter.CLASS_SELF, level, tp.getMessage(),
663 tp.getThrowable());
664 }
665
666
667
668
669
670
671
672 private boolean isLevelEnabled(final Level logLevel) {
673
674
675
676 BukkitPluginLoggerAdapter.init(false);
677
678
679
680
681
682
683 final Level currentLogLevel = this.determineCurrentLevel();
684 return (logLevel.toInt() >= currentLogLevel.toInt())
685 && (BukkitPluginLoggerAdapter.getBukkitLogger().isLoggable(BukkitPluginLoggerAdapter.slf4jLevelIntToBukkitJULLevel(logLevel)));
686 }
687
688
689
690
691
692
693
694 private void
695 julFillCallerData(final String callerFQCN, final LogRecord record) {
696 final StackTraceElement[] steArray = new Throwable().getStackTrace();
697
698 int selfIndex = -1;
699 for (int i = 0; i < steArray.length; i++) {
700 final String className = steArray[i].getClassName();
701 if (className.equals(callerFQCN)
702 || className.equals(BukkitPluginLoggerAdapter.CLASS_SUPER)) {
703 selfIndex = i;
704 break;
705 }
706 }
707
708 int found = -1;
709 for (int i = selfIndex + 1; i < steArray.length; i++) {
710 final String className = steArray[i].getClassName();
711 if (!(className.equals(callerFQCN) || className.equals(BukkitPluginLoggerAdapter.CLASS_SUPER))) {
712 found = i;
713 break;
714 }
715 }
716
717 if (found != -1) {
718 final StackTraceElement ste = steArray[found];
719
720
721 record.setSourceClassName(ste.getClassName());
722 record.setSourceMethodName(ste.getMethodName());
723 }
724 }
725
726
727
728
729
730
731
732
733
734
735
736
737
738 private void julLog(final Logger logger, final String callerFQCN,
739 final java.util.logging.Level level, final String msg,
740 final Throwable t) {
741
742 final LogRecord record = new LogRecord(level, msg);
743 record.setLoggerName(this.getName());
744 record.setThrown(t);
745
746
747 this.julFillCallerData(callerFQCN, record);
748 logger.log(record);
749 }
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764 private void log(final String callerFQCN, final Level level,
765 final String message, final Throwable t) {
766 final Logger logger;
767 synchronized (BukkitPluginLoggerAdapter.INITIALIZATION_LOCK) {
768
769 if (!this.isLevelEnabled(level)) { return; }
770
771 logger = BukkitPluginLoggerAdapter.getBukkitLogger();
772 }
773
774
775 final StringBuilder buf = new StringBuilder(32);
776
777
778 if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_HEADER) {
779 buf.append("SLF4J");
780 }
781
782
783
784 switch (level) {
785 case TRACE:
786 buf.append("[TRACE]");
787 break;
788 case DEBUG:
789 buf.append("[DEBUG]");
790 break;
791 default:
792 break;
793 }
794
795
796 if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_THREAD_NAME) {
797 buf.append('[');
798 buf.append(Thread.currentThread().getName());
799 buf.append("]");
800 }
801
802
803 if (buf.length() > 0) {
804 buf.append(' ');
805 }
806
807
808 if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_SHORT_LOG_NAME) {
809 if (this.shortLogName == null) {
810 this.shortLogName = this.computeShortName();
811 }
812 buf.append(String.valueOf(this.shortLogName)).append(" - ");
813 } else if (BukkitPluginLoggerAdapter.CONFIG_VALUE_SHOW_LOG_NAME) {
814 buf.append(String.valueOf(this.name)).append(" - ");
815 }
816
817
818 buf.append(message);
819
820
821 this.julLog(logger, BukkitPluginLoggerAdapter.CLASS_SELF,
822 BukkitPluginLoggerAdapter.slf4jLevelIntToBukkitJULLevel(level),
823 buf.toString(), t);
824 }
825
826 private String recursivelyComputeLevelString() {
827 String tempName = this.name;
828 String levelString = null;
829 int indexOfLastDot = tempName.length();
830 while ((levelString == null) && (indexOfLastDot > -1)) {
831 tempName = tempName.substring(0, indexOfLastDot);
832 levelString = BukkitPluginLoggerAdapter.getStringProperty(BukkitPluginLoggerAdapter.CONFIG_KEY_PREFIX_LOG
833 + tempName,
834 null);
835 indexOfLastDot = String.valueOf(tempName).lastIndexOf(".");
836 }
837 return levelString;
838 }
839
840 }