KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > utils > ListingErrorHandler


1 /*
2  * Copyright 2000-2004 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 /*
17  * $Id: ListingErrorHandler.java,v 1.7 2004/02/17 04:21:14 minchau Exp $
18  */

19
20 package org.apache.xml.utils;
21
22 import java.io.BufferedReader JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.InputStreamReader JavaDoc;
25 import java.io.PrintWriter JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.URLConnection JavaDoc;
28
29 import javax.xml.transform.ErrorListener JavaDoc;
30 import javax.xml.transform.SourceLocator JavaDoc;
31 import javax.xml.transform.TransformerException JavaDoc;
32
33 import org.apache.xml.res.XMLErrorResources;
34 import org.apache.xml.res.XMLMessages;
35
36 import org.xml.sax.ErrorHandler JavaDoc;
37 import org.xml.sax.SAXException JavaDoc;
38 import org.xml.sax.SAXParseException JavaDoc;
39
40
41 /**
42  * Sample implementation of similar SAX ErrorHandler and JAXP ErrorListener.
43  *
44  * <p>This implementation is suitable for various use cases, and
45  * provides some basic configuration API's as well to control
46  * when we re-throw errors, etc.</p>
47  *
48  * @author shane_curcuru@us.ibm.com
49  * @version $Id: ListingErrorHandler.java,v 1.7 2004/02/17 04:21:14 minchau Exp $
50  * @xsl.usage general
51  */

