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 
SAX2StAXBaseWriter()57     public SAX2StAXBaseWriter() {
58     }
59 
SAX2StAXBaseWriter(XMLReporter reporter)60     public SAX2StAXBaseWriter(XMLReporter reporter) {
61         this.reporter = reporter;
62     }
63 
setXMLReporter(XMLReporter reporter)64     public void setXMLReporter(XMLReporter reporter) {
65         this.reporter = reporter;
66     }
67 
setDocumentLocator(Locator locator)68     public void setDocumentLocator(Locator locator) {
69         this.docLocator = locator;
70     }
71 
updateVersionAndEncoding()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 
setXmlVersion(String version)80     public void setXmlVersion(String version) {
81         this.xmlVersion = version;
82     }
83 
setEncoding(String encoding)84     public void setEncoding(String encoding) {
85         this.encoding = encoding;
86     }
87 
writeStartDocument()88     void writeStartDocument() throws SAXException {
89         updateVersionAndEncoding();
90     }
91 
getCurrentLocation()92     public Location getCurrentLocation() {
93         if (docLocator != null) {
94             return new SAXLocation(docLocator);
95         } else {
96             return null;
97         }
98     }
99 
error(SAXParseException e)100     public void error(SAXParseException e) throws SAXException {
101         reportException("ERROR", e);
102     }
103 
fatalError(SAXParseException e)104     public void fatalError(SAXParseException e) throws SAXException {
105         reportException("FATAL", e);
106     }
107 
warning(SAXParseException e)108     public void warning(SAXParseException e) throws SAXException {
109         reportException("WARNING", e);
110     }
111 
startDocument()112     public void startDocument() throws SAXException {
113         namespaces = new ArrayList<>(2);
114     }
115 
endDocument()116     public void endDocument() throws SAXException {
117         namespaces = null;
118     }
119 
startElement(String uri, String localName, String qName, Attributes attributes)120     public void startElement(String uri, String localName, String qName,
121             Attributes attributes) throws SAXException {
122         namespaces = null;
123     }
124 
endElement(String uri, String localName, String qName)125     public void endElement(String uri, String localName, String qName)
126             throws SAXException {
127         namespaces = null;
128     }
129 
startPrefixMapping(String prefix, String uri)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 
endPrefixMapping(String prefix)146     public void endPrefixMapping(String prefix) throws SAXException {
147     }
148 
startCDATA()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 
characters(char[] ch, int start, int length)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 
endCDATA()165     public void endCDATA() throws SAXException {
166         isCDATA = false;
167         CDATABuffer.setLength(0);
168     }
169 
comment(char[] ch, int start, int length)170     public void comment(char[] ch, int start, int length) throws SAXException {
171     }
172 
endDTD()173     public void endDTD() throws SAXException {
174     }
175 
endEntity(String name)176     public void endEntity(String name) throws SAXException {
177     }
178 
startDTD(String name, String publicId, String systemId)179     public void startDTD(String name, String publicId, String systemId)
180             throws SAXException {
181     }
182 
startEntity(String name)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      */
reportException(String type, SAXException e)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      */
parseQName(String qName, String[] results)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;
SAXLocation(Locator locator)238         private SAXLocation(Locator locator) {
239             lineNumber = locator.getLineNumber();
240             columnNumber = locator.getColumnNumber();
241             publicId = locator.getPublicId();
242             systemId = locator.getSystemId();
243         }
244 
getLineNumber()245         public int getLineNumber() {
246             return lineNumber;
247         }
248 
getColumnNumber()249         public int getColumnNumber() {
250             return columnNumber;
251         }
252 
getCharacterOffset()253         public int getCharacterOffset() {
254             return -1;
255         }
256 
getPublicId()257         public String getPublicId() {
258             return publicId;
259         }
260 
getSystemId()261         public String getSystemId() {
262             return systemId;
263         }
264     }
265 }
266