KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > logging > jdk > format > PatternParser


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.jboss.logging.jdk.format;
17
18 import java.text.DateFormat JavaDoc;
19 import java.text.SimpleDateFormat JavaDoc;
20 import java.util.Date JavaDoc;
21 import java.util.logging.LogRecord JavaDoc;
22
23 // Contributors: Nelson Minar <(nelson@monkey.org>
24
// Igor E. Poteryaev <jah@mail.ru>
25
// Reinhard Deschler <reinhard.deschler@web.de>
26

27 /**
28  * Most of the work of the {@link org.apache.log4j.PatternLayout} class
29  * is delegated to the PatternParser class.
30  * <p/>
31  * <p>It is this class that parses conversion patterns and creates
32  * a chained list of {@link OptionConverter OptionConverters}.
33  *
34  * @author <a HREF=mailto:"cakalijp@Maritz.com">James P. Cakalic</a>
35  * @author Ceki G&uuml;lc&uuml;
36  * @author Anders Kristensen
37  * @author Scott.Stark@jboss.org
38  * @version $Revision: 1958 $
39  */

40 public class PatternParser
41 {
42    public final static String JavaDoc LINE_SEP = System.getProperty("line.separator");
43
44    private static long startTime = System.currentTimeMillis();
45
46    private static final char ESCAPE_CHAR = '%';
47
48    private static final int LITERAL_STATE = 0;
49    private static final int CONVERTER_STATE = 1;
50    private static final int MINUS_STATE = 2;
51    private static final int DOT_STATE = 3;
52    private static final int MIN_STATE = 4;
53    private static final int MAX_STATE = 5;
54
55    static final int FULL_LOCATION_CONVERTER = 1000;
56    static final int METHOD_LOCATION_CONVERTER = 1001;
57    static final int CLASS_LOCATION_CONVERTER = 1002;
58    static final int LINE_LOCATION_CONVERTER = 1003;
59    static final int FILE_LOCATION_CONVERTER = 1004;
60
61    static final int RELATIVE_TIME_CONVERTER = 2000;
62    static final int THREAD_CONVERTER = 2001;
63    static final int LEVEL_CONVERTER = 2002;
64    static final int NDC_CONVERTER = 2003;
65    static final int MESSAGE_CONVERTER = 2004;
66    static final int THREAD_NAME_CONVERTER = 2005;
67
68    int state;
69    protected StringBuffer JavaDoc currentLiteral = new StringBuffer JavaDoc(32);
70    protected int patternLength;
71    protected int i;
72    PatternConverter head;
73    PatternConverter tail;
74    protected FormattingInfo formattingInfo = new FormattingInfo();
75    protected String JavaDoc pattern;
76
77    public PatternParser(String JavaDoc pattern)
78    {
79       this.pattern = pattern;
80       patternLength = pattern.length();
81       state = LITERAL_STATE;
82    }
83
84    private void addToList(PatternConverter pc)
85    {
86       if (head == null)
87       {
88          head = tail = pc;
89       }
90       else
91       {
92          tail.next = pc;
93          tail = pc;
94       }
95    }
96
97    protected String JavaDoc extractOption()
98    {
99       if ((i < patternLength) && (pattern.charAt(i) == '{'))
100       {
101          int end = pattern.indexOf('}', i);
102          if (end > i)
103          {
104             String JavaDoc r = pattern.substring(i + 1, end);
105             i = end + 1;
106             return r;
107          }
108       }
109       return null;
110    }
111
112
113    /**
114     * The option is expected to be in decimal and positive. In case of
115     * error, zero is returned.
116     */

117    protected int extractPrecisionOption()
118    {
119       String JavaDoc opt = extractOption();
120       int r = 0;
121       if (opt != null)
122       {
123          try
124          {
125             r = Integer.parseInt(opt);
126             if (r <= 0)
127             {
128                System.err.println("Precision option (" + opt + ") isn't a positive integer.");
129                r = 0;
130             }
131          }
132          catch (NumberFormatException JavaDoc e)
133          {
134             System.err.println("Category option '" + opt + "' not a decimal integer." + e.getMessage());
135          }
136       }
137       return r;
138    }
139
140    public PatternConverter parse()
141    {
142       char c;
143       i = 0;
144       while (i < patternLength)
145       {
146          c = pattern.charAt(i++);
147          switch (state)
148          {
149             case LITERAL_STATE:
150                // In literal state, the last char is always a literal.
151
if (i == patternLength)
152                {
153                   currentLiteral.append(c);
154                   continue;
155                }
156                if (c == ESCAPE_CHAR)
157                {
158                   // peek at the next char.
159
switch (pattern.charAt(i))
160                   {
161                      case ESCAPE_CHAR:
162                         currentLiteral.append(c);
163                         i++; // move pointer
164
break;
165                      case 'n':
166                         currentLiteral.append(LINE_SEP);
167                         i++; // move pointer
168
break;
169                      default:
170                         if (currentLiteral.length() != 0)
171                         {
172                            addToList(new LiteralPatternConverter(
173                               currentLiteral.toString()));
174                            //LogLog.debug("Parsed LITERAL converter: \""
175
// +currentLiteral+"\".");
176
}
177                         currentLiteral.setLength(0);
178                         currentLiteral.append(c); // append %
179
state = CONVERTER_STATE;
180                         formattingInfo.reset();
181                   }
182                }
183                else
184                {
185                   currentLiteral.append(c);
186                }
187                break;
188             case CONVERTER_STATE:
189                currentLiteral.append(c);
190                switch (c)
191                {
192                   case '-':
193                      formattingInfo.leftAlign = true;
194                      break;
195                   case '.':
196                      state = DOT_STATE;
197                      break;
198                   default:
199                      if (c >= '0' && c <= '9')
200                      {
201                         formattingInfo.min = c - '0';
202                         state = MIN_STATE;
203                      }
204                      else
205                         finalizeConverter(c);
206                } // switch
207
break;
208             case MIN_STATE:
209                currentLiteral.append(c);
210                if (c >= '0' && c <= '9')
211                   formattingInfo.min = formattingInfo.min * 10 + (c - '0');
212                else if (c == '.')
213                   state = DOT_STATE;
214                else
215                {
216                   finalizeConverter(c);
217                }
218                break;
219             case DOT_STATE:
220                currentLiteral.append(c);
221                if (c >= '0' && c <= '9')
222                {
223                   formattingInfo.max = c - '0';
224                   state = MAX_STATE;
225                }
226                else
227                {
228                   System.err.println("Error occured in position " + i
229                      + ".\n Was expecting digit, instead got char \"" + c + "\".");
230                   state = LITERAL_STATE;
231                }
232                break;
233             case MAX_STATE:
234                currentLiteral.append(c);
235                if (c >= '0' && c <= '9')
236                   formattingInfo.max = formattingInfo.max * 10 + (c - '0');
237                else
238                {
239                   finalizeConverter(c);
240                   state = LITERAL_STATE;
241                }
242                break;
243          } // switch
244
} // while
245
if (currentLiteral.length() != 0)
246       {
247          addToList(new LiteralPatternConverter(currentLiteral.toString()));
248          //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
249
}
250       return head;
251    }
252
253    protected void finalizeConverter(char c)
254    {
255       PatternConverter pc = null;
256       switch (c)
257       {
258          case 'c':
259             pc = new CategoryPatternConverter(formattingInfo,
260                extractPrecisionOption());
261             //LogLog.debug("CATEGORY converter.");
262
//formattingInfo.dump();
263
currentLiteral.setLength(0);
264             break;
265          case 'C':
266             pc = new ClassNamePatternConverter(formattingInfo,
267                extractPrecisionOption());
268             //LogLog.debug("CLASS_NAME converter.");
269
//formattingInfo.dump();
270
currentLiteral.setLength(0);
271             break;
272          case 'd':
273             String JavaDoc dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT;
274             DateFormat JavaDoc df;
275             String JavaDoc dOpt = extractOption();
276             if (dOpt != null)
277                dateFormatStr = dOpt;
278
279             if (dateFormatStr.equalsIgnoreCase(
280                AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT))
281                df = new ISO8601DateFormat();
282             else if (dateFormatStr.equalsIgnoreCase(
283                AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT))
284                df = new AbsoluteTimeDateFormat();
285             else if (dateFormatStr.equalsIgnoreCase(
286                AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT))
287                df = new DateTimeDateFormat();
288             else
289             {
290                try
291                {
292                   df = new SimpleDateFormat JavaDoc(dateFormatStr);
293                }
294                catch (IllegalArgumentException JavaDoc e)
295                {
296                   System.err.println("Could not instantiate SimpleDateFormat with " +
297                      dateFormatStr + ", ex=" + e.getMessage());
298                   df = new ISO8601DateFormat();
299                }
300             }
301             pc = new DatePatternConverter(formattingInfo, df);
302             //LogLog.debug("DATE converter {"+dateFormatStr+"}.");
303
//formattingInfo.dump();
304
currentLiteral.setLength(0);
305             break;
306          case 'F':
307             pc = new LocationPatternConverter(formattingInfo,
308                FILE_LOCATION_CONVERTER);
309             //LogLog.debug("File name converter.");
310
//formattingInfo.dump();
311
currentLiteral.setLength(0);
312             break;
313          case 'l':
314             pc = new LocationPatternConverter(formattingInfo,
315                FULL_LOCATION_CONVERTER);
316             //LogLog.debug("Location converter.");
317
//formattingInfo.dump();
318
currentLiteral.setLength(0);
319             break;
320          case 'L':
321             pc = new LocationPatternConverter(formattingInfo,
322                LINE_LOCATION_CONVERTER);
323             //LogLog.debug("LINE NUMBER converter.");
324
//formattingInfo.dump();
325
currentLiteral.setLength(0);
326             break;
327          case 'm':
328             pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
329             //LogLog.debug("MESSAGE converter.");
330
//formattingInfo.dump();
331
currentLiteral.setLength(0);
332             break;
333          case 'M':
334             pc = new LocationPatternConverter(formattingInfo,
335                METHOD_LOCATION_CONVERTER);
336             //LogLog.debug("METHOD converter.");
337
//formattingInfo.dump();
338
currentLiteral.setLength(0);
339             break;
340          case 'p':
341             pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER);
342             //LogLog.debug("LEVEL converter.");
343
//formattingInfo.dump();
344
currentLiteral.setLength(0);
345             break;
346          case 'r':
347             pc = new BasicPatternConverter(formattingInfo,
348                RELATIVE_TIME_CONVERTER);
349             //LogLog.debug("RELATIVE time converter.");
350
//formattingInfo.dump();
351
currentLiteral.setLength(0);
352             break;
353          case 't':
354             pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
355             //LogLog.debug("THREAD converter.");
356
//formattingInfo.dump();
357
currentLiteral.setLength(0);
358             break;
359             /*case 'u':
360             if(i < patternLength) {
361          char cNext = pattern.charAt(i);
362          if(cNext >= '0' && cNext <= '9') {
363            pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
364            LogLog.debug("USER converter ["+cNext+"].");
365            formattingInfo.dump();
366            currentLiteral.setLength(0);
367            i++;
368          }
369          else
370            System.err.println("Unexpected char" +cNext+" at position "+i);
371             }
372             break;*/

373          case 'x':
374             pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
375             //LogLog.debug("NDC converter.");
376
currentLiteral.setLength(0);
377             break;
378          case 'X':
379             String JavaDoc xOpt = extractOption();
380             pc = new MDCPatternConverter(formattingInfo, xOpt);
381             currentLiteral.setLength(0);
382             break;
383          default:
384             System.err.println("Unexpected char [" + c + "] at position " + i
385                + " in conversion patterrn.");
386             pc = new LiteralPatternConverter(currentLiteral.toString());
387             currentLiteral.setLength(0);
388       }
389
390       addConverter(pc);
391    }
392
393    protected void addConverter(PatternConverter pc)
394    {
395       currentLiteral.setLength(0);
396       // Add the pattern converter to the list.
397
addToList(pc);
398       // Next pattern is assumed to be a literal.
399
state = LITERAL_STATE;
400       // Reset formatting info
401
formattingInfo.reset();
402    }
403
404    // ---------------------------------------------------------------------
405
// PatternConverters
406
// ---------------------------------------------------------------------
407

