View Javadoc
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   * @version $Id: XSDocumentInfo.java,v 1.5 2007/10/15 22:27:48 spericas Exp $
47   */
48  class XSDocumentInfo {
49  
50      // Data
51      protected SchemaNamespaceSupport fNamespaceSupport;
52      protected SchemaNamespaceSupport fNamespaceSupportRoot;
53      protected Stack 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      Vector fImportedNS = new Vector();
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 = (SchemaNamespaceSupport)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.addElement(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 Vector 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 Vector();
217         else if (fReportedTNS.contains(uri))
218             return false;
219         fReportedTNS.addElement(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