From c8ead11dcd815dc26885b2b8e866e4ac4e563ae5 Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Thu, 21 Dec 2017 12:42:03 +0200 Subject: [PATCH] Don't continue parsing XML file if root element is not recognised --- .../org/simantics/xml/sax/base/XMLParser.java | 573 +++++++++--------- 1 file changed, 290 insertions(+), 283 deletions(-) diff --git a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java index 9c04001..9689eda 100644 --- a/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java +++ b/org.simantics.xml.sax.base/src/org/simantics/xml/sax/base/XMLParser.java @@ -1,284 +1,291 @@ -package org.simantics.xml.sax.base; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.Serializable; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.exception.DatabaseException; -import org.simantics.message.ILogger; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -public class XMLParser extends DefaultHandler implements Serializable { - - public static String PLUGIN_ID = "org.simantics.xml.sax.base"; - public static String XML_NAMESPACE_REF = "xmlns"; - - private static final long serialVersionUID = 7360740940824360338L; - private static final boolean debug = false; - - private ILogger logger; - private WriteGraph graph; - private Resource root; - private String schemaURI; - private Deque current = new ArrayDeque(); - private Map parsers = new HashMap(); - private Map, XMLElementParser> namedParsers = new HashMap, XMLElementParser>(); - private Map subParsers = new HashMap(); - - public XMLParser() { - - } - - public WriteGraph getGraph() { - return graph; - } - - public void setGraph(WriteGraph graph) { - this.graph = graph; - for (XMLParser p : subParsers.values()) - p.setGraph(graph); - } - - public String getSchemaURI() { - return schemaURI; - } - - public void setSchemaURI(String schemaURI) { - this.schemaURI = schemaURI; - } - - public void add(XMLElementParser parser) { - if (parser.getElementId() != null) - parsers.put(parser.getElementId(), parser); - namedParsers.put(parser.getClass(), parser); - } - - public void add(XMLParser parser) { - subParsers.put(parser.getSchemaURI(), parser); - } - - private List idReferenceElements = new ArrayList(); - private void loadElement(Deque parents, ParserElement element) throws SAXException{ - XMLElementParser parser = null; - ParserElement parent = null; - if (parents.size() > 0) { - parent = parents.peek(); - // check for assigned subparser - if (parent.getXMLParser() != null && parent.getXMLParser() != this) { - element.setXMLParser(parent.getXMLParser()); - parent.getXMLParser().loadElement(parents, element); - return; - } - if (parent.getElementParser() instanceof XMLElementNamedChildParser) { - // use parent's named child parser if it is supported - Class parserClass = ((XMLElementNamedChildParser)parent.getElementParser()).getParser(parsers,parent,element); - if (parserClass != null) { - parser = namedParsers.get(parserClass); - if (parser == null) { - try { - parser = parserClass.newInstance(); - namedParsers.put(parserClass, parser); - } catch (IllegalAccessException | InstantiationException e) { - String err = "Error processing " + parserClass.getName() + " : element parsers must have accessible default constructor"; - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - throw new SAXException(err, e); - } - } - } -// if (parser == null && ((XMLElementNamedChildParser)parent.getParser()).useGlobalRules()) -// parser = parsers.get(element.qName); - } else { - // otherwise use globally configured element parser - parser = parsers.get(element.qName); - } - } else { - // use globally configured element parser - parser = parsers.get(element.qName); - } - - if (parser != null) { - try { - - element.setData(parser.create(graph, element)); - if (parser instanceof IDReferenceParser) - idReferenceElements.add(element); - element.setElementParser(parser); - } catch (DatabaseException e) { - throw new SAXException(e); - } - } else { - // check for schema reference attempt to locate subparser for it. - Attribute schemaRef = element.getAttribute(XML_NAMESPACE_REF); - if (schemaRef != null && subParsers.containsKey(schemaRef.value)) { - XMLParser subParser = subParsers.get(schemaRef.value); - subParser.loadElement(parents, element); - element.setXMLParser(subParser); - } else { - if (parent == null && parents.size() > 0) - parent = parents.peek(); - String err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - if (debug) System.err.println(err); - } - } - } - - private Map idMap = new HashMap(); - - private void handleElement(Deque parents, ParserElement element) throws SAXException{ - XMLElementParser parser = element.getElementParser(); - if (parser != null) { - try { - parser.configure(graph, parents, element); - if (parents.size() > 0) { - ParserElement parent = parents.peek(); - if (parent.getElementParser() != null) { - if (!parent.getElementParser().connectChild(graph, parent, element)) - if (!parser.connectParent(graph, parent, element)) { - String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - if (debug) System.err.println(err); - } - } else { - String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None") + " was not imported"; - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - if (debug) System.err.println(err); - } - } - String id = parser.getID(); - if (id != null) { - ParserElement existing = idMap.put(id, element); - if (existing != null) { - // report error + use id priorities to select the kept element. - boolean useExt = existing.elementParser.idPriority() > element.elementParser.idPriority(); - if (useExt) - idMap.put(id, existing); - String err = "Duplicate XML element id: " + id + " for " + element.getQName() + " and " + existing.getQName() + ", using " + (useExt ? existing.getQName() : element.getQName()); - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - if (debug) System.err.println(err); - } - } - } catch (DatabaseException e) { - throw new SAXException(e); - } - } else { - ParserElement parent = parents.peek(); - if (parent != null) { - parser = parent.getElementParser(); - if (parser != null && parser instanceof UnrecognizedElementParser) { - try { - ((UnrecognizedElementParser)parser).configureChild(graph, parents, parent, element); - } catch (DatabaseException e) { - throw new SAXException(e); - } - } - } - } - } - - private void handleCharacters(ParserElement element, String string) throws SAXException{ - XMLElementParser parser = element.getElementParser(); - if (parser != null) { - try { - parser.configure(graph, element, string); - } catch (DatabaseException e) { - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage())); - throw new SAXException(e); - } - } - } - - - - public void done() throws SAXException{ - try { - for (ParserElement e : idReferenceElements) { - IDReferenceParser parser = (IDReferenceParser)parsers.get(e.qName); - if (!parser.connectReferences(graph, e, idMap)) { - String err ="Could not resolve ID references for " + e.getQName() + " " + e.getUri(); - logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); - if (debug) System.err.println(err); - } - } - } catch (DatabaseException e) { - throw new SAXException(e); - } - } - - public Resource getRoot() { - return root; - } - - StringBuilder charactersValue; - - @Override - public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { - ParserElement e = new ParserElement(uri,localName,name,attributes); - - loadElement(current,e); - current.push(e); - - charactersValue = new StringBuilder(); - } - - @Override - public void endElement(String uri, String localName, String name) - throws SAXException { - ParserElement e = null; - if (!current.isEmpty()) { - e = current.pop(); - } - if (e != null) { - handleCharacters(e, charactersValue.toString()); - handleElement(current,e); - } - if (current.isEmpty()) { - root = e.getData(); - } - - charactersValue = new StringBuilder(); - } - - @Override - public void characters(char[] ch, int start, int length) - throws SAXException { - charactersValue.append(new String(ch,start,length)); -// if (!current.isEmpty()) { -// String s = new String(ch,start,length); -// Element e = current.peek(); -// handleCharacters(e, s); -// } - - } - - public void parse(File file, ILogger logger) throws Exception { - this.logger = logger; - SAXParserFactory spf = SAXParserFactory.newInstance(); - SAXParser saxParser = spf.newSAXParser(); - - XMLReader reader = saxParser.getXMLReader(); - reader.setContentHandler(this); - reader.parse(new InputSource(new BufferedInputStream(new FileInputStream(file)))); - done(); - } - - +package org.simantics.xml.sax.base; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.Serializable; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; +import org.simantics.message.ILogger; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +public class XMLParser extends DefaultHandler implements Serializable { + + public static String PLUGIN_ID = "org.simantics.xml.sax.base"; + public static String XML_NAMESPACE_REF = "xmlns"; + + private static final long serialVersionUID = 7360740940824360338L; + private static final boolean debug = false; + + private ILogger logger; + private WriteGraph graph; + private Resource root; + private String schemaURI; + private Deque current = new ArrayDeque(); + private Map parsers = new HashMap(); + private Map, XMLElementParser> namedParsers = new HashMap, XMLElementParser>(); + private Map subParsers = new HashMap(); + + public XMLParser() { + + } + + public WriteGraph getGraph() { + return graph; + } + + public void setGraph(WriteGraph graph) { + this.graph = graph; + for (XMLParser p : subParsers.values()) + p.setGraph(graph); + } + + public String getSchemaURI() { + return schemaURI; + } + + public void setSchemaURI(String schemaURI) { + this.schemaURI = schemaURI; + } + + public void add(XMLElementParser parser) { + if (parser.getElementId() != null) + parsers.put(parser.getElementId(), parser); + namedParsers.put(parser.getClass(), parser); + } + + public void add(XMLParser parser) { + subParsers.put(parser.getSchemaURI(), parser); + } + + private List idReferenceElements = new ArrayList(); + private void loadElement(Deque parents, ParserElement element) throws SAXException{ + XMLElementParser parser = null; + ParserElement parent = null; + if (parents.size() > 0) { + parent = parents.peek(); + // check for assigned subparser + if (parent.getXMLParser() != null && parent.getXMLParser() != this) { + element.setXMLParser(parent.getXMLParser()); + parent.getXMLParser().loadElement(parents, element); + return; + } + if (parent.getElementParser() instanceof XMLElementNamedChildParser) { + // use parent's named child parser if it is supported + Class parserClass = ((XMLElementNamedChildParser)parent.getElementParser()).getParser(parsers,parent,element); + if (parserClass != null) { + parser = namedParsers.get(parserClass); + if (parser == null) { + try { + parser = parserClass.newInstance(); + namedParsers.put(parserClass, parser); + } catch (IllegalAccessException | InstantiationException e) { + String err = "Error processing " + parserClass.getName() + " : element parsers must have accessible default constructor"; + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + throw new SAXException(err, e); + } + } + } +// if (parser == null && ((XMLElementNamedChildParser)parent.getParser()).useGlobalRules()) +// parser = parsers.get(element.qName); + } else { + // otherwise use globally configured element parser + parser = parsers.get(element.qName); + } + } else { + // use globally configured element parser + parser = parsers.get(element.qName); + } + + if (parser != null) { + try { + + element.setData(parser.create(graph, element)); + if (parser instanceof IDReferenceParser) + idReferenceElements.add(element); + element.setElementParser(parser); + } catch (DatabaseException e) { + throw new SAXException(e); + } + } else { + // check for schema reference attempt to locate subparser for it. + Attribute schemaRef = element.getAttribute(XML_NAMESPACE_REF); + if (schemaRef != null && subParsers.containsKey(schemaRef.value)) { + XMLParser subParser = subParsers.get(schemaRef.value); + subParser.loadElement(parents, element); + element.setXMLParser(subParser); + } else { + if (parent == null && parents.size() > 0) + parent = parents.peek(); + String err = null; + if (parent != null) + err = "Unknown element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); + else { + err = "Unknown root element " + element.qName + ", cannot import the file"; + throw new SAXException(err); + } + + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + if (debug) System.err.println(err); + } + } + } + + private Map idMap = new HashMap(); + + private void handleElement(Deque parents, ParserElement element) throws SAXException{ + XMLElementParser parser = element.getElementParser(); + if (parser != null) { + try { + parser.configure(graph, parents, element); + if (parents.size() > 0) { + ParserElement parent = parents.peek(); + if (parent.getElementParser() != null) { + if (!parent.getElementParser().connectChild(graph, parent, element)) + if (!parser.connectParent(graph, parent, element)) { + String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None"); + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + if (debug) System.err.println(err); + } + } else { + String err = "Did not connect element " + element.qName + ", parent " + (parent != null ? parent.getQName() : "None") + " was not imported"; + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + if (debug) System.err.println(err); + } + } + String id = parser.getID(); + if (id != null) { + ParserElement existing = idMap.put(id, element); + if (existing != null) { + // report error + use id priorities to select the kept element. + boolean useExt = existing.elementParser.idPriority() > element.elementParser.idPriority(); + if (useExt) + idMap.put(id, existing); + String err = "Duplicate XML element id: " + id + " for " + element.getQName() + " and " + existing.getQName() + ", using " + (useExt ? existing.getQName() : element.getQName()); + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + if (debug) System.err.println(err); + } + } + } catch (DatabaseException e) { + throw new SAXException(e); + } + } else { + ParserElement parent = parents.peek(); + if (parent != null) { + parser = parent.getElementParser(); + if (parser != null && parser instanceof UnrecognizedElementParser) { + try { + ((UnrecognizedElementParser)parser).configureChild(graph, parents, parent, element); + } catch (DatabaseException e) { + throw new SAXException(e); + } + } + } + } + } + + private void handleCharacters(ParserElement element, String string) throws SAXException{ + XMLElementParser parser = element.getElementParser(); + if (parser != null) { + try { + parser.configure(graph, element, string); + } catch (DatabaseException e) { + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage())); + throw new SAXException(e); + } + } + } + + + + public void done() throws SAXException{ + try { + for (ParserElement e : idReferenceElements) { + IDReferenceParser parser = (IDReferenceParser)parsers.get(e.qName); + if (!parser.connectReferences(graph, e, idMap)) { + String err ="Could not resolve ID references for " + e.getQName() + " " + e.getUri(); + logger.log(new Status(IStatus.ERROR, PLUGIN_ID, err)); + if (debug) System.err.println(err); + } + } + } catch (DatabaseException e) { + throw new SAXException(e); + } + } + + public Resource getRoot() { + return root; + } + + StringBuilder charactersValue; + + @Override + public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { + ParserElement e = new ParserElement(uri,localName,name,attributes); + + loadElement(current,e); + current.push(e); + + charactersValue = new StringBuilder(); + } + + @Override + public void endElement(String uri, String localName, String name) + throws SAXException { + ParserElement e = null; + if (!current.isEmpty()) { + e = current.pop(); + } + if (e != null) { + handleCharacters(e, charactersValue.toString()); + handleElement(current,e); + } + if (current.isEmpty()) { + root = e.getData(); + } + + charactersValue = new StringBuilder(); + } + + @Override + public void characters(char[] ch, int start, int length) + throws SAXException { + charactersValue.append(new String(ch,start,length)); +// if (!current.isEmpty()) { +// String s = new String(ch,start,length); +// Element e = current.peek(); +// handleCharacters(e, s); +// } + + } + + public void parse(File file, ILogger logger) throws Exception { + this.logger = logger; + SAXParserFactory spf = SAXParserFactory.newInstance(); + SAXParser saxParser = spf.newSAXParser(); + + XMLReader reader = saxParser.getXMLReader(); + reader.setContentHandler(this); + reader.parse(new InputSource(new BufferedInputStream(new FileInputStream(file)))); + done(); + } + + } \ No newline at end of file -- 2.43.2