1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 1999-2005 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.impl.xs.traversers;
  22 
  23 import java.util.Stack;
  24 import java.util.Vector;
  25 
  26 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
  27 import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport;
  28 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  29 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException;
  30 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
  31 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  32 import org.w3c.dom.Element;
  33 import org.w3c.dom.Node;
  34 import org.w3c.dom.Attr;
  35 import org.w3c.dom.NamedNodeMap;
  36 
  37 /**
  38  * Objects of this class hold all information pecular to a
  39  * particular XML Schema document.  This is needed because
  40  * namespace bindings and other settings on the <schema/> element
  41  * affect the contents of that schema document alone.
  42  *
  43  * @xerces.internal
  44  *
  45  * @author Neil Graham, IBM
  46  */
  47 class XSDocumentInfo {
  48 
  49     // Data
  50     protected SchemaNamespaceSupport fNamespaceSupport;
  51     protected SchemaNamespaceSupport fNamespaceSupportRoot;
  52     protected Stack SchemaNamespaceSupportStack = new Stack();
  53 
  54     // schema's attributeFormDefault
  55     protected boolean fAreLocalAttributesQualified;
  56 
  57     // elementFormDefault
  58     protected boolean fAreLocalElementsQualified;
  59 
  60     // [block | final]Default
  61     protected short fBlockDefault;
  62     protected short fFinalDefault;
  63 
  64     // targetNamespace
  65     String fTargetNamespace;
  66 
  67     // represents whether this is a chameleon schema (i.e., whether its TNS is natural or comes from without)
  68     protected boolean fIsChameleonSchema;
  69 
  70     // the root of the schema Document tree itself
  71     protected Element fSchemaElement;
  72 
  73     // all namespaces that this document can refer to
  74     Vector fImportedNS = new Vector();
  75 
  76     protected ValidationState fValidationContext = new ValidationState();
  77 
  78     SymbolTable fSymbolTable = null;
  79 
  80     // attribute checker to which we'll return the attributes
  81     // once we've been told that we're done with them
  82     protected XSAttributeChecker fAttrChecker;
  83 
  84     // array of objects on the schema's root element.  This is null
  85     // once returnSchemaAttrs has been called.
  86     protected Object [] fSchemaAttrs;
  87 
  88     // list of annotations contained in the schema document. This is null
  89     // once removeAnnotations has been called.
  90     protected XSAnnotationInfo fAnnotations = null;
  91 
  92     // note that the caller must ensure to call returnSchemaAttrs()
  93     // to avoid memory leaks!
  94     XSDocumentInfo (Element schemaRoot, XSAttributeChecker attrChecker, SymbolTable symbolTable)
  95                     throws XMLSchemaException {
  96         fSchemaElement = schemaRoot;
  97         initNamespaceSupport(schemaRoot);
  98         fIsChameleonSchema = false;
  99 
 100         fSymbolTable = symbolTable;
 101         fAttrChecker = attrChecker;
 102 
 103         if (schemaRoot != null) {
 104             Element root = schemaRoot;
 105             fSchemaAttrs = attrChecker.checkAttributes(root, true, this);
 106             // schemaAttrs == null means it's not an <xsd:schema> element
 107             // throw an exception, but we don't know the document systemId,
 108             // so we leave that to the caller.
 109             if (fSchemaAttrs == null) {
 110                 throw new XMLSchemaException(null, null);
 111             }
 112             fAreLocalAttributesQualified =
 113                 ((XInt)fSchemaAttrs[XSAttributeChecker.ATTIDX_AFORMDEFAULT]).intValue() == SchemaSymbols.FORM_QUALIFIED;
 114             fAreLocalElementsQualified =
 115                 ((XInt)fSchemaAttrs[XSAttributeChecker.ATTIDX_EFORMDEFAULT]).intValue() == SchemaSymbols.FORM_QUALIFIED;
 116             fBlockDefault =
 117                 ((XInt)fSchemaAttrs[XSAttributeChecker.ATTIDX_BLOCKDEFAULT]).shortValue();
 118             fFinalDefault =
 119                 ((XInt)fSchemaAttrs[XSAttributeChecker.ATTIDX_FINALDEFAULT]).shortValue();
 120             fTargetNamespace =
 121                 (String)fSchemaAttrs[XSAttributeChecker.ATTIDX_TARGETNAMESPACE];
 122             if (fTargetNamespace != null)
 123                 fTargetNamespace = symbolTable.addSymbol(fTargetNamespace);
 124 
 125             fNamespaceSupportRoot = new SchemaNamespaceSupport(fNamespaceSupport);
 126 
 127             //set namespace support
 128             fValidationContext.setNamespaceSupport(fNamespaceSupport);
 129             fValidationContext.setSymbolTable(symbolTable);
 130             // pass null as the schema document, so that the namespace
 131             // context is not popped.
 132 
 133             // don't return the attribute array yet!
 134             //attrChecker.returnAttrArray(schemaAttrs, null);
 135         }
 136     }
 137 
 138     /**
 139      * Initialize namespace support by collecting all of the namespace
 140      * declarations in the root's ancestors. This is necessary to
 141      * support schemas fragments, i.e. schemas embedded in other
 142      * documents. See,
 143      *
 144      * https://jaxp.dev.java.net/issues/show_bug.cgi?id=43
 145      *
 146      * Requires the DOM to be created with namespace support enabled.
 147      */
 148     private void initNamespaceSupport(Element schemaRoot) {
 149         fNamespaceSupport = new SchemaNamespaceSupport();
 150         fNamespaceSupport.reset();
 151 
 152         Node parent = schemaRoot.getParentNode();
 153         while (parent != null && parent.getNodeType() == Node.ELEMENT_NODE
 154                 && !parent.getNodeName().equals("DOCUMENT_NODE"))
 155         {
 156             Element eparent = (Element) parent;
 157             NamedNodeMap map = eparent.getAttributes();
 158             int length = (map != null) ? map.getLength() : 0;
 159             for (int i = 0; i < length; i++) {
 160                 Attr attr = (Attr) map.item(i);
 161                 String uri = attr.getNamespaceURI();
 162 
 163                 // Check if attribute is an ns decl -- requires ns support
 164                 if (uri != null && uri.equals("http://www.w3.org/2000/xmlns/")) {
 165                     String prefix = attr.getLocalName().intern();
 166                     if (prefix == "xmlns") prefix = "";
 167                     // Declare prefix if not set -- moving upwards
 168                     if (fNamespaceSupport.getURI(prefix) == null) {
 169                         fNamespaceSupport.declarePrefix(prefix,
 170                                 attr.getValue().intern());
 171                     }
 172                 }
 173             }
 174             parent = parent.getParentNode();
 175         }
 176     }
 177 
 178     // backup the current ns support, and use the one passed-in.
 179     // if no ns support is passed-in, use the one for <schema> element
 180     void backupNSSupport(SchemaNamespaceSupport nsSupport) {
 181         SchemaNamespaceSupportStack.push(fNamespaceSupport);
 182         if (nsSupport == null)
 183             nsSupport = fNamespaceSupportRoot;
 184         fNamespaceSupport = new SchemaNamespaceSupport(nsSupport);
 185 
 186         fValidationContext.setNamespaceSupport(fNamespaceSupport);
 187     }
 188 
 189     void restoreNSSupport() {
 190         fNamespaceSupport = (SchemaNamespaceSupport)SchemaNamespaceSupportStack.pop();
 191         fValidationContext.setNamespaceSupport(fNamespaceSupport);
 192     }
 193 
 194     // some Object methods
 195     public String toString() {
 196         return fTargetNamespace == null?"no targetNamspace":"targetNamespace is " + fTargetNamespace;
 197     }
 198 
 199     public void addAllowedNS(String namespace) {
 200         fImportedNS.addElement(namespace == null ? "" : namespace);
 201     }
 202 
 203     public boolean isAllowedNS(String namespace) {
 204         return fImportedNS.contains(namespace == null ? "" : namespace);
 205     }
 206 
 207     // store whether we have reported an error about that this document
 208     // can't access components from the given namespace
 209     private Vector fReportedTNS = null;
 210     // check whether we need to report an error against the given uri.
 211     // if we have reported an error, then we don't need to report again;
 212     // otherwise we reported the error, and remember this fact.
 213     final boolean needReportTNSError(String uri) {
 214         if (fReportedTNS == null)
 215             fReportedTNS = new Vector();
 216         else if (fReportedTNS.contains(uri))
 217             return false;
 218         fReportedTNS.addElement(uri);
 219         return true;
 220     }
 221 
 222     // return the attributes on the schema element itself:
 223     Object [] getSchemaAttrs () {
 224         return fSchemaAttrs;
 225     }
 226 
 227     // deallocate the storage set aside for the schema element's
 228     // attributes
 229     void returnSchemaAttrs () {
 230         fAttrChecker.returnAttrArray (fSchemaAttrs, null);
 231         fSchemaAttrs = null;
 232     }
 233 
 234     // adds an annotation to the list of annotations
 235     void addAnnotation(XSAnnotationInfo info) {
 236         info.next = fAnnotations;
 237         fAnnotations = info;
 238     }
 239 
 240     // returns the list of annotations conatined in the
 241     // schema document or null if the document contained no annotations.
 242     XSAnnotationInfo getAnnotations() {
 243         return fAnnotations;
 244     }
 245 
 246     // removes reference to annotation list
 247     void removeAnnotations() {
 248         fAnnotations = null;
 249     }
 250 
 251 } // XSDocumentInfo