Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xerces.impl.xs.traversers;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Stack;
import java.util.Vector;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.XMLEntityManager;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
import org.apache.xerces.impl.dv.SchemaDVFactory;
import org.apache.xerces.impl.dv.xs.DecimalDV;
import org.apache.xerces.impl.dv.xs.TypeValidator;
import org.apache.xerces.impl.dv.xs.TypeValidatorHelper;
import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
import org.apache.xerces.impl.xs.SchemaGrammar;
import org.apache.xerces.impl.xs.SchemaNamespaceSupport;
import org.apache.xerces.impl.xs.SchemaSymbols;
import org.apache.xerces.impl.xs.XMLSchemaException;
import org.apache.xerces.impl.xs.XMLSchemaLoader;
import org.apache.xerces.impl.xs.XSAttributeDecl;
import org.apache.xerces.impl.xs.XSAttributeGroupDecl;
import org.apache.xerces.impl.xs.XSComplexTypeDecl;
import org.apache.xerces.impl.xs.XSConstraints;
import org.apache.xerces.impl.xs.XSDDescription;
import org.apache.xerces.impl.xs.XSDeclarationPool;
import org.apache.xerces.impl.xs.XSElementDecl;
import org.apache.xerces.impl.xs.XSGrammarBucket;
import org.apache.xerces.impl.xs.XSGroupDecl;
import org.apache.xerces.impl.xs.XSMessageFormatter;
import org.apache.xerces.impl.xs.XSModelGroupImpl;
import org.apache.xerces.impl.xs.XSNotationDecl;
import org.apache.xerces.impl.xs.XSParticleDecl;
import org.apache.xerces.impl.xs.identity.IdentityConstraint;
import org.apache.xerces.impl.xs.opti.ElementImpl;
import org.apache.xerces.impl.xs.opti.SchemaDOMParser;
import org.apache.xerces.impl.xs.opti.SchemaParsingConfig;
import org.apache.xerces.impl.xs.util.SimpleLocator;
import org.apache.xerces.impl.xs.util.XSInputSource;
import org.apache.xerces.parsers.SAXParser;
import org.apache.xerces.parsers.XML11Configuration;
import org.apache.xerces.util.DOMInputSource;
import org.apache.xerces.util.DOMUtil;
import org.apache.xerces.util.DefaultErrorHandler;
import org.apache.xerces.util.ErrorHandlerWrapper;
import org.apache.xerces.util.SAXInputSource;
import org.apache.xerces.util.StAXInputSource;
import org.apache.xerces.util.StAXLocationWrapper;
import org.apache.xerces.util.SymbolHash;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.util.URI.MalformedURIException;
import org.apache.xerces.util.XMLSymbols;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.grammars.Grammar;
import org.apache.xerces.xni.grammars.XMLGrammarDescription;
import org.apache.xerces.xni.grammars.XMLGrammarPool;
import org.apache.xerces.xni.grammars.XMLSchemaDescription;
import org.apache.xerces.xni.parser.XMLComponentManager;
import org.apache.xerces.xni.parser.XMLConfigurationException;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLErrorHandler;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.apache.xerces.xni.parser.XMLParseException;
import org.apache.xerces.xs.StringList;
import org.apache.xerces.xs.XSAttributeDeclaration;
import org.apache.xerces.xs.XSAttributeGroupDefinition;
import org.apache.xerces.xs.XSAttributeUse;
import org.apache.xerces.xs.XSConstants;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSModelGroup;
import org.apache.xerces.xs.XSModelGroupDefinition;
import org.apache.xerces.xs.XSNamedMap;
import org.apache.xerces.xs.XSObject;
import org.apache.xerces.xs.XSObjectList;
import org.apache.xerces.xs.XSParticle;
import org.apache.xerces.xs.XSSimpleTypeDefinition;
import org.apache.xerces.xs.XSTerm;
import org.apache.xerces.xs.XSTypeDefinition;
import org.apache.xerces.xs.datatypes.ObjectList;
import org.apache.xerces.xs.datatypes.XSDecimal;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* The purpose of this class is to co-ordinate the construction of a
* grammar object corresponding to a schema. To do this, it must be
* prepared to parse several schema documents (for instance if the
* schema document originally referred to contains or
* information items). If any of the schemas imports a
* schema, other grammars may be constructed as a side-effect.
*
* @xerces.internal
*
* @author Neil Graham, IBM
* @author Pavani Mukthipudi, Sun Microsystems
*
* @version $Id: XSDHandler.java 1565084 2014-02-06 05:39:07Z mukulg $
*/
public class XSDHandler {
/** Feature identifier: validation. */
protected static final String VALIDATION =
Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
/** feature identifier: XML Schema validation */
protected static final String XMLSCHEMA_VALIDATION =
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
/** Feature identifier: allow java encodings */
protected static final String ALLOW_JAVA_ENCODINGS =
Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
/** Feature identifier: continue after fatal error */
protected static final String CONTINUE_AFTER_FATAL_ERROR =
Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
/** Feature identifier: allow java encodings */
protected static final String STANDARD_URI_CONFORMANT_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
/** Feature: disallow doctype*/
protected static final String DISALLOW_DOCTYPE =
Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
/** Feature: generate synthetic annotations */
protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
/** Feature identifier: validate annotations. */
protected static final String VALIDATE_ANNOTATIONS =
Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
/** Feature identifier: honour all schemaLocations */
protected static final String HONOUR_ALL_SCHEMALOCATIONS =
Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
/** Feature identifier: namespace growth */
protected static final String NAMESPACE_GROWTH =
Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
/** Feature identifier: tolerate duplicates */
protected static final String TOLERATE_DUPLICATES =
Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
/** Feature identifier: Full XPath 2.0 for CTA evaluations */
protected static final String CTA_FULL_XPATH =
Constants.XERCES_FEATURE_PREFIX + Constants.CTA_FULL_XPATH_CHECKING_FEATURE;
/** Feature identifier: comment and PI nodes for */
protected static final String ASSERT_COMMENT_PI =
Constants.XERCES_FEATURE_PREFIX + Constants.ASSERT_COMMENT_PI_CHECKING_FEATURE;
/** Feature identifier: namespace prefixes. */
private static final String NAMESPACE_PREFIXES =
Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
/** Feature identifier: string interning. */
protected static final String STRING_INTERNING =
Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
/** Property identifier: error handler. */
protected static final String ERROR_HANDLER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
/** Property identifier: JAXP schema source. */
protected static final String JAXP_SCHEMA_SOURCE =
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
/** Property identifier: entity resolver. */
public static final String ENTITY_RESOLVER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
/** Property identifier: entity manager. */
protected static final String ENTITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
/** Property identifier: error reporter. */
public static final String ERROR_REPORTER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
/** Property identifier: grammar pool. */
public static final String XMLGRAMMAR_POOL =
Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
/** Property identifier: symbol table. */
public static final String SYMBOL_TABLE =
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
/** Property identifier: security manager. */
protected static final String SECURITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
/** Property identifier: locale. */
protected static final String LOCALE =
Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
/** Property identifier: datatype xml version. */
protected static final String DATATYPE_XML_VERSION =
Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_XML_VERSION_PROPERTY;
protected static final boolean DEBUG_NODE_POOL = false;
// Data
// different sorts of declarations; should make lookup and
// traverser calling more efficient/less bulky.
final static int ATTRIBUTE_TYPE = 1;
final static int ATTRIBUTEGROUP_TYPE = 2;
final static int ELEMENT_TYPE = 3;
final static int GROUP_TYPE = 4;
final static int IDENTITYCONSTRAINT_TYPE = 5;
final static int NOTATION_TYPE = 6;
final static int TYPEDECL_TYPE = 7;
// this string gets appended to redefined names; it's purpose is to be
// as unlikely as possible to cause collisions.
public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi";
//
//protected data that can be accessable by any traverser
// stores decl
protected Hashtable fNotationRegistry = new Hashtable();
protected XSDeclarationPool fDeclPool = null;
// These tables correspond to the symbol spaces defined in the
// spec.
// They are keyed with a QName (that is, String("URI,localpart) and
// their values are nodes corresponding to the given name's decl.
// By asking the node for its ownerDocument and looking in
// XSDocumentInfoRegistry we can easily get the corresponding
// XSDocumentInfo object.
private Hashtable fUnparsedAttributeRegistry = new Hashtable();
private Hashtable fUnparsedAttributeGroupRegistry = new Hashtable();
private Hashtable fUnparsedElementRegistry = new Hashtable();
private Hashtable fUnparsedGroupRegistry = new Hashtable();
private Hashtable fUnparsedIdentityConstraintRegistry = new Hashtable();
private Hashtable fUnparsedNotationRegistry = new Hashtable();
private Hashtable fUnparsedTypeRegistry = new Hashtable();
// Compensation for the above hashtables to locate XSDocumentInfo,
// Since we may take Schema Element directly, so can not get the
// corresponding XSDocumentInfo object just using above hashtables.
private Hashtable fUnparsedAttributeRegistrySub = new Hashtable();
private Hashtable fUnparsedAttributeGroupRegistrySub = new Hashtable();
private Hashtable fUnparsedElementRegistrySub = new Hashtable();
private Hashtable fUnparsedGroupRegistrySub = new Hashtable();
private Hashtable fUnparsedIdentityConstraintRegistrySub = new Hashtable();
private Hashtable fUnparsedNotationRegistrySub = new Hashtable();
private Hashtable fUnparsedTypeRegistrySub = new Hashtable();
// Stores XSDocumentInfo (keyed by component name), to check for duplicate
// components declared within the same xsd document
private Hashtable fUnparsedRegistriesExt[] = new Hashtable[] {
null,
new Hashtable(), // ATTRIBUTE_TYPE
new Hashtable(), // ATTRIBUTEGROUP_TYPE
new Hashtable(), // ELEMENT_TYPE
new Hashtable(), // GROUP_TYPE
new Hashtable(), // IDENTITYCONSTRAINT_TYPE
new Hashtable(), // NOTATION_TYPE
new Hashtable(), // TYPEDECL_TYPE
};
// this is keyed with a documentNode (or the schemaRoot nodes
// contained in the XSDocumentInfo objects) and its value is the
// XSDocumentInfo object corresponding to that document.
// Basically, the function of this registry is to be a link
// between the nodes we fetch from calls to the fUnparsed*
// arrays and the XSDocumentInfos they live in.
private Hashtable fXSDocumentInfoRegistry = new Hashtable();
// this hashtable is keyed on by XSDocumentInfo objects. Its values
// are Vectors containing the XSDocumentInfo objects d,
// ed or d by the key XSDocumentInfo.
private Hashtable fDependencyMap = new Hashtable();
// this hashtable is keyed on by a target namespace. Its values
// are Vectors containing namespaces imported by schema documents
// with the key target namespace.
// if an imprted schema has absent namespace, the value "null" is stored.
private Hashtable fImportMap = new Hashtable();
// all namespaces that imports other namespaces
// if the importing schema has absent namespace, empty string is stored.
// (because the key of a hashtable can't be null.)
private Vector fAllTNSs = new Vector();
// stores instance document mappings between namespaces and schema hints
private Hashtable fLocationPairs = null;
private static final Hashtable EMPTY_TABLE = new Hashtable();
// Records which nodes are hidden when the input is a DOMInputSource.
Hashtable fHiddenNodes = null;
// Conditional inclustion
private static final String XSD_VERSION_1_0 = "1.0";
private static final String XSD_VERSION_1_1 = "1.1";
private static final TypeValidator DECIMAL_DV = new DecimalDV();
private static final XSDecimal SUPPORTED_VERSION_1_0 = getSupportedVersion(XSD_VERSION_1_0);
private static final XSDecimal SUPPORTED_VERSION_1_1 = getSupportedVersion(XSD_VERSION_1_1);
private XSDecimal fSupportedVersion = SUPPORTED_VERSION_1_0;
private static XSDecimal getSupportedVersion(String version) {
XSDecimal result = null;
try {
result = (XSDecimal) DECIMAL_DV.getActualValue(version, null);
}
catch (InvalidDatatypeValueException ide) {
}
return result;
}
// convenience methods
private String null2EmptyString(String ns) {
return ns == null ? XMLSymbols.EMPTY_STRING : ns;
}
private String emptyString2Null(String ns) {
return ns == XMLSymbols.EMPTY_STRING ? null : ns;
}
// use Schema Element to lookup the SystemId.
private String doc2SystemId(Element ele) {
String documentURI = null;
final Document ownerDoc = ele.getOwnerDocument();
if (ownerDoc instanceof org.apache.xerces.impl.xs.opti.SchemaDOM) {
documentURI = ((org.apache.xerces.impl.xs.opti.SchemaDOM) ownerDoc).getDocumentURI();
}
else if (ownerDoc.getImplementation().hasFeature("Core", "3.0")) {
documentURI = ownerDoc.getDocumentURI();
}
return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele);
}
// This vector stores strings which are combinations of the
// publicId and systemId of the inputSource corresponding to a
// schema document. This combination is used so that the user's
// EntityResolver can provide a consistent way of identifying a
// schema document that is included in multiple other schemas.
private Hashtable fTraversed = new Hashtable();
// this hashtable contains a mapping from Schema Element to its systemId
// this is useful to resolve a uri relative to the referring document
private Hashtable fDoc2SystemId = new Hashtable();
//
private Hashtable fDoc2DatatypeXMLVersion = null;
// the primary XSDocumentInfo we were called to parse
private XSDocumentInfo fRoot = null;
// This hashtable's job is to act as a link between the Schema Element and its
// XSDocumentInfo object.
private Hashtable fDoc2XSDocumentMap = new Hashtable();
// map between elements and the XSDocumentInfo
// objects that correspond to the documents being redefined.
private Hashtable fRedefine2XSDMap = new Hashtable();
// map between a schema document and the schema documents it is overriding.
// schema documents are represented by XSDocumentInfo objects.
private Hashtable fOverrideDependencyMap = new Hashtable();
// map between elements and the namespace support
private Hashtable fRedefine2NSSupport = new Hashtable();
// these objects store a mapping between the names of redefining
// groups/attributeGroups and the groups/AttributeGroups which
// they redefine by restriction (implicitly). It is up to the
// Group and AttributeGroup traversers to check these restrictions for
// validity.
private Hashtable fRedefinedRestrictedAttributeGroupRegistry = new Hashtable();
private Hashtable fRedefinedRestrictedGroupRegistry = new Hashtable();
// a variable storing whether the last schema document
// processed (by getSchema) was a duplicate.
private boolean fLastSchemaWasDuplicate;
// validate annotations feature
private boolean fValidateAnnotations = false;
//handle multiple import feature
private boolean fHonourAllSchemaLocations = false;
//handle namespace growth feature
boolean fNamespaceGrowth = false;
// handle tolerate duplicates feature
boolean fTolerateDuplicates = false;
// handle full XPath 2.0 feature
boolean fFullXPathForCTA = false;
// handle comments and PIs with
boolean fCommentsAndPIsForAssert = false;
// the XMLErrorReporter
private XMLErrorReporter fErrorReporter;
private XMLEntityResolver fEntityResolver;
// the XSAttributeChecker
private XSAttributeChecker fAttributeChecker;
// the symbol table
private SymbolTable fSymbolTable;
// the GrammarResolver
private XSGrammarBucket fGrammarBucket;
// the Grammar description
private XSDDescription fSchemaGrammarDescription;
// the Grammar Pool
private XMLGrammarPool fGrammarPool;
//override Manager
private OverrideTransformationManager fOverrideHandler;
//************ Traversers **********
XSDAttributeGroupTraverser fAttributeGroupTraverser;
XSDAttributeTraverser fAttributeTraverser;
XSDComplexTypeTraverser fComplexTypeTraverser;
XSDElementTraverser fElementTraverser;
XSDGroupTraverser fGroupTraverser;
XSDKeyrefTraverser fKeyrefTraverser;
XSDNotationTraverser fNotationTraverser;
XSDSimpleTypeTraverser fSimpleTypeTraverser;
XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser;
XSDWildcardTraverser fWildCardTraverser;
XSDTypeAlternativeTraverser fTypeAlternativeTraverser;
SchemaDVFactory fDVFactory;
SchemaDOMParser fSchemaParser;
SchemaContentHandler fXSContentHandler;
StAXSchemaParser fStAXSchemaParser;
XML11Configuration fAnnotationValidator;
XSAnnotationGrammarPool fGrammarBucketAdapter;
// flag to indicate schema 1.1 support
short fSchemaVersion;
// XML Schema constraint checker
XSConstraints fXSConstraints;
// TypeValidatorHelper
TypeValidatorHelper fTypeValidatorHelper;
// Datatype XML version
String fDatatypeXMLVersion;
// these data members are needed for the deferred traversal
// of local elements.
// the initial size of the array to store deferred local elements
private static final int INIT_STACK_SIZE = 30;
// the incremental size of the array to store deferred local elements
private static final int INC_STACK_SIZE = 10;
// current position of the array (# of deferred local elements)
private int fLocalElemStackPos = 0;
private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE];
private Element[] fLocalElementDecl = new Element[INIT_STACK_SIZE];
private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK
private int[] fAllContext = new int[INIT_STACK_SIZE];
private XSObject[] fParent = new XSObject[INIT_STACK_SIZE];
private String [][] fLocalElemNamespaceContext = new String [INIT_STACK_SIZE][1];
// these data members are needed for the deferred traversal
// of keyrefs.
// the initial size of the array to store deferred keyrefs
private static final int INIT_KEYREF_STACK = 2;
// the incremental size of the array to store deferred keyrefs
private static final int INC_KEYREF_STACK_AMOUNT = 2;
// current position of the array (# of deferred keyrefs)
private int fKeyrefStackPos = 0;
private Element [] fKeyrefs = new Element[INIT_KEYREF_STACK];
private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK];
private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK];
private String [][] fKeyrefNamespaceContext = new String[INIT_KEYREF_STACK][1];
// global decls: map from decl name to decl object
SymbolHash fGlobalAttrDecls = new SymbolHash(12);
SymbolHash fGlobalAttrGrpDecls = new SymbolHash(5);
SymbolHash fGlobalElemDecls = new SymbolHash(25);
SymbolHash fGlobalGroupDecls = new SymbolHash(5);
SymbolHash fGlobalNotationDecls = new SymbolHash(1);
SymbolHash fGlobalIDConstraintDecls = new SymbolHash(3);
SymbolHash fGlobalTypeDecls = new SymbolHash(25);
// these data members are needed for the deferred traversal
// of referral identity constraints.
// the initial size of the array to store deferred referral identity constraints
private static final int INIT_IC_REFERRAL_STACK = 2;
// the incremental size of the array to store deferred referral identity constraints
private static final int INC_IC_REFERRAL_STACK_AMOUNT = 2;
// current position of the array (# of deferred referral identity constraints)
private int fICReferralStackPos = 0;
private Element[] fICReferrals = new Element[INIT_IC_REFERRAL_STACK];
private XSDocumentInfo [] fICReferralsMapXSDocumentInfo = new XSDocumentInfo[INIT_IC_REFERRAL_STACK];
private XSElementDecl [] fICReferralElems = new XSElementDecl [INIT_IC_REFERRAL_STACK];
private String [][] fICReferralNamespaceContext = new String[INIT_IC_REFERRAL_STACK][1];
// Constructors
public XSDHandler(short schemaVersion, XSConstraints xsConstraints){
fSchemaVersion = schemaVersion;
fXSConstraints = xsConstraints;
fHiddenNodes = new Hashtable();
fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig());
fSchemaParser.setSupportedVersion(fSupportedVersion); //REVISIT: pass to constructor?
}
// it should be possible to use the same XSDHandler to parse
// multiple schema documents; this will allow one to be
// constructed.
public XSDHandler (XSGrammarBucket gBucket, short schemaVersion, XSConstraints xsConstraints) {
this(schemaVersion, xsConstraints);
fGrammarBucket = gBucket;
// Note: don't use SchemaConfiguration internally
// we will get stack overflaw because
// XMLSchemaValidator will be instantiating XSDHandler...
fSchemaGrammarDescription = new XSDDescription();
} // end constructor
/**
* This method initiates the parse of a schema. It will likely be
* called from the Validator and it will make the
* resulting grammar available; it returns a reference to this object just
* in case. A reset(XMLComponentManager) must be called before this methods is called.
* @param is
* @param desc
* @param locationPairs
* @return the SchemaGrammar
* @throws IOException
*/
public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc,
Hashtable locationPairs)
throws IOException {
fLocationPairs = locationPairs;
fSchemaParser.resetNodePool();
SchemaGrammar grammar = null;
String schemaNamespace = null;
short referType = desc.getContextType();
// if loading using JAXP schemaSource property, or using grammar caching loadGrammar
// the desc.targetNamespace is always null.
// Therefore we should not attempt to find out if
// the schema is already in the bucket, since in the case we have
// no namespace schema in the bucket, findGrammar will always return the
// no namespace schema.
if (referType != XSDDescription.CONTEXT_PREPARSE){
// first try to find it in the bucket/pool, return if one is found
if (fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc, fNamespaceGrowth)) {
grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace());
}
else {
grammar = findGrammar(desc, fNamespaceGrowth);
}
if (grammar != null) {
if (!fNamespaceGrowth) {
return grammar;
}
else {
try {
if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false))) {
return grammar;
}
}
catch (MalformedURIException e) {
//REVISIT: return the grammar?
}
}
}
schemaNamespace = desc.getTargetNamespace();
// handle empty string URI as null
if (schemaNamespace != null) {
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
}
}
// before parsing a schema, need to clear registries associated with
// parsing schemas
prepareForParse();
Element schemaRoot = null;
// first phase: construct trees.
if (is instanceof DOMInputSource) {
schemaRoot = getSchemaDocument(schemaNamespace, (DOMInputSource) is,
referType == XSDDescription.CONTEXT_PREPARSE,
referType, null);
} // DOMInputSource
else if (is instanceof SAXInputSource) {
schemaRoot = getSchemaDocument(schemaNamespace, (SAXInputSource) is,
referType == XSDDescription.CONTEXT_PREPARSE,
referType, null);
} // SAXInputSource
else if (is instanceof StAXInputSource) {
schemaRoot = getSchemaDocument(schemaNamespace, (StAXInputSource) is,
referType == XSDDescription.CONTEXT_PREPARSE,
referType, null);
} // StAXInputSource
else if (is instanceof XSInputSource) {
schemaRoot = getSchemaDocument((XSInputSource) is, desc);
} // XSInputSource
else {
schemaRoot = getSchemaDocument(schemaNamespace, is,
referType == XSDDescription.CONTEXT_PREPARSE,
referType, null);
} //is instanceof XMLInputSource
if (schemaRoot == null) {
if (is instanceof XSInputSource) {
// Need to return a grammar. If the XSInputSource has a list
// of grammar objects, then get the first one and return it.
// If it has a list of components, then get the grammar that
// contains the first component and return it.
// If we return null, the XMLSchemaLoader will think nothing
// was loaded, and will not try to put the grammar objects
// into the grammar pool.
XSInputSource xsinput = (XSInputSource)is;
SchemaGrammar[] grammars = xsinput.getGrammars();
if (grammars != null && grammars.length > 0) {
grammar = fGrammarBucket.getGrammar(grammars[0].getTargetNamespace());
}
else {
XSObject[] components = xsinput.getComponents();
if (components != null && components.length > 0) {
grammar = fGrammarBucket.getGrammar(components[0].getNamespace());
}
}
}
// something went wrong right off the hop
return grammar;
}
if (referType == XSDDescription.CONTEXT_PREPARSE) {
Element schemaElem = schemaRoot;
schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE);
if(schemaNamespace != null && schemaNamespace.length() > 0) {
// Since now we've discovered a namespace, we need to update xsd key
// and store this schema in traversed schemas bucket
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
desc.setTargetNamespace(schemaNamespace);
}
else {
schemaNamespace = null;
}
grammar = findGrammar(desc, fNamespaceGrowth);
String schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false);
if (grammar != null) {
// When namespace growth is enabled and a null location is provided we cannot tell
// whether we've loaded this schema document before so we must assume that we haven't.
if (!fNamespaceGrowth || (schemaId != null && grammar.getDocumentLocations().contains(schemaId))) {
return grammar;
}
}
XSDKey key = new XSDKey(schemaId, referType, schemaNamespace);
fTraversed.put(key, schemaRoot);
if (schemaId != null) {
fDoc2SystemId.put(schemaRoot, schemaId);
}
}
// before constructing trees and traversing a schema, need to reset
// all traversers and clear all registries
prepareForTraverse();
// Tell override handler about the original schema root
// Need to know if that schema would be later overriden - possible collision
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1) {
fOverrideHandler.addSchemaRoot((String)fDoc2SystemId.get(schemaRoot), schemaRoot);
}
fRoot = constructTrees(schemaRoot, is.getSystemId(), desc, grammar != null);
if (fRoot == null) {
return null;
}
// second phase: fill global registries.
buildGlobalNameRegistries();
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1) {
buildDefaultAttributes();
}
// third phase: call traversers
ArrayList annotationInfo = fValidateAnnotations ? new ArrayList() : null;
traverseSchemas(annotationInfo);
// fourth phase: handle local element decls
traverseLocalElements();
// fifth phase: handle Keyrefs
resolveKeyRefs();
// sixth phase: handle identity constraint referral declarations
resolveIdentityConstraintReferrals();
// seventh phase: validate attribute of non-schema namespaces
// REVISIT: skip this for now. we really don't want to do it.
//fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket);
// eighth phase: store imported grammars
// for all grammars with s
for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
// get its target namespace
String tns = (String)fAllTNSs.elementAt(i);
// get all namespaces it imports
Vector ins = (Vector)fImportMap.get(tns);
// get the grammar
SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns));
if (sg == null)
continue;
SchemaGrammar isg;
// for imported namespace
int count = 0;
for (int j = 0; j < ins.size(); j++) {
// get imported grammar
isg = fGrammarBucket.getGrammar((String)ins.elementAt(j));
// reuse the same vector
if (isg != null)
ins.setElementAt(isg, count++);
}
ins.setSize(count);
// set the imported grammars
sg.setImportedGrammars(ins);
}
/** validate annotations **/
if (fValidateAnnotations && annotationInfo.size() > 0) {
validateAnnotations(annotationInfo);
}
// and return.
return fGrammarBucket.getGrammar(fRoot.fTargetNamespace);
} // end parseSchema
private void validateAnnotations(ArrayList annotationInfo) {
if (fAnnotationValidator == null) {
createAnnotationValidator();
}
final int size = annotationInfo.size();
final XMLInputSource src = new XMLInputSource(null, null, null);
fGrammarBucketAdapter.refreshGrammars(fGrammarBucket);
for (int i = 0; i < size; i += 2) {
src.setSystemId((String) annotationInfo.get(i));
XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1);
while (annotation != null) {
src.setCharacterStream(new StringReader(annotation.fAnnotation));
try {
fAnnotationValidator.parse(src);
}
catch (IOException exc) {}
annotation = annotation.next;
}
}
}
private void createAnnotationValidator() {
fAnnotationValidator = new XML11Configuration();
fGrammarBucketAdapter = new XSAnnotationGrammarPool(fSchemaVersion);
fAnnotationValidator.setFeature(VALIDATION, true);
fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true);
fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter);
/** Set error handler. **/
XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler();
fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler());
/** Set locale. **/
Locale locale = fErrorReporter.getLocale();
fAnnotationValidator.setProperty(LOCALE, locale);
}
/**
* Pull the grammar out of the bucket simply using
* its TNS as a key
*/
SchemaGrammar getGrammar(String tns) {
return fGrammarBucket.getGrammar(tns);
}
/**
* First try to find a grammar in the bucket, if failed, consult the
* grammar pool. If a grammar is found in the pool, then add it (and all
* imported ones) into the bucket.
*/
protected SchemaGrammar findGrammar(XSDDescription desc, boolean ignoreConflict) {
SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
if (sg == null) {
if (fGrammarPool != null) {
sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc);
if (sg != null) {
// put this grammar into the bucket, along with grammars
// imported by it (directly or indirectly)
if (!fGrammarBucket.putGrammar(sg, true, ignoreConflict)) {
// REVISIT: a conflict between new grammar(s) and grammars
// in the bucket. What to do? A warning? An exception?
reportSchemaWarning("GrammarConflict", null, null);
sg = null;
}
}
}
}
return sg;
}
// may wish to have setter methods for ErrorHandler,
// EntityResolver...
private static final String[][] NS_ERROR_CODES = {
{"src-include.2.1", "src-include.2.1"},
{"src-redefine.3.1", "src-redefine.3.1"},
{"src-import.3.1", "src-import.3.2"},
null,
{"TargetNamespace.1", "TargetNamespace.2"},
{"TargetNamespace.1", "TargetNamespace.2"},
{"TargetNamespace.1", "TargetNamespace.2"},
{"TargetNamespace.1", "TargetNamespace.2"},
{"src-override.2.1", "src-override.2.1"},
};
private static final String[] ELE_ERROR_CODES = {
"src-include.1", "src-redefine.2", "src-import.2", "schema_reference.4",
"schema_reference.4", "schema_reference.4", "schema_reference.4", "schema_reference.4"
};
// This method does several things:
// It constructs an instance of an XSDocumentInfo object using the
// schemaRoot node. Then, for each , ,
// , and children, it attempts to resolve the
// requested schema document, initiates a DOM parse, and calls
// itself recursively on that document's root. It also records in
// the DependencyMap object what XSDocumentInfo objects its XSDocumentInfo
// depends on.
// It also makes sure the targetNamespace of the schema it was
// called to parse is correct.
protected XSDocumentInfo constructTrees(Element schemaRoot, String locationHint, XSDDescription desc, boolean nsCollision) {
if (schemaRoot == null) return null;
String callerTNS = desc.getTargetNamespace();
short referType = desc.getContextType();
XSDocumentInfo currSchemaInfo = null;
try {
// note that attributes are freed at end of traverseSchemas()
short datatypeXMLVersion = Constants.XML_VERSION_1_0;
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1) {
final Object xmlVer = (fDatatypeXMLVersion == null)
? fDoc2DatatypeXMLVersion.get(schemaRoot) : fDatatypeXMLVersion;
datatypeXMLVersion = "1.1".equals(xmlVer)
? Constants.XML_VERSION_1_1 : Constants.XML_VERSION_1_0;
}
currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker,
fSymbolTable, fTypeValidatorHelper, datatypeXMLVersion);
} catch (XMLSchemaException se) {
reportSchemaError(ELE_ERROR_CODES[referType],
new Object[]{locationHint},
schemaRoot);
return null;
}
// targetNamespace="" is not valid, issue a warning, and ignore it
if (currSchemaInfo.fTargetNamespace != null &&
currSchemaInfo.fTargetNamespace.length() == 0) {
reportSchemaWarning("EmptyTargetNamespace",
new Object[]{locationHint},
schemaRoot);
currSchemaInfo.fTargetNamespace = null;
}
if (callerTNS != null) {
// the second index to the NS_ERROR_CODES array
// if the caller/expected NS is not absent, we use the first column
int secondIdx = 0;
// for include and redefine
if (referType == XSDDescription.CONTEXT_INCLUDE ||
referType == XSDDescription.CONTEXT_REDEFINE ||
referType == XSDDescription.CONTEXT_OVERRIDE ) {
// if the referred document has no targetNamespace,
// it's a chameleon schema
if (currSchemaInfo.fTargetNamespace == null) {
currSchemaInfo.fTargetNamespace = callerTNS;
currSchemaInfo.fIsChameleonSchema = true;
}
// if the referred document has a target namespace differing
// from the caller, it's an error
else if (callerTNS != currSchemaInfo.fTargetNamespace) {
reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
new Object [] {callerTNS, currSchemaInfo.fTargetNamespace},
schemaRoot);
return null;
}
}
// for instance and import, the two NS's must be the same
else if (referType != XSDDescription.CONTEXT_PREPARSE && callerTNS != currSchemaInfo.fTargetNamespace) {
reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
new Object [] {callerTNS, currSchemaInfo.fTargetNamespace},
schemaRoot);
return null;
}
}
// now there is no caller/expected NS, it's an error for the referred
// document to have a target namespace, unless we are preparsing a schema
else if (currSchemaInfo.fTargetNamespace != null) {
// set the target namespace of the description
if (referType == XSDDescription.CONTEXT_PREPARSE) {
desc.setTargetNamespace(currSchemaInfo.fTargetNamespace);
callerTNS = currSchemaInfo.fTargetNamespace;
}
else {
// the second index to the NS_ERROR_CODES array
// if the caller/expected NS is absent, we use the second column
int secondIdx = 1;
reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
new Object [] {callerTNS, currSchemaInfo.fTargetNamespace},
schemaRoot);
return null;
}
}
// the other cases (callerTNS == currSchemaInfo.fTargetNamespce == null)
// are valid
// a schema document can always access it's own target namespace
currSchemaInfo.addAllowedNS(currSchemaInfo.fTargetNamespace);
SchemaGrammar sg = null;
// we have a namespace collision
if (nsCollision) {
SchemaGrammar sg2 = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace);
if (sg2.isImmutable()) {
sg = new SchemaGrammar(sg2);
fGrammarBucket.putGrammar(sg);
// update all the grammars in the bucket to point to the new grammar.
updateImportListWith(sg);
}
else {
sg = sg2;
}
// update import list of the new grammar
updateImportListFor(sg);
}
else if (referType == XSDDescription.CONTEXT_INCLUDE ||
referType == XSDDescription.CONTEXT_REDEFINE ||
referType == XSDDescription.CONTEXT_OVERRIDE) {
sg = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace);
}
else if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT) {
sg = findGrammar(desc, false);
if(sg == null) {
sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable, fSchemaVersion);
fGrammarBucket.putGrammar(sg);
}
}
else {
sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable, fSchemaVersion);
fGrammarBucket.putGrammar(sg);
}
// store the document and its location
// REVISIT: don't expose the DOM tree
sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
Vector dependencies = new Vector();
Vector overrideDependencies = new Vector();
Element rootNode = schemaRoot;
Element newSchemaRoot = null;
for (Element child = DOMUtil.getFirstChildElement(rootNode);
child != null;
child = DOMUtil.getNextSiblingElement(child)) {
String schemaNamespace=null;
String schemaHint=null;
String localName = DOMUtil.getLocalName(child);
short refType = -1;
boolean importCollision = false;
if (localName.equals(SchemaSymbols.ELT_ANNOTATION))
continue;
else if (localName.equals(SchemaSymbols.ELT_IMPORT)) {
refType = XSDDescription.CONTEXT_IMPORT;
// have to handle some validation here too!
// call XSAttributeChecker to fill in attrs
Object[] importAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
schemaHint = (String)importAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
schemaNamespace = (String)importAttrs[XSAttributeChecker.ATTIDX_NAMESPACE];
if (schemaNamespace != null)
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
// check contents and process optional annotations
Element importChild = DOMUtil.getFirstChildElement(child);
if(importChild != null ) {
String importComponentType = DOMUtil.getLocalName(importChild);
if (importComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
// promoting annotations to parent component
sg.addAnnotation(
fElementTraverser.traverseAnnotationDecl(importChild, importAttrs, true, currSchemaInfo));
} else {
reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", importComponentType}, child);
}
if(DOMUtil.getNextSiblingElement(importChild) != null) {
reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(importChild))}, child);
}
}
else {
String text = DOMUtil.getSyntheticAnnotation(child);
if (text != null) {
sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, importAttrs, true, currSchemaInfo));
}
}
fAttributeChecker.returnAttrArray(importAttrs, currSchemaInfo);
// a document can't import another document with the same namespace
if (schemaNamespace == currSchemaInfo.fTargetNamespace) {
reportSchemaError(schemaNamespace != null ?
"src-import.1.1" : "src-import.1.2", new Object [] {schemaNamespace}, child);
continue;
}
// if this namespace has not been imported by this document,
// then import if multiple imports support is enabled.
if(currSchemaInfo.isAllowedNS(schemaNamespace)) {
if(!fHonourAllSchemaLocations && !fNamespaceGrowth)
continue;
}
else {
currSchemaInfo.addAllowedNS(schemaNamespace);
}
// also record the fact that one namespace imports another one
// convert null to ""
String tns = null2EmptyString(currSchemaInfo.fTargetNamespace);
// get all namespaces imported by this one
Vector ins = (Vector)fImportMap.get(tns);
// if no namespace was imported, create new Vector
if (ins == null) {
// record that this one imports other(s)
fAllTNSs.addElement(tns);
ins = new Vector();
fImportMap.put(tns, ins);
ins.addElement(schemaNamespace);
}
else if (!ins.contains(schemaNamespace)){
ins.addElement(schemaNamespace);
}
fSchemaGrammarDescription.reset();
fSchemaGrammarDescription.setContextType(XSDDescription.CONTEXT_IMPORT);
fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot));
fSchemaGrammarDescription.setLiteralSystemId(schemaHint);
fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint});
fSchemaGrammarDescription.setTargetNamespace(schemaNamespace);
// if a grammar with the same namespace and location exists (or being
// built), ignore this one (don't traverse it).
SchemaGrammar isg = findGrammar(fSchemaGrammarDescription, fNamespaceGrowth);
if (isg != null) {
if (fNamespaceGrowth) {
try {
if (isg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(schemaHint, fSchemaGrammarDescription.getBaseSystemId(), false))) {
continue;
}
else {
importCollision = true;
}
}
catch (MalformedURIException e) {
}
}
else if (!fHonourAllSchemaLocations || isExistingGrammar(fSchemaGrammarDescription, false)) {
continue;
}
}
//if ((!fHonourAllSchemaLocations && findGrammar(fSchemaGrammarDescription) != null) || isExistingGrammar(fSchemaGrammarDescription))
// continue;
// If "findGrammar" returns a grammar, then this is not the
// the first time we see a location for a given namespace.
// Don't consult the location pair hashtable in this case,
// otherwise the location will be ignored because it'll get
// resolved to the same location as the first hint.
newSchemaRoot = resolveSchema(fSchemaGrammarDescription, false, child, isg == null);
}
else if ((localName.equals(SchemaSymbols.ELT_INCLUDE)) ||
(localName.equals(SchemaSymbols.ELT_REDEFINE)) ||
(localName.equals(SchemaSymbols.ELT_OVERRIDE) && fSchemaVersion == Constants.SCHEMA_VERSION_1_1)) {
// validation for redefine/include will be the same here; just
// make sure TNS is right (don't care about redef contents
// yet).
Object[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
schemaHint = (String)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
// store the namespace decls of the redefine element
if (localName.equals(SchemaSymbols.ELT_REDEFINE)) {
fRedefine2NSSupport.put(child, new SchemaNamespaceSupport(currSchemaInfo.fNamespaceSupport));
}
// check annotations. Must do this here to avoid having to
// re-parse attributes later
if(localName.equals(SchemaSymbols.ELT_INCLUDE)) {
Element includeChild = DOMUtil.getFirstChildElement(child);
if(includeChild != null ) {
String includeComponentType = DOMUtil.getLocalName(includeChild);
if (includeComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
// promoting annotations to parent component
sg.addAnnotation(
fElementTraverser.traverseAnnotationDecl(includeChild, includeAttrs, true, currSchemaInfo));
} else {
reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", includeComponentType}, child);
}
if(DOMUtil.getNextSiblingElement(includeChild) != null) {
reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(includeChild))}, child);
}
}
else {
String text = DOMUtil.getSyntheticAnnotation(child);
if (text != null) {
sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo));
}
}
}
else {
for (Element redefinedChild = DOMUtil.getFirstChildElement(child);
redefinedChild != null;
redefinedChild = DOMUtil.getNextSiblingElement(redefinedChild)) {
String redefinedComponentType = DOMUtil.getLocalName(redefinedChild);
if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
// promoting annotations to parent component
sg.addAnnotation(
fElementTraverser.traverseAnnotationDecl(redefinedChild, includeAttrs, true, currSchemaInfo));
DOMUtil.setHidden(redefinedChild, fHiddenNodes);
}
else {
String text = DOMUtil.getSyntheticAnnotation(child);
if (text != null) {
sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo));
}
}
// catch all other content errors later
}
}
fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo);
// schemaLocation is required on and
if (schemaHint == null) {
reportSchemaError("s4s-att-must-appear", new Object [] {
" or ", "schemaLocation"},
child);
}
// pass the systemId of the current document as the base systemId
boolean mustResolve = false;
refType = XSDDescription.CONTEXT_INCLUDE;
if (localName.equals(SchemaSymbols.ELT_REDEFINE)) {
mustResolve = nonAnnotationContent(child);
refType = XSDDescription.CONTEXT_REDEFINE;
}
else if (localName.equals(SchemaSymbols.ELT_OVERRIDE)){
mustResolve = nonAnnotationContent(child);
refType = XSDDescription.CONTEXT_OVERRIDE;
}
fSchemaGrammarDescription.reset();
fSchemaGrammarDescription.setContextType(refType);
fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot));
fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint});
fSchemaGrammarDescription.setTargetNamespace(callerTNS);
XMLInputSource schemaSource = resolveSchemaSource(fSchemaGrammarDescription, mustResolve, child, true);
String schemaId = null;
try {
schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
}
catch(MalformedURIException e) {
}
// If namespace growth is enabled, and we have already
// processed the same schema (ie. same system id), we
// treat the schema as duplicate, since we cannot replace
// the existing global components
boolean alreadyTraversed = (fNamespaceGrowth) ? sg.getDocumentLocations().contains(schemaId) : false;
if (!alreadyTraversed) {
newSchemaRoot = resolveSchema(schemaSource, fSchemaGrammarDescription, mustResolve, child);
schemaNamespace = currSchemaInfo.fTargetNamespace;
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1) {
if (refType == XSDDescription.CONTEXT_OVERRIDE) {
if (newSchemaRoot != null && isValidTargetUriForIncludeOrOverride(schemaId, locationHint)) {
final Element transformedSchemaRoot = (Element) fOverrideHandler.transform(schemaId, child, newSchemaRoot);
// Either we had a collision where the transformed
// schema has global components or we hit a
// transformation cycle
if (transformedSchemaRoot == null) {
fLastSchemaWasDuplicate = true;
}
// In case of a collision where the transformed
// schema has no global components, the override
// transformer will return the new transformed
// schema. We need to process that new schema,
// so we set the duplicate schema flag to false
else if (fLastSchemaWasDuplicate && transformedSchemaRoot != newSchemaRoot) {
fLastSchemaWasDuplicate = false;
}
newSchemaRoot = transformedSchemaRoot;
}
else {
// check for override collision
fOverrideHandler.checkSchemaRoot(schemaId, child, newSchemaRoot);
}
}
else if (refType == XSDDescription.CONTEXT_INCLUDE && !isValidTargetUriForIncludeOrOverride(schemaId, locationHint)) {
fLastSchemaWasDuplicate = true;
}
}
}
else {
fLastSchemaWasDuplicate = true;
}
}
else {
// no more possibility of schema references in well-formed
// schema...
break;
}
// If the schema is duplicate, we needn't call constructTrees() again.
// To handle mutual s
XSDocumentInfo newSchemaInfo = null;
if (fLastSchemaWasDuplicate) {
newSchemaInfo = newSchemaRoot == null ? null : (XSDocumentInfo)fDoc2XSDocumentMap.get(newSchemaRoot);
}
else {
newSchemaInfo = constructTrees(newSchemaRoot, schemaHint, fSchemaGrammarDescription, importCollision);
}
if (localName.equals(SchemaSymbols.ELT_REDEFINE) &&
newSchemaInfo != null) {
// must record which schema we're redefining so that we can
// rename the right things later!
fRedefine2XSDMap.put(child, newSchemaInfo);
}
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1 && localName.equals(SchemaSymbols.ELT_OVERRIDE) && newSchemaInfo != null) {
// record this override dependency
overrideDependencies.addElement(newSchemaInfo);
}
if (newSchemaRoot != null) {
if (newSchemaInfo != null)
dependencies.addElement(newSchemaInfo);
newSchemaRoot = null;
}
}
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1) {
fOverrideDependencyMap.put(currSchemaInfo, overrideDependencies);
}
fDependencyMap.put(currSchemaInfo, dependencies);
return currSchemaInfo;
} // end constructTrees
/*
* Check if the target URI for or is correct. It must not be absent, and it should not point
* to the parent schema document.
*/
private boolean isValidTargetUriForIncludeOrOverride(String schemaId, String locationHint) {
boolean isUriValid = true;
try {
String expandedLoctionHint = XMLEntityManager.expandSystemId(locationHint, fSchemaGrammarDescription.getBaseSystemId(), false);
isUriValid = !("".equals(schemaId) || ((expandedLoctionHint != null) ? expandedLoctionHint.equals(schemaId) : true));
}
catch (MalformedURIException ex) {
isUriValid = false;
}
return isUriValid;
} // isValidTargetUriForIncludeOrOverride
private boolean isExistingGrammar(XSDDescription desc, boolean ignoreConflict) {
SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
if (sg == null) {
return findGrammar(desc, ignoreConflict) != null;
}
else if (sg.isImmutable()) {
return true;
}
else {
try {
return sg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(desc.getLiteralSystemId(), desc.getBaseSystemId(), false));
}
catch (MalformedURIException e) {
return false;
}
}
}
/**
* Namespace growth
*
* Go through the import list of a given grammar and for each imported
* grammar, check to see if the grammar bucket has a newer version.
* If a new instance is found, we update the import list with the
* newer version.
*/
private void updateImportListFor(SchemaGrammar grammar) {
Vector importedGrammars = grammar.getImportedGrammars();
if (importedGrammars != null) {
for (int i=0; i). We
// also put names in a registry that we look through in
// case something needs renaming. Once we're done with a schema we
// set its Document node to hidden so that we don't try to traverse
// it again; then we look to its Dependency map entry. We keep a
// stack of schemas that we haven't yet finished processing; this
// is a depth-first traversal.
Stack schemasToProcess = new Stack();
schemasToProcess.push(fRoot);
while (!schemasToProcess.empty()) {
XSDocumentInfo currSchemaDoc =
(XSDocumentInfo)schemasToProcess.pop();
Element currDoc = currSchemaDoc.fSchemaElement;
if(DOMUtil.isHidden(currDoc, fHiddenNodes)){
// must have processed this already!
continue;
}
Element currRoot = currDoc;
// process this schema's global decls
boolean dependenciesCanOccur = true;
for (Element globalComp =
DOMUtil.getFirstChildElement(currRoot);
globalComp != null;
globalComp = DOMUtil.getNextSiblingElement(globalComp)) {
// this loop makes sure the element ordering is
// also valid.
if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_ANNOTATION)) {
//skip it; traverse it later
continue;
}
else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_INCLUDE) ||
DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_IMPORT) ||
(DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_OVERRIDE) && fSchemaVersion == Constants.SCHEMA_VERSION_1_1)) {
if (!dependenciesCanOccur) {
reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp);
}
DOMUtil.setHidden(globalComp, fHiddenNodes);
}
else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) {
if (!dependenciesCanOccur) {
reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp);
}
for (Element redefineComp = DOMUtil.getFirstChildElement(globalComp);
redefineComp != null;
redefineComp = DOMUtil.getNextSiblingElement(redefineComp)) {
String lName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME);
if (lName.length() == 0) // an error we'll catch later
continue;
String qName = currSchemaDoc.fTargetNamespace == null ?
","+lName:
currSchemaDoc.fTargetNamespace +","+lName;
//qName = XMLChar.trim(qName);
String componentType = DOMUtil.getLocalName(redefineComp);
if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc);
// the check will have changed our name;
String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER;
// and all we need to do is error-check+rename our kkids:
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_ATTRIBUTEGROUP,
lName, targetLName);
}
else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) ||
(componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) {
checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, redefineComp, currSchemaDoc);
// the check will have changed our name;
String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME) + REDEF_IDENTIFIER;
// and all we need to do is error-check+rename our kkids:
if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_COMPLEXTYPE,
lName, targetLName);
}
else { // must be simpleType
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_SIMPLETYPE,
lName, targetLName);
}
}
else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, redefineComp, currSchemaDoc);
// the check will have changed our name;
String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER;
// and all we need to do is error-check+rename our kids:
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_GROUP,
lName, targetLName);
}
} // end march through children
// and now set as traversed
//DOMUtil.setHidden(globalComp);
}
else {
String lName = DOMUtil.getAttrValue(globalComp, SchemaSymbols.ATT_NAME);
String componentType = DOMUtil.getLocalName(globalComp);
// In XML Schema 1.1, a defaultOpenContent element may occur
if (fSchemaVersion >= Constants.SCHEMA_VERSION_1_1 && componentType.equals(SchemaSymbols.ELT_DEFAULTOPENCONTENT)) {
if (!dependenciesCanOccur) {
reportSchemaError("s4s-elt-invalid-content.3", new Object [] {componentType}, globalComp);
}
final SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace);
currSchemaDoc.fDefaultOpenContent = fComplexTypeTraverser.traverseOpenContent(globalComp, currSchemaDoc, currSG, true);
DOMUtil.setHidden(globalComp, fHiddenNodes);
dependenciesCanOccur = false;
continue;
}
dependenciesCanOccur = false;
if (lName.length() == 0) // an error we'll catch later
continue;
String qName = currSchemaDoc.fTargetNamespace == null?
","+lName:
currSchemaDoc.fTargetNamespace +","+lName;
//qName = XMLChar.trim(qName);
if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
checkForDuplicateNames(qName, ATTRIBUTE_TYPE, fUnparsedAttributeRegistry, fUnparsedAttributeRegistrySub, globalComp, currSchemaDoc);
}
else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, globalComp, currSchemaDoc);
}
else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) ||
(componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) {
checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, globalComp, currSchemaDoc);
}
else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) {
checkForDuplicateNames(qName, ELEMENT_TYPE, fUnparsedElementRegistry, fUnparsedElementRegistrySub, globalComp, currSchemaDoc);
}
else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, globalComp, currSchemaDoc);
}
else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) {
checkForDuplicateNames(qName, NOTATION_TYPE, fUnparsedNotationRegistry, fUnparsedNotationRegistrySub, globalComp, currSchemaDoc);
}
}
} // end for
// now we're done with this one!
DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
} // while
} // end buildGlobalNameRegistries
protected void buildDefaultAttributes() {
Stack schemasToProcess = new Stack();
setSchemasVisible(fRoot);
schemasToProcess.push(fRoot);
while (!schemasToProcess.empty()) {
XSDocumentInfo currSchemaDoc =
(XSDocumentInfo)schemasToProcess.pop();
final Element currDoc = currSchemaDoc.fSchemaElement;
if(DOMUtil.isHidden(currDoc, fHiddenNodes)) {
// must have processed this already!
continue;
}
// Check that we have a 'defaultAttributes' and that we have not already processed it
if (currSchemaDoc.fDefaultAttributes != null && currSchemaDoc.fDefaultAGroup == null) {
currSchemaDoc.fDefaultAGroup = (XSAttributeGroupDecl) getGlobalDecl(
currSchemaDoc, XSDHandler.ATTRIBUTEGROUP_TYPE, currSchemaDoc.fDefaultAttributes, currDoc);
}
// now we're done with this one!
// now we're done with this one!
DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
} // while
} // end buildDefaultAttributes
// Beginning at the first schema processing was requested for
// (fRoot), this method
// examines each child (global schema information item) of each
// schema document (and of each element)
// corresponding to an XSDocumentInfo object. If the
// readOnly field on that node has not been set, it calls an
// appropriate traverser to traverse it. Once all global decls in
// an XSDocumentInfo object have been traversed, it marks that object
// as traversed (or hidden) in order to avoid infinite loops. It completes
// when it has visited all XSDocumentInfo objects in the
// DependencyMap and marked them as traversed.
protected void traverseSchemas(ArrayList annotationInfo) {
// the process here is very similar to that in
// buildGlobalRegistries, except we can't set our schemas as
// hidden for a second time; so make them all visible again
// first!
setSchemasVisible(fRoot);
Stack schemasToProcess = new Stack();
schemasToProcess.push(fRoot);
while (!schemasToProcess.empty()) {
XSDocumentInfo currSchemaDoc =
(XSDocumentInfo)schemasToProcess.pop();
Element currDoc = currSchemaDoc.fSchemaElement;
SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace);
if(DOMUtil.isHidden(currDoc, fHiddenNodes)) {
// must have processed this already!
continue;
}
Element currRoot = currDoc;
boolean sawAnnotation = false;
// traverse this schema's global decls
for (Element globalComp = DOMUtil.getFirstVisibleChildElement(currRoot, fHiddenNodes);
globalComp != null;
globalComp = DOMUtil.getNextVisibleSiblingElement(globalComp, fHiddenNodes)) {
sawAnnotation = traverseXSDSchemaGlobalDecls(currSchemaDoc, currSG, sawAnnotation, globalComp);
}
if (!sawAnnotation) {
String text = DOMUtil.getSyntheticAnnotation(currRoot);
if (text != null) {
currSG.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(currRoot, text, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc));
}
}
/** Collect annotation information for validation. **/
if (annotationInfo != null) {
XSAnnotationInfo info = currSchemaDoc.getAnnotations();
/** Only add annotations to the list if there were any in this document. **/
if (info != null) {
annotationInfo.add(doc2SystemId(currDoc));
annotationInfo.add(info);
}
}
// now we're done with this one!
currSchemaDoc.returnSchemaAttrs();
DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
} // while
} // end traverseSchemas
/*
* Given a set of XSD schema documents to process, this method traverses global declarations of one of schema documents from this set.
*/
private boolean traverseXSDSchemaGlobalDecls(XSDocumentInfo schemaDoc, SchemaGrammar schGrammar, boolean sawAnnotation, Element globalComp) {
DOMUtil.setHidden(globalComp, fHiddenNodes);
String componentType = DOMUtil.getLocalName(globalComp);
// includes and imports will not show up here!
if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) {
// use the namespace decls for the redefine, instead of for the parent
schemaDoc.backupNSSupport((SchemaNamespaceSupport)fRedefine2NSSupport.get(globalComp));
for (Element redefinedComp = DOMUtil.getFirstVisibleChildElement(globalComp, fHiddenNodes);
redefinedComp != null;
redefinedComp = DOMUtil.getNextVisibleSiblingElement(redefinedComp, fHiddenNodes)) {
String redefinedComponentType = DOMUtil.getLocalName(redefinedComp);
DOMUtil.setHidden(redefinedComp, fHiddenNodes);
if (redefinedComponentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
fAttributeGroupTraverser.traverseGlobal(redefinedComp, schemaDoc, schGrammar);
}
else if (redefinedComponentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
fComplexTypeTraverser.traverseGlobal(redefinedComp, schemaDoc, schGrammar);
}
else if (redefinedComponentType.equals(SchemaSymbols.ELT_GROUP)) {
fGroupTraverser.traverseGlobal(redefinedComp, schemaDoc, schGrammar);
}
else if (redefinedComponentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
fSimpleTypeTraverser.traverseGlobal(redefinedComp, schemaDoc, schGrammar);
}
// annotations will have been processed already; this is now
// unnecessary
//else if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
// fElementTraverser.traverseAnnotationDecl(redefinedComp, null, true, currSchemaDoc);
//}
else {
reportSchemaError("s4s-elt-must-match.1", new Object [] {DOMUtil.getLocalName(globalComp), "(annotation | (simpleType | complexType | group | attributeGroup))*", redefinedComponentType}, redefinedComp);
}
} // end march through children
schemaDoc.restoreNSSupport();
}
else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
fAttributeTraverser.traverseGlobal(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
fAttributeGroupTraverser.traverseGlobal(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
fComplexTypeTraverser.traverseGlobal(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) {
fElementTraverser.traverseGlobal(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
fGroupTraverser.traverseGlobal(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) {
fNotationTraverser.traverse(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
fSimpleTypeTraverser.traverseGlobal(globalComp, schemaDoc, schGrammar);
}
else if (componentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
schGrammar.addAnnotation(fElementTraverser.traverseAnnotationDecl(globalComp, schemaDoc.getSchemaAttrs(), true, schemaDoc));
sawAnnotation = true;
}
else {
reportSchemaError("s4s-elt-invalid-content.1", new Object [] {SchemaSymbols.ELT_SCHEMA, DOMUtil.getLocalName(globalComp)}, globalComp);
}
return sawAnnotation;
} // traverseXSDSchemaGlobalDecls
// store whether we have reported an error about that no grammar
// is found for the given namespace uri
private Vector fReportedTNS = null;
// check whether we need to report an error against the given uri.
// if we have reported an error, then we don't need to report again;
// otherwise we reported the error, and remember this fact.
private final boolean needReportTNSError(String uri) {
if (fReportedTNS == null)
fReportedTNS = new Vector();
else if (fReportedTNS.contains(uri))
return false;
fReportedTNS.addElement(uri);
return true;
}
private static final String[] COMP_TYPE = {
null, // index 0
"attribute declaration",
"attribute group",
"element declaration",
"group",
"identity constraint",
"notation",
"type definition",
};
private static final String[] CIRCULAR_CODES = {
"Internal-Error",
"Internal-Error",
"src-attribute_group.3",
"e-props-correct.6",
"mg-props-correct.2",
"Internal-Error",
"Internal-Error",
"st-props-correct.2", //or ct-props-correct.3
};
// add a global attribute decl from a current schema load (only if no existing decl is found)
void addGlobalAttributeDecl(XSAttributeDecl decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getName() : namespace + "," + decl.getName();
if (fGlobalAttrDecls.get(declKey) == null) {
fGlobalAttrDecls.put(declKey, decl);
}
}
// add a global attribute group decl from a current schema load (only if no existing decl is found)
void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getName() : namespace + "," + decl.getName();
if (fGlobalAttrGrpDecls.get(declKey) == null) {
fGlobalAttrGrpDecls.put(declKey, decl);
}
}
// add a global element decl from a current schema load (only if no existing decl is found)
void addGlobalElementDecl(XSElementDecl decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getName() : namespace + "," + decl.getName();
if (fGlobalElemDecls.get(declKey) == null) {
fGlobalElemDecls.put(declKey, decl);
}
}
// add a global group decl from a current schema load (only if no existing decl is found)
void addGlobalGroupDecl(XSGroupDecl decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getName() : namespace + "," + decl.getName();
if (fGlobalGroupDecls.get(declKey) == null) {
fGlobalGroupDecls.put(declKey, decl);
}
}
// add a global notation decl from a current schema load (only if no existing decl is found)
void addGlobalNotationDecl(XSNotationDecl decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getName() : namespace + "," + decl.getName();
if (fGlobalNotationDecls.get(declKey) == null) {
fGlobalNotationDecls.put(declKey, decl);
}
}
// add a global type decl from a current schema load (only if no existing decl is found)
void addGlobalTypeDecl(XSTypeDefinition decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getName() : namespace + "," + decl.getName();
if (fGlobalTypeDecls.get(declKey) == null) {
fGlobalTypeDecls.put(declKey, decl);
}
}
// add a identity constraint decl from a current schema load (only if no existing decl is found)
void addIDConstraintDecl(IdentityConstraint decl) {
final String namespace = decl.getNamespace();
final String declKey = (namespace == null || namespace.length() == 0)
? "," + decl.getIdentityConstraintName() : namespace + "," + decl.getIdentityConstraintName();
if (fGlobalIDConstraintDecls.get(declKey) == null) {
fGlobalIDConstraintDecls.put(declKey, decl);
}
}
private XSAttributeDecl getGlobalAttributeDecl(String declKey) {
return (XSAttributeDecl)fGlobalAttrDecls.get(declKey);
}
private XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declKey) {
return (XSAttributeGroupDecl)fGlobalAttrGrpDecls.get(declKey);
}
private XSElementDecl getGlobalElementDecl(String declKey) {
return (XSElementDecl)fGlobalElemDecls.get(declKey);
}
private XSGroupDecl getGlobalGroupDecl(String declKey) {
return (XSGroupDecl)fGlobalGroupDecls.get(declKey);
}
private XSNotationDecl getGlobalNotationDecl(String declKey) {
return (XSNotationDecl)fGlobalNotationDecls.get(declKey);
}
private XSTypeDefinition getGlobalTypeDecl(String declKey) {
return (XSTypeDefinition)fGlobalTypeDecls.get(declKey);
}
private IdentityConstraint getIDConstraintDecl(String declKey) {
return (IdentityConstraint)fGlobalIDConstraintDecls.get(declKey);
}
// since it is forbidden for traversers to talk to each other
// directly (except wen a traverser encounters a local declaration),
// this provides a generic means for a traverser to call
// for the traversal of some declaration. An XSDocumentInfo is
// required because the XSDocumentInfo that the traverser is traversing
// may bear no relation to the one the handler is operating on.
// This method will:
// 1. See if a global definition matching declToTraverse exists;
// 2. if so, determine if there is a path from currSchema to the
// schema document where declToTraverse lives (i.e., do a lookup
// in DependencyMap);
// 3. depending on declType (which will be relevant to step 1 as
// well), call the appropriate traverser with the appropriate
// XSDocumentInfo object.
// This method returns whatever the traverser it called returned;
// this will be an Object of some kind
// that lives in the Grammar.
protected Object getGlobalDecl(XSDocumentInfo currSchema,
int declType,
QName declToTraverse,
Element elmNode) {
if (DEBUG_NODE_POOL) {
System.out.println("TRAVERSE_GL: "+declToTraverse.toString());
}
// from the schema spec, all built-in types are present in all schemas,
// so if the requested component is a type, and could be found in the
// default schema grammar, we should return that type.
// otherwise (since we would support user-defined schema grammar) we'll
// use the normal way to get the decl
if (declToTraverse.uri != null &&
declToTraverse.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
if (declType == TYPEDECL_TYPE) {
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_0_EXTENDED) {
if (declToTraverse.localpart.equals("duration") ||
declToTraverse.localpart.equals("yearMonthDuration") ||
declToTraverse.localpart.equals("dayTimeDuration")) {
return null;
}
}
SchemaGrammar s4s = SchemaGrammar.getS4SGrammar(fSchemaVersion);
Object retObj = s4s.getGlobalTypeDecl(declToTraverse.localpart);
if (retObj != null)
return retObj;
}
}
// XML Schema 1.1 allows reference to xsi attributes
if (fSchemaVersion == Constants.SCHEMA_VERSION_1_1 &&
declType == ATTRIBUTE_TYPE &&
declToTraverse.uri == SchemaSymbols.URI_XSI) {
SchemaGrammar xsiGrammar = SchemaGrammar.getXSIGrammar(fSchemaVersion);
Object retObj = xsiGrammar.getGlobalAttributeDecl(declToTraverse.localpart);
if (retObj != null) {
return retObj;
}
}
// now check whether this document can access the requsted namespace
if (!currSchema.isAllowedNS(declToTraverse.uri)) {
// cannot get to this schema from the one containing the requesting decl
if (currSchema.needReportTNSError(declToTraverse.uri)) {
String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2";
reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode);
}
// Recover and continue to look for the component.
// return null;
}
// check whether there is grammar for the requested namespace
SchemaGrammar sGrammar = fGrammarBucket.getGrammar(declToTraverse.uri);
if (sGrammar == null) {
if (needReportTNSError(declToTraverse.uri))
reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode);
return null;
}
// if there is such grammar, check whether the requested component is in the grammar
Object retObj = getGlobalDeclFromGrammar(sGrammar, declType, declToTraverse.localpart);
String declKey = declToTraverse.uri == null? ","+declToTraverse.localpart:
declToTraverse.uri+","+declToTraverse.localpart;
// if the component is parsed, return it
if (!fTolerateDuplicates) {
if (retObj != null) {
return retObj;
}
}
else {
Object retObj2 = getGlobalDecl(declKey, declType);
if (retObj2 != null) {
return retObj2;
}
}
XSDocumentInfo schemaWithDecl = null;
Element decl = null;
XSDocumentInfo declDoc = null;
// the component is not parsed, try to find a DOM element for it
switch (declType) {
case ATTRIBUTE_TYPE :
decl = (Element)fUnparsedAttributeRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedAttributeRegistrySub.get(declKey);
break;
case ATTRIBUTEGROUP_TYPE :
decl = (Element)fUnparsedAttributeGroupRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedAttributeGroupRegistrySub.get(declKey);
break;
case ELEMENT_TYPE :
decl = (Element)fUnparsedElementRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedElementRegistrySub.get(declKey);
break;
case GROUP_TYPE :
decl = (Element)fUnparsedGroupRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedGroupRegistrySub.get(declKey);
break;
case IDENTITYCONSTRAINT_TYPE :
decl = (Element)fUnparsedIdentityConstraintRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedIdentityConstraintRegistrySub.get(declKey);
break;
case NOTATION_TYPE :
decl = (Element)fUnparsedNotationRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedNotationRegistrySub.get(declKey);
break;
case TYPEDECL_TYPE :
decl = (Element)fUnparsedTypeRegistry.get(declKey);
declDoc = (XSDocumentInfo)fUnparsedTypeRegistrySub.get(declKey);
break;
default:
reportSchemaError("Internal-Error", new Object [] {"XSDHandler asked to locate component of type " + declType + "; it does not recognize this type!"}, elmNode);
}
// no DOM element found, so the component can't be located
if (decl == null) {
if (retObj == null) {
reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode);
}
return retObj;
}
// get the schema doc containing the component to be parsed
// it should always return non-null value, but since null-checking
// comes for free, let's be safe and check again
schemaWithDecl = findXSDocumentForDecl(currSchema, decl, declDoc);
if (schemaWithDecl == null) {
// cannot get to this schema from the one containing the requesting decl
if (retObj == null) {
String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2";
reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode);
}
return retObj;
}
// a component is hidden, meaning either it's traversed, or being traversed.
// but we didn't find it in the grammar, so it's the latter case, and
// a circular reference. error!
if (DOMUtil.isHidden(decl, fHiddenNodes)) {
if (retObj == null) {
String code = CIRCULAR_CODES[declType];
if (declType == TYPEDECL_TYPE) {
if (SchemaSymbols.ELT_COMPLEXTYPE.equals(DOMUtil.getLocalName(decl))) {
code = "ct-props-correct.3";
}
}
// decl must not be null if we're here...
reportSchemaError(code, new Object [] {declToTraverse.prefix+":"+declToTraverse.localpart}, elmNode);
}
return retObj;
}
return traverseGlobalDecl(declType, decl, schemaWithDecl, sGrammar);
} // getGlobalDecl(XSDocumentInfo, int, QName): Object
// If we are tolerating duplicate declarations and allowing namespace growth
// use the declaration from the current schema load (if it exists)
protected Object getGlobalDecl(String declKey, int declType) {
Object retObj = null;
switch (declType) {
case ATTRIBUTE_TYPE :
retObj = getGlobalAttributeDecl(declKey);
break;
case ATTRIBUTEGROUP_TYPE :
retObj = getGlobalAttributeGroupDecl(declKey);
break;
case ELEMENT_TYPE :
retObj = getGlobalElementDecl(declKey);
break;
case GROUP_TYPE :
retObj = getGlobalGroupDecl(declKey);
break;
case IDENTITYCONSTRAINT_TYPE :
retObj = getIDConstraintDecl(declKey);
break;
case NOTATION_TYPE :
retObj = getGlobalNotationDecl(declKey);
break;
case TYPEDECL_TYPE :
retObj = getGlobalTypeDecl(declKey);
break;
}
return retObj;
}
protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart) {
Object retObj = null;
switch (declType) {
case ATTRIBUTE_TYPE :
retObj = sGrammar.getGlobalAttributeDecl(localpart);
break;
case ATTRIBUTEGROUP_TYPE :
retObj = sGrammar.getGlobalAttributeGroupDecl(localpart);
break;
case ELEMENT_TYPE :
retObj = sGrammar.getGlobalElementDecl(localpart);
break;
case GROUP_TYPE :
retObj = sGrammar.getGlobalGroupDecl(localpart);
break;
case IDENTITYCONSTRAINT_TYPE :
retObj = sGrammar.getIDConstraintDecl(localpart);
break;
case NOTATION_TYPE :
retObj = sGrammar.getGlobalNotationDecl(localpart);
break;
case TYPEDECL_TYPE :
retObj = sGrammar.getGlobalTypeDecl(localpart);
break;
}
return retObj;
}
protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart, String schemaLoc) {
Object retObj = null;
switch (declType) {
case ATTRIBUTE_TYPE :
retObj = sGrammar.getGlobalAttributeDecl(localpart, schemaLoc);
break;
case ATTRIBUTEGROUP_TYPE :
retObj = sGrammar.getGlobalAttributeGroupDecl(localpart, schemaLoc);
break;
case ELEMENT_TYPE :
retObj = sGrammar.getGlobalElementDecl(localpart, schemaLoc);
break;
case GROUP_TYPE :
retObj = sGrammar.getGlobalGroupDecl(localpart, schemaLoc);
break;
case IDENTITYCONSTRAINT_TYPE :
retObj = sGrammar.getIDConstraintDecl(localpart, schemaLoc);
break;
case NOTATION_TYPE :
retObj = sGrammar.getGlobalNotationDecl(localpart, schemaLoc);
break;
case TYPEDECL_TYPE :
retObj = sGrammar.getGlobalTypeDecl(localpart, schemaLoc);
break;
}
return retObj;
}
protected Object traverseGlobalDecl(int declType, Element decl, XSDocumentInfo schemaDoc, SchemaGrammar grammar) {
Object retObj = null;
DOMUtil.setHidden(decl, fHiddenNodes);
SchemaNamespaceSupport nsSupport = null;
// if the parent is use the namespace delcs for it.
Element parent = DOMUtil.getParent(decl);
if (DOMUtil.getLocalName(parent).equals(SchemaSymbols.ELT_REDEFINE))
nsSupport = (SchemaNamespaceSupport)fRedefine2NSSupport.get(parent);
// back up the current SchemaNamespaceSupport, because we need to provide
// a fresh one to the traverseGlobal methods.
schemaDoc.backupNSSupport(nsSupport);
// traverse the referenced global component
switch (declType) {
case TYPEDECL_TYPE :
if (DOMUtil.getLocalName(decl).equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
retObj = fComplexTypeTraverser.traverseGlobal(decl, schemaDoc, grammar);
}
else {
retObj = fSimpleTypeTraverser.traverseGlobal(decl, schemaDoc, grammar);
}
break;
case ATTRIBUTE_TYPE :
retObj = fAttributeTraverser.traverseGlobal(decl, schemaDoc, grammar);
break;
case ELEMENT_TYPE :
retObj = fElementTraverser.traverseGlobal(decl, schemaDoc, grammar);
break;
case ATTRIBUTEGROUP_TYPE :
retObj = fAttributeGroupTraverser.traverseGlobal(decl, schemaDoc, grammar);
break;
case GROUP_TYPE :
retObj = fGroupTraverser.traverseGlobal(decl, schemaDoc, grammar);
break;
case NOTATION_TYPE :
retObj = fNotationTraverser.traverse(decl, schemaDoc, grammar);
break;
case IDENTITYCONSTRAINT_TYPE :
// identity constraints should have been parsed already...
// we should never get here
break;
}
// restore the previous SchemaNamespaceSupport, so that the caller can get
// proper namespace binding.
schemaDoc.restoreNSSupport();
return retObj;
}
public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) {
return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement);
}
// This method determines whether there is a group
// (attributeGroup) which the given one has redefined by
// restriction. If so, it returns it; else it returns null.
// @param type: whether what's been redefined is an
// attributeGroup or a group;
// @param name: the QName of the component doing the redefining.
// @param currSchema: schema doc in which the redefining component lives.
// @return: Object representing decl redefined if present, null
// otherwise.
Object getGrpOrAttrGrpRedefinedByRestriction(int type, QName name, XSDocumentInfo currSchema, Element elmNode) {
String realName = name.uri != null?name.uri+","+name.localpart:
","+name.localpart;
String nameToFind = null;
switch (type) {
case ATTRIBUTEGROUP_TYPE:
nameToFind = (String)fRedefinedRestrictedAttributeGroupRegistry.get(realName);
break;
case GROUP_TYPE:
nameToFind = (String)fRedefinedRestrictedGroupRegistry.get(realName);
break;
default:
return null;
}
if (nameToFind == null) return null;
int commaPos = nameToFind.indexOf(",");
QName qNameToFind = new QName(XMLSymbols.EMPTY_STRING, nameToFind.substring(commaPos+1),
nameToFind.substring(commaPos), (commaPos == 0)? null : nameToFind.substring(0, commaPos));
Object retObj = getGlobalDecl(currSchema, type, qNameToFind, elmNode);
if(retObj == null) {
switch (type) {
case ATTRIBUTEGROUP_TYPE:
reportSchemaError("src-redefine.7.2.1", new Object []{name.localpart}, elmNode);
break;
case GROUP_TYPE:
reportSchemaError("src-redefine.6.2.1", new Object []{name.localpart}, elmNode);
break;
}
return null;
}
return retObj;
} // getGrpOrAttrGrpRedefinedByRestriction(int, QName, XSDocumentInfo): Object
// Since ID constraints can occur in local elements, unless we
// wish to completely traverse all our DOM trees looking for ID
// constraints while we're building our global name registries,
// which seems terribly inefficient, we need to resolve keyrefs
// after all parsing is complete. This we can simply do by running through
// fIdentityConstraintRegistry and calling traverseKeyRef on all
// of the KeyRef nodes. This unfortunately removes this knowledge
// from the elementTraverser class (which must ignore keyrefs),
// but there seems to be no efficient way around this...
protected void resolveKeyRefs() {
for (int i=0; i to hidden before traversing it,
// because it has global scope
DOMUtil.setHidden(fKeyrefs[i], fHiddenNodes);
fKeyrefTraverser.traverse(fKeyrefs[i], fKeyrefElems[i], keyrefSchemaDoc, keyrefGrammar);
}
} // end resolveKeyRefs
// In xsd 1.1, identity constraint declarations can refer to other identity constraints.
// Because we do not wish to traverse all our DOM trees looking for ID constraints while
// we're building our global name registries, we need to resolve identity constraint
// referrals after all named identity constraints parsing have been complete.
protected void resolveIdentityConstraintReferrals() {
for (int i=0; i declarations--along with the element
// decls and namespace bindings they might find handy.
protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc,
XSElementDecl currElemDecl) {
String keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME);
if (keyrefName.length() != 0) {
String keyrefQName = schemaDoc.fTargetNamespace == null?
"," + keyrefName: schemaDoc.fTargetNamespace+","+keyrefName;
checkForDuplicateNames(keyrefQName, IDENTITYCONSTRAINT_TYPE, fUnparsedIdentityConstraintRegistry, fUnparsedIdentityConstraintRegistrySub, keyrefToStore, schemaDoc);
}
// now set up all the registries we'll need...
// check array sizes
if (fKeyrefStackPos == fKeyrefs.length) {
Element [] elemArray = new Element [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
System.arraycopy(fKeyrefs, 0, elemArray, 0, fKeyrefStackPos);
fKeyrefs = elemArray;
XSElementDecl [] declArray = new XSElementDecl [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
System.arraycopy(fKeyrefElems, 0, declArray, 0, fKeyrefStackPos);
fKeyrefElems = declArray;
String[][] stringArray = new String [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT][];
System.arraycopy(fKeyrefNamespaceContext, 0, stringArray, 0, fKeyrefStackPos);
fKeyrefNamespaceContext = stringArray;
XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
System.arraycopy(fKeyrefsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fKeyrefStackPos);
fKeyrefsMapXSDocumentInfo = xsDocumentInfo;
}
fKeyrefs[fKeyrefStackPos] = keyrefToStore;
fKeyrefElems[fKeyrefStackPos] = currElemDecl;
fKeyrefNamespaceContext[fKeyrefStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext();
fKeyrefsMapXSDocumentInfo[fKeyrefStackPos++] = schemaDoc;
} // storeKeyref (Element, XSDocumentInfo, XSElementDecl): void
// This method squirrels away referral identity cosntraint declarations (for xsd 1.1) along with the element
// decls and namespace bindings they might find handy.
protected void storeIdentityConstraintReferral (Element icToStore, XSDocumentInfo schemaDoc,
XSElementDecl currElemDecl) {
// set up all the registries we'll need...
if (fICReferralStackPos == fICReferrals.length) {
Element [] elemArray = new Element [fICReferralStackPos + INC_IC_REFERRAL_STACK_AMOUNT];
System.arraycopy(fICReferrals, 0, elemArray, 0, fICReferralStackPos);
fICReferrals = elemArray;
XSElementDecl [] declArray = new XSElementDecl [fICReferralStackPos + INC_IC_REFERRAL_STACK_AMOUNT];
System.arraycopy(fICReferralElems, 0, declArray, 0, fICReferralStackPos);
fICReferralElems = declArray;
String[][] stringArray = new String [fICReferralStackPos + INC_IC_REFERRAL_STACK_AMOUNT][];
System.arraycopy(fICReferralNamespaceContext, 0, stringArray, 0, fICReferralStackPos);
fICReferralNamespaceContext = stringArray;
XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fICReferralStackPos + INC_IC_REFERRAL_STACK_AMOUNT];
System.arraycopy(fICReferralsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fICReferralStackPos);
fICReferralsMapXSDocumentInfo = xsDocumentInfo;
}
fICReferrals[fICReferralStackPos] = icToStore;
fICReferralElems[fICReferralStackPos] = currElemDecl;
fICReferralNamespaceContext[fICReferralStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext();
fICReferralsMapXSDocumentInfo[fICReferralStackPos++] = schemaDoc;
} // storeIdentityConstraintReferral (Element, XSDocumentInfo, XSElementDecl): void
/**
* resolveSchema method is responsible for resolving location of the schema (using XMLEntityResolver),
* and if it was succefully resolved getting the schema Document.
* @param desc
* @param mustResolve
* @param referElement
* @return A schema Element or null.
*/
private Element resolveSchema(XSDDescription desc, boolean mustResolve,
Element referElement, boolean usePairs) {
XMLInputSource schemaSource = null;
try {
Hashtable pairs = usePairs ? fLocationPairs : EMPTY_TABLE;
schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver);
}
catch (IOException ex) {
if (mustResolve) {
reportSchemaError("schema_reference.4",
new Object[]{desc.getLocationHints()[0]},
referElement);
}
else {
reportSchemaWarning("schema_reference.4",
new Object[]{desc.getLocationHints()[0]},
referElement);
}
}
if (schemaSource instanceof DOMInputSource) {
return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
} // DOMInputSource
else if (schemaSource instanceof SAXInputSource) {
return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
} // SAXInputSource
else if (schemaSource instanceof StAXInputSource) {
return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
} // StAXInputSource
else if (schemaSource instanceof XSInputSource) {
return getSchemaDocument((XSInputSource) schemaSource, desc);
} // XSInputSource
return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement);
} // getSchema(String, String, String, boolean, short): Document
private Element resolveSchema(XMLInputSource schemaSource, XSDDescription desc,
boolean mustResolve, Element referElement) {
if (schemaSource instanceof DOMInputSource) {
return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
} // DOMInputSource
else if (schemaSource instanceof SAXInputSource) {
return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
} // SAXInputSource
else if (schemaSource instanceof StAXInputSource) {
return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
} // StAXInputSource
else if (schemaSource instanceof XSInputSource) {
return getSchemaDocument((XSInputSource) schemaSource, desc);
} // XSInputSource
return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement);
}
private XMLInputSource resolveSchemaSource(XSDDescription desc, boolean mustResolve,
Element referElement, boolean usePairs) {
XMLInputSource schemaSource = null;
try {
Hashtable pairs = usePairs ? fLocationPairs : EMPTY_TABLE;
schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver);
}
catch (IOException ex) {
if (mustResolve) {
reportSchemaError("schema_reference.4",
new Object[]{desc.getLocationHints()[0]},
referElement);
}
else {
reportSchemaWarning("schema_reference.4",
new Object[]{desc.getLocationHints()[0]},
referElement);
}
}
return schemaSource;
}
/**
* getSchemaDocument method uses XMLInputSource to parse a schema document.
* @param schemaNamespace
* @param schemaSource
* @param mustResolve
* @param referType
* @param referElement
* @return A schema Element.
*/
private Element getSchemaDocument(String schemaNamespace, XMLInputSource schemaSource,
boolean mustResolve, short referType, Element referElement) {
boolean hasInput = true;
IOException exception = null;
// contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc.
Element schemaElement = null;
try {
// when the system id and byte stream and character stream
// of the input source are all null, it's
// impossible to find the schema document. so we skip in
// this case. otherwise we'll receive some NPE or
// file not found errors. but schemaHint=="" is perfectly
// legal for import.
if (schemaSource != null &&
(schemaSource.getSystemId() != null ||
schemaSource.getByteStream() != null ||
schemaSource.getCharacterStream() != null)) {
// When the system id of the input source is used, first try to
// expand it, and check whether the same document has been
// parsed before. If so, return the document corresponding to
// that system id.
XSDKey key = null;
String schemaId = null;
if (referType != XSDDescription.CONTEXT_PREPARSE){
schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
key = new XSDKey(schemaId, referType, schemaNamespace);
if((schemaElement = (Element)fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
}
fSchemaParser.parse(schemaSource);
Document schemaDocument = fSchemaParser.getDocument();
schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null;
return getSchemaDocument0(key, schemaId, schemaElement,
fSchemaVersion == Constants.SCHEMA_VERSION_1_1
? fSchemaParser.getProperty(DATATYPE_XML_VERSION) : null);
}
else {
hasInput = false;
}
}
catch (IOException ex) {
exception = ex;
}
return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception);
} // getSchemaDocument(String, XMLInputSource, boolean, short, Element): Element
/**
* getSchemaDocument method uses SAXInputSource to parse a schema document.
* @param schemaNamespace
* @param schemaSource
* @param mustResolve
* @param referType
* @param referElement
* @return A schema Element.
*/
private Element getSchemaDocument(String schemaNamespace, SAXInputSource schemaSource,
boolean mustResolve, short referType, Element referElement) {
XMLReader parser = schemaSource.getXMLReader();
InputSource inputSource = schemaSource.getInputSource();
boolean hasInput = true;
IOException exception = null;
Element schemaElement = null;
try {
if (inputSource != null &&
(inputSource.getSystemId() != null ||
inputSource.getByteStream() != null ||
inputSource.getCharacterStream() != null)) {
// check whether the same document has been parsed before.
// If so, return the document corresponding to that system id.
XSDKey key = null;
String schemaId = null;
if (referType != XSDDescription.CONTEXT_PREPARSE) {
schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false);
key = new XSDKey(schemaId, referType, schemaNamespace);
if ((schemaElement = (Element) fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
}
boolean namespacePrefixes = false;
if (parser != null) {
try {
namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES);
}
catch (SAXException se) {}
}
else {
try {
parser = XMLReaderFactory.createXMLReader();
}
// If something went wrong with the factory
// just use our own SAX parser.
catch (SAXException se) {
parser = new SAXParser();
}
try {
parser.setFeature(NAMESPACE_PREFIXES, true);
namespacePrefixes = true;
// If this is a Xerces SAX parser set the security manager if there is one
if (parser instanceof SAXParser) {
Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER);
if (securityManager != null) {
parser.setProperty(SECURITY_MANAGER, securityManager);
}
}
}
catch (SAXException se) {}
}
// If XML names and Namespace URIs are already internalized we
// can avoid running them through the SymbolTable.
boolean stringsInternalized = false;
try {
stringsInternalized = parser.getFeature(STRING_INTERNING);
}
catch (SAXException exc) {
// The feature isn't recognized or getting it is not supported.
// In either case, assume that strings are not internalized.
}
if (fXSContentHandler == null) {
fXSContentHandler = new SchemaContentHandler();
}
fXSContentHandler.reset(fSchemaParser, fSymbolTable,
namespacePrefixes, stringsInternalized);
parser.setContentHandler(fXSContentHandler);
parser.setErrorHandler(fErrorReporter.getSAXErrorHandler());
parser.parse(inputSource);
// Disconnect the schema loader and other objects from the XMLReader
try {
parser.setContentHandler(null);
parser.setErrorHandler(null);
}
// Ignore any exceptions thrown by the XMLReader. Old versions of SAX
// required an XMLReader to throw a NullPointerException if an attempt
// to set a handler to null was made.
catch (Exception e) {}
Document schemaDocument = fXSContentHandler.getDocument();
schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null;
return getSchemaDocument0(key, schemaId, schemaElement,
fSchemaVersion == Constants.SCHEMA_VERSION_1_1
? fSchemaParser.getProperty(DATATYPE_XML_VERSION) : null);
}
else {
hasInput = false;
}
}
catch (SAXParseException spe) {
throw SAX2XNIUtil.createXMLParseException0(spe);
}
catch (SAXException se) {
throw SAX2XNIUtil.createXNIException0(se);
}
catch (IOException ioe) {
exception = ioe;
}
return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception);
} // getSchemaDocument(String, SAXInputSource, boolean, short, Element): Element
/**
* getSchemaDocument method uses DOMInputSource to parse a schema document.
* @param schemaNamespace
* @param schemaSource
* @param mustResolve
* @param referType
* @param referElement
* @return A schema Element.
*/
private Element getSchemaDocument(String schemaNamespace, DOMInputSource schemaSource,
boolean mustResolve, short referType, Element referElement) {
boolean hasInput = true;
IOException exception = null;
Element schemaElement = null;
Element schemaRootElement = null;
final Node node = schemaSource.getNode();
short nodeType = -1;
if (node != null) {
nodeType = node.getNodeType();
if (nodeType == Node.DOCUMENT_NODE) {
schemaRootElement = DOMUtil.getRoot((Document) node);
}
else if (nodeType == Node.ELEMENT_NODE) {
schemaRootElement = (Element) node;
}
}
try {
if (schemaRootElement != null) {
// check whether the same document has been parsed before.
// If so, return the document corresponding to that system id.
XSDKey key = null;
String schemaId = null;
if (referType != XSDDescription.CONTEXT_PREPARSE) {
schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
boolean isDocument = (nodeType == Node.DOCUMENT_NODE);
if (!isDocument) {
Node parent = schemaRootElement.getParentNode();
if (parent != null) {
isDocument = (parent.getNodeType() == Node.DOCUMENT_NODE);
}
}
if (isDocument) {
key = new XSDKey(schemaId, referType, schemaNamespace);
if ((schemaElement = (Element) fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
}
}
schemaElement = schemaRootElement;
return getSchemaDocument0(key, schemaId, schemaElement, null);
}
else {
hasInput = false;
}
}
catch (IOException ioe) {
exception = ioe;
}
return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception);
} // getSchemaDocument(String, DOMInputSource, boolean, short, Element): Element
/**
* getSchemaDocument method uses StAXInputSource to parse a schema document.
* @param schemaNamespace
* @param schemaSource
* @param mustResolve
* @param referType
* @param referElement
* @return A schema Element.
*/
private Element getSchemaDocument(String schemaNamespace, StAXInputSource schemaSource,
boolean mustResolve, short referType, Element referElement) {
IOException exception = null;
Element schemaElement = null;
try {
final boolean consumeRemainingContent = schemaSource.shouldConsumeRemainingContent();
final XMLStreamReader streamReader = schemaSource.getXMLStreamReader();
final XMLEventReader eventReader = schemaSource.getXMLEventReader();
// check whether the same document has been parsed before.
// If so, return the document corresponding to that system id.
XSDKey key = null;
String schemaId = null;
if (referType != XSDDescription.CONTEXT_PREPARSE) {
schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
boolean isDocument = consumeRemainingContent;
if (!isDocument) {
if (streamReader != null) {
isDocument = (streamReader.getEventType() == XMLStreamReader.START_DOCUMENT);
}
else {
isDocument = eventReader.peek().isStartDocument();
}
}
if (isDocument) {
key = new XSDKey(schemaId, referType, schemaNamespace);
if ((schemaElement = (Element) fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
}
}
if (fStAXSchemaParser == null) {
fStAXSchemaParser = new StAXSchemaParser();
}
fStAXSchemaParser.reset(fSchemaParser, fSymbolTable);
if (streamReader != null) {
fStAXSchemaParser.parse(streamReader);
if (consumeRemainingContent) {
while (streamReader.hasNext()) {
streamReader.next();
}
}
}
else {
fStAXSchemaParser.parse(eventReader);
if (consumeRemainingContent) {
while (eventReader.hasNext()) {
eventReader.nextEvent();
}
}
}
Document schemaDocument = fStAXSchemaParser.getDocument();
schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null;
return getSchemaDocument0(key, schemaId, schemaElement,
fSchemaVersion == Constants.SCHEMA_VERSION_1_1
? fSchemaParser.getProperty(DATATYPE_XML_VERSION) : null);
}
catch (XMLStreamException e) {
Throwable t = e.getNestedException();
if (t instanceof IOException) {
exception = (IOException) t;
}
else {
StAXLocationWrapper slw = new StAXLocationWrapper();
slw.setLocation(e.getLocation());
throw new XMLParseException(slw, e.getMessage(), e);
}
}
catch (IOException e) {
exception = e;
}
return getSchemaDocument1(mustResolve, true, schemaSource, referElement, exception);
} // getSchemaDocument(String, StAXInputSource, boolean, short, Element): Element
/**
* Code shared between the various getSchemaDocument() methods which
* stores mapping information for the document.
*/
private Element getSchemaDocument0(XSDKey key, String schemaId, Element schemaElement, Object datatypeXMLVersion) {
// now we need to store the mapping information from system id
// to the document. also from the document to the system id.
if (schemaElement != null) {
if (key != null) {
fTraversed.put(key, schemaElement);
}
if (schemaId != null) {
fDoc2SystemId.put(schemaElement, schemaId);
}
if (datatypeXMLVersion != null) {
fDoc2DatatypeXMLVersion.put(schemaElement, datatypeXMLVersion);
}
fLastSchemaWasDuplicate = false;
}
else {
fLastSchemaWasDuplicate = true;
}
return schemaElement;
} // getSchemaDocument0(XSDKey, String, Element): Element
/**
* Error handling code shared between the various getSchemaDocument() methods.
*/
private Element getSchemaDocument1(boolean mustResolve, boolean hasInput,
XMLInputSource schemaSource, Element referElement, IOException ioe) {
// either an error occured (exception), or empty input source was
// returned, we need to report an error or a warning
if (mustResolve) {
if (hasInput) {
reportSchemaError("schema_reference.4",
new Object[]{schemaSource.getSystemId()},
referElement, ioe);
}
else {
reportSchemaError("schema_reference.4",
new Object[]{schemaSource == null ? "" : schemaSource.getSystemId()},
referElement, ioe);
}
}
else if (hasInput) {
reportSchemaWarning("schema_reference.4",
new Object[]{schemaSource.getSystemId()},
referElement, ioe);
}
fLastSchemaWasDuplicate = false;
return null;
} // getSchemaDocument1(boolean, boolean, XMLInputSource, Element): Element
/**
* getSchemaDocument method uses XMLInputSource to parse a schema document.
* @param schemaNamespace
* @param schemaSource
* @param mustResolve
* @param referType
* @param referElement
* @return A schema Element.
*/
private Element getSchemaDocument(XSInputSource schemaSource, XSDDescription desc) {
SchemaGrammar[] grammars = schemaSource.getGrammars();
short referType = desc.getContextType();
if (grammars != null && grammars.length > 0) {
Vector expandedGrammars = expandGrammars(grammars);
// check for existing grammars in our bucket
// and if there exist any, and namespace growth is
// not enabled - we do nothing
if (fNamespaceGrowth || !existingGrammars(expandedGrammars)) {
addGrammars(expandedGrammars);
if (referType == XSDDescription.CONTEXT_PREPARSE) {
desc.setTargetNamespace(grammars[0].getTargetNamespace());
}
}
}
else {
XSObject[] components = schemaSource.getComponents();
if (components != null && components.length > 0) {
Hashtable importDependencies = new Hashtable();
Vector expandedComponents = expandComponents(components, importDependencies);
if (fNamespaceGrowth || canAddComponents(expandedComponents)) {
addGlobalComponents(expandedComponents, importDependencies);
if (referType == XSDDescription.CONTEXT_PREPARSE) {
desc.setTargetNamespace(components[0].getNamespace());
}
}
}
}
return null;
} // getSchemaDocument(String, XSInputSource, boolean, short, Element): Element
private Vector expandGrammars(SchemaGrammar[] grammars) {
Vector currGrammars = new Vector();
for (int i=0; i= 0; j--) {
sg2 = (SchemaGrammar)gs.elementAt(j);
if (!currGrammars.contains(sg2)) {
currGrammars.addElement(sg2);
}
}
}
return currGrammars;
}
private boolean existingGrammars(Vector grammars) {
int length = grammars.size();
final XSDDescription desc = new XSDDescription();
for (int i=0; i < length; i++) {
final SchemaGrammar sg1 = (SchemaGrammar)grammars.elementAt(i);
desc.setNamespace(sg1.getTargetNamespace());
final SchemaGrammar sg2 = findGrammar(desc, false);
if (sg2 != null) {
return true;
}
}
return false;
}
private boolean canAddComponents(Vector components) {
final int size = components.size();
final XSDDescription desc = new XSDDescription();
for (int i=0; i 0) {
for (int i=0; i 0) {
expandImportList(namespace, importList);
}
}
}
private void expandImportList(String namespace, Vector namespaceList) {
SchemaGrammar sg = fGrammarBucket.getGrammar(namespace);
// shouldn't be null
if (sg != null) {
Vector isgs = sg.getImportedGrammars();
if (isgs == null) {
isgs = new Vector();
addImportList(sg, isgs, namespaceList);
sg.setImportedGrammars(isgs);
}
else {
updateImportList(sg, isgs, namespaceList);
}
}
}
private void addImportList(SchemaGrammar sg, Vector importedGrammars, Vector namespaceList) {
final int size = namespaceList.size();
SchemaGrammar isg;
for (int i=0; is and s to ensure that information
// relating to implicit restrictions is preserved for those
// traversers.
private void renameRedefiningComponents(XSDocumentInfo currSchema,
Element child, String componentType,
String oldName, String newName) {
if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
Element grandKid = DOMUtil.getFirstChildElement(child);
if (grandKid == null) {
reportSchemaError("src-redefine.5.a.a", null, child);
}
else {
String grandKidName = DOMUtil.getLocalName(grandKid);
if (grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
grandKid = DOMUtil.getNextSiblingElement(grandKid);
}
if (grandKid == null) {
reportSchemaError("src-redefine.5.a.a", null, child);
}
else {
grandKidName = DOMUtil.getLocalName(grandKid);
if (!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) {
reportSchemaError("src-redefine.5.a.b", new Object[]{grandKidName}, child);
}
else {
Object[] attrs = fAttributeChecker.checkAttributes(grandKid, false, currSchema);
QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE];
if (derivedBase == null ||
derivedBase.uri != currSchema.fTargetNamespace ||
!derivedBase.localpart.equals(oldName)) {
reportSchemaError("src-redefine.5.a.c",
new Object[]{grandKidName,
(currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace)
+ "," + oldName},
child);
}
else {
// now we have to do the renaming...
if (derivedBase.prefix != null && derivedBase.prefix.length() > 0)
grandKid.setAttribute( SchemaSymbols.ATT_BASE,
derivedBase.prefix + ":" + newName );
else
grandKid.setAttribute( SchemaSymbols.ATT_BASE, newName );
// return true;
}
fAttributeChecker.returnAttrArray(attrs, currSchema);
}
}
}
}
else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
Element grandKid = DOMUtil.getFirstChildElement(child);
if (grandKid == null) {
reportSchemaError("src-redefine.5.b.a", null, child);
}
else {
if (DOMUtil.getLocalName(grandKid).equals(SchemaSymbols.ELT_ANNOTATION)) {
grandKid = DOMUtil.getNextSiblingElement(grandKid);
}
if (grandKid == null) {
reportSchemaError("src-redefine.5.b.a", null, child);
}
else {
// have to go one more level down; let another pass worry whether complexType is valid.
Element greatGrandKid = DOMUtil.getFirstChildElement(grandKid);
if (greatGrandKid == null) {
reportSchemaError("src-redefine.5.b.b", null, grandKid);
}
else {
String greatGrandKidName = DOMUtil.getLocalName(greatGrandKid);
if (greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
greatGrandKid = DOMUtil.getNextSiblingElement(greatGrandKid);
}
if (greatGrandKid == null) {
reportSchemaError("src-redefine.5.b.b", null, grandKid);
}
else {
greatGrandKidName = DOMUtil.getLocalName(greatGrandKid);
if (!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) &&
!greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) {
reportSchemaError("src-redefine.5.b.c", new Object[]{greatGrandKidName}, greatGrandKid);
}
else {
Object[] attrs = fAttributeChecker.checkAttributes(greatGrandKid, false, currSchema);
QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE];
if (derivedBase == null ||
derivedBase.uri != currSchema.fTargetNamespace ||
!derivedBase.localpart.equals(oldName)) {
reportSchemaError("src-redefine.5.b.d",
new Object[]{greatGrandKidName,
(currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace)
+ "," + oldName},
greatGrandKid);
}
else {
// now we have to do the renaming...
if (derivedBase.prefix != null && derivedBase.prefix.length() > 0)
greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE,
derivedBase.prefix + ":" + newName );
else
greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE,
newName );
// return true;
}
}
}
}
}
}
}
else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
String processedBaseName = (currSchema.fTargetNamespace == null)?
","+oldName:currSchema.fTargetNamespace+","+oldName;
int attGroupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema);
if (attGroupRefsCount > 1) {
reportSchemaError("src-redefine.7.1", new Object []{new Integer(attGroupRefsCount)}, child);
}
else if (attGroupRefsCount == 1) {
// return true;
}
else
if (currSchema.fTargetNamespace == null)
fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, ","+newName);
else
fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
}
else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
String processedBaseName = (currSchema.fTargetNamespace == null)?
","+oldName:currSchema.fTargetNamespace+","+oldName;
int groupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema);
if (groupRefsCount > 1) {
reportSchemaError("src-redefine.6.1.1", new Object []{new Integer(groupRefsCount)}, child);
}
else if (groupRefsCount == 1) {
// return true;
}
else {
if (currSchema.fTargetNamespace == null)
fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName);
else
fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
}
}
else {
reportSchemaError("Internal-Error", new Object [] {"could not handle this particular ; please submit your schemas and instance document in a bug report!"}, child);
}
// if we get here then we must have reported an error and failed somewhere...
// return false;
} // renameRedefiningComponents(XSDocumentInfo, Element, String, String, String):void
// this method takes a name of the form a:b, determines the URI mapped
// to by a in the current SchemaNamespaceSupport object, and returns this
// information in the form (nsURI,b) suitable for lookups in the global
// decl Hashtables.
// REVISIT: should have it return QName, instead of String. this would
// save lots of string concatenation time. we can use
// QName#equals() to compare two QNames, and use QName directly
// as a key to the SymbolHash.
// And when the DV's are ready to return compiled values from
// validate() method, we should just call QNameDV.validate()
// in this method.
private String findQName(String name, XSDocumentInfo schemaDoc) {
SchemaNamespaceSupport currNSMap = schemaDoc.fNamespaceSupport;
int colonPtr = name.indexOf(':');
String prefix = XMLSymbols.EMPTY_STRING;
if (colonPtr > 0)
prefix = name.substring(0, colonPtr);
String uri = currNSMap.getURI(fSymbolTable.addSymbol(prefix));
String localpart = (colonPtr == 0)?name:name.substring(colonPtr+1);
if (prefix == XMLSymbols.EMPTY_STRING && uri == null && schemaDoc.fIsChameleonSchema)
uri = schemaDoc.fTargetNamespace;
if (uri == null)
return ","+localpart;
return uri+","+localpart;
} // findQName(String, XSDocumentInfo): String
// This function looks among the children of curr for an element of type elementSought.
// If it finds one, it evaluates whether its ref attribute contains a reference
// to originalQName. If it does, it returns 1 + the value returned by
// calls to itself on all other children. In all other cases it returns 0 plus
// the sum of the values returned by calls to itself on curr's children.
// It also resets the value of ref so that it will refer to the renamed type from the schema
// being redefined.
private int changeRedefineGroup(String originalQName, String elementSought,
String newName, Element curr, XSDocumentInfo schemaDoc) {
int result = 0;
for (Element child = DOMUtil.getFirstChildElement(curr);
child != null; child = DOMUtil.getNextSiblingElement(child)) {
String name = DOMUtil.getLocalName(child);
if (!name.equals(elementSought))
result += changeRedefineGroup(originalQName, elementSought, newName, child, schemaDoc);
else {
String ref = child.getAttribute( SchemaSymbols.ATT_REF );
if (ref.length() != 0) {
String processedRef = findQName(ref, schemaDoc);
if (originalQName.equals(processedRef)) {
String prefix = XMLSymbols.EMPTY_STRING;
int colonptr = ref.indexOf(":");
if (colonptr > 0) {
prefix = ref.substring(0,colonptr);
child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName);
}
else
child.setAttribute(SchemaSymbols.ATT_REF, newName);
result++;
if (elementSought.equals(SchemaSymbols.ELT_GROUP)) {
String minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS );
String maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS );
if (!((maxOccurs.length() == 0 || maxOccurs.equals("1"))
&& (minOccurs.length() == 0 || minOccurs.equals("1")))) {
reportSchemaError("src-redefine.6.1.2", new Object [] {ref}, child);
}
}
}
} // if ref was null some other stage of processing will flag the error
}
}
return result;
} // changeRedefineGroup
// this method returns the XSDocumentInfo object that contains the
// component corresponding to decl. If components from this
// document cannot be referred to from those of currSchema, this
// method returns null; it's up to the caller to throw an error.
// @param: currSchema: the XSDocumentInfo object containing the
// decl ref'ing us.
// @param: decl: the declaration being ref'd.
// this method is superficial now. ---Jack
private XSDocumentInfo findXSDocumentForDecl(XSDocumentInfo currSchema,
Element decl, XSDocumentInfo decl_Doc) {
if (DEBUG_NODE_POOL) {
System.out.println("DOCUMENT NS:"+ currSchema.fTargetNamespace+" hashcode:"+ ((Object)currSchema.fSchemaElement).hashCode());
}
Object temp = decl_Doc;
if (temp == null) {
// something went badly wrong; we don't know this doc?
return null;
}
XSDocumentInfo declDocInfo = (XSDocumentInfo)temp;
return declDocInfo;
/*********
Logic here is unnecessary after schema WG's recent decision to allow
schema components from one document to refer to components of any other,
so long as there's some include/import/redefine path amongst them.
If they rver reverse this decision the code's right here though... - neilg
// now look in fDependencyMap to see if this is reachable
if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) {
return declDocInfo;
}
// obviously the requesting doc didn't include, redefine or
// import the one containing decl...
return null;
**********/
} // findXSDocumentForDecl(XSDocumentInfo, Element): XSDocumentInfo
// returns whether more than s occur in children of elem
private boolean nonAnnotationContent(Element elem) {
for(Element child = DOMUtil.getFirstChildElement(elem); child != null; child = DOMUtil.getNextSiblingElement(child)) {
if(!(DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION))) return true;
}
return false;
} // nonAnnotationContent(Element): boolean
private void setSchemasVisible(XSDocumentInfo startSchema) {
if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) {
// make it visible
DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes);
Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema);
for (int i = 0; i < dependingSchemas.size(); i++) {
setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i));
}
}
// if it's visible already than so must be its children
} // setSchemasVisible(XSDocumentInfo): void
private SimpleLocator xl = new SimpleLocator();
/**
* Extract location information from an Element node, and create a
* new SimpleLocator object from such information. Returning null means
* no information can be retrieved from the element.
*/
public SimpleLocator element2Locator(Element e) {
if (!( e instanceof ElementImpl))
return null;
SimpleLocator l = new SimpleLocator();
return element2Locator(e, l) ? l : null;
}
/**
* Extract location information from an Element node, store such
* information in the passed-in SimpleLocator object, then return
* true. Returning false means can't extract or store such information.
*/
public boolean element2Locator(Element e, SimpleLocator l) {
if (l == null)
return false;
if (e instanceof ElementImpl) {
ElementImpl ele = (ElementImpl)e;
// get system id from document object
Document doc = ele.getOwnerDocument();
String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc));
// line/column numbers are stored in the element node
int line = ele.getLineNumber();
int column = ele.getColumnNumber();
l.setValues(sid, sid, line, column, ele.getCharacterOffset());
return true;
}
return false;
}
public void reportSchemaError(String key, Object[] args, Element ele) {
reportSchemaError(key, args, ele, null);
}
void reportSchemaError(String key, Object[] args, Element ele, Exception exception) {
if (element2Locator(ele, xl)) {
fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN,
key, args, XMLErrorReporter.SEVERITY_ERROR, exception);
}
else {
fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
key, args, XMLErrorReporter.SEVERITY_ERROR, exception);
}
}
public void reportSchemaWarning(String key, Object[] args, Element ele) {
reportSchemaWarning(key, args, ele, null);
}
void reportSchemaWarning(String key, Object[] args, Element ele, Exception exception) {
if (element2Locator(ele, xl)) {
fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN,
key, args, XMLErrorReporter.SEVERITY_WARNING, exception);
}
else {
fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
key, args, XMLErrorReporter.SEVERITY_WARNING, exception);
}
}
/**
* Grammar pool used for validating annotations. This will return all of the
* grammars from the grammar bucket. It will also return an object for the
* schema for schemas which will contain at least the relevant declarations
* for annotations.
*/
private static class XSAnnotationGrammarPool implements XMLGrammarPool {
private XSGrammarBucket fGrammarBucket;
private Grammar [] fInitialGrammarSet;
private short fSchemaVersion;
XSAnnotationGrammarPool(short schemaVersion) {
fSchemaVersion = schemaVersion;
}
public Grammar[] retrieveInitialGrammarSet(String grammarType) {
if (grammarType == XMLGrammarDescription.XML_SCHEMA) {
if (fInitialGrammarSet == null) {
if (fGrammarBucket == null) {
fInitialGrammarSet = new Grammar [] {SchemaGrammar.Schema4Annotations.getSchema4Annotations(fSchemaVersion)};
}
else {
SchemaGrammar [] schemaGrammars = fGrammarBucket.getGrammars();
/**
* If the grammar bucket already contains the schema for schemas
* then we already have the definitions for the parts relevant
* to annotations.
*/
for (int i = 0; i < schemaGrammars.length; ++i) {
if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(schemaGrammars[i].getTargetNamespace())) {
fInitialGrammarSet = schemaGrammars;
return fInitialGrammarSet;
}
}
Grammar [] grammars = new Grammar[schemaGrammars.length + 1];
System.arraycopy(schemaGrammars, 0, grammars, 0, schemaGrammars.length);
grammars[grammars.length - 1] = SchemaGrammar.Schema4Annotations.getSchema4Annotations(fSchemaVersion);
fInitialGrammarSet = grammars;
}
}
return fInitialGrammarSet;
}
return new Grammar[0];
}
public void cacheGrammars(String grammarType, Grammar[] grammars) {
}
public Grammar retrieveGrammar(XMLGrammarDescription desc) {
if (desc.getGrammarType() == XMLGrammarDescription.XML_SCHEMA) {
final String tns = ((XMLSchemaDescription) desc).getTargetNamespace();
if (fGrammarBucket != null) {
Grammar grammar = fGrammarBucket.getGrammar(tns);
if (grammar != null) {
return grammar;
}
}
if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(tns)) {
return SchemaGrammar.Schema4Annotations.getSchema4Annotations(fSchemaVersion);
}
}
return null;
}
public void refreshGrammars(XSGrammarBucket gBucket) {
fGrammarBucket = gBucket;
fInitialGrammarSet = null;
}
public void lockPool() {}
public void unlockPool() {}
public void clear() {}
}
/**
* used to identify a reference to a schema document
* if the same document is referenced twice with the same key, then
* we only need to parse it once.
*
* When 2 XSDKey's are compared, the following table can be used to
* determine whether they are equal:
* inc red imp pre ins
* inc N/L ? N/L N/L N/L
* red ? N/L ? ? ?
* imp N/L ? N/P N/P N/P
* pre N/L ? N/P N/P N/P
* ins N/L ? N/P N/P N/P
*
* Where: N/L: duplicate when they have the same namespace and location.
* ? : not clear from the spec.
* REVISIT: to simplify the process, also considering
* it's very rare, we treat them as not duplicate.
* N/P: not possible. imp/pre/ins are referenced by namespace.
* when the first time we encounter a schema document for a
* namespace, we create a grammar and store it in the grammar
* bucket. when we see another reference to the same namespace,
* we first check whether a grammar with the same namespace is
* already in the bucket, which is true in this case, so we
* won't create another XSDKey.
*
* Conclusion from the table: two XSDKey's are duplicate only when all of
* the following are true:
* 1. They are both "redefine", or neither is "redefine";
* 2. They have the same namespace;
* 3. They have the same non-null location.
*
* About 3: if neither has a non-null location, then it's the case where
* 2 input streams are provided, but no system ID is provided. We can't tell
* whether the 2 streams have the same content, so we treat them as not
* duplicate.
*/
private static class XSDKey {
String systemId;
short referType;
// for inclue/redefine, this is the enclosing namespace
// for import/preparse/instance, this is the target namespace
String referNS;
XSDKey(String systemId, short referType, String referNS) {
this.systemId = systemId;
this.referType = referType;
this.referNS = referNS;
}
public int hashCode() {
// according to the description at the beginning of this class,
// we use the hashcode of the namespace as the hashcoe of this key.
return referNS == null ? 0 : referNS.hashCode();
}
public boolean equals(Object obj) {
if (!(obj instanceof XSDKey)) {
return false;
}
XSDKey key = (XSDKey)obj;
// condition 1: both are redefine
/** if (referType == XSDDescription.CONTEXT_REDEFINE ||
key.referType == XSDDescription.CONTEXT_REDEFINE) {
if (referType != key.referType)
return false;
}**/
// condition 2: same namespace
if (referNS != key.referNS)
return false;
// condition 3: same non-null location
if (systemId == null || !systemId.equals(key.systemId)) {
return false;
}
return true;
}
}
private static final class SAX2XNIUtil extends ErrorHandlerWrapper {
public static XMLParseException createXMLParseException0(SAXParseException exception) {
return createXMLParseException(exception);
}
public static XNIException createXNIException0(SAXException exception) {
return createXNIException(exception);
}
}
/**
* @param state
*/
public void setGenerateSyntheticAnnotations(boolean state) {
fSchemaParser.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, state);
}
/**
* Set schema 1.1 support
*
* @param state
*/
public void setSchemaVersionInfo(short version, XSConstraints xsConstraints) {
fSchemaVersion = version;
fXSConstraints = xsConstraints;
if (version < Constants.SCHEMA_VERSION_1_1) {
fSupportedVersion = SUPPORTED_VERSION_1_0;
}
else {
fSupportedVersion = SUPPORTED_VERSION_1_1;
if (fOverrideHandler == null) {
fOverrideHandler = new OverrideTransformationManager(this, new DOMOverrideImpl(this));
}
if (fDoc2DatatypeXMLVersion == null) {
fDoc2DatatypeXMLVersion = new Hashtable();
}
}
fSchemaParser.setSupportedVersion(fSupportedVersion);
}
public String getDocumentURI() {
return fSchemaParser.getDocument().getDocumentURI();
}
public String getDocumentURI(Element ele) {
return doc2SystemId(ele);
}
public short getSchemaVersion() {
return fSchemaVersion;
}
} // XSDHandler