1 /* 2 * Copyright (c) 2005, 2020, 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.org.apache.xalan.internal.xsltc.trax; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 import javax.xml.stream.Location; 31 import javax.xml.stream.XMLReporter; 32 import javax.xml.stream.XMLStreamException; 33 import org.xml.sax.Attributes; 34 import org.xml.sax.Locator; 35 import org.xml.sax.SAXException; 36 import org.xml.sax.SAXParseException; 37 import org.xml.sax.ext.LexicalHandler; 38 import org.xml.sax.ext.Locator2; 39 import org.xml.sax.helpers.DefaultHandler; 40 41 public abstract class SAX2StAXBaseWriter extends DefaultHandler 42 implements 43 LexicalHandler { 44 45 protected boolean isCDATA; 46 47 protected StringBuffer CDATABuffer; 48 49 protected List<String> namespaces; 50 51 protected Locator docLocator; 52 53 protected XMLReporter reporter; 54 55 String xmlVersion = null, encoding = null; 56 57 public SAX2StAXBaseWriter() { 58 } 59 60 public SAX2StAXBaseWriter(XMLReporter reporter) { 61 this.reporter = reporter; 62 } 63 64 public void setXMLReporter(XMLReporter reporter) { 65 this.reporter = reporter; 66 } 67 68 public void setDocumentLocator(Locator locator) { 69 this.docLocator = locator; 70 } 71 72 private void updateVersionAndEncoding() { 73 if (docLocator instanceof Locator2) { 74 Locator2 l2 = (Locator2) docLocator; 75 xmlVersion = l2.getXMLVersion(); 76 encoding = l2.getEncoding(); 77 } 78 } 79 80 public void setXmlVersion(String version) { 81 this.xmlVersion = version; 82 } 83 84 public void setEncoding(String encoding) { 85 this.encoding = encoding; 86 } 87 88 void writeStartDocument() throws SAXException { 89 updateVersionAndEncoding(); 90 } 91 92 public Location getCurrentLocation() { 93 if (docLocator != null) { 94 return new SAXLocation(docLocator); 95 } else { 96 return null; 97 } 98 } 99 100 public void error(SAXParseException e) throws SAXException { 101 reportException("ERROR", e); 102 } 103 104 public void fatalError(SAXParseException e) throws SAXException { 105 reportException("FATAL", e); 106 } 107 108 public void warning(SAXParseException e) throws SAXException { 109 reportException("WARNING", e); 110 } 111 112 public void startDocument() throws SAXException { 113 namespaces = new ArrayList<>(2); 114 } 115 116 public void endDocument() throws SAXException { 117 namespaces = null; 118 } 119 120 public void startElement(String uri, String localName, String qName, 121 Attributes attributes) throws SAXException { 122 namespaces = null; 123 } 124 125 public void endElement(String uri, String localName, String qName) 126 throws SAXException { 127 namespaces = null; 128 } 129 130 public void startPrefixMapping(String prefix, String uri) 131 throws SAXException { 132 133 if (prefix == null) { 134 prefix = ""; 135 } else if (prefix.equals("xml")) { 136 return; 137 } 138 139 if (namespaces == null) { 140 namespaces = new ArrayList<>(2); 141 } 142 namespaces.add(prefix); 143 namespaces.add(uri); 144 } 145 146 public void endPrefixMapping(String prefix) throws SAXException { 147 } 148 149 public void startCDATA() throws SAXException { 150 isCDATA = true; 151 if (CDATABuffer == null) { 152 CDATABuffer = new StringBuffer(); 153 } else { 154 CDATABuffer.setLength(0); 155 } 156 } 157 158 public void characters(char[] ch, int start, int length) 159 throws SAXException { 160 if (isCDATA) { 161 CDATABuffer.append(ch, start, length); 162 } 163 } 164 165 public void endCDATA() throws SAXException { 166 isCDATA = false; 167 CDATABuffer.setLength(0); 168 } 169 170 public void comment(char[] ch, int start, int length) throws SAXException { 171 } 172 173 public void endDTD() throws SAXException { 174 } 175 176 public void endEntity(String name) throws SAXException { 177 } 178 179 public void startDTD(String name, String publicId, String systemId) 180 throws SAXException { 181 } 182 183 public void startEntity(String name) throws SAXException { 184 } 185 186 /** 187 * Used to report a {@link SAXException}to the {@link XMLReporter} 188 * registered with this handler. 189 */ 190 protected void reportException(String type, SAXException e) 191 throws SAXException { 192 193 if (reporter != null) { 194 try { 195 reporter.report(e.getMessage(), type, e, getCurrentLocation()); 196 } catch (XMLStreamException e1) { 197 throw new SAXException(e1); 198 } 199 } 200 } 201 202 /** 203 * Parses an XML qualified name, and places the resulting prefix and local 204 * name in the provided String array. 205 * 206 * @param qName The qualified name to parse. 207 * @param results An array where parse results will be placed. The prefix 208 * will be placed at <code>results[0]</code>, and the local 209 * part at <code>results[1]</code> 210 */ 211 public static final void parseQName(String qName, String[] results) { 212 213 String prefix, local; 214 int idx = qName.indexOf(':'); 215 if (idx >= 0) { 216 prefix = qName.substring(0, idx); 217 local = qName.substring(idx + 1); 218 } else { 219 prefix = ""; 220 local = qName; 221 } 222 results[0] = prefix; 223 results[1] = local; 224 } 225 226 /** 227 * {@Link Location}implementation used to expose details from a SAX 228 * {@link Locator}. 229 * 230 * @author christian 231 */ 232 private static final class SAXLocation implements Location { 233 234 private int lineNumber; 235 private int columnNumber; 236 private String publicId; 237 private String systemId; 238 private SAXLocation(Locator locator) { 239 lineNumber = locator.getLineNumber(); 240 columnNumber = locator.getColumnNumber(); 241 publicId = locator.getPublicId(); 242 systemId = locator.getSystemId(); 243 } 244 245 public int getLineNumber() { 246 return lineNumber; 247 } 248 249 public int getColumnNumber() { 250 return columnNumber; 251 } 252 253 public int getCharacterOffset() { 254 return -1; 255 } 256 257 public String getPublicId() { 258 return publicId; 259 } 260 261 public String getSystemId() { 262 return systemId; 263 } 264 } 265 }