KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > XMLErrorReporter


1 /*
2  * Copyright 1999-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 package org.apache.xerces.impl;
18
19 import java.util.Hashtable JavaDoc;
20 import java.util.Locale JavaDoc;
21
22 import org.apache.xerces.util.DefaultErrorHandler;
23 import org.apache.xerces.util.ErrorHandlerProxy;
24 import org.apache.xerces.util.MessageFormatter;
25 import org.apache.xerces.xni.XMLLocator;
26 import org.apache.xerces.xni.XNIException;
27 import org.apache.xerces.xni.parser.XMLComponent;
28 import org.apache.xerces.xni.parser.XMLComponentManager;
29 import org.apache.xerces.xni.parser.XMLConfigurationException;
30 import org.apache.xerces.xni.parser.XMLErrorHandler;
31 import org.apache.xerces.xni.parser.XMLParseException;
32 import org.xml.sax.ErrorHandler JavaDoc;
33
34 /**
35  * This class is a common element of all parser configurations and is
36  * used to report errors that occur. This component can be queried by
37  * parser components from the component manager using the following
38  * property ID:
39  * <pre>
40  * http://apache.org/xml/properties/internal/error-reporter
41  * </pre>
42  * <p>
43  * Errors are separated into domains that categorize a class of errors.
44  * In a parser configuration, the parser would register a
45  * <code>MessageFormatter</code> for each domain that is capable of
46  * localizing error messages and formatting them based on information
47  * about the error. Any parser component can invent new error domains
48  * and register additional message formatters to localize messages in
49  * those domains.
50  * <p>
51  * This component requires the following features and properties from the
52  * component manager that uses it:
53  * <ul>
54  * <li>http://apache.org/xml/properties/internal/error-handler</li>
55  * </ul>
56  * <p>
57  * This component can use the following features and properties but they
58  * are not required:
59  * <ul>
60  * <li>http://apache.org/xml/features/continue-after-fatal-error</li>
61  * </ul>
62  *
63  * @xerces.internal
64  *
65  * @see MessageFormatter
66  *
67  * @author Eric Ye, IBM
68  * @author Andy Clark, IBM
69  *
70  * @version $Id: XMLErrorReporter.java,v 1.16 2005/06/24 17:56:41 mrglavas Exp $
71  */

72 public class XMLErrorReporter
73     implements XMLComponent {
74
75     //
76
// Constants
77
//
78

79     // severity
80

81     /**
82      * Severity: warning. Warnings represent informational messages only
83      * that should not be considered serious enough to stop parsing or
84      * indicate an error in the document's validity.
85      */

86     public static final short SEVERITY_WARNING = 0;
87
88     /**
89      * Severity: error. Common causes of errors are document structure and/or
90      * content that that does not conform to the grammar rules specified for
91      * the document. These are typically validation errors.
92      */

93     public static final short SEVERITY_ERROR = 1;
94
95     /**
96      * Severity: fatal error. Fatal errors are errors in the syntax of the
97      * XML document or invalid byte sequences for a given encoding. The
98      * XML 1.0 Specification mandates that errors of this type are not
99      * recoverable.
100      * <p>
101      * <strong>Note:</strong> The parser does have a "continue after fatal
102      * error" feature but it should be used with extreme caution and care.
103      */

104     public static final short SEVERITY_FATAL_ERROR = 2;
105     
106     // feature identifiers
107

108     /** Feature identifier: continue after fatal error. */
109     protected static final String JavaDoc CONTINUE_AFTER_FATAL_ERROR =
110         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
111
112     // property identifiers
113

114     /** Property identifier: error handler. */
115     protected static final String JavaDoc ERROR_HANDLER =
116         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
117
118     // recognized features and properties
119

120     /** Recognized features. */
121     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
122         CONTINUE_AFTER_FATAL_ERROR,
123     };
124
125     /** Feature defaults. */
126     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
127         null,
128     };
129
130     /** Recognized properties. */
131     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
132         ERROR_HANDLER,
133     };
134
135     /** Property defaults. */
136     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
137         null,
138     };
139
140     //
141
// Data
142
//
143