52 public class ListingErrorHandler implements ErrorHandler JavaDoc, ErrorListener JavaDoc
53 {
54     protected PrintWriter JavaDoc m_pw = null;
55   
56
57     /**
58      * Constructor ListingErrorHandler; user-supplied PrintWriter.
59      */

60     public ListingErrorHandler(PrintWriter JavaDoc pw)
61     {
62         if (null == pw)
63             throw new NullPointerException JavaDoc(XMLMessages.createXMLMessage(XMLErrorResources.ER_ERRORHANDLER_CREATED_WITH_NULL_PRINTWRITER, null));
64             // "ListingErrorHandler created with null PrintWriter!");
65

66         m_pw = pw;
67     }
68
69     /**
70      * Constructor ListingErrorHandler; uses System.err.
71      */

72     public ListingErrorHandler()
73     {
74         m_pw = new PrintWriter JavaDoc(System.err, true);
75     }
76
77
78     /* ======== Implement org.xml.sax.ErrorHandler ======== */
79     /**
80      * Receive notification of a warning.
81      *
82      * <p>SAX parsers will use this method to report conditions that
83      * are not errors or fatal errors as defined by the XML 1.0
84      * recommendation. The default behaviour is to take no action.</p>
85      *
86      * <p>The SAX parser must continue to provide normal parsing events
87      * after invoking this method: it should still be possible for the
88      * application to process the document through to the end.</p>
89      *
90      * <p>Filters may use this method to report other, non-XML warnings
91      * as well.</p>
92      *
93      * @param exception The warning information encapsulated in a
94      * SAX parse exception.
95      * @exception org.xml.sax.SAXException Any SAX exception, possibly
96      * wrapping another exception; only if setThrowOnWarning is true.
97      * @see org.xml.sax.SAXParseException
98      */

99     public void warning (SAXParseException JavaDoc exception)
100         throws SAXException JavaDoc
101     {
102         logExceptionLocation(m_pw, exception);
103         // Note: should we really call .toString() below, since
104
// sometimes the message is not properly set?
105
m_pw.println("warning: " + exception.getMessage());
106         m_pw.flush();
107
108         if (getThrowOnWarning())
109             throw exception;
110     }
111     
112     
113     /**
114      * Receive notification of a recoverable error.
115      *
116      * <p>This corresponds to the definition of "error" in section 1.2
117      * of the W3C XML 1.0 Recommendation. For example, a validating
118      * parser would use this callback to report the violation of a
119      * validity constraint. The default behaviour is to take no
120      * action.</p>
121      *
122      * <p>The SAX parser must continue to provide normal parsing events
123      * after invoking this method: it should still be possible for the
124      * application to process the document through to the end. If the
125      * application cannot do so, then the parser should report a fatal
126      * error even if the XML 1.0 recommendation does not require it to
127      * do so.</p>
128      *
129      * <p>Filters may use this method to report other, non-XML errors
130      * as well.</p>
131      *
132      * @param exception The error information encapsulated in a
133      * SAX parse exception.
134      * @exception org.xml.sax.SAXException Any SAX exception, possibly
135      * wrapping another exception; only if setThrowOnErroris true.
136      * @see org.xml.sax.SAXParseException
137      */

138     public void error (SAXParseException JavaDoc exception)
139         throws SAXException JavaDoc
140     {
141         logExceptionLocation(m_pw, exception);
142         m_pw.println("error: " + exception.getMessage());
143         m_pw.flush();
144
145         if (getThrowOnError())
146             throw exception;
147     }
148     
149     
150     /**
151      * Receive notification of a non-recoverable error.
152      *
153      * <p>This corresponds to the definition of "fatal error" in
154      * section 1.2 of the W3C XML 1.0 Recommendation. For example, a
155      * parser would use this callback to report the violation of a
156      * well-formedness constraint.</p>
157      *
158      * <p>The application must assume that the document is unusable
159      * after the parser has invoked this method, and should continue
160      * (if at all) only for the sake of collecting addition error
161      * messages: in fact, SAX parsers are free to stop reporting any
162      * other events once this method has been invoked.</p>
163      *
164      * @param exception The error information encapsulated in a
165      * SAX parse exception.
166      * @exception org.xml.sax.SAXException Any SAX exception, possibly
167      * wrapping another exception; only if setThrowOnFatalError is true.
168      * @see org.xml.sax.SAXParseException
169      */

170     public void fatalError (SAXParseException JavaDoc exception)
171         throws SAXException JavaDoc
172     {
173         logExceptionLocation(m_pw, exception);
174         m_pw.println("fatalError: " + exception.getMessage());
175         m_pw.flush();
176
177         if (getThrowOnFatalError())
178             throw exception;
179     }
180
181
182     /* ======== Implement javax.xml.transform.ErrorListener ======== */
183
184     /**
185      * Receive notification of a warning.
186      *
187      * <p>{@link javax.xml.transform.Transformer} can use this method to report
188      * conditions that are not errors or fatal errors. The default behaviour
189      * is to take no action.</p>
190      *
191      * <p>After invoking this method, the Transformer must continue with
192      * the transformation. It should still be possible for the
193      * application to process the document through to the end.</p>
194      *
195      * @param exception The warning information encapsulated in a
196      * transformer exception.
197      *
198      * @throws javax.xml.transform.TransformerException only if
199      * setThrowOnWarning is true.
200      *
201      * @see javax.xml.transform.TransformerException
202      */

203     public void warning(TransformerException JavaDoc exception)
204         throws TransformerException JavaDoc
205     {
206         logExceptionLocation(m_pw, exception);
207         m_pw.println("warning: " + exception.getMessage());
208         m_pw.flush();
209
210         if (getThrowOnWarning())
211             throw exception;
212     }
213
214     /**
215      * Receive notification of a recoverable error.
216      *
217      * <p>The transformer must continue to try and provide normal transformation
218      * after invoking this method. It should still be possible for the
219      * application to process the document through to the end if no other errors
220      * are encountered.</p>
221      *
222      * @param exception The error information encapsulated in a
223      * transformer exception.
224      *
225      * @throws javax.xml.transform.TransformerException only if
226      * setThrowOnError is true.
227      *
228      * @see javax.xml.transform.TransformerException
229      */

230     public void error(TransformerException JavaDoc exception)
231         throws TransformerException JavaDoc
232     {
233         logExceptionLocation(m_pw, exception);
234         m_pw.println("error: " + exception.getMessage());
235         m_pw.flush();
236
237         if (getThrowOnError())
238             throw exception;
239     }
240
241     /**
242      * Receive notification of a non-recoverable error.
243      *
244      * <p>The transformer must continue to try and provide normal transformation
245      * after invoking this method. It should still be possible for the
246      * application to process the document through to the end if no other errors
247      * are encountered, but there is no guarantee that the output will be
248      * useable.</p>
249      *
250      * @param exception The error information encapsulated in a
251      * transformer exception.
252      *
253      * @throws javax.xml.transform.TransformerException only if
254      * setThrowOnError is true.
255      *
256      * @see javax.xml.transform.TransformerException
257      */

258     public void fatalError(TransformerException JavaDoc exception)
259         throws TransformerException JavaDoc
260     {
261         logExceptionLocation(m_pw, exception);
262         m_pw.println("error: " + exception.getMessage());
263         m_pw.flush();
264
265         if (getThrowOnError())
266             throw exception;
267     }
268
269
270
271     /* ======== Implement worker methods ======== */
272
273
274     /**
275      * Print out location information about the exception.
276      *
277      * Cribbed from DefaultErrorHandler.printLocation()
278      * @param pw PrintWriter to send output to
279      * @param exception TransformerException or SAXParseException
280      * to log information about
281      */

282     public static void logExceptionLocation(PrintWriter JavaDoc pw, Throwable JavaDoc exception)
283     {
284         if (null == pw)
285             pw = new PrintWriter JavaDoc(System.err, true);
286         
287         SourceLocator JavaDoc locator = null;
288         Throwable JavaDoc cause = exception;
289
290         // Try to find the locator closest to the cause.
291
do
292         {
293             // Find the current locator, if one present
294
if(cause instanceof SAXParseException JavaDoc)
295             {
296                 // A SAXSourceLocator is a Xalan helper class
297
// that implements both a SourceLocator and a SAX Locator
298
//@todo check that the new locator actually has
299
// as much or more information as the
300
// current one already does
301
locator = new SAXSourceLocator((SAXParseException JavaDoc)cause);
302             }
303             else if (cause instanceof TransformerException JavaDoc)
304             {
305                 SourceLocator JavaDoc causeLocator = ((TransformerException JavaDoc)cause).getLocator();
306                 if(null != causeLocator)
307                 {
308                     locator = causeLocator;
309                 }
310             }
311             
312             // Then walk back down the chain of exceptions
313
if(cause instanceof TransformerException JavaDoc)
314                 cause = ((TransformerException JavaDoc)cause).getCause();
315             else if(cause instanceof WrappedRuntimeException)
316                 cause = ((WrappedRuntimeException)cause).getException();
317             else if(cause instanceof SAXException JavaDoc)
318                 cause = ((SAXException JavaDoc)cause).getException();
319             else
320                 cause = null;
321         }
322         while(null != cause);
323
324         // Formatting note: mimic javac-like errors:
325
// path\filename:123: message-here
326
// systemId:L=1;C=2: message-here
327
if(null != locator)
328         {
329             String JavaDoc id = (locator.getPublicId() != locator.getPublicId())
330                       ? locator.getPublicId()
331                         : (null != locator.getSystemId())
332                           ? locator.getSystemId() : "SystemId-Unknown";
333
334             pw.print(id + ":Line=" + locator.getLineNumber()
335                              + ";Column=" + locator.getColumnNumber()+": ");
336             pw.println("exception:" + exception.getMessage());
337             pw.println("root-cause:"
338                        + ((null != cause) ? cause.getMessage() : "null"));
339             logSourceLine(pw, locator);
340         }
341         else
342         {
343             pw.print("SystemId-Unknown:locator-unavailable: ");
344             pw.println("exception:" + exception.getMessage());
345             pw.println("root-cause:"
346                        + ((null != cause) ? cause.getMessage() : "null"));
347         }
348     }
349
350
351     /**
352      * Print out the specific source line that caused the exception,
353      * if possible to load it.
354      *
355      * @author shane_curcuru@us.ibm.com
356      * @param pw PrintWriter to send output to
357      * @param locator Xalan wrapper for either a JAXP or a SAX
358      * source location object
359      */

360     public static void logSourceLine(PrintWriter JavaDoc pw, SourceLocator JavaDoc locator)
361     {
362         if (null == locator)
363             return;
364             
365         if (null == pw)
366             pw = new PrintWriter JavaDoc(System.err, true);
367
368         String JavaDoc url = locator.getSystemId();
369         // Bail immediately if we get SystemId-Unknown
370
//@todo future improvement: attempt to get resource
371
// from a publicId if possible
372
if (null == url)
373         {
374             pw.println("line: (No systemId; cannot read file)");
375             pw.println();
376             return;
377         }
378         
379         //@todo attempt to get DOM backpointer or other ids
380

381         try
382         {
383             int line = locator.getLineNumber();
384             int column = locator.getColumnNumber();
385             pw.println("line: " + getSourceLine(url, line));
386             StringBuffer JavaDoc buf = new StringBuffer JavaDoc("line: ");
387             for (int i = 1; i < column; i++)
388             {
389                 buf.append(' ');
390             }
391             buf.append('^');
392             pw.println(buf.toString());
393         }
394         catch (Exception JavaDoc e)
395         {
396             pw.println("line: logSourceLine unavailable due to: " + e.getMessage());
397             pw.println();
398         }
399     }
400
401
402     /**
403      * Return the specific source line that caused the exception,
404      * if possible to load it; allow exceptions to be thrown.
405      *
406      * @author shane_curcuru@us.ibm.com
407      */

408     protected static String JavaDoc getSourceLine(String JavaDoc sourceUrl, int lineNum)
409             throws Exception JavaDoc
410     {
411         URL JavaDoc url = null;
412         // Get a URL from the sourceUrl
413
try
414         {
415             // Try to get a URL from it as-is
416
url = new URL JavaDoc(sourceUrl);
417         }
418         catch (java.net.MalformedURLException JavaDoc mue)
419         {
420             int indexOfColon = sourceUrl.indexOf(':');
421             int indexOfSlash = sourceUrl.indexOf('/');
422             
423             if ((indexOfColon != -1)
424                 && (indexOfSlash != -1)
425                 && (indexOfColon < indexOfSlash))
426             {
427                 // The url is already absolute, but we could not get
428
// the system to form it, so bail
429
throw mue;
430             }
431             else
432             {
433                 // The url is relative, so attempt to get absolute
434
url = new URL JavaDoc(SystemIDResolver.getAbsoluteURI(sourceUrl));
435                 // If this fails, allow the exception to propagate
436
}
437         }
438         
439         String JavaDoc line = null;
440         InputStream JavaDoc is = null;
441         BufferedReader JavaDoc br = null;
442         try
443         {
444             // Open the URL and read to our specified line
445
URLConnection JavaDoc uc = url.openConnection();
446             is = uc.getInputStream();
447             br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is));
448
449             // Not the most efficient way, but it works
450
// (Feel free to patch to seek to the appropriate line)
451
for (int i = 1; i <= lineNum; i++)
452             {
453                 line = br.readLine();
454             }
455             
456         }
457         // Allow exceptions to propagate from here, but ensure
458
// streams are closed!
459
finally
460         {
461             br.close();
462             is.close();
463         }
464         
465         // Return whatever we found
466
return line;
467     }
468
469
470     /* ======== Implement settable properties ======== */
471
472     /**
473      * User-settable behavior: when to re-throw exceptions.
474      *
475      * <p>This allows per-instance configuration of
476      * ListingErrorHandlers. You can ask us to either throw
477      * an exception when we're called for various warning /
478      * error / fatalErrors, or simply log them and continue.</p>
479      *
480      * @param t if we should throw an exception on warnings
481      */

