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