144     /** The locale to be used to format error messages. */
145     protected Locale JavaDoc fLocale;
146
147     /** Mapping of Message formatters for domains. */
148     protected Hashtable JavaDoc fMessageFormatters;
149
150     /** Error handler. */
151     protected XMLErrorHandler fErrorHandler;
152
153     /** Document locator. */
154     protected XMLLocator fLocator;
155
156     /** Continue after fatal error feature. */
157     protected boolean fContinueAfterFatalError;
158
159     /**
160      * Default error handler. This error handler is only used in the
161      * absence of a registered error handler so that errors are not
162      * "swallowed" silently. This is one of the most common "problems"
163      * reported by users of the parser.
164      */

165     protected XMLErrorHandler fDefaultErrorHandler;
166     
167     /** A SAX proxy to the error handler contained in this error reporter. */
168     private ErrorHandler fSaxProxy = null;
169
170     //
171
// Constructors
172
//
173

174     /** Constructs an error reporter with a locator. */
175     public XMLErrorReporter() {
176
177         // REVISIT: [Q] Should the locator be passed to the reportError
178
// method? Otherwise, there is no way for a parser
179
// component to store information about where an
180
// error occurred so as to report it later.
181
//
182
// An example would be to record the location of
183
// IDREFs so that, at the end of the document, if
184
// there is no associated ID declared, the error
185
// could report the location information of the
186
// reference. -Ac
187
//
188
// NOTE: I added another reportError method that allows the
189
// caller to specify the location of the error being
190
// reported. -Ac
191

192         fMessageFormatters = new Hashtable JavaDoc();
193
194     } // <init>()
195

196     //
197
// Methods
198
//
199

200     /**
201      * Sets the current locale.
202      *
203      * @param locale The new locale.
204      */

205     public void setLocale(Locale JavaDoc locale) {
206         fLocale = locale;
207     } // setLocale(Locale)
208

209     /**
210      * Gets the current locale.
211      *
212      * @return the current Locale
213      */

214     public Locale JavaDoc getLocale() {
215         return fLocale ;
216     } // getLocale(): Locale
217

218     /**
219      * Sets the document locator.
220      *
221      * @param locator The locator.
222      */

223     public void setDocumentLocator(XMLLocator locator) {
224         fLocator = locator;
225     } // setDocumentLocator(XMLLocator)
226

227     /**
228      * Registers a message formatter for the specified domain.
229      * <p>
230      * <strong>Note:</strong> Registering a message formatter for a domain
231      * when there is already a formatter registered will cause the previous
232      * formatter to be lost. This method replaces any previously registered
233      * message formatter for the specified domain.
234      *
235      * @param domain
236      * @param messageFormatter
237      */

238     public void putMessageFormatter(String JavaDoc domain,
239                                     MessageFormatter messageFormatter) {
240         fMessageFormatters.put(domain, messageFormatter);
241     } // putMessageFormatter(String,MessageFormatter)
242

243     /**
244      * Returns the message formatter associated with the specified domain,
245      * or null if no message formatter is registered for that domain.
246      *
247      * @param domain The domain of the message formatter.
248      */

249     public MessageFormatter getMessageFormatter(String JavaDoc domain) {
250         return (MessageFormatter)fMessageFormatters.get(domain);
251     } // getMessageFormatter(String):MessageFormatter
252

253     /**
254      * Removes the message formatter for the specified domain and
255      * returns the removed message formatter.
256      *
257      * @param domain The domain of the message formatter.
258      */

259     public MessageFormatter removeMessageFormatter(String JavaDoc domain) {
260         return (MessageFormatter) fMessageFormatters.remove(domain);
261     } // removeMessageFormatter(String):MessageFormatter
262

263     /**
264      * Reports an error. The error message passed to the error handler
265      * is formatted for the locale by the message formatter installed
266      * for the specified error domain.
267      *
268      * @param domain The error domain.
269      * @param key The key of the error message.
270      * @param arguments The replacement arguments for the error message,
271      * if needed.
272      * @param severity The severity of the error.
273      *
274      * @see #SEVERITY_WARNING
275      * @see #SEVERITY_ERROR
276      * @see #SEVERITY_FATAL_ERROR
277      */

