KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > XMLErrorReporter


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2004 The Apache Software Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.impl;
59
60 import java.util.Hashtable JavaDoc;
61 import java.util.Locale JavaDoc;
62
63 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler;
64 import com.sun.org.apache.xerces.internal.util.ErrorHandlerProxy;
65 import com.sun.org.apache.xerces.internal.util.MessageFormatter;
66 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
67 import com.sun.org.apache.xerces.internal.xni.XNIException;
68 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
69 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
70 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
71 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
72 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
73 import org.xml.sax.ErrorHandler JavaDoc;
74
75 /**
76  * This class is a common element of all parser configurations and is
77  * used to report errors that occur. This component can be queried by
78  * parser components from the component manager using the following
79  * property ID:
80  * <pre>
81  * http://apache.org/xml/properties/internal/error-reporter
82  * </pre>
83  * <p>
84  * Errors are separated into domains that categorize a class of errors.
85  * In a parser configuration, the parser would register a
86  * <code>MessageFormatter</code> for each domain that is capable of
87  * localizing error messages and formatting them based on information
88  * about the error. Any parser component can invent new error domains
89  * and register additional message formatters to localize messages in
90  * those domains.
91  * <p>
92  * This component requires the following features and properties from the
93  * component manager that uses it:
94  * <ul>
95  * <li>http://apache.org/xml/properties/internal/error-handler</li>
96  * </ul>
97  * <p>
98  * This component can use the following features and properties but they
99  * are not required:
100  * <ul>
101  * <li>http://apache.org/xml/features/continue-after-fatal-error</li>
102  * </ul>
103  *
104  * @see MessageFormatter
105  *
106  * @author Eric Ye, IBM
107  * @author Andy Clark, IBM
108  *
109  * @version $Id: XMLErrorReporter.java,v 1.13 2004/01/26 17:28:12 mrglavas Exp $
110  */

111 public class XMLErrorReporter
112     implements XMLComponent {
113
114     //
115
// Constants
116
//
117

118     // severity
119

120     /**
121      * Severity: warning. Warnings represent informational messages only
122      * that should not be considered serious enough to stop parsing or
123      * indicate an error in the document's validity.
124      */

125     public static final short SEVERITY_WARNING = 0;
126
127     /**
128      * Severity: error. Common causes of errors are document structure and/or
129      * content that that does not conform to the grammar rules specified for
130      * the document. These are typically validation errors.
131      */

132     public static final short SEVERITY_ERROR = 1;
133
134     /**
135      * Severity: fatal error. Fatal errors are errors in the syntax of the
136      * XML document or invalid byte sequences for a given encoding. The
137      * XML 1.0 Specification mandates that errors of this type are not
138      * recoverable.
139      * <p>
140      * <strong>Note:</strong> The parser does have a "continue after fatal
141      * error" feature but it should be used with extreme caution and care.
142      */

143     public static final short SEVERITY_FATAL_ERROR = 2;
144     
145     // feature identifiers
146

147     /** Feature identifier: continue after fatal error. */
148     protected static final String JavaDoc CONTINUE_AFTER_FATAL_ERROR =
149         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
150
151     // property identifiers
152

153     /** Property identifier: error handler. */
154     protected static final String JavaDoc ERROR_HANDLER =
155         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
156
157     // recognized features and properties
158

159     /** Recognized features. */
160     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
161         CONTINUE_AFTER_FATAL_ERROR,
162     };
163
164     /** Feature defaults. */
165     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = {
166         null,
167     };
168
169     /** Recognized properties. */
170     private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
171         ERROR_HANDLER,
172     };
173
174     /** Property defaults. */
175     private static final Object JavaDoc[] PROPERTY_DEFAULTS = {
176         null,
177     };
178
179     //
180
// Data
181
//
182