408    private static class BasicPatternConverter extends PatternConverter
409    {
410       int type;
411
412       BasicPatternConverter(FormattingInfo formattingInfo, int type)
413       {
414          super(formattingInfo);
415          this.type = type;
416       }
417
418       public String JavaDoc convert(LogRecord JavaDoc event)
419       {
420          switch (type)
421          {
422             case RELATIVE_TIME_CONVERTER:
423                return (Long.toString(event.getMillis() - startTime));
424             case THREAD_CONVERTER:
425                StringBuffer JavaDoc tmp = new StringBuffer JavaDoc("tid(");
426                tmp.append(event.getThreadID());
427                tmp.append(')');
428                return tmp.toString();
429             case THREAD_NAME_CONVERTER:
430                // @todo figure how to map the thread id to its name
431
return "null";
432             case LEVEL_CONVERTER:
433                return event.getLevel().toString();
434             case NDC_CONVERTER:
435                return "NDC not supported";
436             case MESSAGE_CONVERTER:
437             {
438                return event.getMessage();
439             }
440             default:
441                return null;
442          }
443       }
444    }
445
446    private static class LiteralPatternConverter extends PatternConverter
447    {
448       private String JavaDoc literal;
449
450       LiteralPatternConverter(String JavaDoc value)
451       {
452          literal = value;
453       }
454
455       public
456       final void format(StringBuffer JavaDoc sbuf, LogRecord JavaDoc event)
457       {
458          sbuf.append(literal);
459       }
460
461       public String JavaDoc convert(LogRecord JavaDoc event)
462       {
463          return literal;
464       }
465    }
466
467    private static class DatePatternConverter extends PatternConverter
468    {
469       private DateFormat JavaDoc df;
470       private Date JavaDoc date;
471
472       DatePatternConverter(FormattingInfo formattingInfo, DateFormat JavaDoc df)
473       {
474          super(formattingInfo);
475          date = new Date JavaDoc();
476          this.df = df;
477       }
478
479       public String JavaDoc convert(LogRecord JavaDoc event)
480       {
481          date.setTime(event.getMillis());
482          String JavaDoc converted = null;
483          try
484          {
485             converted = df.format(date);
486          }
487          catch (Exception JavaDoc ex)
488          {
489             System.err.println("Error occured while converting date, " + ex.getMessage());
490          }
491          return converted;
492       }
493    }
494
495    /**
496     * @todo how can this functionality be restored
497     */

