提交 4ff5f207 编写于 作者: S Serge Rider

XML utils code cleanup. SAX parser fix (custom handlers).

上级 ceb541d9
......@@ -24,19 +24,19 @@ import org.xml.sax.Attributes;
*/
public interface SAXListener {
public void saxStartElement(
void saxStartElement(
SAXReader reader,
String namespaceURI,
String localName,
org.xml.sax.Attributes atts)
throws XMLException;
public void saxText(
void saxText(
SAXReader reader,
String data)
throws XMLException;
public void saxEndElement(
void saxEndElement(
SAXReader reader,
String namespaceURI,
String localName)
......@@ -46,7 +46,7 @@ public interface SAXListener {
/**
* Empty listener supposed to skip element subtrees
*/
public static class EmptyListener implements SAXListener {
class BaseListener implements SAXListener {
@Override
public void saxStartElement(SAXReader reader, String namespaceURI, String localName, Attributes atts) throws XMLException {
......@@ -60,6 +60,6 @@ public interface SAXListener {
public void saxEndElement(SAXReader reader, String namespaceURI, String localName) throws XMLException {
}
}
public static final SAXListener EMPTY_LISTENER = new EmptyListener();
SAXListener EMPTY_LISTENER = new BaseListener();
}
......@@ -16,6 +16,11 @@
*/
package org.jkiss.utils.xml;
import org.xml.sax.*;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
......@@ -24,7 +29,7 @@ import java.util.Map;
/**
* SAX document reader
*/
public final class SAXReader implements org.xml.sax.ContentHandler {
public final class SAXReader implements ContentHandler, EntityResolver, DTDHandler {
public static final int DEFAULT_POOL_SIZE = 10;
......@@ -32,7 +37,7 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
private static List<Parser> parsersPool = new ArrayList<>();
private org.xml.sax.InputSource inputSource;
private org.xml.sax.Locator locator;
private Locator locator;
private Map<String, Object> attributes = new HashMap<>();
private List<SAXListener> elementLayers = new ArrayList<>();
......@@ -52,8 +57,7 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
* Standard constructor.
* Initialize parser and prepare input stream for reading.
*/
public SAXReader(
java.io.InputStream stream) {
public SAXReader(InputStream stream) {
this();
inputSource = new org.xml.sax.InputSource(stream);
}
......@@ -62,8 +66,7 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
* Standard constructor.
* Initialize parser and prepare input stream for reading.
*/
public SAXReader(
java.io.Reader reader) {
public SAXReader(Reader reader) {
this();
inputSource = new org.xml.sax.InputSource(reader);
}
......@@ -77,35 +80,36 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
handleWhiteSpaces = flag;
}
public org.xml.sax.Locator getLocator() {
public Locator getLocator() {
return locator;
}
/**
* Parse input stream and handle XML tags.
*/
public void parse(
SAXListener listener)
throws java.io.IOException, XMLException {
public void parse(SAXListener listener)
throws IOException, XMLException {
// Initialize SAX parser
Parser parser = acquireParser();
// Get reader and parse using SAX2 API
try {
org.xml.sax.XMLReader saxReader = parser.getSAXParser().getXMLReader();
XMLReader saxReader = parser.getSAXParser().getXMLReader();
saxReader.setErrorHandler(new ParseErrorHandler());
saxReader.setContentHandler(this);
saxReader.setEntityResolver(this);
saxReader.setDTDHandler(this);
curListener = listener;
elementLayers.add(listener);
saxReader.parse(inputSource);
} catch (org.xml.sax.SAXParseException toCatch) {
} catch (SAXParseException toCatch) {
throw new XMLException(
"Document parse error (line " + toCatch.getLineNumber() + ", pos " + toCatch.getColumnNumber(),
toCatch);
} catch (org.xml.sax.SAXException toCatch) {
} catch (SAXException toCatch) {
throw new XMLException(
"Document reading SAX exception",
XMLUtils.adaptSAXException(toCatch));
......@@ -114,15 +118,14 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
}
}
public synchronized static Parser acquireParser()
throws XMLException {
public synchronized static Parser acquireParser() throws XMLException {
try {
if (saxParserFactory == null) {
try {
saxParserFactory = javax.xml.parsers.SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true);
saxParserFactory.setValidating(false);
} catch (javax.xml.parsers.FactoryConfigurationError toCatch) {
} catch (FactoryConfigurationError toCatch) {
throw new XMLException(
"SAX factory configuration error",
toCatch);
......@@ -150,11 +153,11 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
Parser parser = new Parser(saxParserFactory.newSAXParser(), true);
parsersPool.add(parser);
return parser;
} catch (javax.xml.parsers.ParserConfigurationException toCatch) {
} catch (ParserConfigurationException toCatch) {
throw new XMLException(
"SAX Parser Configuration error",
toCatch);
} catch (org.xml.sax.SAXException toCatch) {
} catch (SAXException toCatch) {
throw new XMLException(
"SAX Parser error",
toCatch);
......@@ -203,14 +206,14 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
}
private void handleText()
throws org.xml.sax.SAXException {
throws SAXException {
curListener = elementLayers.get(elementLayers.size() - 1);
try {
String value = textValue.toString();
curListener.saxText(this, value);
} catch (Exception toCatch) {
throw new org.xml.sax.SAXException(toCatch);
throw new SAXException(toCatch);
} finally {
textValue.setLength(0);
}
......@@ -236,7 +239,7 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
String localName,
String qName,
org.xml.sax.Attributes attributes)
throws org.xml.sax.SAXException {
throws SAXException {
if (depth++ > 0) {
this.handleText();
}
......@@ -246,7 +249,7 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
try {
curListener.saxStartElement(this, namespaceURI, localName, attributes);
} catch (XMLException toCatch) {
throw new org.xml.sax.SAXException(toCatch);
throw new SAXException(toCatch);
}
elementLayers.add(curListener);
......@@ -257,7 +260,7 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
String namespaceURI,
String localName,
String qName)
throws org.xml.sax.SAXException {
throws SAXException {
this.handleText();
elementLayers.remove(elementLayers.size() - 1);
......@@ -266,61 +269,64 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
try {
curListener.saxEndElement(this, namespaceURI, localName);
} catch (XMLException toCatch) {
throw new org.xml.sax.SAXException(toCatch);
throw new SAXException(toCatch);
}
depth--;
}
@Override
public void startPrefixMapping(
String prefix,
String uri) {
public void startPrefixMapping(String prefix, String uri) {
// just do-nothing
}
@Override
public void endPrefixMapping(
String prefix) {
public void endPrefixMapping(String prefix) {
// just do-nothing
}
@Override
public void characters(
char[] ch,
int start,
int length) {
public void characters(char[] ch, int start, int length) {
textValue.append(ch, start, length);
}
@Override
public void ignorableWhitespace(
char[] ch,
int start,
int length) {
public void ignorableWhitespace(char[] ch, int start, int length) {
if (handleWhiteSpaces) {
textValue.append(ch, start, length);
}
}
@Override
public void processingInstruction(
String target,
String data) {
public void processingInstruction(String target, String data) {
// just do-nothing
}
@Override
public void setDocumentLocator(
org.xml.sax.Locator locator) {
public void setDocumentLocator(Locator locator) {
this.locator = locator;
}
@Override
public void skippedEntity(
String name) {
public void skippedEntity(String name) {
// just do-nothing
}
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
// Return empty stream - we don't need entities by default
return new InputSource(new StringReader(""));
}
@Override
public void notationDecl(String name, String publicId, String systemId) throws SAXException {
// do nothing
}
@Override
public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
// do nothing
}
static public class Parser {
private javax.xml.parsers.SAXParser saxParser;
private boolean isAcquired;
......@@ -354,17 +360,17 @@ public final class SAXReader implements org.xml.sax.ContentHandler {
static class ParseErrorHandler implements org.xml.sax.ErrorHandler {
@Override
public void error(org.xml.sax.SAXParseException exception) {
public void error(SAXParseException exception) {
}
@Override
public void fatalError(org.xml.sax.SAXParseException exception) {
public void fatalError(SAXParseException exception) {
}
@Override
public void warning(org.xml.sax.SAXParseException exception) {
public void warning(SAXParseException exception) {
}
......
......@@ -19,11 +19,15 @@ package org.jkiss.utils.xml;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
......@@ -31,278 +35,251 @@ import java.util.List;
/**
* Common XML utils
*/
public class XMLUtils
{
public class XMLUtils {
public static org.w3c.dom.Document parseDocument(String fileName)
throws XMLException
{
return parseDocument(new java.io.File(fileName));
}
public static Document parseDocument(String fileName)
throws XMLException {
return parseDocument(new java.io.File(fileName));
}
public static org.w3c.dom.Document parseDocument(java.io.File file)
throws XMLException
{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
return xmlBuilder.parse(file);
} catch (Exception er) {
throw new XMLException("Error parsing XML document", er);
}
}
public static Document parseDocument(java.io.File file) throws XMLException {
try (InputStream is = new FileInputStream(file)) {
return parseDocument(new InputSource(is));
} catch (IOException e) {
throw new XMLException("Error opening file '" + file + "'", e);
}
}
public static org.w3c.dom.Document parseDocument(java.io.InputStream is)
throws XMLException
{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
return xmlBuilder.parse(is);
} catch (Exception er) {
throw new XMLException("Error parsing XML document", er);
}
}
public static Document parseDocument(java.io.InputStream is) throws XMLException {
return parseDocument(new InputSource(is));
}
public static org.w3c.dom.Document parseDocument(java.io.Reader is)
throws XMLException
{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
return xmlBuilder.parse(new InputSource(is));
} catch (Exception er) {
throw new XMLException("Error parsing XML document", er);
}
}
public static Document parseDocument(java.io.Reader is) throws XMLException {
return parseDocument(new InputSource(is));
}
public static org.w3c.dom.Document createDocument()
throws XMLException
{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
return xmlBuilder.newDocument();
} catch (Exception er) {
throw new XMLException("Error creating XML document", er);
}
}
public static Document parseDocument(InputSource source) throws XMLException {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
return xmlBuilder.parse(source);
} catch (Exception er) {
throw new XMLException("Error parsing XML document", er);
}
}
public static Element getChildElement(Element element,
String childName)
{
for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
((Element) node).getTagName().equals(childName)) {
return (Element) node;
}
}
return null;
}
public static Document createDocument()
throws XMLException {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
return xmlBuilder.newDocument();
} catch (Exception er) {
throw new XMLException("Error creating XML document", er);
}
}
public static Element getChildElement(Element element,
String childName) {
for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
((Element) node).getTagName().equals(childName)) {
return (Element) node;
}
}
return null;
}
@Nullable
public static String getChildElementBody(Element element,
String childName)
{
for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
((Element) node).getTagName().equals(childName)) {
return getElementBody((Element) node);
}
}
return null;
}
@Nullable
public static String getChildElementBody(Element element,
String childName) {
for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
((Element) node).getTagName().equals(childName)) {
return getElementBody((Element) node);
}
}
return null;
}
@Nullable
public static String getElementBody(Element element)
{
org.w3c.dom.Node valueNode = element.getFirstChild();
if (valueNode == null) {
return null;
}
if (valueNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
return valueNode.getNodeValue();
} else {
return null;
}
}
@Nullable
public static String getElementBody(Element element) {
org.w3c.dom.Node valueNode = element.getFirstChild();
if (valueNode == null) {
return null;
}
if (valueNode.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
return valueNode.getNodeValue();
} else {
return null;
}
}
// Get list of all child elements of specified node
@NotNull
public static List<Element> getChildElementList(
// Get list of all child elements of specified node
@NotNull
public static List<Element> getChildElementList(
Element parent,
String nodeName)
{
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
nodeName.equals(node.getNodeName()))
{
list.add((Element) node);
}
}
return list;
}
String nodeName) {
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
nodeName.equals(node.getNodeName())) {
list.add((Element) node);
}
}
return list;
}
// Get list of all child elements of specified node
@NotNull
public static Collection<Element> getChildElementListNS(
Element parent,
String nsURI)
{
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
node.getNamespaceURI().equals( nsURI ))
{
list.add((Element) node);
}
}
return list;
}
// Get list of all child elements of specified node
@NotNull
public static Collection<Element> getChildElementListNS(
Element parent,
String nsURI) {
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
node.getNamespaceURI().equals(nsURI)) {
list.add((Element) node);
}
}
return list;
}
// Get list of all child elements of specified node
public static Collection<Element> getChildElementListNS(
Element parent,
String nodeName,
String nsURI)
{
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
node.getLocalName().equals( nodeName ) &&
node.getNamespaceURI().equals( nsURI ))
{
list.add((Element) node);
}
}
return list;
}
// Get list of all child elements of specified node
public static Collection<Element> getChildElementListNS(
Element parent,
String nodeName,
String nsURI) {
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE &&
node.getLocalName().equals(nodeName) &&
node.getNamespaceURI().equals(nsURI)) {
list.add((Element) node);
}
}
return list;
}
// Get list of all child elements of specified node
@NotNull
public static Collection<Element> getChildElementList(
Element parent,
String[] nodeNameList)
{
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
for (int i = 0; i < nodeNameList.length; i++) {
if (node.getNodeName().equals( nodeNameList[i] )) {
list.add((Element) node);
}
}
}
}
return list;
}
// Get list of all child elements of specified node
@NotNull
public static Collection<Element> getChildElementList(
Element parent,
String[] nodeNameList) {
List<Element> list = new ArrayList<>();
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
for (int i = 0; i < nodeNameList.length; i++) {
if (node.getNodeName().equals(nodeNameList[i])) {
list.add((Element) node);
}
}
}
}
return list;
}
// Find one child element with specified name
@Nullable
public static Element findChildElement(
Element parent)
{
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
{
return (Element)node;
}
}
return null;
}
// Find one child element with specified name
@Nullable
public static Element findChildElement(
Element parent) {
for (org.w3c.dom.Node node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
return (Element) node;
}
}
return null;
}
public static Object escapeXml(Object obj) {
if (obj == null) {
return null;
} else if (obj instanceof CharSequence) {
return escapeXml((CharSequence)obj);
} else {
return obj;
}
}
public static Object escapeXml(Object obj) {
if (obj == null) {
return null;
} else if (obj instanceof CharSequence) {
return escapeXml((CharSequence) obj);
} else {
return obj;
}
}
public static String escapeXml(CharSequence str) {
if (str == null) {
return null;
}
StringBuilder res = null;
int strLength = str.length();
for (int i = 0; i < strLength; i++) {
char c = str.charAt(i);
String repl = encodeXMLChar(c);
if (repl == null) {
if (res != null) {
res.append(c);
}
} else {
if (res == null) {
res = new StringBuilder(str.length() + 5);
for (int k = 0; k < i; k++) {
res.append(str.charAt(k));
}
}
res.append(repl);
}
}
return res == null ? str.toString() : res.toString();
}
public static String escapeXml(CharSequence str) {
if (str == null) {
return null;
}
StringBuilder res = null;
int strLength = str.length();
for (int i = 0; i < strLength; i++) {
char c = str.charAt(i);
String repl = encodeXMLChar(c);
if (repl == null) {
if (res != null) {
res.append(c);
}
} else {
if (res == null) {
res = new StringBuilder(str.length() + 5);
for (int k = 0; k < i; k++) {
res.append(str.charAt(k));
}
}
res.append(repl);
}
}
return res == null ? str.toString() : res.toString();
}
public static boolean isValidXMLChar(char c)
{
return (c >= 32 || c == '\n' || c == '\r' || c == '\t');
}
public static boolean isValidXMLChar(char c) {
return (c >= 32 || c == '\n' || c == '\r' || c == '\t');
}
/**
* Encodes a char to XML-valid form replacing &,',",<,> with special XML encoding.
*
* @param ch char to convert
* @return XML-encoded text
*/
public static String encodeXMLChar(char ch) {
switch (ch) {
case '&':
return "&amp;";
case '\"':
return "&quot;";
case '\'':
return "&#39;";
case '<':
return "&lt;";
case '>':
return "&gt;";
default:
return null;
}
}
/**
* Encodes a char to XML-valid form replacing &,',",<,> with special XML encoding.
*
* @param ch char to convert
* @return XML-encoded text
*/
public static String encodeXMLChar(char ch) {
switch (ch) {
case '&':
return "&amp;";
case '\"':
return "&quot;";
case '\'':
return "&#39;";
case '<':
return "&lt;";
case '>':
return "&gt;";
default:
return null;
}
}
public static XMLException adaptSAXException(Exception toCatch)
{
public static XMLException adaptSAXException(Exception toCatch) {
if (toCatch instanceof XMLException) {
return (XMLException)toCatch;
return (XMLException) toCatch;
} else if (toCatch instanceof org.xml.sax.SAXException) {
String message = toCatch.getMessage();
Exception embedded = ((org.xml.sax.SAXException)toCatch).getException();
Exception embedded = ((org.xml.sax.SAXException) toCatch).getException();
if (embedded != null && embedded.getMessage() != null && embedded.getMessage().equals(message)) {
// Just SAX wrapper - skip it
return adaptSAXException(embedded);
} else {
return new XMLException(
message,
embedded != null ? adaptSAXException(embedded) : null);
message,
embedded != null ? adaptSAXException(embedded) : null);
}
} else {
return new XMLException(toCatch.getMessage(), toCatch);
}
}
public static Collection<Element> getChildElementList(Element element) {
List<Element> children = new ArrayList<>();
for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
children.add((Element)node);
}
}
return children;
}
public static Collection<Element> getChildElementList(Element element) {
List<Element> children = new ArrayList<>();
for (org.w3c.dom.Node node = element.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
children.add((Element) node);
}
}
return children;
}
}
......@@ -213,7 +213,7 @@ public class DataFormatterRegistry
}
}
private class FormattersParser implements SAXListener
private class FormattersParser extends SAXListener.BaseListener
{
private String profileName;
private SimplePreferenceStore curStore;
......@@ -234,12 +234,6 @@ public class DataFormatterRegistry
}
}
@Override
public void saxText(SAXReader reader, String data)
throws XMLException
{
}
@Override
public void saxEndElement(SAXReader reader, String namespaceURI, String localName)
throws XMLException
......
......@@ -159,7 +159,7 @@ class ViewerColumnRegistry {
}
private class ColumnsParser implements SAXListener {
private class ColumnsParser extends SAXListener.BaseListener {
private List<ColumnState> curColumnState = null;
......@@ -188,12 +188,5 @@ class ViewerColumnRegistry {
}
}
@Override
public void saxText(SAXReader reader, String data) throws XMLException {
}
@Override
public void saxEndElement(SAXReader reader, String namespaceURI, String localName) throws XMLException {
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册