KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > uihandler > LogRecords


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
16  */

17
18 package org.netbeans.lib.uihandler;
19
20 import java.io.ByteArrayInputStream JavaDoc;
21 import java.io.EOFException JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.OutputStream JavaDoc;
25 import java.io.PushbackInputStream JavaDoc;
26 import java.io.SequenceInputStream JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collections JavaDoc;
29 import java.util.EnumMap JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.MissingResourceException JavaDoc;
34 import java.util.ResourceBundle JavaDoc;
35 import java.util.logging.Formatter JavaDoc;
36 import java.util.logging.Handler JavaDoc;
37 import java.util.logging.Level JavaDoc;
38 import java.util.logging.LogRecord JavaDoc;
39 import java.util.logging.Logger JavaDoc;
40 import java.util.logging.XMLFormatter JavaDoc;
41 import javax.xml.parsers.ParserConfigurationException JavaDoc;
42 import javax.xml.parsers.SAXParser JavaDoc;
43 import javax.xml.parsers.SAXParserFactory JavaDoc;
44 import org.xml.sax.Attributes JavaDoc;
45 import org.xml.sax.Locator JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47 import org.xml.sax.SAXParseException JavaDoc;
48 import org.xml.sax.helpers.DefaultHandler JavaDoc;
49
50 /** Can persist and read log records from streams.
51  *
52  * @author Jaroslav Tulach
53  */

