View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *      http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package com.sun.org.apache.xerces.internal.dom;
22  
23  import com.sun.org.apache.xerces.internal.impl.Constants;
24  import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
25  import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
26  import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
27  import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
28  import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
29  import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper;
30  import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
31  import com.sun.org.apache.xerces.internal.util.MessageFormatter;
32  import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
33  import com.sun.org.apache.xerces.internal.util.PropertyState;
34  import com.sun.org.apache.xerces.internal.util.SymbolTable;
35  import com.sun.org.apache.xerces.internal.utils.ObjectFactory;
36  import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
37  import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
38  import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
39  import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
40  import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
41  import com.sun.org.apache.xerces.internal.xni.XNIException;
42  import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
43  import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
44  import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
45  import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
46  import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
47  import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
48  import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
49  import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
50  import java.io.IOException;
51  import java.util.ArrayList;
52  import java.util.HashMap;
53  import java.util.Locale;
54  import java.util.Vector;
55  import javax.xml.XMLConstants;
56  import org.w3c.dom.DOMConfiguration;
57  import org.w3c.dom.DOMErrorHandler;
58  import org.w3c.dom.DOMException;
59  import org.w3c.dom.DOMStringList;
60  import org.w3c.dom.ls.LSResourceResolver;
61  
62  
63  
64  /**
65   * Xerces implementation of DOMConfiguration that maintains a table of recognized parameters.
66   *
67   * @xerces.internal
68   *
69   * @author Elena Litani, IBM
70   * @author Neeraj Bajaj, Sun Microsystems.
71   * @version $Id: DOMConfigurationImpl.java,v 1.9 2010-11-01 04:39:37 joehw Exp $
72   */
73  public class DOMConfigurationImpl extends ParserConfigurationSettings
74      implements XMLParserConfiguration, DOMConfiguration {
75  
76      //
77      // Constants
78      //
79  
80      // feature identifiers
81  
82      /** Feature identifier: validation. */
83      protected static final String XERCES_VALIDATION =
84          Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
85  
86      /** Feature identifier: namespaces. */
87      protected static final String XERCES_NAMESPACES =
88          Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
89  
90      protected static final String SCHEMA =
91          Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
92  
93      protected static final String SCHEMA_FULL_CHECKING =
94          Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
95  
96      protected static final String DYNAMIC_VALIDATION =
97          Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
98  
99      protected static final String NORMALIZE_DATA =
100         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
101 
102     /** sending psvi in the pipeline */
103     protected static final String SEND_PSVI =
104         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
105 
106     protected final static String DTD_VALIDATOR_FACTORY_PROPERTY =
107         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
108 
109     /** Feature identifier: namespace growth */
110     protected static final String NAMESPACE_GROWTH =
111         Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
112 
113     protected static final String TOLERATE_DUPLICATES =
114         Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
115 
116     // property identifiers
117 
118     /** Property identifier: entity manager. */
119     protected static final String ENTITY_MANAGER =
120         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
121 
122     /** Property identifier: error reporter. */
123     protected static final String ERROR_REPORTER =
124         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
125 
126     /** Property identifier: xml string. */
127     protected static final String XML_STRING =
128         Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
129 
130     /** Property identifier: symbol table. */
131     protected static final String SYMBOL_TABLE =
132         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
133 
134     /** Property id: Grammar pool*/
135     protected static final String GRAMMAR_POOL =
136     Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
137 
138     /** Property identifier: error handler. */
139     protected static final String ERROR_HANDLER =
140         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
141 
142     /** Property identifier: entity resolver. */
143     protected static final String ENTITY_RESOLVER =
144         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
145 
146     /** Property identifier: JAXP schema language / DOM schema-type. */
147     protected static final String JAXP_SCHEMA_LANGUAGE =
148     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
149 
150     /** Property identifier: JAXP schema source/ DOM schema-location. */
151     protected static final String JAXP_SCHEMA_SOURCE =
152     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
153 
154     protected static final String VALIDATION_MANAGER =
155         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
156 
157     /** Property identifier: Schema DV Factory */
158     protected static final String SCHEMA_DV_FACTORY =
159         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
160 
161     /** Property identifier: Security manager. */
162     private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER;
163 
164     /** Property identifier: Security property manager. */
165     private static final String XML_SECURITY_PROPERTY_MANAGER =
166             Constants.XML_SECURITY_PROPERTY_MANAGER;
167 
168     //
169     // Data
170     //
171     XMLDocumentHandler fDocumentHandler;
172 
173     /** Normalization features*/
174     protected short features = 0;
175 
176     protected final static short NAMESPACES          = 0x1<<0;
177     protected final static short DTNORMALIZATION     = 0x1<<1;
178     protected final static short ENTITIES            = 0x1<<2;
179     protected final static short CDATA               = 0x1<<3;
180     protected final static short SPLITCDATA          = 0x1<<4;
181     protected final static short COMMENTS            = 0x1<<5;
182     protected final static short VALIDATE            = 0x1<<6;
183     protected final static short PSVI                = 0x1<<7;
184     protected final static short WELLFORMED          = 0x1<<8;
185     protected final static short NSDECL              = 0x1<<9;
186 
187     protected final static short INFOSET_TRUE_PARAMS = NAMESPACES | COMMENTS | WELLFORMED | NSDECL;
188     protected final static short INFOSET_FALSE_PARAMS = ENTITIES | DTNORMALIZATION | CDATA;
189     protected final static short INFOSET_MASK = INFOSET_TRUE_PARAMS | INFOSET_FALSE_PARAMS;
190 
191     // components
192 
193     /** Symbol table. */
194     protected SymbolTable fSymbolTable;
195 
196     /** Components. */
197     protected ArrayList fComponents;
198 
199     protected ValidationManager fValidationManager;
200 
201     /** Locale. */
202     protected Locale fLocale;
203 
204     /** Error reporter */
205     protected XMLErrorReporter fErrorReporter;
206 
207     protected final DOMErrorHandlerWrapper fErrorHandlerWrapper =
208                 new DOMErrorHandlerWrapper();
209 
210     // private data
211 
212     private DOMStringList fRecognizedParameters;
213 
214 
215     //
216     // Constructors
217     //
218 
219     /** Default Constructor. */
220     protected DOMConfigurationImpl() {
221         this(null, null);
222     } // <init>()
223 
224     /**
225      * Constructs a parser configuration using the specified symbol table.
226      *
227      * @param symbolTable The symbol table to use.
228      */
229     protected DOMConfigurationImpl(SymbolTable symbolTable) {
230         this(symbolTable, null);
231     } // <init>(SymbolTable)
232 
233     /**
234      * Constructs a parser configuration using the specified symbol table
235      * and parent settings.
236      *
237      * @param symbolTable    The symbol table to use.
238      * @param parentSettings The parent settings.
239      */
240     protected DOMConfigurationImpl(SymbolTable symbolTable,
241                                     XMLComponentManager parentSettings) {
242         super(parentSettings);
243 
244 
245         // create table for features and properties
246         fFeatures = new HashMap();
247         fProperties = new HashMap();
248 
249         // add default recognized features
250         final String[] recognizedFeatures = {
251             XERCES_VALIDATION,
252             XERCES_NAMESPACES,
253             SCHEMA,
254             SCHEMA_FULL_CHECKING,
255             DYNAMIC_VALIDATION,
256             NORMALIZE_DATA,
257             SEND_PSVI,
258             NAMESPACE_GROWTH,
259             TOLERATE_DUPLICATES
260         };
261         addRecognizedFeatures(recognizedFeatures);
262 
263         // set state for default features
264         setFeature(XERCES_VALIDATION, false);
265         setFeature(SCHEMA, false);
266         setFeature(SCHEMA_FULL_CHECKING, false);
267         setFeature(DYNAMIC_VALIDATION, false);
268         setFeature(NORMALIZE_DATA, false);
269         setFeature(XERCES_NAMESPACES, true);
270         setFeature(SEND_PSVI, true);
271         setFeature(NAMESPACE_GROWTH, false);
272 
273         // add default recognized properties
274         final String[] recognizedProperties = {
275             XML_STRING,
276             SYMBOL_TABLE,
277             ERROR_HANDLER,
278             ENTITY_RESOLVER,
279             ERROR_REPORTER,
280             ENTITY_MANAGER,
281             VALIDATION_MANAGER,
282             GRAMMAR_POOL,
283             JAXP_SCHEMA_SOURCE,
284             JAXP_SCHEMA_LANGUAGE,
285             DTD_VALIDATOR_FACTORY_PROPERTY,
286             SCHEMA_DV_FACTORY,
287             SECURITY_MANAGER,
288             XML_SECURITY_PROPERTY_MANAGER
289         };
290         addRecognizedProperties(recognizedProperties);
291 
292         // set default values for normalization features
293         features |= NAMESPACES;
294         features |= ENTITIES;
295         features |= COMMENTS;
296         features |= CDATA;
297         features |= SPLITCDATA;
298         features |= WELLFORMED;
299         features |= NSDECL;
300 
301         if (symbolTable == null) {
302             symbolTable = new SymbolTable();
303         }
304         fSymbolTable = symbolTable;
305 
306         fComponents = new ArrayList();
307 
308         setProperty(SYMBOL_TABLE, fSymbolTable);
309         fErrorReporter = new XMLErrorReporter();
310         setProperty(ERROR_REPORTER, fErrorReporter);
311         addComponent(fErrorReporter);
312 
313         setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, DTDDVFactory.getInstance());
314 
315         XMLEntityManager manager =  new XMLEntityManager();
316         setProperty(ENTITY_MANAGER, manager);
317         addComponent(manager);
318 
319         fValidationManager = createValidationManager();
320         setProperty(VALIDATION_MANAGER, fValidationManager);
321 
322         setProperty(SECURITY_MANAGER, new XMLSecurityManager(true));
323 
324         setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER,
325                 new XMLSecurityPropertyManager());
326 
327         // add message formatters
328         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
329             XMLMessageFormatter xmft = new XMLMessageFormatter();
330             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
331             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
332         }
333 
334         // REVISIT: try to include XML Schema formatter.
335         //          This is a hack to allow DTD configuration to be build.
336         //
337         if (fErrorReporter.getMessageFormatter("http://www.w3.org/TR/xml-schema-1") == null) {
338             MessageFormatter xmft = null;
339             try {
340                xmft = (MessageFormatter)(
341                     ObjectFactory.newInstance("com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter", true));
342             } catch (Exception exception){
343             }
344 
345              if (xmft !=  null) {
346                  fErrorReporter.putMessageFormatter("http://www.w3.org/TR/xml-schema-1", xmft);
347              }
348         }
349 
350 
351         // set locale
352         try {
353             setLocale(Locale.getDefault());
354         }
355         catch (XNIException e) {
356             // do nothing
357             // REVISIT: What is the right thing to do? -Ac
358         }
359 
360 
361     } // <init>(SymbolTable)
362 
363 
364     //
365     // XMLParserConfiguration methods
366     //
367 
368     /**
369      * Parse an XML document.
370      * <p>
371      * The parser can use this method to instruct this configuration
372      * to begin parsing an XML document from any valid input source
373      * (a character stream, a byte stream, or a URI).
374      * <p>
375      * Parsers may not invoke this method while a parse is in progress.
376      * Once a parse is complete, the parser may then parse another XML
377      * document.
378      * <p>
379      * This method is synchronous: it will not return until parsing
380      * has ended.  If a client application wants to terminate
381      * parsing early, it should throw an exception.
382      *
383      * @param source The input source for the top-level of the
384      *               XML document.
385      *
386      * @exception XNIException Any XNI exception, possibly wrapping
387      *                         another exception.
388      * @exception IOException  An IO exception from the parser, possibly
389      *                         from a byte stream or character stream
390      *                         supplied by the parser.
391      */
392     public void parse(XMLInputSource inputSource)
393         throws XNIException, IOException{
394         // no-op
395     }
396 
397     /**
398      * Sets the document handler on the last component in the pipeline
399      * to receive information about the document.
400      *
401      * @param documentHandler   The document handler.
402      */
403     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
404         fDocumentHandler = documentHandler;
405     } // setDocumentHandler(XMLDocumentHandler)
406 
407     /** Returns the registered document handler. */
408     public XMLDocumentHandler getDocumentHandler() {
409         return fDocumentHandler;
410     } // getDocumentHandler():XMLDocumentHandler
411 
412     /**
413      * Sets the DTD handler.
414      *
415      * @param dtdHandler The DTD handler.
416      */
417     public void setDTDHandler(XMLDTDHandler dtdHandler) {
418         //no-op
419     } // setDTDHandler(XMLDTDHandler)
420 
421     /** Returns the registered DTD handler. */
422     public XMLDTDHandler getDTDHandler() {
423         return null;
424     } // getDTDHandler():XMLDTDHandler
425 
426     /**
427      * Sets the DTD content model handler.
428      *
429      * @param handler The DTD content model handler.
430      */
431     public void setDTDContentModelHandler(XMLDTDContentModelHandler handler) {
432         //no-op
433 
434     } // setDTDContentModelHandler(XMLDTDContentModelHandler)
435 
436     /** Returns the registered DTD content model handler. */
437     public XMLDTDContentModelHandler getDTDContentModelHandler() {
438         return null;
439     } // getDTDContentModelHandler():XMLDTDContentModelHandler
440 
441     /**
442      * Sets the resolver used to resolve external entities. The EntityResolver
443      * interface supports resolution of public and system identifiers.
444      *
445      * @param resolver The new entity resolver. Passing a null value will
446      *                 uninstall the currently installed resolver.
447      */
448     public void setEntityResolver(XMLEntityResolver resolver) {
449         if (resolver !=null) {
450             fProperties.put(ENTITY_RESOLVER, resolver);
451         }
452     } // setEntityResolver(XMLEntityResolver)
453 
454     /**
455      * Return the current entity resolver.
456      *
457      * @return The current entity resolver, or null if none
458      *         has been registered.
459      * @see #setEntityResolver
460      */
461     public XMLEntityResolver getEntityResolver() {
462         return (XMLEntityResolver)fProperties.get(ENTITY_RESOLVER);
463     } // getEntityResolver():XMLEntityResolver
464 
465     /**
466      * Allow an application to register an error event handler.
467      *
468      * <p>If the application does not register an error handler, all
469      * error events reported by the SAX parser will be silently
470      * ignored; however, normal processing may not continue.  It is
471      * highly recommended that all SAX applications implement an
472      * error handler to avoid unexpected bugs.</p>
473      *
474      * <p>Applications may register a new or different handler in the
475      * middle of a parse, and the SAX parser must begin using the new
476      * handler immediately.</p>
477      *
478      * @param errorHandler The error handler.
479      * @exception java.lang.NullPointerException If the handler
480      *            argument is null.
481      * @see #getErrorHandler
482      */
483     public void setErrorHandler(XMLErrorHandler errorHandler) {
484         if (errorHandler != null) {
485             fProperties.put(ERROR_HANDLER, errorHandler);
486         }
487     } // setErrorHandler(XMLErrorHandler)
488 
489     /**
490      * Return the current error handler.
491      *
492      * @return The current error handler, or null if none
493      *         has been registered.
494      * @see #setErrorHandler
495      */
496     public XMLErrorHandler getErrorHandler() {
497         return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
498     } // getErrorHandler():XMLErrorHandler
499 
500     /**
501      * Set the state of a feature.
502      *
503      * Set the state of any feature in a SAX2 parser.  The parser
504      * might not recognize the feature, and if it does recognize
505      * it, it might not be able to fulfill the request.
506      *
507      * @param featureId The unique identifier (URI) of the feature.
508      * @param state The requested state of the feature (true or false).
509      *
510      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
511      *            requested feature is not known.
512      */
513     public void setFeature(String featureId, boolean state)
514         throws XMLConfigurationException {
515 
516         // save state if noone "objects"
517         super.setFeature(featureId, state);
518 
519     } // setFeature(String,boolean)
520 
521     /**
522      * setProperty
523      *
524      * @param propertyId
525      * @param value
526      */
527     public void setProperty(String propertyId, Object value)
528         throws XMLConfigurationException {
529 
530         // store value if noone "objects"
531         super.setProperty(propertyId, value);
532 
533     } // setProperty(String,Object)
534 
535     /**
536      * Set the locale to use for messages.
537      *
538      * @param locale The locale object to use for localization of messages.
539      *
540      * @exception XNIException Thrown if the parser does not support the
541      *                         specified locale.
542      */
543     public void setLocale(Locale locale) throws XNIException {
544         fLocale = locale;
545         fErrorReporter.setLocale(locale);
546 
547     } // setLocale(Locale)
548 
549     /** Returns the locale. */
550     public Locale getLocale() {
551         return fLocale;
552     } // getLocale():Locale
553 
554     /**
555      * DOM Level 3 WD - Experimental.
556      * setParameter
557      */
558     public void setParameter(String name, Object value) throws DOMException {
559         boolean found = true;
560 
561         // REVISIT: Recognizes DOM L3 default features only.
562         //          Does not yet recognize Xerces features.
563                 if(value instanceof Boolean){
564                         boolean state = ((Boolean)value).booleanValue();
565 
566             if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
567                 features = (short) (state ? features | COMMENTS : features & ~COMMENTS);
568             }
569             else if (name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
570                 setFeature(NORMALIZE_DATA, state);
571                 features =
572                     (short) (state ? features | DTNORMALIZATION : features & ~DTNORMALIZATION);
573                 if (state) {
574                     features = (short) (features | VALIDATE);
575                 }
576             }
577             else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
578                 features = (short) (state ? features | NAMESPACES : features & ~NAMESPACES);
579             }
580             else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
581                 features = (short) (state ? features | CDATA : features & ~CDATA);
582             }
583             else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
584                 features = (short) (state ? features | ENTITIES : features & ~ENTITIES);
585             }
586             else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
587                 features = (short) (state ? features | SPLITCDATA : features & ~SPLITCDATA);
588             }
589             else if (name.equalsIgnoreCase(Constants.DOM_VALIDATE)) {
590                 features = (short) (state ? features | VALIDATE : features & ~VALIDATE);
591             }
592             else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
593                 features = (short) (state ? features | WELLFORMED : features & ~WELLFORMED );
594             }
595             else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
596                 features = (short) (state ? features | NSDECL : features & ~NSDECL);
597             }
598             else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
599                 // Setting to false has no effect.
600                 if (state) {
601                     features = (short) (features | INFOSET_TRUE_PARAMS);
602                     features = (short) (features & ~INFOSET_FALSE_PARAMS);
603                     setFeature(NORMALIZE_DATA, false);
604                 }
605             }
606             else if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
607                     || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
608                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
609                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
610                     ) {
611                 if (state) { // true is not supported
612                     String msg =
613                         DOMMessageFormatter.formatMessage(
614                             DOMMessageFormatter.DOM_DOMAIN,
615                             "FEATURE_NOT_SUPPORTED",
616                             new Object[] { name });
617                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
618                 }
619             }
620                         else if ( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
621                 if (!state) { // false is not supported
622                     String msg =
623                         DOMMessageFormatter.formatMessage(
624                             DOMMessageFormatter.DOM_DOMAIN,
625                             "FEATURE_NOT_SUPPORTED",
626                             new Object[] { name });
627                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
628                 }
629             }
630             else if (name.equalsIgnoreCase(SEND_PSVI) ){
631                 // REVISIT: turning augmentation of PSVI is not support,
632                 // because in this case we won't be able to retrieve element
633                 // default value.
634                 if (!state) { // false is not supported
635                     String msg =
636                         DOMMessageFormatter.formatMessage(
637                             DOMMessageFormatter.DOM_DOMAIN,
638                             "FEATURE_NOT_SUPPORTED",
639                             new Object[] { name });
640                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
641                 }
642             }
643             else if (name.equalsIgnoreCase(Constants.DOM_PSVI)){
644                   features = (short) (state ? features | PSVI : features & ~PSVI);
645             }
646             else {
647                 found = false;
648                 /*
649                 String msg =
650                     DOMMessageFormatter.formatMessage(
651                         DOMMessageFormatter.DOM_DOMAIN,
652                         "FEATURE_NOT_FOUND",
653                         new Object[] { name });
654                 throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
655                 */
656             }
657 
658         }
659 
660                 if (!found || !(value instanceof Boolean))  { // set properties
661                         found = true;
662 
663             if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
664                 if (value instanceof DOMErrorHandler || value == null) {
665                     fErrorHandlerWrapper.setErrorHandler((DOMErrorHandler)value);
666                     setErrorHandler(fErrorHandlerWrapper);
667                 }
668 
669                 else {
670                     // REVISIT: type mismatch
671                     String msg =
672                         DOMMessageFormatter.formatMessage(
673                             DOMMessageFormatter.DOM_DOMAIN,
674                             "TYPE_MISMATCH_ERR",
675                             new Object[] { name });
676                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
677                 }
678             }
679             else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
680                 if (value instanceof LSResourceResolver || value == null) {
681                     try {
682                         setEntityResolver(new DOMEntityResolverWrapper((LSResourceResolver) value));
683                     }
684                     catch (XMLConfigurationException e) {}
685                 }
686                 else {
687                     // REVISIT: type mismatch
688                     String msg =
689                         DOMMessageFormatter.formatMessage(
690                             DOMMessageFormatter.DOM_DOMAIN,
691                             "TYPE_MISMATCH_ERR",
692                             new Object[] { name });
693                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
694                 }
695 
696             }
697             else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
698                 if (value instanceof String || value == null) {
699                     try {
700                         // map DOM schema-location to JAXP schemaSource property
701                         setProperty(
702                             Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
703                             value);
704                     }
705                     catch (XMLConfigurationException e) {}
706                 }
707                 else {
708                     // REVISIT: type mismatch
709                     String msg =
710                         DOMMessageFormatter.formatMessage(
711                             DOMMessageFormatter.DOM_DOMAIN,
712                             "TYPE_MISMATCH_ERR",
713                             new Object[] { name });
714                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
715                 }
716 
717             }
718             else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
719                 if (value instanceof String || value == null) {
720                     try {
721                         if (value == null) {
722                             setProperty(
723                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
724                                 null);
725                         }
726                         else if (value.equals(Constants.NS_XMLSCHEMA)) {
727                             // REVISIT: when add support to DTD validation
728                             setProperty(
729                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
730                                 Constants.NS_XMLSCHEMA);
731                         }
732                         else if (value.equals(Constants.NS_DTD)) {
733                             // Added support for revalidation against DTDs
734                                 setProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
735                                                 Constants.NS_DTD);
736                         }
737                     }
738                     catch (XMLConfigurationException e) {}
739                 }
740                 else {
741                     String msg =
742                         DOMMessageFormatter.formatMessage(
743                             DOMMessageFormatter.DOM_DOMAIN,
744                             "TYPE_MISMATCH_ERR",
745                             new Object[] { name });
746                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
747                 }
748 
749             }
750             else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
751                 // Xerces Symbol Table
752                 if (value instanceof SymbolTable){
753                     setProperty(SYMBOL_TABLE, value);
754                 }
755                 else {
756                     // REVISIT: type mismatch
757                     String msg =
758                         DOMMessageFormatter.formatMessage(
759                             DOMMessageFormatter.DOM_DOMAIN,
760                             "TYPE_MISMATCH_ERR",
761                             new Object[] { name });
762                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
763                 }
764             }
765             else if (name.equalsIgnoreCase (GRAMMAR_POOL)){
766                 if (value instanceof XMLGrammarPool){
767                     setProperty(GRAMMAR_POOL, value);
768                 }
769                 else {
770                     // REVISIT: type mismatch
771                     String msg =
772                         DOMMessageFormatter.formatMessage(
773                             DOMMessageFormatter.DOM_DOMAIN,
774                             "TYPE_MISMATCH_ERR",
775                             new Object[] { name });
776                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
777                 }
778 
779             }
780             else {
781                 // REVISIT: check if this is a boolean parameter -- type mismatch should be thrown.
782                 //parameter is not recognized
783                 String msg =
784                     DOMMessageFormatter.formatMessage(
785                         DOMMessageFormatter.DOM_DOMAIN,
786                         "FEATURE_NOT_FOUND",
787                         new Object[] { name });
788                 throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
789             }
790         }
791 
792     }
793 
794 
795     /**
796      * DOM Level 3 WD - Experimental.
797      * getParameter
798      */
799         public Object getParameter(String name) throws DOMException {
800 
801                 // REVISIT: Recognizes DOM L3 default features only.
802                 //          Does not yet recognize Xerces features.
803 
804                 if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
805                         return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
806                 }
807                 else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
808                         return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
809                 }
810                 else if (name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
811                         // REVISIT: datatype-normalization only takes effect if validation is on
812                         return (features & DTNORMALIZATION) != 0 ? Boolean.TRUE : Boolean.FALSE;
813                 }
814                 else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
815                         return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
816                 }
817                 else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
818                         return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
819                 }
820                 else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
821                         return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
822                 }
823                 else if (name.equalsIgnoreCase(Constants.DOM_VALIDATE)) {
824                         return (features & VALIDATE) != 0 ? Boolean.TRUE : Boolean.FALSE;
825                 }
826                 else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
827                         return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
828                 }
829                 else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
830                     return (features & NSDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
831                 }
832                 else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
833                         return (features & INFOSET_MASK) == INFOSET_TRUE_PARAMS ? Boolean.TRUE : Boolean.FALSE;
834                 }
835                 else if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
836                                 || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
837                                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
838                                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
839                 ) {
840                         return Boolean.FALSE;
841                 }
842         else if (name.equalsIgnoreCase(SEND_PSVI)) {
843             return Boolean.TRUE;
844         }
845         else if (name.equalsIgnoreCase(Constants.DOM_PSVI)) {
846             return (features & PSVI) != 0 ? Boolean.TRUE : Boolean.FALSE;
847         }
848         else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
849                         return Boolean.TRUE;
850                 }
851                 else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
852             return fErrorHandlerWrapper.getErrorHandler();
853                 }
854                 else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
855                         XMLEntityResolver entityResolver = getEntityResolver();
856                         if (entityResolver != null && entityResolver instanceof DOMEntityResolverWrapper) {
857                                 return ((DOMEntityResolverWrapper) entityResolver).getEntityResolver();
858                         }
859                         return null;
860                 }
861                 else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
862                         return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
863                 }
864                 else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
865                         return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE);
866                 }
867         else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
868             return getProperty(SYMBOL_TABLE);
869         }
870         else if (name.equalsIgnoreCase(GRAMMAR_POOL)){
871             return getProperty(GRAMMAR_POOL);
872         }
873                 else {
874                         String msg =
875                                 DOMMessageFormatter.formatMessage(
876                                         DOMMessageFormatter.DOM_DOMAIN,
877                                         "FEATURE_NOT_FOUND",
878                                         new Object[] { name });
879                         throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
880                 }
881 
882         }
883 
884     /**
885      * DOM Level 3 WD - Experimental.
886      * Check if setting a parameter to a specific value is supported.
887      *
888      * @param name The name of the parameter to check.
889      *
890      * @param value An object. if null, the returned value is true.
891      *
892      * @return true if the parameter could be successfully set to the
893      * specified value, or false if the parameter is not recognized or
894      * the requested value is not supported. This does not change the
895      * current value of the parameter itself.
896      */
897         public boolean canSetParameter(String name, Object value) {
898 
899         if (value == null){
900             //if null, the returned value is true.
901             //REVISIT: I dont like this --- even for unrecognized parameter it would
902             //return 'true'. I think it should return false in that case.
903             // Application will be surprised to find that setParameter throws not
904             //recognized exception when canSetParameter returns 'true' Then what is the use
905             //of having canSetParameter ??? - nb.
906             return true ;
907         }
908         if( value instanceof Boolean ){
909             //features whose parameter value can be set either 'true' or 'false'
910             // or they accept any boolean value -- so we just need to check that
911             // its a boolean value..
912             if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)
913                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)
914                 || name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)
915                 || name.equalsIgnoreCase(Constants.DOM_ENTITIES)
916                 || name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)
917                 || name.equalsIgnoreCase(Constants.DOM_NAMESPACES)
918                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
919                 || name.equalsIgnoreCase(Constants.DOM_WELLFORMED)
920                 || name.equalsIgnoreCase(Constants.DOM_INFOSET)
921                 || name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
922                 ) {
923                 return true;
924             }//features whose parameter value can not be set to 'true'
925             else if (
926                 name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
927                     || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
928                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
929                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
930                     ) {
931                     return (value.equals(Boolean.TRUE)) ? false : true;
932             }//features whose parameter value can not be set to 'false'
933             else if( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
934                     || name.equalsIgnoreCase(SEND_PSVI)
935                     ) {
936                     return (value.equals(Boolean.TRUE)) ? true : false;
937             }// if name is not among the above listed above -- its not recognized. return false
938             else {
939                 return false ;
940             }
941         }
942                 else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
943             return (value instanceof DOMErrorHandler) ? true : false ;
944         }
945         else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
946             return (value instanceof LSResourceResolver) ? true : false ;
947         }
948         else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
949             return (value instanceof String) ? true : false ;
950         }
951         else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
952             // REVISIT: should null value be supported?
953             //as of now we are only supporting W3C XML Schema
954             return ( (value instanceof String) && value.equals(Constants.NS_XMLSCHEMA) ) ? true : false ;
955         }
956         else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
957             // Xerces Symbol Table
958             return (value instanceof SymbolTable) ? true : false ;
959         }
960         else if (name.equalsIgnoreCase (GRAMMAR_POOL)){
961             return (value instanceof XMLGrammarPool) ? true : false ;
962         }
963         else {
964             //false if the parameter is not recognized or the requested value is not supported.
965             return false ;
966         }
967 
968         } //canSetParameter
969 
970     /**
971      *  DOM Level 3 CR - Experimental.
972      *
973      *  The list of the parameters supported by this
974      * <code>DOMConfiguration</code> object and for which at least one value
975      * can be set by the application. Note that this list can also contain
976      * parameter names defined outside this specification.
977      */
978     public DOMStringList getParameterNames() {
979         if (fRecognizedParameters == null){
980                         Vector parameters = new Vector();
981 
982                         //Add DOM recognized parameters
983                         //REVISIT: Would have been nice to have a list of
984                         //recognized paramters.
985                         parameters.add(Constants.DOM_COMMENTS);
986                         parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
987                         parameters.add(Constants.DOM_CDATA_SECTIONS);
988                         parameters.add(Constants.DOM_ENTITIES);
989                         parameters.add(Constants.DOM_SPLIT_CDATA);
990                         parameters.add(Constants.DOM_NAMESPACES);
991                         parameters.add(Constants.DOM_VALIDATE);
992 
993                         parameters.add(Constants.DOM_INFOSET);
994                         parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
995                         parameters.add(Constants.DOM_CANONICAL_FORM);
996                         parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
997                         parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
998                         parameters.add(Constants.DOM_WELLFORMED);
999 
1000                         parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
1001                         parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
1002 
1003                         parameters.add(Constants.DOM_ERROR_HANDLER);
1004                         parameters.add(Constants.DOM_SCHEMA_TYPE);
1005                         parameters.add(Constants.DOM_SCHEMA_LOCATION);
1006                         parameters.add(Constants.DOM_RESOURCE_RESOLVER);
1007 
1008                         //Add recognized xerces features and properties
1009                         parameters.add(GRAMMAR_POOL);
1010                         parameters.add(SYMBOL_TABLE);
1011                         parameters.add(SEND_PSVI);
1012 
1013                         fRecognizedParameters = new DOMStringListImpl(parameters);
1014 
1015         }
1016 
1017         return fRecognizedParameters;
1018     }//getParameterNames
1019 
1020     //
1021     // Protected methods
1022     //
1023 
1024     /**
1025      * reset all components before parsing
1026      */
1027     protected void reset() throws XNIException {
1028 
1029         if (fValidationManager != null)
1030             fValidationManager.reset();
1031 
1032         int count = fComponents.size();
1033         for (int i = 0; i < count; i++) {
1034             XMLComponent c = (XMLComponent) fComponents.get(i);
1035             c.reset(this);
1036         }
1037 
1038     } // reset()
1039 
1040     /**
1041      * Check a property. If the property is known and supported, this method
1042      * simply returns. Otherwise, the appropriate exception is thrown.
1043      *
1044      * @param propertyId The unique identifier (URI) of the property
1045      *                   being set.
1046      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
1047      *            requested feature is not known or supported.
1048      */
1049     protected PropertyState checkProperty(String propertyId)
1050         throws XMLConfigurationException {
1051 
1052         // special cases
1053         if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1054             final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
1055 
1056             //
1057             // http://xml.org/sax/properties/xml-string
1058             // Value type: String
1059             // Access: read-only
1060             //   Get the literal string of characters associated with the
1061             //   current event.  If the parser recognises and supports this
1062             //   property but is not currently parsing text, it should return
1063             //   null (this is a good way to check for availability before the
1064             //   parse begins).
1065             //
1066             if (suffixLength == Constants.XML_STRING_PROPERTY.length() &&
1067                 propertyId.endsWith(Constants.XML_STRING_PROPERTY)) {
1068                 // REVISIT - we should probably ask xml-dev for a precise
1069                 // definition of what this is actually supposed to return, and
1070                 // in exactly which circumstances.
1071                 return PropertyState.NOT_SUPPORTED;
1072             }
1073         }
1074 
1075         // check property
1076         return super.checkProperty(propertyId);
1077 
1078     } // checkProperty(String)
1079 
1080 
1081     protected void addComponent(XMLComponent component) {
1082 
1083         // don't add a component more than once
1084         if (fComponents.contains(component)) {
1085             return;
1086         }
1087         fComponents.add(component);
1088 
1089         // register component's recognized features
1090         String[] recognizedFeatures = component.getRecognizedFeatures();
1091         addRecognizedFeatures(recognizedFeatures);
1092 
1093         // register component's recognized properties
1094         String[] recognizedProperties = component.getRecognizedProperties();
1095         addRecognizedProperties(recognizedProperties);
1096 
1097     } // addComponent(XMLComponent)
1098 
1099     protected ValidationManager createValidationManager(){
1100         return new ValidationManager();
1101     }
1102 
1103 } // class XMLParser