183     /** The locale to be used to format error messages. */
184     protected Locale JavaDoc fLocale;
185
186     /** Mapping of Message formatters for domains. */
187     protected Hashtable JavaDoc fMessageFormatters;
188
189     /** Error handler. */
190     protected XMLErrorHandler fErrorHandler;
191
192     /** Document locator. */
193     protected XMLLocator fLocator;
194
195     /** Continue after fatal error feature. */
196     protected boolean fContinueAfterFatalError;
197
198     /**
199      * Default error handler. This error handler is only used in the
200      * absence of a registered error handler so that errors are not
201      * "swallowed" silently. This is one of the most common "problems"
202      * reported by users of the parser.
203      */

204     protected XMLErrorHandler fDefaultErrorHandler;
205
206     //
207
// Constructors
208
//
209

210     /** Constructs an error reporter with a locator. */
211     public XMLErrorReporter() {
212
213         // REVISIT: [Q] Should the locator be passed to the reportError
214
// method? Otherwise, there is no way for a parser
215
// component to store information about where an
216
// error occurred so as to report it later.
217
//
218
// An example would be to record the location of
219
// IDREFs so that, at the end of the document, if
220
// there is no associated ID declared, the error
221
// could report the location information of the
222
// reference. -Ac
223
//
224
// NOTE: I added another reportError method that allows the
225
// caller to specify the location of the error being
226
// reported. -Ac
227

228         fMessageFormatters = new Hashtable JavaDoc();
229
230     } // <init>()
231

232     //
233
// Methods
234
//
235

236     /**
237      * Sets the current locale.
238      *
239      * @param locale The new locale.
240      */

241     public void setLocale(Locale JavaDoc locale) {
242         fLocale = locale;
243     } // setLocale(Locale)
244

245     /**
246      * Gets the current locale.
247      *
248      * @return the current Locale
249      */

250     public Locale JavaDoc getLocale() {
251         return fLocale ;
252     } // getLocale(): Locale
253

254     /**
255      * Sets the document locator.
256      *
257      * @param locator The locator.
258      */

259     public void setDocumentLocator(XMLLocator locator) {
260         fLocator = locator;
261     } // setDocumentLocator(XMLLocator)
262

263     /**
264      * Registers a message formatter for the specified domain.
265      * <p>
266      * <strong>Note:</strong> Registering a message formatter for a domain
267      * when there is already a formatter registered will cause the previous
268      * formatter to be lost. This method replaces any previously registered
269      * message formatter for the specified domain.
270      *
271      * @param domain
272      * @param messageFormatter
273      */

274     public void putMessageFormatter(String JavaDoc domain,
275                                     MessageFormatter messageFormatter) {
276         fMessageFormatters.put(domain, messageFormatter);
277     } // putMessageFormatter(String,MessageFormatter)
278

279     /**
280      * Returns the message formatter associated with the specified domain,
281      * or null if no message formatter is registered for that domain.
282      *
283      * @param domain The domain of the message formatter.
284      */

285     public MessageFormatter getMessageFormatter(String JavaDoc domain) {
286         return (MessageFormatter)fMessageFormatters.get(domain);
287     } // getMessageFormatter(String):MessageFormatter
288

289     /**
290      * Removes the message formatter for the specified domain and
291      * returns the removed message formatter.
292      *
293      * @param domain The domain of the message formatter.
294      */

295     public MessageFormatter removeMessageFormatter(String JavaDoc domain) {
296         return (MessageFormatter) fMessageFormatters.remove(domain);
297     } // removeMessageFormatter(String):MessageFormatter
298

299     /**
300      * Reports an error. The error message passed to the error handler
301      * is formatted for the locale by the message formatter installed
302      * for the specified error domain.
303      *
304      * @param domain The error domain.
305      * @param key The key of the error message.
306      * @param arguments The replacement arguments for the error message,
307      * if needed.
308      * @param severity The severity of the error.
309      *
310      * @see #SEVERITY_WARNING
311      * @see #SEVERITY_ERROR
312      * @see #SEVERITY_FATAL_ERROR
313      */

314     public void reportError(String JavaDoc domain, String JavaDoc key, Object JavaDoc[] arguments,
315                             short severity) throws XNIException {
316         reportError(fLocator, domain, key, arguments, severity);
317     } // reportError(String,String,Object[],short)
318

