1 /*
2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.xml.internal.stream.writers;
27 
28 import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
29 import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
30 import java.lang.reflect.InvocationTargetException;
31 import java.lang.reflect.Method;
32 import javax.xml.XMLConstants;
33 import javax.xml.namespace.NamespaceContext;
34 import javax.xml.stream.XMLStreamException;
35 import javax.xml.stream.XMLStreamWriter;
36 import javax.xml.transform.dom.DOMResult;
37 import org.w3c.dom.Attr;
38 import org.w3c.dom.CDATASection;
39 import org.w3c.dom.Comment;
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.w3c.dom.EntityReference;
43 import org.w3c.dom.Node;
44 import org.w3c.dom.ProcessingInstruction;
45 import org.w3c.dom.Text;
46 import org.xml.sax.helpers.NamespaceSupport;
47 
48 /**
49  * This class provides support to build a DOM tree using XMLStreamWriter API's.
50  * @author K Venugopal
51  */
52 
53 /*
54  * TODO : -Venu
55  * Internal NamespaceManagement
56  * setPrefix
57  * support for isRepairNamespace property.
58  * Some Unsupported Methods.
59  * Change StringBuffer to StringBuilder, when JDK 1.5 will be minimum requirement for SJSXP.
60  */
61 
62 public class XMLDOMWriterImpl implements XMLStreamWriterBase  {
63 
64 
65     private Document ownerDoc = null;
66     private Node currentNode = null;
67     private Node node = null;
68     private NamespaceSupport namespaceContext = null;
69     private boolean [] needContextPop = null;
70     private StringBuffer stringBuffer = null;
71     private int resizeValue = 20;
72     private int depth = 0;
73     /**
74      * Creates a new instance of XMLDOMwriterImpl
75      * @param result DOMResult object @javax.xml.transform.dom.DOMResult
76      */
XMLDOMWriterImpl(DOMResult result)77     public XMLDOMWriterImpl(DOMResult result) {
78 
79         node = result.getNode();
80         if( node.getNodeType() == Node.DOCUMENT_NODE){
81             ownerDoc = (Document)node;
82             currentNode = ownerDoc;
83         }else{
84             ownerDoc = node.getOwnerDocument();
85             currentNode = node;
86         }
87         stringBuffer = new StringBuffer();
88         needContextPop = new boolean[resizeValue];
89         namespaceContext = new NamespaceSupport();
90     }
91 
92     /**
93      * This method has no effect when called.
94      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
95      */
close()96     public void close() throws XMLStreamException {
97         //no-op
98     }
99 
100     /**
101      * This method has no effect when called.
102      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
103      */
flush()104     public void flush() throws XMLStreamException {
105         //no-op
106     }
107 
108     /**
109      * {@inheritDoc}
110      * @return {@inheritDoc}
111      */
getNamespaceContext()112     public javax.xml.namespace.NamespaceContext getNamespaceContext() {
113         return null;
114     }
115 
116     /**
117      * {@inheritDoc}
118      * @param namespaceURI {@inheritDoc}
119      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
120      * @return {@inheritDoc}
121      */
getPrefix(String namespaceURI)122     public String getPrefix(String namespaceURI) throws XMLStreamException {
123         String prefix = null;
124         if(this.namespaceContext != null){
125             prefix = namespaceContext.getPrefix(namespaceURI);
126         }
127         return prefix;
128     }
129 
130     /**
131      * Is not supported in this implementation.
132      * @param str {@inheritDoc}
133      * @throws java.lang.IllegalArgumentException {@inheritDoc}
134      * @return {@inheritDoc}
135      */
getProperty(String str)136     public Object getProperty(String str) throws IllegalArgumentException {
137         throw new UnsupportedOperationException();
138     }
139 
140     /**
141      * Is not supported in this version of the implementation.
142      * @param uri {@inheritDoc}
143      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
144      */
setDefaultNamespace(String uri)145     public void setDefaultNamespace(String uri) throws XMLStreamException {
146         namespaceContext.declarePrefix(XMLConstants.DEFAULT_NS_PREFIX, uri);
147         if(!needContextPop[depth]){
148             needContextPop[depth] = true;
149         }
150     }
151 
152     /**
153      * {@inheritDoc}
154      * @param namespaceContext {@inheritDoc}
155      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
156      */
setNamespaceContext(javax.xml.namespace.NamespaceContext namespaceContext)157     public void setNamespaceContext(javax.xml.namespace.NamespaceContext namespaceContext) throws XMLStreamException {
158         throw new UnsupportedOperationException();
159     }
160 
161     /**
162      * Is not supported in this version of the implementation.
163      * @param prefix {@inheritDoc}
164      * @param uri {@inheritDoc}
165      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
166      */
setPrefix(String prefix, String uri)167     public void setPrefix(String prefix, String uri) throws XMLStreamException {
168         if(prefix == null){
169             throw new XMLStreamException("Prefix cannot be null");
170         }
171         namespaceContext.declarePrefix(prefix, uri);
172         if(!needContextPop[depth]){
173             needContextPop[depth] = true;
174         }
175     }
176 
177     /**
178      * Creates a DOM Atrribute @see org.w3c.dom.Node and associates it with the current DOM element @see org.w3c.dom.Node.
179      * @param localName {@inheritDoc}
180      * @param value {@inheritDoc}
181      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
182      */
writeAttribute(String localName, String value)183     public void writeAttribute(String localName, String value) throws XMLStreamException {
184 
185         if(currentNode.getNodeType() == Node.ELEMENT_NODE){
186             Attr attr = ownerDoc.createAttribute(localName);
187             attr.setValue(value);
188             ((Element)currentNode).setAttributeNode(attr);
189         }else{
190             //Convert node type to String
191             throw new IllegalStateException("Current DOM Node type  is "+ currentNode.getNodeType() +
192                     "and does not allow attributes to be set ");
193         }
194     }
195 
196     /**
197      * Creates a DOM Atrribute @see org.w3c.dom.Node and associates it with the current DOM element @see org.w3c.dom.Node.
198      * @param namespaceURI {@inheritDoc}
199      * @param localName {@inheritDoc}
200      * @param value {@inheritDoc}
201      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
202      */
writeAttribute(String namespaceURI,String localName,String value)203     public void writeAttribute(String namespaceURI,String localName,String value)throws XMLStreamException {
204         if(currentNode.getNodeType() == Node.ELEMENT_NODE){
205             String prefix = null;
206             if(namespaceURI == null ){
207                 throw new XMLStreamException("NamespaceURI cannot be null");
208             }
209             if(localName == null){
210                 throw new XMLStreamException("Local name cannot be null");
211             }
212             if(namespaceContext != null){
213                 prefix = namespaceContext.getPrefix(namespaceURI);
214             }
215 
216             if(prefix == null){
217                 throw new XMLStreamException("Namespace URI "+namespaceURI +
218                         "is not bound to any prefix" );
219             }
220 
221             String qualifiedName = null;
222             if(prefix.equals("")){
223                 qualifiedName = localName;
224             }else{
225                 qualifiedName = getQName(prefix,localName);
226             }
227             Attr attr = ownerDoc.createAttributeNS(namespaceURI, qualifiedName);
228             attr.setValue(value);
229             ((Element)currentNode).setAttributeNode(attr);
230         }else{
231             //Convert node type to String
232             throw new IllegalStateException("Current DOM Node type  is "+ currentNode.getNodeType() +
233                     "and does not allow attributes to be set ");
234         }
235     }
236 
237     /**
238      * Creates a DOM Atrribute @see org.w3c.dom.Node and associates it with the current DOM element @see org.w3c.dom.Node.
239      * @param prefix {@inheritDoc}
240      * @param namespaceURI {@inheritDoc}
241      * @param localName {@inheritDoc}
242      * @param value {@inheritDoc}
243      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
244      */
writeAttribute(String prefix,String namespaceURI,String localName,String value)245     public void writeAttribute(String prefix,String namespaceURI,String localName,String value)throws XMLStreamException {
246         if(currentNode.getNodeType() == Node.ELEMENT_NODE){
247             if(namespaceURI == null ){
248                 throw new XMLStreamException("NamespaceURI cannot be null");
249             }
250             if(localName == null){
251                 throw new XMLStreamException("Local name cannot be null");
252             }
253             if(prefix == null){
254                 throw new XMLStreamException("prefix cannot be null");
255             }
256             String qualifiedName = null;
257             if(prefix.equals("")){
258                 qualifiedName = localName;
259             }else{
260 
261                 qualifiedName = getQName(prefix,localName);
262             }
263             Attr attr = ownerDoc.createAttributeNS(namespaceURI, qualifiedName);
264             attr.setValue(value);
265             ((Element)currentNode).setAttributeNodeNS(attr);
266         }else{
267             //Convert node type to String
268             throw new IllegalStateException("Current DOM Node type  is "+ currentNode.getNodeType() +
269                     "and does not allow attributes to be set ");
270         }
271 
272     }
273 
274     /**
275      * Creates a CDATA object @see org.w3c.dom.CDATASection.
276      * @param data {@inheritDoc}
277      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
278      */
writeCData(String data)279     public void writeCData(String data) throws XMLStreamException {
280         if(data == null){
281             throw new XMLStreamException("CDATA cannot be null");
282         }
283 
284         CDATASection cdata = ownerDoc.createCDATASection(data);
285         getNode().appendChild(cdata);
286     }
287 
288     /**
289      * Creates a character object @see org.w3c.dom.Text and appends it to the current
290      * element in the DOM tree.
291      * @param charData {@inheritDoc}
292      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
293      */
writeCharacters(String charData)294     public void writeCharacters(String charData) throws XMLStreamException {
295         Text text = ownerDoc.createTextNode(charData);
296         currentNode.appendChild(text);
297     }
298 
299     /**
300      * Creates a character object @see org.w3c.dom.Text and appends it to the current
301      * element in the DOM tree.
302      * @param values {@inheritDoc}
303      * @param param {@inheritDoc}
304      * @param param2 {@inheritDoc}
305      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
306      */
writeCharacters(char[] values, int param, int param2)307     public void writeCharacters(char[] values, int param, int param2) throws XMLStreamException {
308 
309         Text text = ownerDoc.createTextNode(new String(values,param,param2));
310         currentNode.appendChild(text);
311     }
312 
313     /**
314      * Creates a Comment object @see org.w3c.dom.Comment and appends it to the current
315      * element in the DOM tree.
316      * @param str {@inheritDoc}
317      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
318      */
writeComment(String str)319     public void writeComment(String str) throws XMLStreamException {
320         Comment comment = ownerDoc.createComment(str);
321         getNode().appendChild(comment);
322     }
323 
324     /**
325      * This method is not supported in this implementation.
326      * @param str {@inheritDoc}
327      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
328      */
writeDTD(String str)329     public void writeDTD(String str) throws XMLStreamException {
330         throw new UnsupportedOperationException();
331     }
332 
333     /**
334      * Creates a DOM attribute and adds it to the current element in the DOM tree.
335      * @param namespaceURI {@inheritDoc}
336      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
337      */
writeDefaultNamespace(String namespaceURI)338     public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
339         if(currentNode.getNodeType() == Node.ELEMENT_NODE){
340             String qname = XMLConstants.XMLNS_ATTRIBUTE;
341             ((Element)currentNode).setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,qname, namespaceURI);
342         }else{
343             //Convert node type to String
344             throw new IllegalStateException("Current DOM Node type  is "+ currentNode.getNodeType() +
345                     "and does not allow attributes to be set ");
346         }
347     }
348 
349     /**
350      * creates a DOM Element and appends it to the current element in the tree.
351      * @param localName {@inheritDoc}
352      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
353      */
writeEmptyElement(String localName)354     public void writeEmptyElement(String localName) throws XMLStreamException {
355         if(ownerDoc != null){
356             Element element = ownerDoc.createElement(localName);
357             if(currentNode!=null){
358                 currentNode.appendChild(element);
359             }else{
360                 ownerDoc.appendChild(element);
361             }
362         }
363 
364     }
365 
366     /**
367      * creates a DOM Element and appends it to the current element in the tree.
368      * @param namespaceURI {@inheritDoc}
369      * @param localName {@inheritDoc}
370      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
371      */
writeEmptyElement(String namespaceURI, String localName)372     public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
373         if(ownerDoc != null){
374             String qualifiedName = null;
375             String prefix = null;
376             if(namespaceURI == null ){
377                 throw new XMLStreamException("NamespaceURI cannot be null");
378             }
379             if(localName == null){
380                 throw new XMLStreamException("Local name cannot be null");
381             }
382 
383             if(namespaceContext != null){
384                 prefix = namespaceContext.getPrefix(namespaceURI);
385             }
386             if(prefix == null){
387                 throw new XMLStreamException("Namespace URI "+namespaceURI +
388                         "is not bound to any prefix" );
389             }
390             if("".equals(prefix)){
391                 qualifiedName = localName;
392             }else{
393 
394                 qualifiedName = getQName(prefix,localName);
395 
396             }
397             Element element = ownerDoc.createElementNS(namespaceURI, qualifiedName);
398             if(currentNode!=null){
399                 currentNode.appendChild(element);
400             }else{
401                 ownerDoc.appendChild(element);
402             }
403             //currentNode = element;
404         }
405     }
406 
407     /**
408      * creates a DOM Element and appends it to the current element in the tree.
409      * @param prefix {@inheritDoc}
410      * @param localName {@inheritDoc}
411      * @param namespaceURI {@inheritDoc}
412      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
413      */
writeEmptyElement(String prefix, String localName, String namespaceURI)414     public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
415         if(ownerDoc != null){
416             if(namespaceURI == null ){
417                 throw new XMLStreamException("NamespaceURI cannot be null");
418             }
419             if(localName == null){
420                 throw new XMLStreamException("Local name cannot be null");
421             }
422             if(prefix == null){
423                 throw new XMLStreamException("Prefix cannot be null");
424             }
425             String qualifiedName = null;
426             if("".equals(prefix)){
427                 qualifiedName = localName;
428             }else{
429                 qualifiedName = getQName(prefix,localName);
430             }
431             Element el  = ownerDoc.createElementNS(namespaceURI,qualifiedName);
432             if(currentNode!=null){
433                 currentNode.appendChild(el);
434             }else{
435                 ownerDoc.appendChild(el);
436             }
437 
438         }
439     }
440 
441     /**
442      * Will reset current Node pointer maintained by the implementation.
443      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
444      */
writeEndDocument()445     public void writeEndDocument() throws XMLStreamException {
446         //What do you want me to do eh! :)
447         currentNode = null;
448         for(int i=0; i< depth;i++){
449             if(needContextPop[depth]){
450                 needContextPop[depth] = false;
451                 namespaceContext.popContext();
452             }
453             depth--;
454         }
455         depth =0;
456     }
457 
458     /**
459      * Internal current Node pointer will point to the parent of the current Node.
460      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
461      */
writeEndElement()462     public void writeEndElement() throws XMLStreamException {
463         Node node= currentNode.getParentNode();
464         if(currentNode.getNodeType() == Node.DOCUMENT_NODE){
465             currentNode = null;
466         }else{
467             currentNode = node;
468         }
469         if(needContextPop[depth]){
470             needContextPop[depth] = false;
471             namespaceContext.popContext();
472         }
473         depth--;
474     }
475 
476     /**
477      * Is not supported in this implementation.
478      * @param name {@inheritDoc}
479      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
480      */
writeEntityRef(String name)481     public void writeEntityRef(String name) throws XMLStreamException {
482         EntityReference er = ownerDoc.createEntityReference(name);
483         currentNode.appendChild(er);
484     }
485 
486     /**
487      * creates a namespace attribute and will associate it with the current element in
488      * the DOM tree.
489      * @param prefix {@inheritDoc}
490      * @param namespaceURI {@inheritDoc}
491      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
492      */
writeNamespace(String prefix, String namespaceURI)493     public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
494 
495         if (prefix == null) {
496             throw new XMLStreamException("prefix cannot be null");
497         }
498 
499         if (namespaceURI == null) {
500             throw new XMLStreamException("NamespaceURI cannot be null");
501         }
502 
503         String qname = null;
504 
505         if (prefix.equals("")) {
506             qname = XMLConstants.XMLNS_ATTRIBUTE;
507         } else {
508             qname = getQName(XMLConstants.XMLNS_ATTRIBUTE,prefix);
509         }
510 
511         ((Element)currentNode).setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,qname, namespaceURI);
512     }
513 
514     /**
515      * is not supported in this release.
516      * @param target {@inheritDoc}
517      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
518      */
writeProcessingInstruction(String target)519     public void writeProcessingInstruction(String target) throws XMLStreamException {
520         if(target == null){
521             throw new XMLStreamException("Target cannot be null");
522         }
523         ProcessingInstruction pi = ownerDoc.createProcessingInstruction(target, "");
524         currentNode.appendChild(pi);
525     }
526 
527     /**
528      * is not supported in this release.
529      * @param target {@inheritDoc}
530      * @param data {@inheritDoc}
531      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
532      */
writeProcessingInstruction(String target, String data)533     public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
534         if(target == null){
535             throw new XMLStreamException("Target cannot be null");
536         }
537         ProcessingInstruction pi  = ownerDoc.createProcessingInstruction(target, data);
538         currentNode.appendChild(pi);
539     }
540 
541     /**
542      * will set version on the Document object when the DOM Node passed to this implementation
543      * supports DOM Level3 API's.
544      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
545      */
writeStartDocument()546     public void writeStartDocument() throws XMLStreamException {
547         ownerDoc.setXmlVersion("1.0");
548     }
549 
550     /**
551      * will set version on the Document object when the DOM Node passed to this implementation
552      * supports DOM Level3 API's.
553      * @param version {@inheritDoc}
554      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
555      */
writeStartDocument(String version)556     public void writeStartDocument(String version) throws XMLStreamException {
557         writeStartDocument(null, version, false, false);
558     }
559 
560     /**
561      * will set version on the Document object when the DOM Node passed to this implementation
562      * supports DOM Level3 API's.
563      * @param encoding {@inheritDoc}
564      * @param version {@inheritDoc}
565      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
566      */
writeStartDocument(String encoding, String version)567     public void writeStartDocument(String encoding, String version) throws XMLStreamException {
568         writeStartDocument(encoding, version, false, false);
569     }
570 
571     @Override
writeStartDocument(String encoding, String version, boolean standalone, boolean standaloneSet)572     public void writeStartDocument(String encoding, String version, boolean standalone, boolean standaloneSet) throws XMLStreamException {
573         if (encoding != null && ownerDoc.getClass().isAssignableFrom(DocumentImpl.class)) {
574             ((DocumentImpl)ownerDoc).setXmlEncoding(encoding);
575         }
576 
577         ownerDoc.setXmlVersion(version);
578 
579         if (standaloneSet) {
580             ownerDoc.setXmlStandalone(standalone);
581         }
582     }
583 
584     /**
585      * creates a DOM Element and appends it to the current element in the tree.
586      * @param localName {@inheritDoc}
587      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
588      */
writeStartElement(String localName)589     public void writeStartElement(String localName) throws XMLStreamException {
590         if(ownerDoc != null){
591             Element element = ownerDoc.createElement(localName);
592             if(currentNode!=null){
593                 currentNode.appendChild(element);
594             }else{
595                 ownerDoc.appendChild(element);
596             }
597             currentNode = element;
598         }
599         if(needContextPop[depth]){
600             namespaceContext.pushContext();
601         }
602         incDepth();
603     }
604 
605     /**
606      * creates a DOM Element and appends it to the current element in the tree.
607      * @param namespaceURI {@inheritDoc}
608      * @param localName {@inheritDoc}
609      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
610      */
writeStartElement(String namespaceURI, String localName)611     public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
612         if(ownerDoc != null){
613             String qualifiedName = null;
614             String prefix = null;
615 
616             if(namespaceURI == null ){
617                 throw new XMLStreamException("NamespaceURI cannot be null");
618             }
619             if(localName == null){
620                 throw new XMLStreamException("Local name cannot be null");
621             }
622 
623             if(namespaceContext != null){
624                 prefix = namespaceContext.getPrefix(namespaceURI);
625             }
626             if(prefix == null){
627                 throw new XMLStreamException("Namespace URI "+namespaceURI +
628                         "is not bound to any prefix" );
629             }
630             if("".equals(prefix)){
631                 qualifiedName = localName;
632             }else{
633                 qualifiedName =  getQName(prefix,localName);
634             }
635 
636             Element element = ownerDoc.createElementNS(namespaceURI, qualifiedName);
637 
638             if(currentNode!=null){
639                 currentNode.appendChild(element);
640             }else{
641                 ownerDoc.appendChild(element);
642             }
643             currentNode = element;
644         }
645         if(needContextPop[depth]){
646             namespaceContext.pushContext();
647         }
648         incDepth();
649     }
650 
651     /**
652      * creates a DOM Element and appends it to the current element in the tree.
653      * @param prefix {@inheritDoc}
654      * @param localName {@inheritDoc}
655      * @param namespaceURI {@inheritDoc}
656      * @throws javax.xml.stream.XMLStreamException {@inheritDoc}
657      */
writeStartElement(String prefix, String localName, String namespaceURI)658     public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
659 
660         if(ownerDoc != null){
661             String qname = null;
662             if(namespaceURI == null ){
663                 throw new XMLStreamException("NamespaceURI cannot be null");
664             }
665             if(localName == null){
666                 throw new XMLStreamException("Local name cannot be null");
667             }
668             if(prefix == null){
669                 throw new XMLStreamException("Prefix cannot be null");
670             }
671 
672             if(prefix.equals("")){
673                 qname = localName;
674             }else{
675                 qname = getQName(prefix,localName);
676             }
677 
678             Element el = ownerDoc.createElementNS(namespaceURI,qname);
679 
680             if(currentNode!=null){
681                 currentNode.appendChild(el);
682             }else{
683                 ownerDoc.appendChild(el);
684             }
685             currentNode = el;
686             if(needContextPop[depth]){
687                 namespaceContext.pushContext();
688             }
689             incDepth();
690 
691         }
692     }
693 
getQName(String prefix , String localName)694     private String getQName(String prefix , String localName){
695         stringBuffer.setLength(0);
696         stringBuffer.append(prefix);
697         stringBuffer.append(":");
698         stringBuffer.append(localName);
699         return stringBuffer.toString();
700     }
701 
getNode()702     private Node getNode(){
703         if(currentNode == null){
704             return ownerDoc;
705         } else{
706             return currentNode;
707         }
708     }
incDepth()709     private void incDepth() {
710         depth++;
711         if (depth == needContextPop.length) {
712             boolean[] array = new boolean[depth + resizeValue];
713             System.arraycopy(needContextPop, 0, array, 0, depth);
714             needContextPop = array;
715         }
716     }
717 }
718