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