001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.jaxp.validation;
019:
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.Map;
023:
024: import javax.xml.XMLConstants;
025:
026: import org.apache.xerces.impl.Constants;
027: import org.apache.xerces.impl.XMLEntityManager;
028: import org.apache.xerces.impl.XMLErrorReporter;
029: import org.apache.xerces.impl.validation.ValidationManager;
030: import org.apache.xerces.impl.xs.XMLSchemaValidator;
031: import org.apache.xerces.impl.xs.XSMessageFormatter;
032: import org.apache.xerces.util.DOMEntityResolverWrapper;
033: import org.apache.xerces.util.ErrorHandlerWrapper;
034: import org.apache.xerces.util.NamespaceSupport;
035: import org.apache.xerces.util.ParserConfigurationSettings;
036: import org.apache.xerces.util.SecurityManager;
037: import org.apache.xerces.util.SymbolTable;
038: import org.apache.xerces.xni.NamespaceContext;
039: import org.apache.xerces.xni.XNIException;
040: import org.apache.xerces.xni.parser.XMLComponent;
041: import org.apache.xerces.xni.parser.XMLComponentManager;
042: import org.apache.xerces.xni.parser.XMLConfigurationException;
043: import org.w3c.dom.ls.LSResourceResolver;
044: import org.xml.sax.ErrorHandler;
045:
046: /**
047: * <p>An implementation of XMLComponentManager for a schema validator.</p>
048: *
049: * @author Michael Glavassevich, IBM
050: * @version $Id: XMLSchemaValidatorComponentManager.java 447235 2006-09-18 05:01:44Z mrglavas $
051: */
052: final class XMLSchemaValidatorComponentManager extends
053: ParserConfigurationSettings implements XMLComponentManager {
054:
055: // feature identifiers
056:
057: /** Feature identifier: schema validation. */
058: private static final String SCHEMA_VALIDATION = Constants.XERCES_FEATURE_PREFIX
059: + Constants.SCHEMA_VALIDATION_FEATURE;
060:
061: /** Feature identifier: validation. */
062: private static final String VALIDATION = Constants.SAX_FEATURE_PREFIX
063: + Constants.VALIDATION_FEATURE;
064:
065: /** Feature identifier: use grammar pool only. */
066: private static final String USE_GRAMMAR_POOL_ONLY = Constants.XERCES_FEATURE_PREFIX
067: + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
068:
069: /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
070: protected static final String IGNORE_XSI_TYPE = Constants.XERCES_FEATURE_PREFIX
071: + Constants.IGNORE_XSI_TYPE_FEATURE;
072:
073: /** Feature identifier: whether to ignore ID/IDREF errors */
074: protected static final String ID_IDREF_CHECKING = Constants.XERCES_FEATURE_PREFIX
075: + Constants.ID_IDREF_CHECKING_FEATURE;
076:
077: /** Feature identifier: whether to ignore unparsed entity errors */
078: protected static final String UNPARSED_ENTITY_CHECKING = Constants.XERCES_FEATURE_PREFIX
079: + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
080:
081: /** Feature identifier: whether to ignore identity constraint errors */
082: protected static final String IDENTITY_CONSTRAINT_CHECKING = Constants.XERCES_FEATURE_PREFIX
083: + Constants.IDC_CHECKING_FEATURE;
084:
085: // property identifiers
086:
087: /** Property identifier: entity manager. */
088: private static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX
089: + Constants.ENTITY_MANAGER_PROPERTY;
090:
091: /** Property identifier: entity resolver. */
092: private static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX
093: + Constants.ENTITY_RESOLVER_PROPERTY;
094:
095: /** Property identifier: error handler. */
096: private static final String ERROR_HANDLER = Constants.XERCES_PROPERTY_PREFIX
097: + Constants.ERROR_HANDLER_PROPERTY;
098:
099: /** Property identifier: error reporter. */
100: private static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX
101: + Constants.ERROR_REPORTER_PROPERTY;
102:
103: /** Property identifier: namespace context. */
104: private static final String NAMESPACE_CONTEXT = Constants.XERCES_PROPERTY_PREFIX
105: + Constants.NAMESPACE_CONTEXT_PROPERTY;
106:
107: /** Property identifier: XML Schema validator. */
108: private static final String SCHEMA_VALIDATOR = Constants.XERCES_PROPERTY_PREFIX
109: + Constants.SCHEMA_VALIDATOR_PROPERTY;
110:
111: /** Property identifier: security manager. */
112: private static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX
113: + Constants.SECURITY_MANAGER_PROPERTY;
114:
115: /** Property identifier: symbol table. */
116: private static final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX
117: + Constants.SYMBOL_TABLE_PROPERTY;
118:
119: /** Property identifier: validation manager. */
120: private static final String VALIDATION_MANAGER = Constants.XERCES_PROPERTY_PREFIX
121: + Constants.VALIDATION_MANAGER_PROPERTY;
122:
123: /** Property identifier: grammar pool. */
124: private static final String XMLGRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX
125: + Constants.XMLGRAMMAR_POOL_PROPERTY;
126:
127: //
128: // Data
129: //
130:
131: /**
132: * fConfigUpdated is set to true if there has been any change to the configuration settings,
133: * i.e a feature or a property was changed.
134: */
135: private boolean fConfigUpdated = true;
136:
137: /**
138: * Tracks whether the validator should use components from
139: * the grammar pool to the exclusion of all others.
140: */
141: private boolean fUseGrammarPoolOnly;
142:
143: /** Lookup map for components required for validation. **/
144: private final HashMap fComponents = new HashMap();
145:
146: //
147: // Components
148: //
149:
150: /** Entity manager. */
151: private XMLEntityManager fEntityManager;
152:
153: /** Error reporter. */
154: private XMLErrorReporter fErrorReporter;
155:
156: /** Namespace context. */
157: private NamespaceContext fNamespaceContext;
158:
159: /** XML Schema validator. */
160: private XMLSchemaValidator fSchemaValidator;
161:
162: /** Validation manager. */
163: private ValidationManager fValidationManager;
164:
165: //
166: // Configuration
167: //
168:
169: /** Stores initial feature values for validator reset. */
170: private HashMap fInitFeatures = new HashMap();
171:
172: /** Stores initial property values for validator reset. */
173: private HashMap fInitProperties = new HashMap();
174:
175: /** Stores the initial security manager. */
176: private SecurityManager fInitSecurityManager = null;
177:
178: //
179: // User Objects
180: //
181:
182: /** Application's ErrorHandler. **/
183: private ErrorHandler fErrorHandler = null;
184:
185: /** Application's LSResourceResolver. */
186: private LSResourceResolver fResourceResolver = null;
187:
188: /** Constructs a component manager suitable for Xerces' schema validator. */
189: public XMLSchemaValidatorComponentManager(
190: XSGrammarPoolContainer grammarContainer) {
191:
192: // setup components
193: fEntityManager = new XMLEntityManager();
194: fComponents.put(ENTITY_MANAGER, fEntityManager);
195:
196: fErrorReporter = new XMLErrorReporter();
197: fComponents.put(ERROR_REPORTER, fErrorReporter);
198:
199: fNamespaceContext = new NamespaceSupport();
200: fComponents.put(NAMESPACE_CONTEXT, fNamespaceContext);
201:
202: fSchemaValidator = new XMLSchemaValidator();
203: fComponents.put(SCHEMA_VALIDATOR, fSchemaValidator);
204:
205: fValidationManager = new ValidationManager();
206: fComponents.put(VALIDATION_MANAGER, fValidationManager);
207:
208: // setup other properties
209: fComponents.put(ENTITY_RESOLVER, null);
210: fComponents.put(ERROR_HANDLER, null);
211: fComponents.put(SECURITY_MANAGER, null);
212: fComponents.put(SYMBOL_TABLE, new SymbolTable());
213:
214: // setup grammar pool
215: fComponents.put(XMLGRAMMAR_POOL, grammarContainer
216: .getGrammarPool());
217: fUseGrammarPoolOnly = grammarContainer.isFullyComposed();
218:
219: // add schema message formatter to error reporter
220: fErrorReporter.putMessageFormatter(
221: XSMessageFormatter.SCHEMA_DOMAIN,
222: new XSMessageFormatter());
223:
224: // add all recognized features and properties and apply their defaults
225: addRecognizedParamsAndSetDefaults(fEntityManager,
226: grammarContainer);
227: addRecognizedParamsAndSetDefaults(fErrorReporter,
228: grammarContainer);
229: addRecognizedParamsAndSetDefaults(fSchemaValidator,
230: grammarContainer);
231:
232: // if the secure processing feature is set to true, add a security manager to the configuration
233: Boolean secureProcessing = grammarContainer
234: .getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
235: if (Boolean.TRUE.equals(secureProcessing)) {
236: fInitSecurityManager = new SecurityManager();
237: }
238: fComponents.put(SECURITY_MANAGER, fInitSecurityManager);
239:
240: /* TODO: are other XMLSchemaValidator default values never set?
241: * Initial investigation indicates that they aren't set, but
242: * that they all have default values of false, so it works out
243: * anyway -PM
244: */
245: fFeatures.put(IGNORE_XSI_TYPE, Boolean.FALSE);
246: fFeatures.put(ID_IDREF_CHECKING, Boolean.TRUE);
247: fFeatures.put(IDENTITY_CONSTRAINT_CHECKING, Boolean.TRUE);
248: fFeatures.put(UNPARSED_ENTITY_CHECKING, Boolean.TRUE);
249: }
250:
251: /**
252: * Returns the state of a feature.
253: *
254: * @param featureId The feature identifier.
255: * @return true if the feature is supported
256: *
257: * @throws XMLConfigurationException Thrown for configuration error.
258: * In general, components should
259: * only throw this exception if
260: * it is <strong>really</strong>
261: * a critical error.
262: */
263: public boolean getFeature(String featureId)
264: throws XMLConfigurationException {
265: if (PARSER_SETTINGS.equals(featureId)) {
266: return fConfigUpdated;
267: } else if (VALIDATION.equals(featureId)
268: || SCHEMA_VALIDATION.equals(featureId)) {
269: return true;
270: } else if (USE_GRAMMAR_POOL_ONLY.equals(featureId)) {
271: return fUseGrammarPoolOnly;
272: } else if (XMLConstants.FEATURE_SECURE_PROCESSING
273: .equals(featureId)) {
274: return getProperty(SECURITY_MANAGER) != null;
275: }
276: return super .getFeature(featureId);
277: }
278:
279: /**
280: * Set the state of a feature.
281: *
282: * @param featureId The unique identifier (URI) of the feature.
283: * @param state The requested state of the feature (true or false).
284: *
285: * @exception XMLConfigurationException If the requested feature is not known.
286: */
287: public void setFeature(String featureId, boolean value)
288: throws XMLConfigurationException {
289: if (PARSER_SETTINGS.equals(featureId)) {
290: throw new XMLConfigurationException(
291: XMLConfigurationException.NOT_SUPPORTED, featureId);
292: } else if (value == false
293: && (VALIDATION.equals(featureId) || SCHEMA_VALIDATION
294: .equals(featureId))) {
295: throw new XMLConfigurationException(
296: XMLConfigurationException.NOT_SUPPORTED, featureId);
297: } else if (USE_GRAMMAR_POOL_ONLY.equals(featureId)
298: && value != fUseGrammarPoolOnly) {
299: throw new XMLConfigurationException(
300: XMLConfigurationException.NOT_SUPPORTED, featureId);
301: }
302: if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(featureId)) {
303: setProperty(SECURITY_MANAGER, value ? new SecurityManager()
304: : null);
305: return;
306: }
307: fConfigUpdated = true;
308: fEntityManager.setFeature(featureId, value);
309: fErrorReporter.setFeature(featureId, value);
310: fSchemaValidator.setFeature(featureId, value);
311: if (!fInitFeatures.containsKey(featureId)) {
312: boolean current = super .getFeature(featureId);
313: fInitFeatures.put(featureId, current ? Boolean.TRUE
314: : Boolean.FALSE);
315: }
316: super .setFeature(featureId, value);
317: }
318:
319: /**
320: * Returns the value of a property.
321: *
322: * @param propertyId The property identifier.
323: * @return the value of the property
324: *
325: * @throws XMLConfigurationException Thrown for configuration error.
326: * In general, components should
327: * only throw this exception if
328: * it is <strong>really</strong>
329: * a critical error.
330: */
331: public Object getProperty(String propertyId)
332: throws XMLConfigurationException {
333: final Object component = fComponents.get(propertyId);
334: if (component != null) {
335: return component;
336: } else if (fComponents.containsKey(propertyId)) {
337: return null;
338: }
339: return super .getProperty(propertyId);
340: }
341:
342: /**
343: * Sets the state of a property.
344: *
345: * @param propertyId The unique identifier (URI) of the property.
346: * @param value The requested state of the property.
347: *
348: * @exception XMLConfigurationException If the requested property is not known.
349: */
350: public void setProperty(String propertyId, Object value)
351: throws XMLConfigurationException {
352: if (ENTITY_MANAGER.equals(propertyId)
353: || ERROR_REPORTER.equals(propertyId)
354: || NAMESPACE_CONTEXT.equals(propertyId)
355: || SCHEMA_VALIDATOR.equals(propertyId)
356: || SYMBOL_TABLE.equals(propertyId)
357: || VALIDATION_MANAGER.equals(propertyId)
358: || XMLGRAMMAR_POOL.equals(propertyId)) {
359: throw new XMLConfigurationException(
360: XMLConfigurationException.NOT_SUPPORTED, propertyId);
361: }
362: fConfigUpdated = true;
363: fEntityManager.setProperty(propertyId, value);
364: fErrorReporter.setProperty(propertyId, value);
365: fSchemaValidator.setProperty(propertyId, value);
366: if (ENTITY_RESOLVER.equals(propertyId)
367: || ERROR_HANDLER.equals(propertyId)
368: || SECURITY_MANAGER.equals(propertyId)) {
369: fComponents.put(propertyId, value);
370: return;
371: }
372: if (!fInitProperties.containsKey(propertyId)) {
373: fInitProperties.put(propertyId, super
374: .getProperty(propertyId));
375: }
376: super .setProperty(propertyId, value);
377: }
378:
379: /**
380: * Adds all of the component's recognized features and properties
381: * to the list of default recognized features and properties, and
382: * sets default values on the configuration for features and
383: * properties which were previously absent from the configuration.
384: *
385: * @param component The component whose recognized features
386: * and properties will be added to the configuration
387: */
388: public void addRecognizedParamsAndSetDefaults(
389: XMLComponent component,
390: XSGrammarPoolContainer grammarContainer) {
391:
392: // register component's recognized features
393: final String[] recognizedFeatures = component
394: .getRecognizedFeatures();
395: addRecognizedFeatures(recognizedFeatures);
396:
397: // register component's recognized properties
398: final String[] recognizedProperties = component
399: .getRecognizedProperties();
400: addRecognizedProperties(recognizedProperties);
401:
402: // set default values
403: setFeatureDefaults(component, recognizedFeatures,
404: grammarContainer);
405: setPropertyDefaults(component, recognizedProperties);
406: }
407:
408: /** Calls reset on each of the components owned by this component manager. **/
409: public void reset() throws XNIException {
410: fNamespaceContext.reset();
411: fValidationManager.reset();
412: fEntityManager.reset(this );
413: fErrorReporter.reset(this );
414: fSchemaValidator.reset(this );
415: // Mark configuration as fixed.
416: fConfigUpdated = false;
417: }
418:
419: void setErrorHandler(ErrorHandler errorHandler) {
420: fErrorHandler = errorHandler;
421: setProperty(ERROR_HANDLER,
422: (errorHandler != null) ? new ErrorHandlerWrapper(
423: errorHandler) : new ErrorHandlerWrapper(
424: DraconianErrorHandler.getInstance()));
425: }
426:
427: ErrorHandler getErrorHandler() {
428: return fErrorHandler;
429: }
430:
431: void setResourceResolver(LSResourceResolver resourceResolver) {
432: fResourceResolver = resourceResolver;
433: setProperty(ENTITY_RESOLVER, new DOMEntityResolverWrapper(
434: resourceResolver));
435: }
436:
437: public LSResourceResolver getResourceResolver() {
438: return fResourceResolver;
439: }
440:
441: /** Cleans out configuration, restoring it to its initial state. */
442: void restoreInitialState() {
443: fConfigUpdated = true;
444:
445: // Remove error resolver and error handler
446: fComponents.put(ENTITY_RESOLVER, null);
447: fComponents.put(ERROR_HANDLER, null);
448:
449: // Restore initial security manager
450: fComponents.put(SECURITY_MANAGER, fInitSecurityManager);
451:
452: // Reset feature and property values to their initial values
453: if (!fInitFeatures.isEmpty()) {
454: Iterator iter = fInitFeatures.entrySet().iterator();
455: while (iter.hasNext()) {
456: Map.Entry entry = (Map.Entry) iter.next();
457: String name = (String) entry.getKey();
458: boolean value = ((Boolean) entry.getValue())
459: .booleanValue();
460: super .setFeature(name, value);
461: }
462: fInitFeatures.clear();
463: }
464: if (!fInitProperties.isEmpty()) {
465: Iterator iter = fInitProperties.entrySet().iterator();
466: while (iter.hasNext()) {
467: Map.Entry entry = (Map.Entry) iter.next();
468: String name = (String) entry.getKey();
469: Object value = entry.getValue();
470: super .setProperty(name, value);
471: }
472: fInitProperties.clear();
473: }
474: }
475:
476: /** Sets feature defaults for the given component on this configuration. */
477: private void setFeatureDefaults(final XMLComponent component,
478: final String[] recognizedFeatures,
479: XSGrammarPoolContainer grammarContainer) {
480: if (recognizedFeatures != null) {
481: for (int i = 0; i < recognizedFeatures.length; ++i) {
482: String featureId = recognizedFeatures[i];
483: Boolean state = grammarContainer.getFeature(featureId);
484: if (state == null) {
485: state = component.getFeatureDefault(featureId);
486: }
487: if (state != null) {
488: // Do not overwrite values already set on the configuration.
489: if (!fFeatures.containsKey(featureId)) {
490: fFeatures.put(featureId, state);
491: // For newly added components who recognize this feature
492: // but did not offer a default value, we need to make
493: // sure these components will get an opportunity to read
494: // the value before parsing begins.
495: fConfigUpdated = true;
496: }
497: }
498: }
499: }
500: }
501:
502: /** Sets property defaults for the given component on this configuration. */
503: private void setPropertyDefaults(final XMLComponent component,
504: final String[] recognizedProperties) {
505: if (recognizedProperties != null) {
506: for (int i = 0; i < recognizedProperties.length; ++i) {
507: String propertyId = recognizedProperties[i];
508: Object value = component.getPropertyDefault(propertyId);
509: if (value != null) {
510: // Do not overwrite values already set on the configuration.
511: if (!fProperties.containsKey(propertyId)) {
512: fProperties.put(propertyId, value);
513: // For newly added components who recognize this property
514: // but did not offer a default value, we need to make
515: // sure these components will get an opportunity to read
516: // the value before parsing begins.
517: fConfigUpdated = true;
518: }
519: }
520: }
521: }
522: }
523:
524: } // XMLSchemaValidatorComponentManager
|