54 public final class LogRecords {
55     private LogRecords() {
56     }
57
58     private static final Logger JavaDoc LOG = Logger.getLogger(LogRecords.class.getName());
59     
60     private static final Formatter JavaDoc FORMATTER = new XMLFormatter JavaDoc() {
61         public String JavaDoc formatMessage(LogRecord JavaDoc r) {
62             return super.formatMessage(r);
63         // return r.getMessage();
64
}
65     };
66     
67     public static void write(OutputStream JavaDoc os, LogRecord JavaDoc rec) throws IOException JavaDoc {
68         String JavaDoc formated = FORMATTER.format(rec);
69         byte[] arr = formated.getBytes("utf-8");
70         os.write(arr);
71     }
72
73     public static void scan(InputStream JavaDoc is, Handler JavaDoc h) throws IOException JavaDoc {
74         PushbackInputStream JavaDoc wrap = new PushbackInputStream JavaDoc(is, 32);
75         byte[] arr = new byte[5];
76         int len = wrap.read(arr);
77         if (len == -1) {
78             return;
79         }
80         wrap.unread(arr, 0, len);
81         
82         if (arr[0] == '<' &&
83             arr[1] == '?' &&
84             arr[2] == 'x' &&
85             arr[3] == 'm' &&
86             arr[4] == 'l'
87         ) {
88             is = wrap;
89         } else {
90             ByteArrayInputStream JavaDoc header = new ByteArrayInputStream JavaDoc(
91     "<?xml version='1.0' encoding='UTF-8'?><uigestures version='1.0'>".getBytes()
92             );
93             ByteArrayInputStream JavaDoc footer = new ByteArrayInputStream JavaDoc(
94                 "</uigestures>".getBytes()
95             );
96             is = new SequenceInputStream JavaDoc(
97                 new SequenceInputStream JavaDoc(header, wrap),
98                 footer
99             );
100         }
101         
102         SAXParserFactory JavaDoc f = SAXParserFactory.newInstance();
103         f.setValidating(false);
104         SAXParser JavaDoc p;
105         try {
106             f.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); // NOI18N
107
p = f.newSAXParser();
108         } catch (ParserConfigurationException JavaDoc ex) {
109             LOG.log(Level.SEVERE, null, ex);
110             throw (IOException JavaDoc)new IOException JavaDoc(ex.getMessage()).initCause(ex);
111         } catch (SAXException JavaDoc ex) {
112             LOG.log(Level.SEVERE, null, ex);
113             throw (IOException JavaDoc)new IOException JavaDoc(ex.getMessage()).initCause(ex);
114         }
115         
116         Parser JavaDoc parser = new Parser JavaDoc(h);
117         try {
118             p.parse(is, parser);
119         } catch (SAXException JavaDoc ex) {
120             LOG.log(Level.WARNING, null, ex);
121             throw (IOException JavaDoc)new IOException JavaDoc(ex.getMessage()).initCause(ex);
122         }
123     }
124     
125     
126     public static LogRecord JavaDoc read(InputStream JavaDoc is) throws IOException JavaDoc {
127         int[] end = new int[1];
128         byte[] data = readXMLBlock(is, end);
129         if (data == null) {
130             return null;
131         }
132         
133         String JavaDoc s = new String JavaDoc(data, 0, end[0]);
134         
135         // in case the block is not ours
136
if (s.indexOf("record>") == -1) { // NOI18N
137
Logger.getLogger(LogRecords.class.getName()).info("Skipping: " + s); // NOI18N
138
data = readXMLBlock(is, end);
139             if (data == null) {
140                 return null;
141             }
142             s = new String JavaDoc(data, 0, end[0]);
143         }
144         
145         s = s.replaceAll("&amp;", "&").replaceAll("&gt;", ">")
146             .replaceAll("&lt;", "<");
147
148         String JavaDoc millis = content(s, "millis", true);
149         String JavaDoc seq = content(s, "sequence", true);
150         String JavaDoc lev = content(s, "level", true);
151         String JavaDoc thread = content(s, "thread", true);
152         String JavaDoc msg = content(s, "message", true);
153         String JavaDoc key = content(s, "key", false);
154         String JavaDoc catalog = content(s, "catalog", false);
155         
156         LogRecord JavaDoc r = new LogRecord JavaDoc(parseLevel(lev), key != null && catalog != null ? key : msg);
157         r.setThreadID(Integer.parseInt(thread));
158         r.setSequenceNumber(Long.parseLong(seq));
159         r.setMillis(Long.parseLong(millis));
160         if (catalog != null && key != null) {
161             r.setResourceBundleName(catalog);
162             if (!"<null>".equals(catalog)) { // NOI18N
163
try {
164                     ResourceBundle JavaDoc b = ResourceBundle.getBundle(catalog);
165                     b.getObject(key);
166                     // ok, the key is there
167
r.setResourceBundle(b);
168                 } catch (MissingResourceException JavaDoc e) {
169                     LOG.log(Level.CONFIG, "Cannot find resource bundle for {0} and key {1}", new Object JavaDoc[] { catalog, key });
170                     r.setResourceBundle(new FakeBundle(key, msg));
171                 }
172             }
173         
174             int[] paramFrom = new int[1];
175             List JavaDoc<String JavaDoc> params = new ArrayList JavaDoc<String JavaDoc>();
176             for (;;) {
177                 String JavaDoc p = content(s, "param", false, paramFrom);
178                 if (p == null) {
179                     break;
180                 }
181                 params.add(p);
182             }
183             
184             r.setParameters(params.toArray());
185         }
186         
187         String JavaDoc exception = content(s, "exception", false);
188         if (exception != null) {
189             FakeException currentEx = new FakeException(null);
190             int[] stackIndex = new int[1];
191             currentEx.message = content(exception, "message", true, stackIndex);
192             
193             if (currentEx.message.equals(r.getMessage())) {
194                 // probably parsed message inside the exception block
195
r.setMessage(null);
196             }
197             
198             for (;;) {
199                 String JavaDoc frame = content(exception, "frame", false, stackIndex);
200                 if (frame == null) {
201                     break;
202                 }
203                 
204                 String JavaDoc clazz = content(frame, "class", true);
205                 String JavaDoc method = content(frame, "method", false);
206                 String JavaDoc line = content(frame, "line", false);
207                 LOG.finer("StackTrace " + clazz + "." + method + ":" + line);
208                 StackTraceElement JavaDoc elem = new StackTraceElement JavaDoc(
209                     clazz,
210                     method,
211                     null,
212                     line == null ? -1 : Integer.parseInt(line)
213                 );
214                 currentEx.trace.add(elem);
215             }
216             r.setThrown(currentEx);
217         }
218         
219         return r;
220     }
221
222     static Level JavaDoc parseLevel(String JavaDoc lev) {
223         return "USER".equals(lev) ? Level.SEVERE : Level.parse(lev);
224     }
225     private static String JavaDoc content(String JavaDoc where, String JavaDoc what, boolean fail) throws IOException JavaDoc {
226         return content(where, what, fail, new int[1]);
227     }
228     private static String JavaDoc content(String JavaDoc where, String JavaDoc what, boolean fail, int[] from) throws IOException JavaDoc {
229         int indx = where.indexOf("<" + what + ">", from[0]);
230         if (indx == -1) {
231             if (fail) {
232                 throw new IOException JavaDoc("Not found: <" + what + "> inside of:\n"+ where); // NOI18N
233
} else {
234                 return null;
235             }
236         }
237         int begin = indx + what.length() + 2;
238         
239         int end = where.indexOf("</" + what + ">", indx);
240         if (indx == -1) {
241             throw new IOException JavaDoc("Not found: </" + what + "> inside of:\n"+ where); // NOI18N
242
}
243         from[0] = end;
244         
245         return where.substring(begin, end);
246     }
247     
248     private static byte[] readXMLBlock(InputStream JavaDoc is, int[] len) throws IOException JavaDoc {
249         byte[] arr = new byte[4096 * 12];
250         int index = 0;
251         
252         for (;;) {
253             int ch = is.read();
254             if (ch == -1) {
255                 return null;
256             }
257
258             if (ch == '<') {
259                 arr[index++] = '<';
260                 break;
261             }
262         }
263         
264         int depth = 0;
265         boolean inTag = true;
266         boolean seenSlash = false;
267         boolean seenQuest = false;
268         int uigestures = 0;
269         for (;;) {
270             if (!inTag && depth == 0) {
271                 break;
272             }
273             
274             int ch = is.read();
275             if (ch == -1) {
276                 throw new EOFException JavaDoc();
277             }
278             if (index == arr.length) {
279                 throw new EOFException JavaDoc("Buffer size " + arr.length + " exceeded"); // NOI18N
280
}
281             
282             arr[index++] = (byte)ch;
283             
284             if (inTag) {
285                 switch (uigestures) {
286                     case 0: if (ch == 'u') uigestures = 1; else uigestures = 0; break;
287                     case 1: if (ch == 'i') uigestures = 2; else uigestures = 0; break;
288                     case 2: if (ch == 'g') uigestures = 3; else uigestures = 0; break;
289                     case 3: if (ch == 'e') uigestures = 4; else uigestures = 0; break;
290                     case 4: if (ch == 's') uigestures = 5; else uigestures = 0; break;
291                     case 5: if (ch == 't') uigestures = 6; else uigestures = 0; break;
292                     case 6: if (ch == 'u') uigestures = 7; else uigestures = 0; break;
293                     case 7: if (ch == 'r') uigestures = 8; else uigestures = 0; break;
294                     case 8: if (ch == 'e') uigestures = 9; else uigestures = 0; break;
295                     case 9: if (ch == 's') uigestures = 10; else uigestures = 0; break;
296                     case 10: // ok, stay at 10
297
}
298                 
299                 if (ch == '?') {
300                     seenQuest = true;
301                 } else if (ch == '/') {
302                     seenSlash = true;
303                 } else if (ch == '>') {
304                     inTag = false;
305                     if (uigestures == 10) {
306                         // header found, restart
307
return readXMLBlock(is, len);
308                     }
309                     if (seenSlash) {
310                         depth--;
311                     } else if (seenQuest) {
312               // depth--;
313
} else {
314                         depth++;
315                     }
316                 }
317             } else {
318                 if (ch == '<') {
319                     inTag = true;
320                     seenSlash = false;
321                     seenQuest = false;
322                     uigestures = 0;
323                 }
324             }
325         }
326         len[0] = index;
327         return arr;
328     }
329     
330     private static final class Parser extends DefaultHandler JavaDoc {
331         private Handler JavaDoc callback;
332         private static enum Elem {
333             UIGESTURES, RECORD, DATE, MILLIS, SEQUENCE, LEVEL, THREAD,
334             MESSAGE, KEY, PARAM, FRAME, CLASS, METHOD, LOGGER, EXCEPTION, LINE,
335             CATALOG;
336                 
337             public String JavaDoc parse(Map JavaDoc<Elem,String JavaDoc> values) {
338                 String JavaDoc v = values.get(this);
339                 return v;
340             }
341         }
342         private Map JavaDoc<Elem,String JavaDoc> values = new EnumMap JavaDoc<Elem,String JavaDoc>(Elem.class);
343         private Elem current;
344         private FakeException currentEx;
345         private List JavaDoc<String JavaDoc> params;
346         private StringBuilder JavaDoc chars = new StringBuilder JavaDoc();
347         
348         public Parser(Handler JavaDoc c) {
349             this.callback = c;
350         }
351         
352         
353         public void setDocumentLocator(Locator JavaDoc locator) {
354         }
355
356         public void startDocument() throws SAXException JavaDoc {
357         }
358
359         public void endDocument() throws SAXException JavaDoc {
360             callback.flush();
361         }
362
363         public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) throws SAXException JavaDoc {
364         }
365
366         public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc {
367         }
368
369         public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc {
370             if (LOG.isLoggable(Level.FINEST)) {
371                 LOG.log(Level.FINEST, "uri: {0} localName: {1} qName: {2} atts: {3}", new Object JavaDoc[] { uri, localName, qName, atts });
372             }
373
374             try {
375                 current = Elem.valueOf(qName.toUpperCase());
376                 if (current == Elem.EXCEPTION) {
377                     currentEx = new FakeException(new EnumMap JavaDoc<Elem,String JavaDoc>(values));
378                 }
379             } catch (IllegalArgumentException JavaDoc ex) {
380                 LOG.log(Level.FINE, "Uknown tag " + qName, ex);
381                 current = null;
382             }
383             chars = new StringBuilder JavaDoc();
384         }
385
386         public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
387             if (current != null) {
388                 String JavaDoc v = chars.toString();
389                 values.put(current, v);
390                 if (current == Elem.PARAM) {
391                     if (params == null) {
392                         params = new ArrayList JavaDoc<String JavaDoc>();
393                     }
394                     params.add(v);
395                     if (params.size() > 500) {
396                         LOG.severe("Too long params when reading a record. Deleting few."); // NOI18N
397
for (String JavaDoc p : params) {
398                             LOG.fine(p);
399                         }
400                         params.clear();
401                     }
402                 }
403             }
404             current = null;
405             chars = new StringBuilder JavaDoc();
406             
407             if (currentEx != null && currentEx.values != null) {
408                 if ("frame".equals(qName)) { // NOI18N
409
String JavaDoc line = Elem.LINE.parse(values);
410                     StackTraceElement JavaDoc elem = new StackTraceElement JavaDoc(
411                         Elem.CLASS.parse(values),
412                         Elem.METHOD.parse(values),
413                         null,
414                         line == null ? -1 : Integer.parseInt(line)
415                     );
416                     currentEx.trace.add(elem);
417                     values.remove(Elem.CLASS);
418                     values.remove(Elem.METHOD);
419                     values.remove(Elem.LINE);
420                 }
421                 if ("exception".equals(qName)) {
422                     currentEx.message = values.get(Elem.MESSAGE);
423                     values = currentEx.values;
424                     currentEx.values = null;
425                 }
426                 return;
427             }
428             
429             if ("record".equals(qName)) { // NOI18N
430
String JavaDoc millis = Elem.MILLIS.parse(values);
431                 String JavaDoc seq = Elem.SEQUENCE.parse(values);
432                 String JavaDoc lev = Elem.LEVEL.parse(values);
433                 String JavaDoc thread = Elem.THREAD.parse(values);
434                 String JavaDoc msg = Elem.MESSAGE.parse(values);
435                 String JavaDoc key = Elem.KEY.parse(values);
436                 String JavaDoc catalog = Elem.CATALOG.parse(values);
437                 
438                 LogRecord JavaDoc r = new LogRecord JavaDoc(parseLevel(lev), key != null && catalog != null ? key : msg);
439                 r.setThreadID(Integer.parseInt(thread));
440                 r.setSequenceNumber(Long.parseLong(seq));
441                 r.setMillis(Long.parseLong(millis));
442                 r.setResourceBundleName(key);
443                 if (catalog != null && key != null) {
444                     r.setResourceBundleName(catalog);
445                     if (!"<null>".equals(catalog)) { // NOI18N
446
try {
447                             ResourceBundle JavaDoc b = ResourceBundle.getBundle(catalog);
448                             b.getObject(key);
449                             // ok, the key is there
450
r.setResourceBundle(b);
451                         } catch (MissingResourceException JavaDoc e) {
452                             LOG.log(Level.CONFIG, "Cannot find resource bundle {0} for key {1}", new Object JavaDoc[] { catalog, key });
453                             r.setResourceBundle(new FakeBundle(key, msg));
454                         }
455                     } else {
456                         LOG.log(Level.CONFIG, "Cannot find resource bundle <null> for key {1}", key);
457                     }
458                     if (params != null) {
459                         r.setParameters(params.toArray());
460                     }
461                 }
462                 if (currentEx != null) {
463                     r.setThrown(currentEx);
464                 }
465                 
466                 callback.publish(r);
467
468                 currentEx = null;
469                 params = null;
470                 values.clear();
471             }
472             
473         }
474
475         public void characters(char[] ch, int start, int length) throws SAXException JavaDoc {
476             chars.append(ch, start, length);
477         }
478
479         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException JavaDoc {
480         }
481
482         public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc {
483         }
484
485         public void skippedEntity(String JavaDoc name) throws SAXException JavaDoc {
486         }
487
488         public void fatalError(SAXParseException JavaDoc e) throws SAXException JavaDoc {
489             LOG.log(Level.FINE, null, e);
490         }
491         
492     }
493     
494     private static final class FakeBundle extends ResourceBundle JavaDoc {
495         private String JavaDoc key;
496         private String JavaDoc value;
497          
498         public FakeBundle(String JavaDoc key, String JavaDoc value) {
499             this.key = key;
500             this.value = value;
501         }
502
503     
504         protected Object JavaDoc handleGetObject(String JavaDoc arg0) {
505             if (key.equals(arg0)) {
506                 return value;
507             } else {
508                 return null;
509             }
510         }
511
512         public Enumeration JavaDoc<String JavaDoc> getKeys() {
513             return Collections.enumeration(Collections.singleton(key));
514         }
515     } // end of FakeBundle
516

517     private static final class FakeException extends Exception JavaDoc {
518         final List JavaDoc<StackTraceElement JavaDoc> trace = new ArrayList JavaDoc<StackTraceElement JavaDoc>();
519         Map JavaDoc<Parser.Elem JavaDoc,String JavaDoc> values;
520         String JavaDoc message;
521         
522         public FakeException(Map JavaDoc<Parser.Elem JavaDoc,String JavaDoc> values) {
523             this.values = values;
524         }
525        
526         public StackTraceElement JavaDoc[] getStackTrace() {
527             return trace.toArray(new StackTraceElement JavaDoc[0]);
528         }
529
530         public String JavaDoc getMessage() {
531             return message;
532         }
533     } // end of FakeException
534
}
535
Popular Tags