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
26package com.sun.xml.internal.stream.writers;
27
28import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
29import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
30import java.lang.reflect.InvocationTargetException;
31import java.lang.reflect.Method;
32import javax.xml.XMLConstants;
33import javax.xml.namespace.NamespaceContext;
34import javax.xml.stream.XMLStreamException;
35import javax.xml.stream.XMLStreamWriter;
36import javax.xml.transform.dom.DOMResult;
37import org.w3c.dom.Attr;
38import org.w3c.dom.CDATASection;
39import org.w3c.dom.Comment;
40import org.w3c.dom.Document;
41import org.w3c.dom.Element;
42import org.w3c.dom.EntityReference;
43import org.w3c.dom.Node;
44import org.w3c.dom.ProcessingInstruction;
45import org.w3c.dom.Text;
46import 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@sun.com
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
62public 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     */
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     */
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     */
104    public void flush() throws XMLStreamException {
105        //no-op
106    }
107
108    /**
109     * {@inheritDoc}
110     * @return {@inheritDoc}
111     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
567    public void writeStartDocument(String encoding, String version) throws XMLStreamException {
568        writeStartDocument(encoding, version, false, false);
569    }
570
571    @Override
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     */
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     */
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     */
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
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
702    private Node getNode(){
703        if(currentNode == null){
704            return ownerDoc;
705        } else{
706            return currentNode;
707        }
708    }
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