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

     1 /*
     2  * Copyright (c) 1997, 2010, 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  */
    26 package com.sun.xml.internal.bind.unmarshaller;
    28 import java.util.Enumeration;
    30 import javax.xml.bind.ValidationEventLocator;
    31 import javax.xml.bind.helpers.AbstractUnmarshallerImpl;
    32 import javax.xml.bind.helpers.ValidationEventLocatorImpl;
    34 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LocatorEx;
    36 import org.w3c.dom.Attr;
    37 import org.w3c.dom.Document;
    38 import org.w3c.dom.Element;
    39 import org.w3c.dom.NamedNodeMap;
    40 import org.w3c.dom.Node;
    41 import org.w3c.dom.NodeList;
    42 import org.w3c.dom.ProcessingInstruction;
    43 import org.xml.sax.ContentHandler;
    44 import org.xml.sax.Locator;
    45 import org.xml.sax.SAXException;
    46 import org.xml.sax.helpers.AttributesImpl;
    47 import org.xml.sax.helpers.NamespaceSupport;
    49 /**
    50  * Visits a W3C DOM tree and generates SAX2 events from it.
    51  *
    52  * <p>
    53  * This class is just intended to be used by {@link AbstractUnmarshallerImpl}.
    54  * The javax.xml.bind.helpers package is generally a wrong place to put
    55  * classes like this.
    56  *
    57  * @author <ul><li>Kohsuke Kawaguchi, Sun Microsystems, Inc.</li></ul>
    58  * @since JAXB1.0
    59  */
    60 public class DOMScanner implements LocatorEx,InfosetScanner/*<Node> --- but can't do this to protect 1.0 clients, or can I? */
    61 {
    63     /** reference to the current node being scanned - used for determining
    64      *  location info for validation events */
    65     private Node currentNode = null;
    67     /** To save memory, only one instance of AttributesImpl will be used. */
    68     private final AttributesImpl atts = new AttributesImpl();
    70     /** This handler will receive SAX2 events. */
    71     private ContentHandler receiver=null;
    73     private Locator locator=this;
    75     public DOMScanner() {
    76     }
    79     /**
    80      * Configures the locator object that the SAX {@link ContentHandler} will see.
    81      */
    82     public void setLocator( Locator loc ) {
    83         this.locator = loc;
    84     }
    86     public void scan(Object node) throws SAXException {
    87         if( node instanceof Document ) {
    88             scan( (Document)node );
    89         } else {
    90             scan( (Element)node );
    91         }
    92     }
    94     public void scan( Document doc ) throws SAXException {
    95         scan( doc.getDocumentElement() );
    96     }
    98     public void scan( Element e) throws SAXException {
    99         setCurrentLocation( e );
   101         receiver.setDocumentLocator(locator);
   102         receiver.startDocument();
   104         NamespaceSupport nss = new NamespaceSupport();
   105         buildNamespaceSupport( nss, e.getParentNode() );
   107         for( Enumeration en = nss.getPrefixes(); en.hasMoreElements(); ) {
   108             String prefix = (String)en.nextElement();
   109             receiver.startPrefixMapping( prefix, nss.getURI(prefix) );
   110         }
   112         visit(e);
   114         for( Enumeration en = nss.getPrefixes(); en.hasMoreElements(); ) {
   115             String prefix = (String)en.nextElement();
   116             receiver.endPrefixMapping( prefix );
   117         }
   120         setCurrentLocation( e );
   121         receiver.endDocument();
   122     }
   124     /**
   125      * Parses a subtree starting from the element e and
   126      * reports SAX2 events to the specified handler.
   127      *
   128      * @deprecated in JAXB 2.0
   129      *      Use {@link #scan(Element)}
   130      */
   131     public void parse( Element e, ContentHandler handler ) throws SAXException {
   132         // it might be better to set receiver at the constructor.
   133         receiver = handler;
   135         setCurrentLocation( e );
   136         receiver.startDocument();
   138         receiver.setDocumentLocator(locator);
   139         visit(e);
   141         setCurrentLocation( e );
   142         receiver.endDocument();
   143     }
   145     /**
   146      * Similar to the parse method but it visits the ancestor nodes
   147      * and properly emulate the all in-scope namespace declarations.
   148      *
   149      * @deprecated in JAXB 2.0
   150      *      Use {@link #scan(Element)}
   151      */
   152     public void parseWithContext( Element e, ContentHandler handler ) throws SAXException {
   153         setContentHandler(handler);
   154         scan(e);
   155     }
   157     /**
   158      * Recursively visit ancestors and build up {@link NamespaceSupport} oject.
   159      */
   160     private void buildNamespaceSupport(NamespaceSupport nss, Node node) {
   161         if(node==null || node.getNodeType()!=Node.ELEMENT_NODE)
   162             return;
   164         buildNamespaceSupport( nss, node.getParentNode() );
   166         nss.pushContext();
   167         NamedNodeMap atts = node.getAttributes();
   168         for( int i=0; i<atts.getLength(); i++ ) {
   169             Attr a = (Attr)atts.item(i);
   170             if( "xmlns".equals(a.getPrefix()) ) {
   171                 nss.declarePrefix( a.getLocalName(), a.getValue() );
   172                 continue;
   173             }
   174             if( "xmlns".equals(a.getName()) ) {
   175                 nss.declarePrefix( "", a.getValue() );
   176                 continue;
   177             }
   178         }
   179     }
   181     /**
   182      * Visits an element and its subtree.
   183      */
   184     public void visit( Element e ) throws SAXException {
   185         setCurrentLocation( e );
   186         final NamedNodeMap attributes = e.getAttributes();
   188         atts.clear();
   189         int len = attributes==null ? 0: attributes.getLength();
   191         for( int i=len-1; i>=0; i-- ) {
   192             Attr a = (Attr)attributes.item(i);
   193             String name = a.getName();
   194             // start namespace binding
   195            if(name.startsWith("xmlns")) {
   196                 if(name.length()==5) {
   197                     receiver.startPrefixMapping( "", a.getValue() );
   198                 } else {
   199                     String localName = a.getLocalName();
   200                     if(localName==null) {
   201                         // DOM built without namespace support has this problem
   202                         localName = name.substring(6);
   203                     }
   204                     receiver.startPrefixMapping( localName, a.getValue() );
   205                 }
   206                 continue;
   207             }
   209             String uri = a.getNamespaceURI();
   210             if(uri==null)   uri="";
   212             String local = a.getLocalName();
   213             if(local==null) local = a.getName();
   214             // add other attributes to the attribute list
   215             // that we will pass to the ContentHandler
   216             atts.addAttribute(
   217                 uri,
   218                 local,
   219                 a.getName(),
   220                 "CDATA",
   221                 a.getValue());
   222         }
   224         String uri = e.getNamespaceURI();
   225         if(uri==null)   uri="";
   226         String local = e.getLocalName();
   227         String qname = e.getTagName();
   228         if(local==null) local = qname;
   229         receiver.startElement( uri, local, qname, atts );
   231         // visit its children
   232         NodeList children = e.getChildNodes();
   233         int clen = children.getLength();
   234         for( int i=0; i<clen; i++ )
   235             visit(children.item(i));
   239         setCurrentLocation( e );
   240         receiver.endElement( uri, local, qname );
   242         // call the endPrefixMapping method
   243         for( int i=len-1; i>=0; i-- ) {
   244             Attr a = (Attr)attributes.item(i);
   245             String name = a.getName();
   246             if(name.startsWith("xmlns")) {
   247                 if(name.length()==5)
   248                     receiver.endPrefixMapping("");
   249                 else
   250                     receiver.endPrefixMapping(a.getLocalName());
   251             }
   252         }
   253     }
   255     private void visit( Node n ) throws SAXException {
   256         setCurrentLocation( n );
   258         // if a case statement gets too big, it should be made into a separate method.
   259         switch(n.getNodeType()) {
   260         case Node.CDATA_SECTION_NODE:
   261         case Node.TEXT_NODE:
   262             String value = n.getNodeValue();
   263             receiver.characters( value.toCharArray(), 0, value.length() );
   264             break;
   265         case Node.ELEMENT_NODE:
   266             visit( (Element)n );
   267             break;
   268         case Node.ENTITY_REFERENCE_NODE:
   269             receiver.skippedEntity(n.getNodeName());
   270             break;
   271         case Node.PROCESSING_INSTRUCTION_NODE:
   272             ProcessingInstruction pi = (ProcessingInstruction)n;
   273             receiver.processingInstruction(pi.getTarget(),pi.getData());
   274             break;
   275         }
   276     }
   278     private void setCurrentLocation( Node currNode ) {
   279         currentNode = currNode;
   280     }
   282     /**
   283      * The same as {@link #getCurrentElement()} but
   284      * better typed.
   285      */
   286     public Node getCurrentLocation() {
   287         return currentNode;
   288     }
   290     public Object getCurrentElement() {
   291         return currentNode;
   292     }
   294     public LocatorEx getLocator() {
   295         return this;
   296     }
   298     public void setContentHandler(ContentHandler handler) {
   299         this.receiver = handler;
   300     }
   302     public ContentHandler getContentHandler() {
   303         return this.receiver;
   304     }
   307     // LocatorEx implementation
   308     public String getPublicId() { return null; }
   309     public String getSystemId() { return null; }
   310     public int getLineNumber() { return -1; }
   311     public int getColumnNumber() { return -1; }
   313     public ValidationEventLocator getLocation() {
   314         return new ValidationEventLocatorImpl(getCurrentLocation());
   315     }
   316 }

mercurial