278     public void reportError(String JavaDoc domain, String JavaDoc key, Object JavaDoc[] arguments,
279                             short severity) throws XNIException {
280         reportError(fLocator, domain, key, arguments, severity);
281     } // reportError(String,String,Object[],short)
282

283     /**
284      * Reports an error at a specific location.
285      *
286      * @param location The error location.
287      * @param domain The error domain.
288      * @param key The key of the error message.
289      * @param arguments The replacement arguments for the error message,
290      * if needed.
291      * @param severity The severity of the error.
292      *
293      * @see #SEVERITY_WARNING
294      * @see #SEVERITY_ERROR
295      * @see #SEVERITY_FATAL_ERROR
296      */

297     public void reportError(XMLLocator location,
298                             String JavaDoc domain, String JavaDoc key, Object JavaDoc[] arguments,
299                             short severity) throws XNIException {
300
301         // REVISIT: [Q] Should we do anything about invalid severity
302
// parameter? -Ac
303

304         // format error message and create parse exception
305
MessageFormatter messageFormatter = getMessageFormatter(domain);
306         String JavaDoc message;
307         if (messageFormatter != null) {
308             message = messageFormatter.formatMessage(fLocale, key, arguments);
309         }
310         else {
311             StringBuffer JavaDoc str = new StringBuffer JavaDoc();
312             str.append(domain);
313             str.append('#');
314             str.append(key);
315             int argCount = arguments != null ? arguments.length : 0;
316             if (argCount > 0) {
317                 str.append('?');
318                 for (int i = 0; i < argCount; i++) {
319                     str.append(arguments[i]);
320                     if (i < argCount -1) {
321                         str.append('&');
322                     }
323                 }
324             }
325             message = str.toString();
326         }
327         XMLParseException parseException =
328             new XMLParseException(location, message);
329
330         // get error handler
331
XMLErrorHandler errorHandler = fErrorHandler;
332         if (errorHandler == null) {
333             if (fDefaultErrorHandler == null) {
334                 fDefaultErrorHandler = new DefaultErrorHandler();
335             }
336             errorHandler = fDefaultErrorHandler;
337         }
338
339         // call error handler
340
switch (severity) {
341             case SEVERITY_WARNING: {
342                 errorHandler.warning(domain, key, parseException);
343                 break;
344             }
345             case SEVERITY_ERROR: {
346                 errorHandler.error(domain, key, parseException);
347                 break;
348             }
349             case SEVERITY_FATAL_ERROR: {
350                 errorHandler.fatalError(domain, key, parseException);
351                 if (!fContinueAfterFatalError) {
352                     throw parseException;
353                 }
354                 break;
355             }
356         }
357
358     } // reportError(XMLLocator,String,String,Object[],short)
359

360     //
361
// XMLComponent methods
362
//
363

364     /**
365      * Resets the component. The component can query the component manager
366      * about any features and properties that affect the operation of the
367      * component.
368      *
369      * @param componentManager The component manager.
370      *
371      * @throws SAXException Thrown by component on initialization error.
372      * For example, if a feature or property is
373      * required for the operation of the component, the
374      * component manager may throw a
375      * SAXNotRecognizedException or a
376      * SAXNotSupportedException.
377      */

378     public void reset(XMLComponentManager componentManager)
379         throws XNIException {
380
381         // features
382
try {
383             fContinueAfterFatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR);
384         }
385         catch (XNIException e) {
386             fContinueAfterFatalError = false;
387         }
388
389         // properties
390
fErrorHandler = (XMLErrorHandler)componentManager.getProperty(ERROR_HANDLER);
391
392     } // reset(XMLComponentManager)
393

394     /**
395      * Returns a list of feature identifiers that are recognized by
396      * this component. This method may return null if no features
397      * are recognized by this component.
398      */

399     public String JavaDoc[] getRecognizedFeatures() {
400         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
401     } // getRecognizedFeatures():String[]
402