498    private static class MDCPatternConverter extends PatternConverter
499    {
500       private String JavaDoc key;
501
502       MDCPatternConverter(FormattingInfo formattingInfo, String JavaDoc key)
503       {
504          super(formattingInfo);
505          this.key = key;
506       }
507
508       public String JavaDoc convert(LogRecord JavaDoc event)
509       {
510          Object JavaDoc val = null; // event.getMDC(key);
511
if (val == null)
512          {
513             return null;
514          }
515          else
516          {
517             return val.toString();
518          }
519       }
520    }
521
522
523    private class LocationPatternConverter extends PatternConverter
524    {
525       int type;
526
527       LocationPatternConverter(FormattingInfo formattingInfo, int type)
528       {
529          super(formattingInfo);
530          this.type = type;
531       }
532
533       public String JavaDoc convert(LogRecord JavaDoc event)
534       {
535          switch (type)
536          {
537             case FULL_LOCATION_CONVERTER:
538                return "Class: " + event.getSourceClassName() + "." + event.getSourceMethodName();
539             case METHOD_LOCATION_CONVERTER:
540                return event.getSourceMethodName();
541             case LINE_LOCATION_CONVERTER:
542                return "0";
543             case FILE_LOCATION_CONVERTER:
544                return event.getSourceClassName();
545             default:
546                return null;
547          }
548       }
549    }
550
551    private static abstract class NamedPatternConverter extends PatternConverter
552    {
553       int precision;
554
555       NamedPatternConverter(FormattingInfo formattingInfo, int precision)
556       {
557          super(formattingInfo);
558          this.precision = precision;
559       }
560
561       abstract String JavaDoc getFullyQualifiedName(LogRecord JavaDoc event);
562
563       public String JavaDoc convert(LogRecord JavaDoc event)
564       {
565          String JavaDoc n = getFullyQualifiedName(event);
566          if (precision <= 0)
567             return n;
568          else
569          {
570             int len = n.length();
571
572             // We substract 1 from 'len' when assigning to 'end' to avoid out of
573
// bounds exception in return r.substring(end+1, len). This can happen if
574
// precision is 1 and the category name ends with a dot.
575
int end = len - 1;
576             for (int i = precision; i > 0; i--)
577             {
578                end = n.lastIndexOf('.', end - 1);
579                if (end == -1)
580                   return n;
581             }
582             return n.substring(end + 1, len);
583          }
584       }
585    }
586
587    private class ClassNamePatternConverter extends NamedPatternConverter
588    {
589
590       ClassNamePatternConverter(FormattingInfo formattingInfo, int precision)
591       {
592          super(formattingInfo, precision);
593       }
594
595       String JavaDoc getFullyQualifiedName(LogRecord JavaDoc event)
596       {
597          return event.getSourceClassName();
598       }
599    }
600
601    private class CategoryPatternConverter extends NamedPatternConverter
602    {
603
604       CategoryPatternConverter(FormattingInfo formattingInfo, int precision)
605       {
606          super(formattingInfo, precision);
607       }
608
609       String JavaDoc getFullyQualifiedName(LogRecord JavaDoc event)
610       {
611          return event.getLoggerName();
612       }
613    }
614
615 }
616
Popular Tags