src/share/jaxws_classes/com/sun/xml/internal/bind/unmarshaller/DOMScanner.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.bind.unmarshaller;
aoqi@0 27
aoqi@0 28 import java.util.Enumeration;
aoqi@0 29
aoqi@0 30 import javax.xml.bind.ValidationEventLocator;
aoqi@0 31 import javax.xml.bind.helpers.AbstractUnmarshallerImpl;
aoqi@0 32 import javax.xml.bind.helpers.ValidationEventLocatorImpl;
aoqi@0 33
aoqi@0 34 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LocatorEx;
aoqi@0 35
aoqi@0 36 import org.w3c.dom.Attr;
aoqi@0 37 import org.w3c.dom.Document;
aoqi@0 38 import org.w3c.dom.Element;
aoqi@0 39 import org.w3c.dom.NamedNodeMap;
aoqi@0 40 import org.w3c.dom.Node;
aoqi@0 41 import org.w3c.dom.NodeList;
aoqi@0 42 import org.w3c.dom.ProcessingInstruction;
aoqi@0 43 import org.xml.sax.ContentHandler;
aoqi@0 44 import org.xml.sax.Locator;
aoqi@0 45 import org.xml.sax.SAXException;
aoqi@0 46 import org.xml.sax.helpers.AttributesImpl;
aoqi@0 47 import org.xml.sax.helpers.NamespaceSupport;
aoqi@0 48
aoqi@0 49 /**
aoqi@0 50 * Visits a W3C DOM tree and generates SAX2 events from it.
aoqi@0 51 *
aoqi@0 52 * <p>
aoqi@0 53 * This class is just intended to be used by {@link AbstractUnmarshallerImpl}.
aoqi@0 54 * The javax.xml.bind.helpers package is generally a wrong place to put
aoqi@0 55 * classes like this.
aoqi@0 56 *
aoqi@0 57 * @author <ul><li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li></ul>
aoqi@0 58 * @since JAXB1.0
aoqi@0 59 */
aoqi@0 60 public class DOMScanner implements LocatorEx,InfosetScanner/*<Node> --- but can't do this to protect 1.0 clients, or can I? */
aoqi@0 61 {
aoqi@0 62
aoqi@0 63 /** reference to the current node being scanned - used for determining
aoqi@0 64 * location info for validation events */
aoqi@0 65 private Node currentNode = null;
aoqi@0 66
aoqi@0 67 /** To save memory, only one instance of AttributesImpl will be used. */
aoqi@0 68 private final AttributesImpl atts = new AttributesImpl();
aoqi@0 69
aoqi@0 70 /** This handler will receive SAX2 events. */
aoqi@0 71 private ContentHandler receiver=null;
aoqi@0 72
aoqi@0 73 private Locator locator=this;
aoqi@0 74
aoqi@0 75 public DOMScanner() {
aoqi@0 76 }
aoqi@0 77
aoqi@0 78
aoqi@0 79 /**
aoqi@0 80 * Configures the locator object that the SAX {@link ContentHandler} will see.
aoqi@0 81 */
aoqi@0 82 public void setLocator( Locator loc ) {
aoqi@0 83 this.locator = loc;
aoqi@0 84 }
aoqi@0 85
aoqi@0 86 public void scan(Object node) throws SAXException {
aoqi@0 87 if( node instanceof Document ) {
aoqi@0 88 scan( (Document)node );
aoqi@0 89 } else {
aoqi@0 90 scan( (Element)node );
aoqi@0 91 }
aoqi@0 92 }
aoqi@0 93
aoqi@0 94 public void scan( Document doc ) throws SAXException {
aoqi@0 95 scan( doc.getDocumentElement() );
aoqi@0 96 }
aoqi@0 97
aoqi@0 98 public void scan( Element e) throws SAXException {
aoqi@0 99 setCurrentLocation( e );
aoqi@0 100
aoqi@0 101 receiver.setDocumentLocator(locator);
aoqi@0 102 receiver.startDocument();
aoqi@0 103
aoqi@0 104 NamespaceSupport nss = new NamespaceSupport();
aoqi@0 105 buildNamespaceSupport( nss, e.getParentNode() );
aoqi@0 106
aoqi@0 107 for( Enumeration en = nss.getPrefixes(); en.hasMoreElements(); ) {
aoqi@0 108 String prefix = (String)en.nextElement();
aoqi@0 109 receiver.startPrefixMapping( prefix, nss.getURI(prefix) );
aoqi@0 110 }
aoqi@0 111
aoqi@0 112 visit(e);
aoqi@0 113
aoqi@0 114 for( Enumeration en = nss.getPrefixes(); en.hasMoreElements(); ) {
aoqi@0 115 String prefix = (String)en.nextElement();
aoqi@0 116 receiver.endPrefixMapping( prefix );
aoqi@0 117 }
aoqi@0 118
aoqi@0 119
aoqi@0 120 setCurrentLocation( e );
aoqi@0 121 receiver.endDocument();
aoqi@0 122 }
aoqi@0 123
aoqi@0 124 /**
aoqi@0 125 * Parses a subtree starting from the element e and
aoqi@0 126 * reports SAX2 events to the specified handler.
aoqi@0 127 *
aoqi@0 128 * @deprecated in JAXB 2.0
aoqi@0 129 * Use {@link #scan(Element)}
aoqi@0 130 */
aoqi@0 131 public void parse( Element e, ContentHandler handler ) throws SAXException {
aoqi@0 132 // it might be better to set receiver at the constructor.
aoqi@0 133 receiver = handler;
aoqi@0 134
aoqi@0 135 setCurrentLocation( e );
aoqi@0 136 receiver.startDocument();
aoqi@0 137
aoqi@0 138 receiver.setDocumentLocator(locator);
aoqi@0 139 visit(e);
aoqi@0 140
aoqi@0 141 setCurrentLocation( e );
aoqi@0 142 receiver.endDocument();
aoqi@0 143 }
aoqi@0 144
aoqi@0 145 /**
aoqi@0 146 * Similar to the parse method but it visits the ancestor nodes
aoqi@0 147 * and properly emulate the all in-scope namespace declarations.
aoqi@0 148 *
aoqi@0 149 * @deprecated in JAXB 2.0
aoqi@0 150 * Use {@link #scan(Element)}
aoqi@0 151 */
aoqi@0 152 public void parseWithContext( Element e, ContentHandler handler ) throws SAXException {
aoqi@0 153 setContentHandler(handler);
aoqi@0 154 scan(e);
aoqi@0 155 }
aoqi@0 156
aoqi@0 157 /**
aoqi@0 158 * Recursively visit ancestors and build up {@link NamespaceSupport} oject.
aoqi@0 159 */
aoqi@0 160 private void buildNamespaceSupport(NamespaceSupport nss, Node node) {
aoqi@0 161 if(node==null || node.getNodeType()!=Node.ELEMENT_NODE)
aoqi@0 162 return;
aoqi@0 163
aoqi@0 164 buildNamespaceSupport( nss, node.getParentNode() );
aoqi@0 165
aoqi@0 166 nss.pushContext();
aoqi@0 167 NamedNodeMap atts = node.getAttributes();
aoqi@0 168 for( int i=0; i<atts.getLength(); i++ ) {
aoqi@0 169 Attr a = (Attr)atts.item(i);
aoqi@0 170 if( "xmlns".equals(a.getPrefix()) ) {
aoqi@0 171 nss.declarePrefix( a.getLocalName(), a.getValue() );
aoqi@0 172 continue;
aoqi@0 173 }
aoqi@0 174 if( "xmlns".equals(a.getName()) ) {
aoqi@0 175 nss.declarePrefix( "", a.getValue() );
aoqi@0 176 continue;
aoqi@0 177 }
aoqi@0 178 }
aoqi@0 179 }
aoqi@0 180
aoqi@0 181 /**
aoqi@0 182 * Visits an element and its subtree.
aoqi@0 183 */
aoqi@0 184 public void visit( Element e ) throws SAXException {
aoqi@0 185 setCurrentLocation( e );
aoqi@0 186 final NamedNodeMap attributes = e.getAttributes();
aoqi@0 187
aoqi@0 188 atts.clear();
aoqi@0 189 int len = attributes==null ? 0: attributes.getLength();
aoqi@0 190
aoqi@0 191 for( int i=len-1; i>=0; i-- ) {
aoqi@0 192 Attr a = (Attr)attributes.item(i);
aoqi@0 193 String name = a.getName();
aoqi@0 194 // start namespace binding
aoqi@0 195 if(name.startsWith("xmlns")) {
aoqi@0 196 if(name.length()==5) {
aoqi@0 197 receiver.startPrefixMapping( "", a.getValue() );
aoqi@0 198 } else {
aoqi@0 199 String localName = a.getLocalName();
aoqi@0 200 if(localName==null) {
aoqi@0 201 // DOM built without namespace support has this problem
aoqi@0 202 localName = name.substring(6);
aoqi@0 203 }
aoqi@0 204 receiver.startPrefixMapping( localName, a.getValue() );
aoqi@0 205 }
aoqi@0 206 continue;
aoqi@0 207 }
aoqi@0 208
aoqi@0 209 String uri = a.getNamespaceURI();
aoqi@0 210 if(uri==null) uri="";
aoqi@0 211
aoqi@0 212 String local = a.getLocalName();
aoqi@0 213 if(local==null) local = a.getName();
aoqi@0 214 // add other attributes to the attribute list
aoqi@0 215 // that we will pass to the ContentHandler
aoqi@0 216 atts.addAttribute(
aoqi@0 217 uri,
aoqi@0 218 local,
aoqi@0 219 a.getName(),
aoqi@0 220 "CDATA",
aoqi@0 221 a.getValue());
aoqi@0 222 }
aoqi@0 223
aoqi@0 224 String uri = e.getNamespaceURI();
aoqi@0 225 if(uri==null) uri="";
aoqi@0 226 String local = e.getLocalName();
aoqi@0 227 String qname = e.getTagName();
aoqi@0 228 if(local==null) local = qname;
aoqi@0 229 receiver.startElement( uri, local, qname, atts );
aoqi@0 230
aoqi@0 231 // visit its children
aoqi@0 232 NodeList children = e.getChildNodes();
aoqi@0 233 int clen = children.getLength();
aoqi@0 234 for( int i=0; i<clen; i++ )
aoqi@0 235 visit(children.item(i));
aoqi@0 236
aoqi@0 237
aoqi@0 238
aoqi@0 239 setCurrentLocation( e );
aoqi@0 240 receiver.endElement( uri, local, qname );
aoqi@0 241
aoqi@0 242 // call the endPrefixMapping method
aoqi@0 243 for( int i=len-1; i>=0; i-- ) {
aoqi@0 244 Attr a = (Attr)attributes.item(i);
aoqi@0 245 String name = a.getName();
aoqi@0 246 if(name.startsWith("xmlns")) {
aoqi@0 247 if(name.length()==5)
aoqi@0 248 receiver.endPrefixMapping("");
aoqi@0 249 else
aoqi@0 250 receiver.endPrefixMapping(a.getLocalName());
aoqi@0 251 }
aoqi@0 252 }
aoqi@0 253 }
aoqi@0 254
aoqi@0 255 private void visit( Node n ) throws SAXException {
aoqi@0 256 setCurrentLocation( n );
aoqi@0 257
aoqi@0 258 // if a case statement gets too big, it should be made into a separate method.
aoqi@0 259 switch(n.getNodeType()) {
aoqi@0 260 case Node.CDATA_SECTION_NODE:
aoqi@0 261 case Node.TEXT_NODE:
aoqi@0 262 String value = n.getNodeValue();
aoqi@0 263 receiver.characters( value.toCharArray(), 0, value.length() );
aoqi@0 264 break;
aoqi@0 265 case Node.ELEMENT_NODE:
aoqi@0 266 visit( (Element)n );
aoqi@0 267 break;
aoqi@0 268 case Node.ENTITY_REFERENCE_NODE:
aoqi@0 269 receiver.skippedEntity(n.getNodeName());
aoqi@0 270 break;
aoqi@0 271 case Node.PROCESSING_INSTRUCTION_NODE:
aoqi@0 272 ProcessingInstruction pi = (ProcessingInstruction)n;
aoqi@0 273 receiver.processingInstruction(pi.getTarget(),pi.getData());
aoqi@0 274 break;
aoqi@0 275 }
aoqi@0 276 }
aoqi@0 277
aoqi@0 278 private void setCurrentLocation( Node currNode ) {
aoqi@0 279 currentNode = currNode;
aoqi@0 280 }
aoqi@0 281
aoqi@0 282 /**
aoqi@0 283 * The same as {@link #getCurrentElement()} but
aoqi@0 284 * better typed.
aoqi@0 285 */
aoqi@0 286 public Node getCurrentLocation() {
aoqi@0 287 return currentNode;
aoqi@0 288 }
aoqi@0 289
aoqi@0 290 public Object getCurrentElement() {
aoqi@0 291 return currentNode;
aoqi@0 292 }
aoqi@0 293
aoqi@0 294 public LocatorEx getLocator() {
aoqi@0 295 return this;
aoqi@0 296 }
aoqi@0 297
aoqi@0 298 public void setContentHandler(ContentHandler handler) {
aoqi@0 299 this.receiver = handler;
aoqi@0 300 }
aoqi@0 301
aoqi@0 302 public ContentHandler getContentHandler() {
aoqi@0 303 return this.receiver;
aoqi@0 304 }
aoqi@0 305
aoqi@0 306
aoqi@0 307 // LocatorEx implementation
aoqi@0 308 public String getPublicId() { return null; }
aoqi@0 309 public String getSystemId() { return null; }
aoqi@0 310 public int getLineNumber() { return -1; }
aoqi@0 311 public int getColumnNumber() { return -1; }
aoqi@0 312
aoqi@0 313 public ValidationEventLocator getLocation() {
aoqi@0 314 return new ValidationEventLocatorImpl(getCurrentLocation());
aoqi@0 315 }
aoqi@0 316 }

mercurial