1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util.log;
20
21 import java.io.PrintStream;
22 import java.security.AccessControlException;
23 import java.util.Properties;
24
25 import org.eclipse.jetty.util.DateCache;
26 import org.eclipse.jetty.util.annotation.ManagedAttribute;
27 import org.eclipse.jetty.util.annotation.ManagedObject;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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 @ManagedObject("Jetty StdErr Logging Implementation")
88 public class StdErrLog extends AbstractLogger
89 {
90 private static final String EOL = System.getProperty("line.separator");
91 private static DateCache _dateCache;
92 private static final Properties __props = new Properties();
93
94 private final static boolean __source = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE",
95 Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE","false")));
96 private final static boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG","false"));
97
98 static
99 {
100 __props.putAll(Log.__props);
101
102 String deprecatedProperties[] =
103 { "DEBUG", "org.eclipse.jetty.util.log.DEBUG", "org.eclipse.jetty.util.log.stderr.DEBUG" };
104
105
106 for (String deprecatedProp : deprecatedProperties)
107 {
108 if (System.getProperty(deprecatedProp) != null)
109 {
110 System.err.printf("System Property [%s] has been deprecated! (Use org.eclipse.jetty.LEVEL=DEBUG instead)%n",deprecatedProp);
111 }
112 }
113
114 try
115 {
116 _dateCache = new DateCache("yyyy-MM-dd HH:mm:ss");
117 }
118 catch (Exception x)
119 {
120 x.printStackTrace(System.err);
121 }
122 }
123
124 public static final int LEVEL_ALL = 0;
125 public static final int LEVEL_DEBUG = 1;
126 public static final int LEVEL_INFO = 2;
127 public static final int LEVEL_WARN = 3;
128 public static final int LEVEL_OFF = 10;
129
130 private int _level = LEVEL_INFO;
131
132 private int _configuredLevel;
133 private PrintStream _stderr = null;
134 private boolean _source = __source;
135
136 private boolean _printLongNames = __long;
137
138 private final String _name;
139
140 private final String _abbrevname;
141 private boolean _hideStacks = false;
142
143
144
145
146
147
148
149
150
151
152
153
154 public static StdErrLog getLogger(Class<?> clazz)
155 {
156 Logger log = Log.getLogger(clazz);
157 if (log instanceof StdErrLog)
158 {
159 return (StdErrLog)log;
160 }
161 throw new RuntimeException("Logger for " + clazz + " is not of type StdErrLog");
162 }
163
164
165
166
167
168
169 public StdErrLog()
170 {
171 this(null);
172 }
173
174
175
176
177
178
179
180 public StdErrLog(String name)
181 {
182 this(name,__props);
183 }
184
185
186
187
188
189
190
191
192
193 public StdErrLog(String name, Properties props)
194 {
195 if (props!=null && props!=__props)
196 __props.putAll(props);
197 this._name = name == null?"":name;
198 this._abbrevname = condensePackageString(this._name);
199 this._level = getLoggingLevel(props,this._name);
200 this._configuredLevel = this._level;
201
202 try
203 {
204 String source = getLoggingProperty(props,_name,"SOURCE");
205 _source = source==null?__source:Boolean.parseBoolean(source);
206 }
207 catch (AccessControlException ace)
208 {
209 _source = __source;
210 }
211
212 try
213 {
214
215 String stacks = getLoggingProperty(props,_name,"STACKS");
216 _hideStacks = stacks==null?false:!Boolean.parseBoolean(stacks);
217 }
218 catch (AccessControlException ignore)
219 {
220
221 }
222 }
223
224
225
226
227
228
229
230
231
232
233
234 public static int getLoggingLevel(Properties props, final String name)
235 {
236
237
238 String nameSegment = name;
239
240 while ((nameSegment != null) && (nameSegment.length() > 0))
241 {
242 String levelStr = props.getProperty(nameSegment + ".LEVEL");
243
244 int level = getLevelId(nameSegment + ".LEVEL",levelStr);
245 if (level != (-1))
246 {
247 return level;
248 }
249
250
251 int idx = nameSegment.lastIndexOf('.');
252 if (idx >= 0)
253 {
254 nameSegment = nameSegment.substring(0,idx);
255 }
256 else
257 {
258 nameSegment = null;
259 }
260 }
261
262
263 return getLevelId("log.LEVEL",props.getProperty("log.LEVEL","INFO"));
264 }
265
266 public static String getLoggingProperty(Properties props, String name, String property)
267 {
268
269
270 String nameSegment = name;
271
272 while ((nameSegment != null) && (nameSegment.length() > 0))
273 {
274 String s = props.getProperty(nameSegment+"."+property);
275 if (s!=null)
276 return s;
277
278
279 int idx = nameSegment.lastIndexOf('.');
280 nameSegment = (idx >= 0)?nameSegment.substring(0,idx):null;
281 }
282
283 return null;
284 }
285
286 protected static int getLevelId(String levelSegment, String levelName)
287 {
288 if (levelName == null)
289 {
290 return -1;
291 }
292 String levelStr = levelName.trim();
293 if ("ALL".equalsIgnoreCase(levelStr))
294 {
295 return LEVEL_ALL;
296 }
297 else if ("DEBUG".equalsIgnoreCase(levelStr))
298 {
299 return LEVEL_DEBUG;
300 }
301 else if ("INFO".equalsIgnoreCase(levelStr))
302 {
303 return LEVEL_INFO;
304 }
305 else if ("WARN".equalsIgnoreCase(levelStr))
306 {
307 return LEVEL_WARN;
308 }
309 else if ("OFF".equalsIgnoreCase(levelStr))
310 {
311 return LEVEL_OFF;
312 }
313
314 System.err.println("Unknown StdErrLog level [" + levelSegment + "]=[" + levelStr + "], expecting only [ALL, DEBUG, INFO, WARN, OFF] as values.");
315 return -1;
316 }
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333 protected static String condensePackageString(String classname)
334 {
335 String parts[] = classname.split("\\.");
336 StringBuilder dense = new StringBuilder();
337 for (int i = 0; i < (parts.length - 1); i++)
338 {
339 dense.append(parts[i].charAt(0));
340 }
341 if (dense.length() > 0)
342 {
343 dense.append('.');
344 }
345 dense.append(parts[parts.length - 1]);
346 return dense.toString();
347 }
348
349 public String getName()
350 {
351 return _name;
352 }
353
354 public void setPrintLongNames(boolean printLongNames)
355 {
356 this._printLongNames = printLongNames;
357 }
358
359 public boolean isPrintLongNames()
360 {
361 return this._printLongNames;
362 }
363
364 public boolean isHideStacks()
365 {
366 return _hideStacks;
367 }
368
369 public void setHideStacks(boolean hideStacks)
370 {
371 _hideStacks = hideStacks;
372 }
373
374
375
376
377
378
379
380 public boolean isSource()
381 {
382 return _source;
383 }
384
385
386
387
388
389
390
391
392 public void setSource(boolean source)
393 {
394 _source = source;
395 }
396
397 public void warn(String msg, Object... args)
398 {
399 if (_level <= LEVEL_WARN)
400 {
401 StringBuilder buffer = new StringBuilder(64);
402 format(buffer,":WARN:",msg,args);
403 (_stderr==null?System.err:_stderr).println(buffer);
404 }
405 }
406
407 public void warn(Throwable thrown)
408 {
409 warn("",thrown);
410 }
411
412 public void warn(String msg, Throwable thrown)
413 {
414 if (_level <= LEVEL_WARN)
415 {
416 StringBuilder buffer = new StringBuilder(64);
417 format(buffer,":WARN:",msg,thrown);
418 (_stderr==null?System.err:_stderr).println(buffer);
419 }
420 }
421
422 public void info(String msg, Object... args)
423 {
424 if (_level <= LEVEL_INFO)
425 {
426 StringBuilder buffer = new StringBuilder(64);
427 format(buffer,":INFO:",msg,args);
428 (_stderr==null?System.err:_stderr).println(buffer);
429 }
430 }
431
432 public void info(Throwable thrown)
433 {
434 info("",thrown);
435 }
436
437 public void info(String msg, Throwable thrown)
438 {
439 if (_level <= LEVEL_INFO)
440 {
441 StringBuilder buffer = new StringBuilder(64);
442 format(buffer,":INFO:",msg,thrown);
443 (_stderr==null?System.err:_stderr).println(buffer);
444 }
445 }
446
447 @ManagedAttribute("is debug enabled for root logger Log.LOG")
448 public boolean isDebugEnabled()
449 {
450 return (_level <= LEVEL_DEBUG);
451 }
452
453
454
455
456
457 @Override
458 public void setDebugEnabled(boolean enabled)
459 {
460 if (enabled)
461 {
462 this._level = LEVEL_DEBUG;
463
464 for (Logger log : Log.getLoggers().values())
465 {
466 if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
467 ((StdErrLog)log).setLevel(LEVEL_DEBUG);
468 }
469 }
470 else
471 {
472 this._level = this._configuredLevel;
473
474 for (Logger log : Log.getLoggers().values())
475 {
476 if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
477 ((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel);
478 }
479 }
480 }
481
482 public int getLevel()
483 {
484 return _level;
485 }
486
487
488
489
490
491
492
493
494
495
496 public void setLevel(int level)
497 {
498 this._level = level;
499 }
500
501 public void setStdErrStream(PrintStream stream)
502 {
503 this._stderr = stream==System.err?null:stream;
504 }
505
506 public void debug(String msg, Object... args)
507 {
508 if (_level <= LEVEL_DEBUG)
509 {
510 StringBuilder buffer = new StringBuilder(64);
511 format(buffer,":DBUG:",msg,args);
512 (_stderr==null?System.err:_stderr).println(buffer);
513 }
514 }
515
516 public void debug(Throwable thrown)
517 {
518 debug("",thrown);
519 }
520
521 public void debug(String msg, Throwable thrown)
522 {
523 if (_level <= LEVEL_DEBUG)
524 {
525 StringBuilder buffer = new StringBuilder(64);
526 format(buffer,":DBUG:",msg,thrown);
527 (_stderr==null?System.err:_stderr).println(buffer);
528 }
529 }
530
531 private void format(StringBuilder buffer, String level, String msg, Object... args)
532 {
533 long now = System.currentTimeMillis();
534 int ms=(int)(now%1000);
535 String d = _dateCache.now();
536 tag(buffer,d,ms,level);
537 format(buffer,msg,args);
538 }
539
540 private void format(StringBuilder buffer, String level, String msg, Throwable thrown)
541 {
542 format(buffer,level,msg);
543 if (isHideStacks())
544 {
545 format(buffer,": "+String.valueOf(thrown));
546 }
547 else
548 {
549 format(buffer,thrown);
550 }
551 }
552
553 private void tag(StringBuilder buffer, String d, int ms, String tag)
554 {
555 buffer.setLength(0);
556 buffer.append(d);
557 if (ms > 99)
558 {
559 buffer.append('.');
560 }
561 else if (ms > 9)
562 {
563 buffer.append(".0");
564 }
565 else
566 {
567 buffer.append(".00");
568 }
569 buffer.append(ms).append(tag);
570 if (_printLongNames)
571 {
572 buffer.append(_name);
573 }
574 else
575 {
576 buffer.append(_abbrevname);
577 }
578 buffer.append(':');
579 buffer.append(Thread.currentThread().getName()).append(": ");
580 if (_source)
581 {
582 Throwable source = new Throwable();
583 StackTraceElement[] frames = source.getStackTrace();
584 for (int i = 0; i < frames.length; i++)
585 {
586 final StackTraceElement frame = frames[i];
587 String clazz = frame.getClassName();
588 if (clazz.equals(StdErrLog.class.getName()) || clazz.equals(Log.class.getName()))
589 {
590 continue;
591 }
592 if (!_printLongNames && clazz.startsWith("org.eclipse.jetty."))
593 {
594 buffer.append(condensePackageString(clazz));
595 }
596 else
597 {
598 buffer.append(clazz);
599 }
600 buffer.append('#').append(frame.getMethodName());
601 if (frame.getFileName() != null)
602 {
603 buffer.append('(').append(frame.getFileName()).append(':').append(frame.getLineNumber()).append(')');
604 }
605 buffer.append(':');
606 break;
607 }
608 }
609 }
610
611 private void format(StringBuilder builder, String msg, Object... args)
612 {
613 if (msg == null)
614 {
615 msg = "";
616 for (int i = 0; i < args.length; i++)
617 {
618 msg += "{} ";
619 }
620 }
621 String braces = "{}";
622 int start = 0;
623 for (Object arg : args)
624 {
625 int bracesIndex = msg.indexOf(braces,start);
626 if (bracesIndex < 0)
627 {
628 escape(builder,msg.substring(start));
629 builder.append(" ");
630 builder.append(arg);
631 start = msg.length();
632 }
633 else
634 {
635 escape(builder,msg.substring(start,bracesIndex));
636 builder.append(String.valueOf(arg));
637 start = bracesIndex + braces.length();
638 }
639 }
640 escape(builder,msg.substring(start));
641 }
642
643 private void escape(StringBuilder builder, String string)
644 {
645 for (int i = 0; i < string.length(); ++i)
646 {
647 char c = string.charAt(i);
648 if (Character.isISOControl(c))
649 {
650 if (c == '\n')
651 {
652 builder.append('|');
653 }
654 else if (c == '\r')
655 {
656 builder.append('<');
657 }
658 else
659 {
660 builder.append('?');
661 }
662 }
663 else
664 {
665 builder.append(c);
666 }
667 }
668 }
669
670 private void format(StringBuilder buffer, Throwable thrown)
671 {
672 if (thrown == null)
673 {
674 buffer.append("null");
675 }
676 else
677 {
678 buffer.append(EOL);
679 format(buffer,thrown.toString());
680 StackTraceElement[] elements = thrown.getStackTrace();
681 for (int i = 0; elements != null && i < elements.length; i++)
682 {
683 buffer.append(EOL).append("\tat ");
684 format(buffer,elements[i].toString());
685 }
686
687 Throwable cause = thrown.getCause();
688 if (cause != null && cause != thrown)
689 {
690 buffer.append(EOL).append("Caused by: ");
691 format(buffer,cause);
692 }
693 }
694 }
695
696
697
698
699
700 @Override
701 protected Logger newLogger(String fullname)
702 {
703 StdErrLog logger = new StdErrLog(fullname);
704
705 logger.setPrintLongNames(_printLongNames);
706 logger._stderr = this._stderr;
707
708
709 if (_level!=_configuredLevel)
710 logger._level=_level;
711
712 return logger;
713 }
714
715 @Override
716 public String toString()
717 {
718 StringBuilder s = new StringBuilder();
719 s.append("StdErrLog:");
720 s.append(_name);
721 s.append(":LEVEL=");
722 switch (_level)
723 {
724 case LEVEL_ALL:
725 s.append("ALL");
726 break;
727 case LEVEL_DEBUG:
728 s.append("DEBUG");
729 break;
730 case LEVEL_INFO:
731 s.append("INFO");
732 break;
733 case LEVEL_WARN:
734 s.append("WARN");
735 break;
736 default:
737 s.append("?");
738 break;
739 }
740 return s.toString();
741 }
742
743 public static void setProperties(Properties props)
744 {
745 __props.clear();
746 __props.putAll(props);
747 }
748
749 public void ignore(Throwable ignored)
750 {
751 if (_level <= LEVEL_ALL)
752 {
753 StringBuilder buffer = new StringBuilder(64);
754 format(buffer,":IGNORED:","",ignored);
755 (_stderr==null?System.err:_stderr).println(buffer);
756 }
757 }
758 }