mrglavas 2004/03/10 15:05:24 Modified: java/src/org/apache/xerces/impl/xs XMLSchemaValidator.java java/src/org/apache/xerces/impl/xs/identity Field.java FieldActivator.java Log: Fixing a thread-safety problem regarding identity constraints. Fields
which are contained in a SchemaGrammar were mutable; keeping the state of whether a field is permitted to match a value in order to detect whether there is more than one match for a field in a given scope. This caused spurious errors about duplicate field matches when a grammar with identity constraints was shared across parsers on different threads. Applying a similar fix to the one that Khaled made to Xerces-C++ to make this portion of the grammar stateless. Revision Changes Path 1.153 +47 -18 xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaValidator.java Index: XMLSchemaValidator.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaValidator.java,v retrieving revision 1.152 retrieving revision 1.153 diff -u -r1.152 -r1.153 --- XMLSchemaValidator.java 24 Feb 2004 22:59:11 -0000 1.152 +++ XMLSchemaValidator.java 10 Mar 2004 23:05:24 -0000 1.153 @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.Enumeration; import java.util.Hashtable; +import java.util.HashMap; import java.util.Stack; import java.util.Vector; @@ -251,6 +252,12 @@ // If it is not present in calls that we're passing on, we *must* // clear this before we introduce it into the pipeline. protected final AugmentationsImpl fAugmentations = new AugmentationsImpl(); + + /** + * Map which is used to catch instance documents that try + * and match a field several times in the same scope. + */ + protected final HashMap fMayMatchFieldMap = new HashMap(); // this is included for the convenience of handleEndElement protected XMLString fDefaultValue; @@ -1233,7 +1240,7 @@ fInCDATA = false; fMatcherStack.clear(); - + fMayMatchFieldMap.clear(); // get error reporter fXSIErrorReporter.reset((XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER)); @@ -1380,21 +1387,21 @@ } // startValueScopeFor(IdentityConstraint identityConstraint) - /** - * Request to activate the specified field. This method returns the - * matcher for the field. - * - * @param field The field to activate. - */ - public XPathMatcher activateField(Field field, int initialDepth) { - ValueStore valueStore = - fValueStoreCache.getValueStoreFor(field.getIdentityConstraint(), initialDepth); - field.setMayMatch(true); - XPathMatcher matcher = field.createMatcher(valueStore); - fMatcherStack.addMatcher(matcher); - matcher.startDocumentFragment(); - return matcher; - } // activateField(Field):XPathMatcher + /** + * Request to activate the specified field. This method returns the + * matcher for the field. + * + * @param field The field to activate. + */ + public XPathMatcher activateField(Field field, int initialDepth) { + ValueStore valueStore = + fValueStoreCache.getValueStoreFor(field.getIdentityConstraint(), initialDepth); + setMayMatch(field, Boolean.TRUE); + XPathMatcher matcher = field.createMatcher(this, valueStore); + fMatcherStack.addMatcher(matcher); + matcher.startDocumentFragment(); + return matcher; + } // activateField(Field):XPathMatcher /** * Ends the value scope for the specified identity constraint. @@ -1408,6 +1415,28 @@ valueStore.endValueScope(); } // endValueScopeFor(IdentityConstraint) + + /** + * Sets whether the given field is permitted to match a value. + * This should be used to catch instance documents that try + * and match a field several times in the same scope. + * + * @param field The field that may be permitted to be matched. + * @param state Boolean indiciating whether the field may be matched. + */ + public void setMayMatch(Field field, Boolean state) { + fMayMatchFieldMap.put(field, state); + } // setMayMatch(Field, Boolean) + + /** + * Returns whether the given field is permitted to match a value. + * + * @param field The field that may be permitted to be matched. + * @return Boolean indicating whether the field may be matched. + */ + public Boolean mayMatch(Field field) { + return (Boolean) fMayMatchFieldMap.get(field); + } // mayMatch(Field):Boolean // a utility method for Identity constraints private void activateSelectorFor(IdentityConstraint ic) { @@ -3345,7 +3374,7 @@ reportSchemaError(code, new Object[] { field.toString()}); return; } - if (!field.mayMatch()) { + if (Boolean.TRUE != mayMatch(field)) { String code = "FieldMultipleMatch"; reportSchemaError(code, new Object[] { field.toString()}); } else { 1.16 +12 -8 xml-xerces/java/src/org/apache/xerces/impl/xs/identity/Field.java Index: Field.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/identity/Field.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- Field.java 24 Feb 2004 22:59:14 -0000 1.15 +++ Field.java 10 Mar 2004 23:05:24 -0000 1.16 @@ -43,7 +43,7 @@ // whether this field can be matched; used to catch instance documents // that try and match a field several times in the same scope. - protected boolean mayMatch = true; + // protected boolean mayMatch = true; // // Constructors @@ -60,7 +60,7 @@ // Public methods // - // sets mayMatch + /** // sets mayMatch public void setMayMatch(boolean b) { mayMatch = b; } // setMayMatch(boolean); @@ -68,7 +68,7 @@ // returns mayMatch public boolean mayMatch() { return mayMatch; - } // mayMatch():boolean + } // mayMatch():boolean **/ /** Returns the field XPath. */ public org.apache.xerces.impl.xpath.XPath getXPath() { @@ -83,8 +83,8 @@ // factory method /** Creates a field matcher. */ - public XPathMatcher createMatcher(ValueStore store) { - return new Field.Matcher(fXPath, store); + public XPathMatcher createMatcher(FieldActivator activator, ValueStore store) { + return new Field.Matcher(fXPath, activator, store); } // createMatcher(ValueStore):XPathMatcher // @@ -153,6 +153,9 @@ // Data // + /** Field activator. */ + protected FieldActivator fFieldActivator; + /** Value store for data values. */ protected ValueStore fStore; @@ -161,8 +164,9 @@ // /** Constructs a field matcher. */ - public Matcher(Field.XPath xpath, ValueStore store) { + public Matcher(Field.XPath xpath, FieldActivator activator, ValueStore store) { super(xpath); + fFieldActivator = activator; fStore = store; } // <init>(Field.XPath,ValueStore) @@ -184,7 +188,7 @@ // once we've stored the value for this field, we set the mayMatch // member to false so that, in the same scope, we don't match any more // values (and throw an error instead). - mayMatch = false; + fFieldActivator.setMayMatch(Field.this, Boolean.FALSE); } // matched(String) protected void handleContent(XSTypeDefinition type, boolean nillable, Object actualValue) { 1.6 +23 -5 xml-xerces/java/src/org/apache/xerces/impl/xs/identity/FieldActivator.java Index: FieldActivator.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/identity/FieldActivator.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- FieldActivator.java 24 Feb 2004 22:59:14 -0000 1.5 +++ FieldActivator.java 10 Mar 2004 23:05:24 -0000 1.6 @@ -1,5 +1,5 @@ /* - * Copyright 2001, 2002,2004 The Apache Software Foundation. + * Copyright 2001,2002,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,13 +46,31 @@ /** * Request to activate the specified field. This method returns the * matcher for the field. - * It's also important for the implementor to ensure that the Field realizes that - * it is permitted to match a value--that is, to call the field's setMayMatch(boolean) method. + * It's also important for the implementor to ensure that it marks whether a Field + * is permitted to match a value--that is, to call the setMayMatch(Field, Boolean) method. * * @param field The field to activate. - * @param initialDepth the 0-indexed depth in the instance document at which the Selector began to match. + * @param initialDepth the 0-indexed depth in the instance document at which the Selector began to match. */ public XPathMatcher activateField(Field field, int initialDepth); + + /** + * Sets whether the given field is permitted to match a value. + * This should be used to catch instance documents that try + * and match a field several times in the same scope. + * + * @param field The field that may be permitted to be matched. + * @param state Boolean indiciating whether the field may be matched. + */ + public void setMayMatch(Field field, Boolean state); + + /** + * Returns whether the given field is permitted to match a value. + * + * @param field The field that may be permitted to be matched. + * @return Boolean indicating whether the field may be matched. + */ + public Boolean mayMatch(Field field); /** * Ends the value scope for the specified identity constraint. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]