403     /**
404      * Sets the state of a feature. This method is called by the component
405      * manager any time after reset when a feature changes state.
406      * <p>
407      * <strong>Note:</strong> Components should silently ignore features
408      * that do not affect the operation of the component.
409      *
410      * @param featureId The feature identifier.
411      * @param state The state of the feature.
412      *
413      * @throws SAXNotRecognizedException The component should not throw
414      * this exception.
415      * @throws SAXNotSupportedException The component should not throw
416      * this exception.
417      */

418     public void setFeature(String JavaDoc featureId, boolean state)
419         throws XMLConfigurationException {
420
421         //
422
// Xerces features
423
//
424

425         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
426             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
427             
428             //
429
// http://apache.org/xml/features/continue-after-fatal-error
430
// Allows the parser to continue after a fatal error.
431
// Normally, a fatal error would stop the parse.
432
//
433
if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
434                 featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
435                 fContinueAfterFatalError = state;
436             }
437         }
438
439     } // setFeature(String,boolean)
440

441     // return state of given feature or false if unsupported.
442
public boolean getFeature(String JavaDoc featureId)
443         throws XMLConfigurationException {
444
445         //
446
// Xerces features
447
//
448

449         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
450             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
451             
452             //
453
// http://apache.org/xml/features/continue-after-fatal-error
454
// Allows the parser to continue after a fatal error.
455
// Normally, a fatal error would stop the parse.
456
//
457
if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
458                 featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
459                 return fContinueAfterFatalError ;
460             }
461         }
462         return false;
463
464     } // setFeature(String,boolean)
465

466     /**
467      * Returns a list of property identifiers that are recognized by
468      * this component. This method may return null if no properties
469      * are recognized by this component.
470      */

471     public String JavaDoc[] getRecognizedProperties() {
472         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
473     } // getRecognizedProperties():String[]
474

475     /**
476      * Sets the value of a property. This method is called by the component
477      * manager any time after reset when a property changes value.
478      * <p>
479      * <strong>Note:</strong> Components should silently ignore properties
480      * that do not affect the operation of the component.
481      *
482      * @param propertyId The property identifier.
483      * @param value The value of the property.
484      *
485      * @throws SAXNotRecognizedException The component should not throw
486      * this exception.
487      * @throws SAXNotSupportedException The component should not throw
488      * this exception.
489      */

490     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
491         throws XMLConfigurationException {
492
493         //
494
// Xerces properties
495
//
496

497         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
498             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
499
500             if (suffixLength == Constants.ERROR_HANDLER_PROPERTY.length() &&
501                 propertyId.endsWith(Constants.ERROR_HANDLER_PROPERTY)) {
502                 fErrorHandler = (XMLErrorHandler)value;
503             }
504         }
505
506     } // setProperty(String,Object)
507

508     /**
509      * Returns the default state for a feature, or null if this
510      * component does not want to report a default value for this
511      * feature.
512      *
513      * @param featureId The feature identifier.
514      *
515      * @since Xerces 2.2.0
516      */

517     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
518         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
519             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
520                 return FEATURE_DEFAULTS[i];
521             }
522         }
523         return null;
524     } // getFeatureDefault(String):Boolean
525

526     /**
527      * Returns the default state for a property, or null if this
528      * component does not want to report a default value for this
529      * property.
530      *
531      * @param propertyId The property identifier.
532      *
533      * @since Xerces 2.2.0
534      */

535     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
536         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
537             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
538                 return PROPERTY_DEFAULTS[i];
539             }
540         }
541         return null;
542     } // getPropertyDefault(String):Object
543

544     /**
545      * Get the internal XMLErrrorHandler.
546      */

547     public XMLErrorHandler getErrorHandler() {
548         return fErrorHandler;
549     }
550     
551     /**
552      * Gets the internal XMLErrorHandler
553      * as SAX ErrorHandler.
554      */

555     public ErrorHandler getSAXErrorHandler() {
556         if (fSaxProxy == null) {
557             fSaxProxy = new ErrorHandlerProxy() {
558                 protected XMLErrorHandler getErrorHandler() {
559                     return fErrorHandler;
560                 }
561             };
562         }
563         return fSaxProxy;
564     }
565     
566 } // class XMLErrorReporter
567
Popular Tags