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