KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > StandardErrorListener


1 package net.sf.saxon;
2 import net.sf.saxon.expr.XPathContext;
3 import net.sf.saxon.om.NodeInfo;
4 import net.sf.saxon.style.StandardNames;
5 import net.sf.saxon.trace.InstructionInfo;
6 import net.sf.saxon.trace.InstructionInfoProvider;
7 import net.sf.saxon.trace.Location;
8 import net.sf.saxon.trans.DynamicError;
9 import net.sf.saxon.trans.XPathException;
10 import net.sf.saxon.type.ValidationException;
11 import org.xml.sax.SAXException JavaDoc;
12
13 import javax.xml.transform.ErrorListener JavaDoc;
14 import javax.xml.transform.SourceLocator JavaDoc;
15 import javax.xml.transform.TransformerException JavaDoc;
16 import javax.xml.transform.dom.DOMLocator JavaDoc;
17 import java.io.PrintStream JavaDoc;
18
19 /**
20   * <B>StandardErrorListener</B> is the standard error handler for XSLT processing
21   * errors, used if no other ErrorListener is nominated.
22   * @author Michael H. Kay
23   */

24
25 public class StandardErrorListener implements ErrorListener JavaDoc {
26
27     private int recoveryPolicy = Configuration.RECOVER_WITH_WARNINGS;
28     private int warningCount = 0;
29     protected transient PrintStream JavaDoc errorOutput = System.err;
30
31     public StandardErrorListener() {}
32
33     /**
34      * Make a clean copy of this ErrorListener. This is necessary because the
35      * standard error listener is stateful (it remembers how many errors there have been)
36      */

37
38     public StandardErrorListener makeAnother(int hostLanguage) {
39         return new StandardErrorListener();
40     }
41
42     // Note, when the standard error listener is used, a new
43
// one is created for each transformation, because it holds
44
// the recovery policy and the warning count.
45

46     /**
47     * Set output destination for error messages (default is System.err)
48     * @param writer The PrintStream to use for error messages
49     */

50
51     public void setErrorOutput(PrintStream JavaDoc writer) {
52         errorOutput = writer;
53     }
54
55     /**
56      * Get the error output stream
57      */

58
59     public PrintStream JavaDoc getErrorOutput() {
60         return errorOutput;
61     }
62
63     /**
64     * Set the recovery policy
65     */

66
67     public void setRecoveryPolicy(int policy) {
68         recoveryPolicy = policy;
69     }
70
71     /**
72      * Get the recovery policy
73      */

74
75     public int getRecoveryPolicy() {
76         return recoveryPolicy;
77     }
78
79     /**
80      * Receive notification of a warning.
81      *
82      * <p>Transformers can use this method to report conditions that
83      * are not errors or fatal errors. The default behaviour is to
84      * take no action.</p>
85      *
86      * <p>After invoking this method, the Transformer must continue with
87      * the transformation. It should still be possible for the
88      * application to process the document through to the end.</p>
89      *
90      * @param exception The warning information encapsulated in a
91      * transformer exception.
92      *
93      * @throws javax.xml.transform.TransformerException if the application
94      * chooses to discontinue the transformation.
95      *
96      * @see javax.xml.transform.TransformerException
97      */

98
99     public void warning(TransformerException JavaDoc exception)
100         throws TransformerException JavaDoc {
101
102         if (recoveryPolicy==Configuration.RECOVER_SILENTLY) {
103             // do nothing
104
return;
105         }
106
107         if (errorOutput == null) {
108             // can happen after deserialization
109
errorOutput = System.err;
110         }
111         String JavaDoc message = "";
112         if (exception.getLocator()!=null) {
113             message = getLocationMessage(exception) + "\n ";
114         }
115         message += wordWrap(getExpandedMessage(exception));
116
117         if (exception instanceof ValidationException) {
118             errorOutput.println("Validation error " + message);
119
120         } else {
121             errorOutput.println("Warning: " + message);
122             warningCount++;
123             if (warningCount > 25) {
124                 errorOutput.println("No more warnings will be displayed");
125                 recoveryPolicy = Configuration.RECOVER_SILENTLY;
126                 warningCount = 0;
127             }
128         }
129     }
130
131     /**
132      * Receive notification of a recoverable error.
133      *
134      * <p>The transformer must continue to provide normal parsing events
135      * after invoking this method. It should still be possible for the
136      * application to process the document through to the end.</p>
137      *
138      * <p>The action of the standard error listener depends on the
139      * recovery policy that has been set, which may be one of RECOVER_SILENTLY,
140      * RECOVER_WITH_WARNING, or DO_NOT_RECOVER
141      *
142      * @param exception The error information encapsulated in a
143      * transformer exception.
144      *
145      * @throws TransformerException if the application
146      * chooses to discontinue the transformation.
147      *
148      * @see TransformerException
149      */

150
151     public void error(TransformerException JavaDoc exception) throws TransformerException JavaDoc {
152         if (recoveryPolicy==Configuration.RECOVER_SILENTLY) {
153             // do nothing
154
return;
155         }
156         if (errorOutput == null) {
157             // can happen after deserialization
158
errorOutput = System.err;
159         }
160         String JavaDoc message = getLocationMessage(exception) +
161                          "\n " +
162                          wordWrap(getExpandedMessage(exception));
163
164         if (exception instanceof ValidationException) {
165             errorOutput.println("Validation error " + message);
166
167         } else if (recoveryPolicy==Configuration.RECOVER_WITH_WARNINGS) {
168             errorOutput.println("Recoverable error " + message);
169             warningCount++;
170             if (warningCount > 25) {
171                 errorOutput.println("No more warnings will be displayed");
172                 recoveryPolicy = Configuration.RECOVER_SILENTLY;
173                 warningCount = 0;
174             }
175         } else {
176             errorOutput.println("Recoverable error " + message);
177             errorOutput.println("Processing terminated because error recovery is disabled");
178             throw new DynamicError(exception);
179         }
180     }
181
182     /**
183      * Receive notification of a non-recoverable error.
184      *
185      * <p>The application must assume that the transformation cannot
186      * continue after the Transformer has invoked this method,
187      * and should continue (if at all) only to collect
188      * addition error messages. In fact, Transformers are free
189      * to stop reporting events once this method has been invoked.</p>
190      *
191      * @param exception The error information encapsulated in a
192      * transformer exception.
193      *
194      * @throws TransformerException if the application
195      * chooses to discontinue the transformation.
196      *
197      * @see TransformerException
198      */

199
200     public void fatalError(TransformerException JavaDoc exception) throws TransformerException JavaDoc {
201         if (exception instanceof XPathException && ((XPathException)exception).hasBeenReported()) {
202             // don't report the same error twice
203
return;
204         }
205         if (errorOutput == null) {
206             // can happen after deserialization
207
errorOutput = System.err;
208         }
209         String JavaDoc message = (exception instanceof ValidationException ?
210                             "Validation error " :
211                             "Error ") +
212                          getLocationMessage(exception) +
213                          "\n " +
214                          wordWrap(getExpandedMessage(exception));
215         errorOutput.println(message);
216         if (exception instanceof XPathException) {
217             // TODO: should mark errors as reported even when the user supplies their own error listener
218
((XPathException)exception).setHasBeenReported();
219         }
220     }
221
222     /**
223     * Get a string identifying the location of an error.
224     */

225
226     public static String JavaDoc getLocationMessage(TransformerException JavaDoc err) {
227         SourceLocator JavaDoc loc = err.getLocator();
228         while (loc == null) {
229             if (err.getException() instanceof TransformerException JavaDoc) {
230                 err = (TransformerException JavaDoc)err.getException();
231                 loc = err.getLocator();
232             } else if (err.getCause() instanceof TransformerException JavaDoc) {
233                 err = (TransformerException JavaDoc)err.getCause();
234                 loc = err.getLocator();
235             } else {
236                 return "";
237             }
238         }
239         XPathContext context = null;
240         if (err instanceof DynamicError) {
241             context = ((DynamicError)err).getXPathContext();
242         }
243         return getLocationMessage(loc, context);
244     }
245
246     private static String JavaDoc getLocationMessage(SourceLocator JavaDoc loc, XPathContext context) {
247         String JavaDoc locmessage = "";
248         String JavaDoc systemId = null;
249         int lineNumber = -1;
250         if (loc instanceof DOMLocator JavaDoc) {
251             locmessage += "at " + ((DOMLocator JavaDoc)loc).getOriginatingNode().getNodeName() + ' ';
252         } else if (loc instanceof NodeInfo) {
253             locmessage += "at " + ((NodeInfo)loc).getDisplayName() + ' ';
254         } else if (loc instanceof InstructionInfoProvider) {
255             String JavaDoc instructionName = getInstructionName(((InstructionInfoProvider)loc), context);
256             if (!"".equals(instructionName)) {
257                 locmessage += "at " + instructionName + ' ';
258             }
259             systemId = ((InstructionInfoProvider)loc).getInstructionInfo().getSystemId();
260             lineNumber = ((InstructionInfoProvider)loc).getInstructionInfo().getLineNumber();
261         }
262         if (lineNumber == -1) {
263             lineNumber = loc.getLineNumber();
264         }
265         if (lineNumber != -1) {
266             locmessage += "on line " + lineNumber + ' ';
267         }
268         if (loc.getColumnNumber() != -1) {
269             locmessage += "column " + loc.getColumnNumber() + ' ';
270         }
271         if (systemId == null) {
272             systemId = loc.getSystemId();
273         }
274         if (systemId != null) {
275             locmessage += "of " + systemId + ':';
276         }
277         return locmessage;
278     }
279
280     /**
281     * Get a string containing the message for this exception and all contained exceptions
282     */

283
284     public static String JavaDoc getExpandedMessage(TransformerException JavaDoc err) {
285
286         String JavaDoc code = null;
287         if (err instanceof XPathException) {
288             code = ((XPathException)err).getErrorCodeLocalPart();
289         } else if (err.getException() instanceof XPathException) {
290             code = ((XPathException)err.getException()).getErrorCodeLocalPart();
291         }
292         String JavaDoc message = "";
293         if (code != null) {
294             message = code;
295         }
296
297         Throwable JavaDoc e = err;
298         while (true) {
299             if (e == null) {
300                 break;
301             }
302             String JavaDoc next = e.getMessage();
303             if (next==null) next="";
304             if (next.startsWith("net.sf.saxon.trans.StaticError: ")) {
305                 next = next.substring(next.indexOf(": ") + 2);
306             }
307             if (!("TRaX Transform Exception".equals(next) || message.endsWith(next))) {
308                 if (!"".equals(message) && !message.trim().endsWith(":")) {
309                     message += ": ";
310                 }
311                 message += next;
312             }
313             if (e instanceof TransformerException JavaDoc) {
314                 e = ((TransformerException JavaDoc)e).getException();
315             } else if (e instanceof SAXException JavaDoc) {
316                 e = ((SAXException JavaDoc)e).getException();
317             } else {
318                 // e.printStackTrace();
319
break;
320             }
321         }
322
323         return message;
324     }
325
326     /**
327      * Extract a name identifying the instruction at which an error occurred
328      */

329
330     private static String JavaDoc getInstructionName(InstructionInfoProvider inst, XPathContext context) {
331         // TODO: subclass this for XSLT and XQuery
332
if (context==null) {
333             return "";
334         }
335         try {
336             InstructionInfo info = inst.getInstructionInfo();
337             int construct = info.getConstructType();
338             if (construct < 1024 &&
339                     construct != StandardNames.XSL_FUNCTION &&
340                     construct != StandardNames.XSL_TEMPLATE) {
341                 // it's a standard name
342
if (context.getController().getExecutable().getHostLanguage() == Configuration.XSLT) {
343                     return StandardNames.getDisplayName(construct);
344                 } else {
345                     String JavaDoc s = StandardNames.getDisplayName(construct);
346                     int colon = s.indexOf(':');
347                     if (colon > 0) {
348                         String JavaDoc local = s.substring(colon+1);
349                         if (local.equals("document")) {
350                             return "document node constructor";
351                         } else if (local.equals("text") || s.equals("value-of")) {
352                             return "text node constructor";
353                         } else if (local.equals("element")) {
354                             return "computed element constructor";
355                         } else if (local.equals("attribute")) {
356                             return "computed attribute constructor";
357                         }
358                     }
359                     return s;
360                 }
361             }
362             switch (construct) {
363                 case Location.LITERAL_RESULT_ELEMENT: {
364                     int fp = info.getObjectNameCode();
365                     String JavaDoc name = "element constructor";
366                     if (context != null) {
367                         name += " <" + context.getController().getNamePool().getDisplayName(fp) + '>';
368                     }
369                     return name;
370                 }
371                 case Location.LITERAL_RESULT_ATTRIBUTE: {
372                     int fp = info.getObjectNameCode();
373                     String JavaDoc name = "attribute constructor";
374                     if (context != null) {
375                         name += ' ' + context.getController().getNamePool().getDisplayName(fp) + "=\"{...}\"";
376                     }
377                     return name;
378                 }
379                 case StandardNames.XSL_FUNCTION: {
380                     int fp = info.getObjectNameCode();
381                     String JavaDoc name = "function";
382                     if (context != null) {
383                         name += ' ' + context.getController().getNamePool().getDisplayName(fp) + "()";
384                     }
385                     return name;
386                 }
387                 case StandardNames.XSL_TEMPLATE: {
388                     int fp = info.getObjectNameCode();
389                     String JavaDoc name = "template";
390                     if (context != null && fp != -1) {
391                         name += " name=\"" + context.getController().getNamePool().getDisplayName(fp) + '\"';
392                     }
393                     return name;
394                 }
395                 default:
396                     return "";
397             }
398
399         } catch (Exception JavaDoc err) {
400             return "";
401         }
402     }
403
404     /**
405      * Wordwrap an error message into lines of 72 characters or less (if possible)
406      */

407
408     private static String JavaDoc wordWrap(String JavaDoc message) {
409         int nl = message.indexOf('\n');
410         if (nl < 0) {
411             nl = message.length();
412         }
413         if (nl > 100) {
414             int i = 90;
415             while (message.charAt(i) != ' ' && i>0) {
416                 i--;
417             }
418             if (i>10) {
419                 return message.substring(0, i) + "\n " + wordWrap(message.substring(i+1));
420             } else {
421                 return message;
422             }
423         } else if (nl < message.length()) {
424             return message.substring(0, nl) + '\n' + wordWrap(message.substring(nl+1));
425         } else {
426             return message;
427         }
428     }
429
430
431 }
432
433 // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
434
// you may not use this file except in compliance with the License. You may obtain a copy of the
435
// License at http://www.mozilla.org/MPL/
436
//
437
// Software distributed under the License is distributed on an "AS IS" basis,
438
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
439
// See the License for the specific language governing rights and limitations under the License.
440
//
441
// The Original Code is: all this file.
442
//
443
// The Initial Developer of the Original Code is Michael H. Kay.
444
//
445
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
446
//
447
// Contributor(s):
448
// Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
449
//
450
Popular Tags