319     /**
320      * Reports an error at a specific location.
321      *
322      * @param location The error location.
323      * @param domain The error domain.
324      * @param key The key of the error message.
325      * @param arguments The replacement arguments for the error message,
326      * if needed.
327      * @param severity The severity of the error.
328      *
329      * @see #SEVERITY_WARNING
330      * @see #SEVERITY_ERROR
331      * @see #SEVERITY_FATAL_ERROR
332      */

333     public void reportError(XMLLocator location,
334                             String JavaDoc domain, String JavaDoc key, Object JavaDoc[] arguments,
335                             short severity) throws XNIException {
336
337         // REVISIT: [Q] Should we do anything about invalid severity
338
// parameter? -Ac
339

340         // format error message and create parse exception
341
MessageFormatter messageFormatter = getMessageFormatter(domain);
342         String JavaDoc message;
343         if (messageFormatter != null) {
344             message = messageFormatter.formatMessage(fLocale, key, arguments);
345         }
346         else {
347             StringBuffer JavaDoc str = new StringBuffer JavaDoc();
348             str.append(domain);
349             str.append('#');
350             str.append(key);
351             int argCount = arguments != null ? arguments.length : 0;
352             if (argCount > 0) {
353                 str.append('?');
354                 for (int i = 0; i < argCount; i++) {
355                     str.append(arguments[i]);
356                     if (i < argCount -1) {
357                         str.append('&');
358                     }
359                 }
360             }
361             message = str.toString();
362         }
363         XMLParseException parseException =
364             new XMLParseException(location, message);
365
366         // get error handler
367
XMLErrorHandler errorHandler = fErrorHandler;
368         if (errorHandler == null) {
369             if (fDefaultErrorHandler == null) {
370                 fDefaultErrorHandler = new DefaultErrorHandler();
371             }
372             errorHandler = fDefaultErrorHandler;
373         }
374
375         // call error handler
376
switch (severity) {
377             case SEVERITY_WARNING: {
378                 errorHandler.warning(domain, key, parseException);
379                 break;
380             }
381             case SEVERITY_ERROR: {
382                 errorHandler.error(domain, key, parseException);
383                 break;
384             }
385             case SEVERITY_FATAL_ERROR: {
386                 errorHandler.fatalError(domain, key, parseException);
387                 if (!fContinueAfterFatalError) {
388                     throw parseException;
389                 }
390                 break;
391             }
392         }
393
394     } // reportError(XMLLocator,String,String,Object[],short)
395

396     //
397
// XMLComponent methods
398
//
399

400     /**
401      * Resets the component. The component can query the component manager
402      * about any features and properties that affect the operation of the
403      * component.
404      *
405      * @param componentManager The component manager.
406      *
407      * @throws SAXException Thrown by component on initialization error.
408      * For example, if a feature or property is
409      * required for the operation of the component, the
410      * component manager may throw a
411      * SAXNotRecognizedException or a
412      * SAXNotSupportedException.
413      */

414     public void reset(XMLComponentManager componentManager)
415         throws XNIException {
416
417         // features
418
try {
419             fContinueAfterFatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR);
420         }
421         catch (XNIException e) {
422             fContinueAfterFatalError = false;
423         }
424
425         // properties
426
fErrorHandler = (XMLErrorHandler)componentManager.getProperty(ERROR_HANDLER);
427
428     } // reset(XMLComponentManager)
429

430     /**
431      * Returns a list of feature identifiers that are recognized by
432      * this component. This method may return null if no features
433      * are recognized by this component.
434      */

435     public String JavaDoc[] getRecognizedFeatures() {
436         return (String JavaDoc[])(RECOGNIZED_FEATURES.clone());
437     } // getRecognizedFeatures():String[]
438

439     /**
440      * Sets the state of a feature. This method is called by the component
441      * manager any time after reset when a feature changes state.
442      * <p>
443      * <strong>Note:</strong> Components should silently ignore features
444      * that do not affect the operation of the component.
445      *
446      * @param featureId The feature identifier.
447      * @param state The state of the feature.
448      *
449      * @throws SAXNotRecognizedException The component should not throw
450      * this exception.
451      * @throws SAXNotSupportedException The component should not throw
452      * this exception.
453      */

