author | joehw |
Mon, 22 Feb 2016 11:00:06 -0800 | |
changeset 36146 | eca249f3c768 |
parent 33352 | 35c096b5709c |
child 39798 | 550955727ef7 |
permissions | -rw-r--r-- |
12005 | 1 |
/* |
36146
eca249f3c768
8149915: enabling validate-annotations feature for xsd schema with annotation causes NPE
joehw
parents:
33352
diff
changeset
|
2 |
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. |
12005 | 3 |
*/ |
4 |
||
5 |
/* |
|
6 |
* Copyright 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; |
|
22 |
||
23 |
import java.io.IOException; |
|
24 |
import com.sun.org.apache.xerces.internal.xni.XMLString; |
|
25 |
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter; |
|
26 |
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; |
|
27 |
import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; |
|
28 |
import com.sun.org.apache.xerces.internal.util.XMLSymbols; |
|
29 |
import com.sun.org.apache.xerces.internal.xni.NamespaceContext; |
|
30 |
import com.sun.org.apache.xerces.internal.xni.QName; |
|
31 |
import com.sun.org.apache.xerces.internal.xni.XNIException; |
|
32 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; |
|
33 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; |
|
34 |
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; |
|
35 |
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; |
|
33352 | 36 |
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; |
12005 | 37 |
|
38 |
import javax.xml.stream.events.XMLEvent; |
|
39 |
||
40 |
/** |
|
41 |
* This class adds the functionality of namespace processing. |
|
42 |
* |
|
43 |
* This class has been modified as per the new design which is more suited to |
|
44 |
* efficiently build pull parser. Lot of improvements have been done and |
|
45 |
* the code has been added to support stax functionality/features. |
|
46 |
* |
|
47 |
* |
|
48 |
* This class scans an XML document, checks if document has a DTD, and if |
|
49 |
* DTD is not found the scanner will remove the DTD Validator from the pipeline and perform |
|
50 |
* namespace binding. |
|
51 |
* |
|
52 |
* |
|
53 |
* @author Neeraj Bajaj, Sun Microsystems |
|
54 |
* @author Venugopal Rao K, Sun Microsystems |
|
55 |
* @author Elena Litani, IBM |
|
56 |
*/ |
|
57 |
public class XMLNSDocumentScannerImpl |
|
58 |
extends XMLDocumentScannerImpl { |
|
59 |
||
60 |
/** |
|
61 |
* If is true, the dtd validator is no longer in the pipeline |
|
62 |
* and the scanner should bind namespaces |
|
63 |
*/ |
|
64 |
protected boolean fBindNamespaces; |
|
65 |
||
66 |
/** If validating parser, make sure we report an error in the |
|
67 |
* scanner if DTD grammar is missing.*/ |
|
68 |
protected boolean fPerformValidation; |
|
69 |
||
70 |
||
71 |
/** Default value of this feature is false, when in Stax mode this should be true */ |
|
72 |
protected boolean fNotAddNSDeclAsAttribute = false; |
|
73 |
||
74 |
/** DTD validator */ |
|
75 |
private XMLDTDValidatorFilter fDTDValidator; |
|
76 |
||
77 |
/** xmlns, default Namespace, declared */ |
|
78 |
private boolean fXmlnsDeclared = false; |
|
79 |
||
80 |
/** Resets the fields of this scanner. |
|
81 |
*/ |
|
82 |
public void reset(PropertyManager propertyManager) { |
|
83 |
setPropertyManager(propertyManager); |
|
84 |
super.reset(propertyManager); |
|
85 |
fBindNamespaces = false; |
|
86 |
fNotAddNSDeclAsAttribute = !((Boolean)propertyManager.getProperty(Constants.ADD_NAMESPACE_DECL_AS_ATTRIBUTE)).booleanValue(); |
|
87 |
} |
|
88 |
||
89 |
public void reset(XMLComponentManager componentManager) |
|
90 |
throws XMLConfigurationException { |
|
91 |
super.reset(componentManager); |
|
92 |
fNotAddNSDeclAsAttribute = false ; |
|
93 |
fPerformValidation = false; |
|
94 |
fBindNamespaces = false; |
|
95 |
} |
|
96 |
||
97 |
/** return the next state on the input |
|
98 |
* |
|
99 |
* @return int |
|
100 |
*/ |
|
101 |
||
102 |
public int next() throws IOException, XNIException { |
|
103 |
//since namespace context should still be valid when the parser is at the end element state therefore |
|
104 |
//we pop the context only when next() has been called after the end element state was encountered. - nb. |
|
105 |
||
106 |
if((fScannerLastState == XMLEvent.END_ELEMENT) && fBindNamespaces){ |
|
107 |
fScannerLastState = -1; |
|
108 |
fNamespaceContext.popContext(); |
|
109 |
} |
|
110 |
||
111 |
return fScannerLastState = super.next(); |
|
112 |
} |
|
113 |
||
114 |
/** |
|
115 |
* The scanner is responsible for removing DTD validator |
|
116 |
* from the pipeline if it is not needed. |
|
117 |
* |
|
118 |
* @param previous The filter component before DTDValidator |
|
119 |
* @param dtdValidator |
|
120 |
* The DTDValidator |
|
121 |
* @param next The documentHandler after the DTDValidator |
|
122 |
*/ |
|
123 |
public void setDTDValidator(XMLDTDValidatorFilter dtd){ |
|
124 |
fDTDValidator = dtd; |
|
125 |
} |
|
126 |
||
127 |
||
128 |
||
129 |
/** |
|
130 |
* Scans a start element. This method will handle the binding of |
|
131 |
* namespace information and notifying the handler of the start |
|
132 |
* of the element. |
|
133 |
* <p> |
|
134 |
* <pre> |
|
135 |
* [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' |
|
136 |
* [40] STag ::= '<' Name (S Attribute)* S? '>' |
|
137 |
* </pre> |
|
138 |
* <p> |
|
139 |
* <strong>Note:</strong> This method assumes that the leading |
|
140 |
* '<' character has been consumed. |
|
141 |
* <p> |
|
142 |
* <strong>Note:</strong> This method uses the fElementQName and |
|
143 |
* fAttributes variables. The contents of these variables will be |
|
144 |
* destroyed. The caller should copy important information out of |
|
145 |
* these variables before calling this method. |
|
146 |
* |
|
147 |
* @return True if element is empty. (i.e. It matches |
|
148 |
* production [44]. |
|
149 |
*/ |
|
150 |
protected boolean scanStartElement() |
|
151 |
throws IOException, XNIException { |
|
152 |
||
153 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanStartElement()"); |
|
154 |
//when skipping is true and no more elements should be added |
|
155 |
if(fSkip && !fAdd){ |
|
156 |
//get the stored element -- if everything goes right this should match the |
|
157 |
//token in the buffer |
|
158 |
||
159 |
QName name = fElementStack.getNext(); |
|
160 |
||
161 |
if(DEBUG_SKIP_ALGORITHM){ |
|
162 |
System.out.println("Trying to skip String = " + name.rawname); |
|
163 |
} |
|
164 |
||
165 |
//Be conservative -- if skipping fails -- stop. |
|
166 |
fSkip = fEntityScanner.skipString(name.rawname); // skipQElement(name); |
|
167 |
||
168 |
if(fSkip){ |
|
169 |
if(DEBUG_SKIP_ALGORITHM){ |
|
170 |
System.out.println("Element SUCESSFULLY skipped = " + name.rawname); |
|
171 |
} |
|
172 |
fElementStack.push(); |
|
173 |
fElementQName = name; |
|
174 |
}else{ |
|
175 |
//if skipping fails reposition the stack or fallback to normal way of processing |
|
176 |
fElementStack.reposition(); |
|
177 |
if(DEBUG_SKIP_ALGORITHM){ |
|
178 |
System.out.println("Element was NOT skipped, REPOSITIONING stack" ); |
|
179 |
} |
|
180 |
} |
|
181 |
} |
|
182 |
||
183 |
//we are still at the stage of adding elements |
|
184 |
//the elements were not matched or |
|
185 |
//fSkip is not set to true |
|
186 |
if(!fSkip || fAdd){ |
|
187 |
//get the next element from the stack |
|
188 |
fElementQName = fElementStack.nextElement(); |
|
189 |
// There are two variables,fNamespaces and fBindNamespaces |
|
190 |
//StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained |
|
191 |
if (fNamespaces) { |
|
192 |
fEntityScanner.scanQName(fElementQName); |
|
193 |
} else { |
|
194 |
String name = fEntityScanner.scanName(); |
|
195 |
fElementQName.setValues(null, name, name, null); |
|
196 |
} |
|
197 |
||
198 |
if(DEBUG)System.out.println("Element scanned in start element is " + fElementQName.toString()); |
|
199 |
if(DEBUG_SKIP_ALGORITHM){ |
|
200 |
if(fAdd){ |
|
201 |
System.out.println("Elements are being ADDED -- elemet added is = " + fElementQName.rawname + " at count = " + fElementStack.fCount); |
|
202 |
} |
|
203 |
} |
|
204 |
||
205 |
} |
|
206 |
||
207 |
//when the elements are being added , we need to check if we are set for skipping the elements |
|
208 |
if(fAdd){ |
|
209 |
//this sets the value of fAdd variable |
|
210 |
fElementStack.matchElement(fElementQName); |
|
211 |
} |
|
212 |
||
213 |
//xxx: We dont need another pointer, fCurrentElement, we can use fElementQName |
|
214 |
fCurrentElement = fElementQName; |
|
215 |
||
216 |
String rawname = fElementQName.rawname; |
|
25591 | 217 |
checkDepth(rawname); |
12005 | 218 |
if (fBindNamespaces) { |
219 |
fNamespaceContext.pushContext(); |
|
220 |
if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) { |
|
221 |
if (fPerformValidation) { |
|
222 |
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
223 |
"MSG_GRAMMAR_NOT_FOUND", |
|
224 |
new Object[]{ rawname}, |
|
225 |
XMLErrorReporter.SEVERITY_ERROR); |
|
226 |
||
227 |
if (fDoctypeName == null || !fDoctypeName.equals(rawname)) { |
|
228 |
fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, |
|
229 |
"RootElementTypeMustMatchDoctypedecl", |
|
230 |
new Object[]{fDoctypeName, rawname}, |
|
231 |
XMLErrorReporter.SEVERITY_ERROR); |
|
232 |
} |
|
233 |
} |
|
234 |
} |
|
235 |
} |
|
236 |
||
237 |
||
238 |
fEmptyElement = false; |
|
239 |
fAttributes.removeAllAttributes(); |
|
240 |
||
241 |
if(!seekCloseOfStartTag()){ |
|
242 |
fReadingAttributes = true; |
|
243 |
fAttributeCacheUsedCount =0; |
|
244 |
fStringBufferIndex =0; |
|
245 |
fAddDefaultAttr = true; |
|
246 |
fXmlnsDeclared = false; |
|
247 |
||
248 |
do { |
|
249 |
scanAttribute(fAttributes); |
|
20968 | 250 |
if (fSecurityManager != null && (!fSecurityManager.isNoLimit(fElementAttributeLimit)) && |
251 |
fAttributes.getLength() > fElementAttributeLimit){ |
|
12005 | 252 |
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
253 |
"ElementAttributeLimit", |
|
21470 | 254 |
new Object[]{rawname, fElementAttributeLimit }, |
12005 | 255 |
XMLErrorReporter.SEVERITY_FATAL_ERROR ); |
256 |
} |
|
257 |
||
258 |
} while (!seekCloseOfStartTag()); |
|
259 |
fReadingAttributes=false; |
|
260 |
} |
|
261 |
||
262 |
if (fBindNamespaces) { |
|
263 |
// REVISIT: is it required? forbit xmlns prefix for element |
|
264 |
if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) { |
|
265 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
266 |
"ElementXMLNSPrefix", |
|
267 |
new Object[]{fElementQName.rawname}, |
|
268 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
269 |
} |
|
270 |
||
271 |
// bind the element |
|
272 |
String prefix = fElementQName.prefix != null |
|
273 |
? fElementQName.prefix : XMLSymbols.EMPTY_STRING; |
|
274 |
// assign uri to the element |
|
275 |
fElementQName.uri = fNamespaceContext.getURI(prefix); |
|
276 |
// make sure that object in the element stack is updated as well |
|
277 |
fCurrentElement.uri = fElementQName.uri; |
|
278 |
||
279 |
if (fElementQName.prefix == null && fElementQName.uri != null) { |
|
280 |
fElementQName.prefix = XMLSymbols.EMPTY_STRING; |
|
281 |
} |
|
282 |
if (fElementQName.prefix != null && fElementQName.uri == null) { |
|
283 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
284 |
"ElementPrefixUnbound", |
|
285 |
new Object[]{fElementQName.prefix, fElementQName.rawname}, |
|
286 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
287 |
} |
|
288 |
||
289 |
// bind attributes (xmlns are already bound bellow) |
|
290 |
int length = fAttributes.getLength(); |
|
291 |
// fLength = 0; //initialize structure |
|
292 |
for (int i = 0; i < length; i++) { |
|
293 |
fAttributes.getName(i, fAttributeQName); |
|
294 |
||
295 |
String aprefix = fAttributeQName.prefix != null |
|
296 |
? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; |
|
297 |
String uri = fNamespaceContext.getURI(aprefix); |
|
298 |
// REVISIT: try removing the first "if" and see if it is faster. |
|
299 |
// |
|
300 |
if (fAttributeQName.uri != null && fAttributeQName.uri == uri) { |
|
301 |
// checkDuplicates(fAttributeQName, fAttributes); |
|
302 |
continue; |
|
303 |
} |
|
304 |
if (aprefix != XMLSymbols.EMPTY_STRING) { |
|
305 |
fAttributeQName.uri = uri; |
|
306 |
if (uri == null) { |
|
307 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
308 |
"AttributePrefixUnbound", |
|
309 |
new Object[]{fElementQName.rawname,fAttributeQName.rawname,aprefix}, |
|
310 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
311 |
} |
|
312 |
fAttributes.setURI(i, uri); |
|
313 |
// checkDuplicates(fAttributeQName, fAttributes); |
|
314 |
} |
|
315 |
} |
|
316 |
||
317 |
if (length > 1) { |
|
318 |
QName name = fAttributes.checkDuplicatesNS(); |
|
319 |
if (name != null) { |
|
320 |
if (name.uri != null) { |
|
321 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
322 |
"AttributeNSNotUnique", |
|
323 |
new Object[]{fElementQName.rawname, name.localpart, name.uri}, |
|
324 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
325 |
} else { |
|
326 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
327 |
"AttributeNotUnique", |
|
328 |
new Object[]{fElementQName.rawname, name.rawname}, |
|
329 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
330 |
} |
|
331 |
} |
|
332 |
} |
|
333 |
} |
|
334 |
||
335 |
||
336 |
if (fEmptyElement) { |
|
337 |
//decrease the markup depth.. |
|
338 |
fMarkupDepth--; |
|
339 |
||
340 |
// check that this element was opened in the same entity |
|
341 |
if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) { |
|
342 |
reportFatalError("ElementEntityMismatch", |
|
343 |
new Object[]{fCurrentElement.rawname}); |
|
344 |
} |
|
345 |
// call handler |
|
346 |
if (fDocumentHandler != null) { |
|
347 |
if(DEBUG) |
|
348 |
System.out.println("emptyElement = " + fElementQName); |
|
349 |
||
350 |
fDocumentHandler.emptyElement(fElementQName, fAttributes, null); |
|
351 |
} |
|
352 |
||
353 |
//We should not be popping out the context here in endELement becaause the namespace context is still |
|
354 |
//valid when parser is at the endElement state. |
|
355 |
fScanEndElement = true; |
|
356 |
//if (fBindNamespaces) { |
|
357 |
// fNamespaceContext.popContext(); |
|
358 |
//} |
|
359 |
||
360 |
//pop the element off the stack.. |
|
361 |
fElementStack.popElement(); |
|
362 |
||
363 |
} else { |
|
364 |
||
365 |
if(dtdGrammarUtil != null) |
|
366 |
dtdGrammarUtil.startElement(fElementQName,fAttributes); |
|
367 |
if(fDocumentHandler != null){ |
|
368 |
//complete element and attributes are traversed in this function so we can send a callback |
|
369 |
//here. |
|
370 |
//<strong>we shouldn't be sending callback in scanDocument()</strong> |
|
371 |
if(DEBUG) |
|
372 |
System.out.println("startElement = " + fElementQName); |
|
373 |
fDocumentHandler.startElement(fElementQName, fAttributes, null); |
|
374 |
} |
|
375 |
} |
|
376 |
||
377 |
||
378 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanStartElement(): "+fEmptyElement); |
|
379 |
return fEmptyElement; |
|
380 |
||
381 |
} // scanStartElement():boolean |
|
382 |
||
383 |
||
384 |
||
385 |
/** |
|
386 |
* Scans an attribute. |
|
387 |
* <p> |
|
388 |
* <pre> |
|
389 |
* [41] Attribute ::= Name Eq AttValue |
|
390 |
* </pre> |
|
391 |
* <p> |
|
392 |
* <strong>Note:</strong> This method assumes that the next |
|
393 |
* character on the stream is the first character of the attribute |
|
394 |
* name. |
|
395 |
* <p> |
|
396 |
* <strong>Note:</strong> This method uses the fAttributeQName and |
|
397 |
* fQName variables. The contents of these variables will be |
|
398 |
* destroyed. |
|
399 |
* |
|
400 |
* @param attributes The attributes list for the scanned attribute. |
|
401 |
*/ |
|
402 |
protected void scanAttribute(XMLAttributesImpl attributes) |
|
403 |
throws IOException, XNIException { |
|
404 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()"); |
|
405 |
||
406 |
// name |
|
407 |
fEntityScanner.scanQName(fAttributeQName); |
|
408 |
||
409 |
// equals |
|
410 |
fEntityScanner.skipSpaces(); |
|
411 |
if (!fEntityScanner.skipChar('=')) { |
|
412 |
reportFatalError("EqRequiredInAttribute", |
|
413 |
new Object[]{fCurrentElement.rawname,fAttributeQName.rawname}); |
|
414 |
} |
|
415 |
fEntityScanner.skipSpaces(); |
|
416 |
||
417 |
// content |
|
418 |
int attrIndex = 0 ; |
|
419 |
||
420 |
||
421 |
//REVISIT: one more case needs to be included: external PE and standalone is no |
|
422 |
boolean isVC = fHasExternalDTD && !fStandalone; |
|
423 |
||
424 |
// REVISIT: it seems that this function should not take attributes, and length |
|
425 |
//fTempString would store attribute value |
|
426 |
///fTempString2 would store attribute non-normalized value |
|
427 |
||
428 |
//this function doesn't use 'attIndex'. We are adding the attribute later |
|
429 |
//after we have figured out that current attribute is not namespace declaration |
|
430 |
//since scanAttributeValue doesn't use attIndex parameter therefore we |
|
431 |
//can safely add the attribute later.. |
|
432 |
XMLString tmpStr = getString(); |
|
433 |
scanAttributeValue(tmpStr, fTempString2, |
|
434 |
fAttributeQName.rawname, attributes, |
|
29765
d0707eacc322
8073385: Bad error message on parsing illegal character in XML attribute
aefimov
parents:
25868
diff
changeset
|
435 |
attrIndex, isVC, fCurrentElement.rawname); |
12005 | 436 |
|
437 |
String value = null; |
|
438 |
//fTempString.toString(); |
|
439 |
||
440 |
// record namespace declarations if any. |
|
441 |
if (fBindNamespaces) { |
|
442 |
||
443 |
String localpart = fAttributeQName.localpart; |
|
444 |
String prefix = fAttributeQName.prefix != null |
|
445 |
? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; |
|
446 |
// when it's of form xmlns="..." or xmlns:prefix="...", |
|
447 |
// it's a namespace declaration. but prefix:xmlns="..." isn't. |
|
448 |
if (prefix == XMLSymbols.PREFIX_XMLNS || |
|
449 |
prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) { |
|
33352 | 450 |
//check the length of URI |
451 |
if (tmpStr.length > fXMLNameLimit) { |
|
452 |
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, |
|
453 |
"MaxXMLNameLimit", |
|
454 |
new Object[]{new String(tmpStr.ch,tmpStr.offset,tmpStr.length), |
|
455 |
tmpStr.length, fXMLNameLimit, |
|
456 |
fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.MAX_NAME_LIMIT)}, |
|
457 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
458 |
} |
|
12005 | 459 |
// get the internalized value of this attribute |
460 |
String uri = fSymbolTable.addSymbol(tmpStr.ch,tmpStr.offset,tmpStr.length); |
|
461 |
value = uri; |
|
462 |
// 1. "xmlns" can't be bound to any namespace |
|
463 |
if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) { |
|
464 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
465 |
"CantBindXMLNS", |
|
466 |
new Object[]{fAttributeQName}, |
|
467 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
468 |
} |
|
469 |
||
470 |
// 2. the namespace for "xmlns" can't be bound to any prefix |
|
471 |
if (uri == NamespaceContext.XMLNS_URI) { |
|
472 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
473 |
"CantBindXMLNS", |
|
474 |
new Object[]{fAttributeQName}, |
|
475 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
476 |
} |
|
477 |
||
478 |
// 3. "xml" can't be bound to any other namespace than it's own |
|
479 |
if (localpart == XMLSymbols.PREFIX_XML) { |
|
480 |
if (uri != NamespaceContext.XML_URI) { |
|
481 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
482 |
"CantBindXML", |
|
483 |
new Object[]{fAttributeQName}, |
|
484 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
485 |
} |
|
486 |
} |
|
487 |
// 4. the namespace for "xml" can't be bound to any other prefix |
|
488 |
else { |
|
489 |
if (uri ==NamespaceContext.XML_URI) { |
|
490 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
491 |
"CantBindXML", |
|
492 |
new Object[]{fAttributeQName}, |
|
493 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
494 |
} |
|
495 |
} |
|
496 |
prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING; |
|
497 |
//set it equal to XMLSymbols.PREFIX_XMLNS when namespace declaration |
|
498 |
// is of type xmlns = "..", in this case prefix = "" and localname = XMLSymbols.PREFIX_XMLNS |
|
499 |
//this special behavior is because of dependency on this behavior in DOM components |
|
500 |
if(prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS){ |
|
501 |
fAttributeQName.prefix = XMLSymbols.PREFIX_XMLNS; |
|
502 |
} |
|
503 |
// http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix |
|
504 |
// We should only report an error if there is a prefix, |
|
505 |
// that is, the local part is not "xmlns". -SG |
|
506 |
if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) { |
|
507 |
fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN, |
|
508 |
"EmptyPrefixedAttName", |
|
509 |
new Object[]{fAttributeQName}, |
|
510 |
XMLErrorReporter.SEVERITY_FATAL_ERROR); |
|
511 |
} |
|
512 |
||
513 |
// check for duplicate prefix bindings |
|
514 |
if (((com.sun.org.apache.xerces.internal.util.NamespaceSupport) fNamespaceContext).containsPrefixInCurrentContext(prefix)) { |
|
515 |
reportFatalError("AttributeNotUnique", |
|
516 |
new Object[]{fCurrentElement.rawname, |
|
517 |
fAttributeQName.rawname}); |
|
518 |
} |
|
519 |
||
520 |
// declare prefix in context |
|
521 |
boolean declared = fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null); |
|
522 |
||
523 |
// check for duplicate xmlns declarations |
|
524 |
if (!declared) { // by convention, prefix == "xmlns" | "xml" |
|
525 |
// error if duplicate declaration |
|
526 |
if (fXmlnsDeclared) { |
|
527 |
reportFatalError("AttributeNotUnique", |
|
528 |
new Object[]{fCurrentElement.rawname, |
|
529 |
fAttributeQName.rawname}); |
|
530 |
} |
|
531 |
||
532 |
// xmlns declared |
|
533 |
fXmlnsDeclared = true; |
|
534 |
} |
|
535 |
||
536 |
//xerces internals (XSAttributeChecker) has dependency on namespace declaration returned |
|
537 |
//as part of XMLAttributes. |
|
538 |
//addition of namespace declaration to the attribute list is controlled by fNotAddNSDeclAsAttribute |
|
539 |
//feature. This is required in Stax where namespace declarations are not considered as attribute |
|
540 |
||
541 |
if(fNotAddNSDeclAsAttribute){ |
|
542 |
return ; |
|
543 |
} |
|
544 |
} |
|
545 |
} |
|
546 |
||
547 |
//add the attributes to the list of attributes |
|
548 |
if (fBindNamespaces) { |
|
549 |
attrIndex = attributes.getLength(); |
|
550 |
attributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, null); |
|
551 |
} else { |
|
552 |
int oldLen = attributes.getLength(); |
|
553 |
attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null); |
|
554 |
||
555 |
// WFC: Unique Att Spec |
|
556 |
if (oldLen == attributes.getLength()) { |
|
557 |
reportFatalError("AttributeNotUnique", |
|
558 |
new Object[]{fCurrentElement.rawname, |
|
559 |
fAttributeQName.rawname}); |
|
560 |
} |
|
561 |
} |
|
562 |
||
563 |
attributes.setValue(attrIndex, value,tmpStr); |
|
564 |
//attributes.setNonNormalizedValue(attrIndex, fTempString2.toString()); |
|
565 |
//removing as we are not using non-normalized values . -Venu |
|
566 |
attributes.setSpecified(attrIndex, true); |
|
567 |
||
568 |
// attempt to bind attribute |
|
569 |
if (fAttributeQName.prefix != null) { |
|
570 |
attributes.setURI(attrIndex, fNamespaceContext.getURI(fAttributeQName.prefix)); |
|
571 |
} |
|
572 |
||
573 |
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanAttribute()"); |
|
574 |
} // scanAttribute(XMLAttributes) |
|
575 |
||
576 |
||
577 |
||
578 |
||
579 |
||
580 |
/** Creates a content driver. */ |
|
581 |
protected Driver createContentDriver() { |
|
582 |
return new NSContentDriver(); |
|
583 |
} // createContentDriver():Driver |
|
584 |
||
585 |
/** |
|
586 |
* Driver to handle content scanning. |
|
587 |
*/ |
|
588 |
protected final class NSContentDriver |
|
589 |
extends ContentDriver { |
|
590 |
/** |
|
591 |
* Scan for root element hook. This method is a hook for |
|
592 |
* subclasses to add code that handles scanning for the root |
|
593 |
* element. This method will also attempt to remove DTD validator |
|
594 |
* from the pipeline, if there is no DTD grammar. If DTD validator |
|
595 |
* is no longer in the pipeline bind namespaces in the scanner. |
|
596 |
* |
|
597 |
* |
|
598 |
* @return True if the caller should stop and return true which |
|
599 |
* allows the scanner to switch to a new scanning |
|
600 |
* driver. A return value of false indicates that |
|
601 |
* the content driver should continue as normal. |
|
602 |
*/ |
|
603 |
protected boolean scanRootElementHook() |
|
604 |
throws IOException, XNIException { |
|
605 |
||
606 |
reconfigurePipeline(); |
|
607 |
if (scanStartElement()) { |
|
608 |
setScannerState(SCANNER_STATE_TRAILING_MISC); |
|
609 |
setDriver(fTrailingMiscDriver); |
|
610 |
return true; |
|
611 |
} |
|
612 |
return false; |
|
613 |
||
614 |
} // scanRootElementHook():boolean |
|
615 |
||
616 |
/** |
|
617 |
* Re-configures pipeline by removing the DTD validator |
|
618 |
* if no DTD grammar exists. If no validator exists in the |
|
619 |
* pipeline or there is no DTD grammar, namespace binding |
|
620 |
* is performed by the scanner in the enclosing class. |
|
621 |
*/ |
|
622 |
private void reconfigurePipeline() { |
|
623 |
//fDTDValidator will be null in Stax mode |
|
624 |
if (fNamespaces && fDTDValidator == null) { |
|
625 |
fBindNamespaces = true; |
|
626 |
} |
|
627 |
else if (fNamespaces && !fDTDValidator.hasGrammar() ) { |
|
628 |
fBindNamespaces = true; |
|
629 |
fPerformValidation = fDTDValidator.validate(); |
|
630 |
// re-configure pipeline by removing DTDValidator |
|
631 |
XMLDocumentSource source = fDTDValidator.getDocumentSource(); |
|
632 |
XMLDocumentHandler handler = fDTDValidator.getDocumentHandler(); |
|
633 |
source.setDocumentHandler(handler); |
|
634 |
if (handler != null) |
|
635 |
handler.setDocumentSource(source); |
|
636 |
fDTDValidator.setDocumentSource(null); |
|
637 |
fDTDValidator.setDocumentHandler(null); |
|
638 |
} |
|
639 |
} // reconfigurePipeline() |
|
640 |
} |
|
641 |
||
642 |
} // class XMLNSDocumentScannerImpl |