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 */ 25 26 package com.sun.tools.internal.ws.wsdl.parser; 27 28 import com.sun.xml.internal.bind.unmarshaller.DOMScanner; 29 import org.w3c.dom.Document; 30 import org.w3c.dom.Element; 31 import org.w3c.dom.Node; 32 import org.xml.sax.Attributes; 33 import org.xml.sax.ContentHandler; 34 import org.xml.sax.Locator; 35 import org.xml.sax.SAXException; 36 import org.xml.sax.helpers.XMLFilterImpl; 37 38 /** 39 * Produces a complete series of SAX events from any DOM node 40 * in the DOMForest. 41 * 42 * <p> 43 * This class hides a logic of re-associating {@link org.xml.sax.Locator} 44 * to the generated SAX event stream. 45 * 46 * @author 47 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 48 */ 49 public class DOMForestScanner { 50 51 private final DOMForest forest; 52 53 /** 54 * Scans DOM nodes of the given forest. 55 * 56 * DOM node parameters to the scan method must be a part of 57 * this forest. 58 */ 59 public DOMForestScanner( DOMForest _forest ) { 60 this.forest = _forest; 61 } 62 63 /** 64 * Generates the whole set of SAX events by treating 65 * element e as if it's a root element. 66 */ 67 public void scan( Element e, ContentHandler contentHandler ) throws SAXException { 68 DOMScanner scanner = new DOMScanner(); 69 70 // insert the location resolver into the pipe line 71 LocationResolver resolver = new LocationResolver(scanner); 72 resolver.setContentHandler(contentHandler); 73 74 // parse this DOM. 75 scanner.setContentHandler(resolver); 76 scanner.scan(e); 77 } 78 79 /** 80 * Generates the whole set of SAX events from the given Document 81 * in the DOMForest. 82 */ 83 public void scan( Document d, ContentHandler contentHandler ) throws SAXException { 84 scan( d.getDocumentElement(), contentHandler ); 85 } 86 87 /** 88 * Intercepts the invocation of the setDocumentLocator method 89 * and passes itself as the locator. 90 * 91 * If the client calls one of the methods on the Locator interface, 92 * use the LocatorTable to resolve the source location. 93 */ 94 private class LocationResolver extends XMLFilterImpl implements Locator { 95 LocationResolver( DOMScanner _parent ) { 96 this.parent = _parent; 97 } 98 99 private final DOMScanner parent; 100 101 /** 102 * Flag that tells us whether we are processing a start element event 103 * or an end element event. 104 * 105 * DOMScanner's getCurrentLocation method doesn't tell us which, but 106 * this information is necessary to return the correct source line information. 107 * 108 * Thus we set this flag appropriately before we pass an event to 109 * the next ContentHandler, thereby making it possible to figure 110 * out which location to return. 111 */ 112 private boolean inStart = false; 113 114 public void setDocumentLocator(Locator locator) { 115 // ignore one set by the parent. 116 117 super.setDocumentLocator(this); 118 } 119 120 public void endElement(String namespaceURI, String localName, String qName) throws SAXException { 121 inStart = false; 122 super.endElement(namespaceURI, localName, qName); 123 } 124 125 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) 126 throws SAXException { 127 inStart = true; 128 super.startElement(namespaceURI, localName, qName, atts); 129 } 130 131 132 133 134 private Locator findLocator() { 135 Node n = parent.getCurrentLocation(); 136 if( n instanceof Element ) { 137 Element e = (Element)n; 138 if( inStart ) 139 return forest.locatorTable.getStartLocation( e ); 140 else 141 return forest.locatorTable.getEndLocation( e ); 142 } 143 return null; 144 } 145 146 // 147 // 148 // Locator methods 149 // 150 // 151 public int getColumnNumber() { 152 Locator l = findLocator(); 153 if(l!=null) return l.getColumnNumber(); 154 return -1; 155 } 156 157 public int getLineNumber() { 158 Locator l = findLocator(); 159 if(l!=null) return l.getLineNumber(); 160 return -1; 161 } 162 163 public String getPublicId() { 164 Locator l = findLocator(); 165 if(l!=null) return l.getPublicId(); 166 return null; 167 } 168 169 public String getSystemId() { 170 Locator l = findLocator(); 171 if(l!=null) return l.getSystemId(); 172 return null; 173 } 174 175 } 176 }