View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.test.utils;
20  
21  import org.w3c.dom.*;
22  
23  import javax.xml.parsers.DocumentBuilder;
24  import javax.xml.stream.Location;
25  import javax.xml.stream.XMLStreamConstants;
26  import javax.xml.stream.XMLStreamException;
27  import javax.xml.stream.XMLStreamReader;
28  
29  public class StAX2DOM {
30      static final String XML_NS = "http://www.w3.org/2000/xmlns/";
31  
32      public static Document readDoc(DocumentBuilder documentBuilder, XMLStreamReader xmlStreamReader) throws XMLStreamException {
33          //skip possible text at the beginning of a document and go directly to the root tag
34          while (xmlStreamReader.hasNext() && xmlStreamReader.next() != XMLStreamConstants.START_ELEMENT) { //NOPMD
35          }
36          Document document = documentBuilder.newDocument();
37          StAX2DOM.readDocElements(document, document, xmlStreamReader, false, false);
38          xmlStreamReader.close();
39          return document;
40      }
41  
42      public static void readDocElements(Document doc, Node parent,
43                                         XMLStreamReader reader, boolean repairing, boolean recordLoc)
44              throws XMLStreamException {
45  
46          int event = reader.getEventType();
47          while (reader.hasNext()) {
48              switch (event) {
49                  case XMLStreamConstants.START_ELEMENT:
50                      startElement(doc, parent, reader, repairing, recordLoc);
51  /*
52                      if (parent instanceof Document) {
53                          return;
54                      }
55  */
56                      break;
57                  case XMLStreamConstants.END_DOCUMENT:
58                      return;
59                  case XMLStreamConstants.END_ELEMENT:
60                      return;
61                  case XMLStreamConstants.NAMESPACE:
62                      break;
63                  case XMLStreamConstants.ATTRIBUTE:
64                      break;
65                  case XMLStreamConstants.CHARACTERS:
66                      if (parent != null) {
67                          recordLoc = addLocation(doc,
68                                  parent.appendChild(doc.createTextNode(reader.getText())),
69                                  reader, recordLoc);
70                      }
71                      break;
72                  case XMLStreamConstants.COMMENT:
73                      if (parent != null) {
74                          parent.appendChild(doc.createComment(reader.getText()));
75                      }
76                      break;
77                  case XMLStreamConstants.CDATA:
78                      recordLoc = addLocation(doc,
79                              parent.appendChild(doc.createCDATASection(reader.getText())),
80                              reader, recordLoc);
81                      break;
82                  case XMLStreamConstants.PROCESSING_INSTRUCTION:
83                      parent.appendChild(doc.createProcessingInstruction(reader.getPITarget(), reader.getPIData()));
84                      break;
85                  case XMLStreamConstants.ENTITY_REFERENCE:
86                      parent.appendChild(doc.createProcessingInstruction(reader.getPITarget(), reader.getPIData()));
87                      break;
88                  default:
89                      break;
90              }
91  
92              if (reader.hasNext()) {
93                  event = reader.next();
94              }
95          }
96      }
97  
98      static boolean addLocation(Document doc, Node node,
99                                 XMLStreamReader reader,
100                                boolean recordLoc) {
101         if (recordLoc) {
102             Location loc = reader.getLocation();
103             if (loc != null && (loc.getColumnNumber() != 0 || loc.getLineNumber() != 0)) {
104                 try {
105                     final int charOffset = loc.getCharacterOffset();
106                     final int colNum = loc.getColumnNumber();
107                     final int linNum = loc.getLineNumber();
108                     final String pubId = loc.getPublicId() == null ? doc.getDocumentURI() : loc.getPublicId();
109                     final String sysId = loc.getSystemId() == null ? doc.getDocumentURI() : loc.getSystemId();
110                     Location loc2 = new Location() {
111                         @Override
112                         public int getCharacterOffset() {
113                             return charOffset;
114                         }
115 
116                         @Override
117                         public int getColumnNumber() {
118                             return colNum;
119                         }
120 
121                         @Override
122                         public int getLineNumber() {
123                             return linNum;
124                         }
125 
126                         @Override
127                         public String getPublicId() {
128                             return pubId;
129                         }
130 
131                         @Override
132                         public String getSystemId() {
133                             return sysId;
134                         }
135                     };
136                     node.setUserData("location", loc2, new UserDataHandler() {
137                         @Override
138                         public void handle(short operation, String key, Object data, Node src, Node dst) {
139                             if (operation == NODE_CLONED) {
140                                 dst.setUserData(key, data, this);
141                             }
142                         }
143                     });
144                 } catch (Exception ex) {
145                     //possibly not DOM level 3, won't be able to record this then
146                     return false;
147                 }
148             }
149         }
150         return recordLoc;
151     }
152 
153     static Element startElement(Document doc,
154                                 Node parent,
155                                 XMLStreamReader reader,
156                                 boolean repairing,
157                                 boolean recordLocation)
158             throws XMLStreamException {
159 
160         Element e = doc.createElementNS(reader.getNamespaceURI(), reader.getLocalName());
161         if (reader.getPrefix() != null) {
162             e.setPrefix(reader.getPrefix());
163         }
164         e = (Element) parent.appendChild(e);
165         recordLocation = addLocation(doc, e, reader, recordLocation);
166 
167         for (int ns = 0; ns < reader.getNamespaceCount(); ns++) {
168             String uri = reader.getNamespaceURI(ns);
169             String prefix = reader.getNamespacePrefix(ns);
170 
171             declare(e, uri, prefix);
172         }
173 
174         for (int att = 0; att < reader.getAttributeCount(); att++) {
175             String name = reader.getAttributeLocalName(att);
176             String prefix = reader.getAttributePrefix(att);
177             if (prefix != null && prefix.length() > 0) {
178                 name = prefix + ":" + name;
179             }
180 
181             Attr attr = doc.createAttributeNS(reader.getAttributeNamespace(att), name);
182             attr.setValue(reader.getAttributeValue(att));
183             e.setAttributeNode(attr);
184         }
185 
186         if (repairing && !isDeclared(e, reader.getNamespaceURI(), reader.getPrefix())) {
187             declare(e, reader.getNamespaceURI(), reader.getPrefix());
188         }
189 
190         reader.next();
191 
192         readDocElements(doc, e, reader, repairing, recordLocation);
193 
194         return e;
195     }
196 
197     static void declare(Element node, String uri, String prefix) {
198         String qualname;
199         if (prefix != null && prefix.length() > 0) {
200             qualname = "xmlns:" + prefix;
201         } else {
202             qualname = "xmlns";
203         }
204         Attr attr = node.getOwnerDocument().createAttributeNS(XML_NS, qualname);
205         attr.setValue(uri);
206         node.setAttributeNodeNS(attr);
207     }
208 
209     static boolean isDeclared(Element e, String namespaceURI, String prefix) {
210         Attr att;
211         if (prefix != null && prefix.length() > 0) {
212             att = e.getAttributeNodeNS(XML_NS, prefix);
213         } else {
214             att = e.getAttributeNode("xmlns");
215         }
216 
217         if (att != null && att.getNodeValue().equals(namespaceURI)) {
218             return true;
219         }
220 
221         if (e.getParentNode() instanceof Element) {
222             return isDeclared((Element) e.getParentNode(), namespaceURI, prefix);
223         }
224 
225         return false;
226     }
227 }