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