454     public void setFeature(String JavaDoc featureId, boolean state)
455         throws XMLConfigurationException {
456
457         //
458
// Xerces features
459
//
460

461         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
462             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
463             
464             //
465
// http://apache.org/xml/features/continue-after-fatal-error
466
// Allows the parser to continue after a fatal error.
467
// Normally, a fatal error would stop the parse.
468
//
469
if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
470                 featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
471                 fContinueAfterFatalError = state;
472             }
473         }
474
475     } // setFeature(String,boolean)
476

477     // return state of given feature or false if unsupported.
478
public boolean getFeature(String JavaDoc featureId)
479         throws XMLConfigurationException {
480
481         //
482
// Xerces features
483
//
484

485         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
486             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
487             
488             //
489
// http://apache.org/xml/features/continue-after-fatal-error
490
// Allows the parser to continue after a fatal error.
491
// Normally, a fatal error would stop the parse.
492
//
493
if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
494                 featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
495                 return fContinueAfterFatalError ;
496             }
497         }
498         return false;
499
500     } // setFeature(String,boolean)
501

502     /**
503      * Returns a list of property identifiers that are recognized by
504      * this component. This method may return null if no properties
505      * are recognized by this component.
506      */

507     public String JavaDoc[] getRecognizedProperties() {
508         return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
509     } // getRecognizedProperties():String[]
510

511     /**
512      * Sets the value of a property. This method is called by the component
513      * manager any time after reset when a property changes value.
514      * <p>
515      * <strong>Note:</strong> Components should silently ignore properties
516      * that do not affect the operation of the component.
517      *
518      * @param propertyId The property identifier.
519      * @param value The value of the property.
520      *
521      * @throws SAXNotRecognizedException The component should not throw
522      * this exception.
523      * @throws SAXNotSupportedException The component should not throw
524      * this exception.
525      */

526     public void setProperty(String JavaDoc propertyId, Object JavaDoc value)
527         throws XMLConfigurationException {
528
529         //
530
// Xerces properties
531
//
532

533         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
534             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
535
536             if (suffixLength == Constants.ERROR_HANDLER_PROPERTY.length() &&
537                 propertyId.endsWith(Constants.ERROR_HANDLER_PROPERTY)) {
538                 fErrorHandler = (XMLErrorHandler)value;
539             }
540         }
541
542     } // setProperty(String,Object)
543

544     /**
545      * Returns the default state for a feature, or null if this
546      * component does not want to report a default value for this
547      * feature.
548      *
549      * @param featureId The feature identifier.
550      *
551      * @since Xerces 2.2.0
552      */

553     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
554         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
555             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
556                 return FEATURE_DEFAULTS[i];
557             }
558         }
559         return null;
560     } // getFeatureDefault(String):Boolean
561

562     /**
563      * Returns the default state for a property, or null if this
564      * component does not want to report a default value for this
565      * property.
566      *
567      * @param propertyId The property identifier.
568      *
569      * @since Xerces 2.2.0
570      */

571     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
572         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
573             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
574                 return PROPERTY_DEFAULTS[i];
575             }
576         }
577         return null;
578     } // getPropertyDefault(String):Object
579

580     /**
581      * Get the internal XMLErrrorHandler.
582      */

583     public XMLErrorHandler getErrorHandler() {
584         return fErrorHandler;
585     }
586     
587     
588     private ErrorHandler fSaxProxy = null;
589     
590     /**
591      * Gets the internal XMLErrorHandler
592      * as SAX ErrorHandler.
593      */

594     public ErrorHandler getSAXErrorHandler() {
595         if( fSaxProxy==null )
596             fSaxProxy = new ErrorHandlerProxy() {
597                 protected XMLErrorHandler getErrorHandler() {
598                     return fErrorHandler;
599                 }
600             };
601         return fSaxProxy;
602     }
603 } // class XMLErrorReporter
604
Popular Tags