482     public void setThrowOnWarning(boolean b)
483     {
484         throwOnWarning = b;
485     }
486
487     /**
488      * User-settable behavior: when to re-throw exceptions.
489      *
490      * @return if we throw an exception on warnings
491      */

492     public boolean getThrowOnWarning()
493     {
494         return throwOnWarning;
495     }
496
497     /** If we should throw exception on warnings; default:false. */
498     protected boolean throwOnWarning = false;
499
500
501     /**
502      * User-settable behavior: when to re-throw exceptions.
503      *
504      * <p>This allows per-instance configuration of
505      * ListingErrorHandlers. You can ask us to either throw
506      * an exception when we're called for various warning /
507      * error / fatalErrors, or simply log them and continue.</p>
508      *
509      * <p>Note that the behavior of many parsers/transformers
510      * after an error is not necessarily defined!</p>
511      *
512      * @param t if we should throw an exception on errors
513      */

514     public void setThrowOnError(boolean b)
515     {
516         throwOnError = b;
517     }
518
519     /**
520      * User-settable behavior: when to re-throw exceptions.
521      *
522      * @return if we throw an exception on errors
523      */

524     public boolean getThrowOnError()
525     {
526         return throwOnError;
527     }
528
529     /** If we should throw exception on errors; default:true. */
530     protected boolean throwOnError = true;
531
532
533     /**
534      * User-settable behavior: when to re-throw exceptions.
535      *
536      * <p>This allows per-instance configuration of
537      * ListingErrorHandlers. You can ask us to either throw
538      * an exception when we're called for various warning /
539      * error / fatalErrors, or simply log them and continue.</p>
540      *
541      * <p>Note that the behavior of many parsers/transformers
542      * after a fatalError is not necessarily defined, most
543      * products will probably barf if you continue.</p>
544      *
545      * @param t if we should throw an exception on fatalErrors
546      */

547     public void setThrowOnFatalError(boolean b)
548     {
549         throwOnFatalError = b;
550     }
551
552     /**
553      * User-settable behavior: when to re-throw exceptions.
554      *
555      * @return if we throw an exception on fatalErrors
556      */

557     public boolean getThrowOnFatalError()
558     {
559         return throwOnFatalError;
560     }
561
562     /** If we should throw exception on fatalErrors; default:true. */
563     protected boolean throwOnFatalError = true;
564
565 }
566
Popular Tags