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