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