# HG changeset patch
# User František Kučera <franta-hg@frantovo.cz>
# Date 1402175879 -7200
# Node ID 5af9c7693d709889e6e986349f1b7d25fd9bb091
# Parent  e853e5b5bfdfeb3d420b071c089f548aaa6b045d
Fallback SAXParserFactory
→ we can parse also pure/standard XML files
→ seamless integration of multiple formats

diff -r e853e5b5bfdf -r 5af9c7693d70 java/alt2xml-cli/nbproject/project.properties
--- a/java/alt2xml-cli/nbproject/project.properties	Sat Jun 07 22:12:11 2014 +0200
+++ b/java/alt2xml-cli/nbproject/project.properties	Sat Jun 07 23:17:59 2014 +0200
@@ -64,10 +64,6 @@
 run.classpath=\
     ${javac.classpath}:\
     ${build.classes.dir}
-# Space-separated list of JVM arguments used when running the project
-# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
-# or test-sys-prop.name=value to set system properties for unit tests):
-run.jvmargs=
 run.test.classpath=\
     ${javac.test.classpath}:\
     ${build.test.classes.dir}
diff -r e853e5b5bfdf -r 5af9c7693d70 java/alt2xml-lib-input/dist/alt2xml-lib-input.jar
Binary file java/alt2xml-lib-input/dist/alt2xml-lib-input.jar has changed
diff -r e853e5b5bfdf -r 5af9c7693d70 java/alt2xml-lib-input/src/cz/frantovo/alt2xml/Alt2XmlReaderFactory.java
--- a/java/alt2xml-lib-input/src/cz/frantovo/alt2xml/Alt2XmlReaderFactory.java	Sat Jun 07 22:12:11 2014 +0200
+++ b/java/alt2xml-lib-input/src/cz/frantovo/alt2xml/Alt2XmlReaderFactory.java	Sat Jun 07 23:17:59 2014 +0200
@@ -17,6 +17,7 @@
  */
 package cz.frantovo.alt2xml;
 
+import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
 
 /**
@@ -31,5 +32,5 @@
 	 */
 	public boolean canRead(String systemId);
 
-	public XMLReader getReader();
+	public XMLReader getReader() throws SAXException;
 }
diff -r e853e5b5bfdf -r 5af9c7693d70 java/alt2xml-lib-input/src/cz/frantovo/alt2xml/ParserFactory.java
--- a/java/alt2xml-lib-input/src/cz/frantovo/alt2xml/ParserFactory.java	Sat Jun 07 22:12:11 2014 +0200
+++ b/java/alt2xml-lib-input/src/cz/frantovo/alt2xml/ParserFactory.java	Sat Jun 07 23:17:59 2014 +0200
@@ -20,6 +20,7 @@
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.ServiceLoader;
+import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -36,6 +37,16 @@
 public class ParserFactory extends SAXParserFactory implements ReaderFinder {
 
 	private final Deque<Alt2XmlReaderFactory> readerFactories = new LinkedList();
+	/**
+	 * @see #DEFAULT_FACTORY_PROPERTY
+	 */
+	private SAXParserFactory fallbackFactory;
+
+	/**
+	 * System property which contains SAXParserFactory class name for XML.
+	 * Will be used as fallback if no alternative factory matches systemId to be parsed.
+	 */
+	public static final String DEFAULT_FACTORY_PROPERTY = "cz.frantovo.alt2xml.fallback.javax.xml.parsers.SAXParserFactory";
 
 	public ParserFactory() {
 		super();
@@ -43,6 +54,51 @@
 			readerFactories.add(f);
 		}
 
+		readerFactories.add(new FallbackReaderFactory());
+	}
+
+	/**
+	 * @return factory to be used for XML documents (default/fallback)
+	 * @throws FactoryConfigurationError if fallback factory is the same one as this – avoid
+	 * infinite recursion.
+	 */
+	public SAXParserFactory getFallbackFactory() {
+		if (fallbackFactory == null) {
+			String className = System.getProperty(DEFAULT_FACTORY_PROPERTY);
+			if (className == null) {
+				fallbackFactory = SAXParserFactory.newInstance();
+			} else {
+				fallbackFactory = SAXParserFactory.newInstance(className, null);
+			}
+		}
+
+		if (fallbackFactory.getClass().equals(getClass())) {
+			throw new FactoryConfigurationError("Fallback factory is the same class as this one – avoid infinite recursion: " + getClass());
+		} else {
+			return fallbackFactory;
+		}
+	}
+
+	public void setFallbackFactory(SAXParserFactory fallbackFactory) {
+		this.fallbackFactory = fallbackFactory;
+	}
+
+	private class FallbackReaderFactory implements Alt2XmlReaderFactory {
+
+		@Override
+		public boolean canRead(String systemId) {
+			return true;
+		}
+
+		@Override
+		public XMLReader getReader() throws SAXException {
+
+			try {
+				return getFallbackFactory().newSAXParser().getXMLReader();
+			} catch (ParserConfigurationException e) {
+				throw new SAXException("Unable to instantiate the fallback factory.", e);
+			}
+		}
 	}
 
 	@Override
@@ -60,6 +116,9 @@
 		return new AltSAXParser(new SuperReader(this));
 	}
 
+	/**
+	 * TODO: feature for disabling default SAXParserFactory
+	 */
 	@Override
 	public void setFeature(String name, boolean value) throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException {
 		throw new SAXNotSupportedException("Zatím není podporováno.");
diff -r e853e5b5bfdf -r 5af9c7693d70 scripts/alt2xml.sh
--- a/scripts/alt2xml.sh	Sat Jun 07 22:12:11 2014 +0200
+++ b/scripts/alt2xml.sh	Sat Jun 07 23:17:59 2014 +0200
@@ -19,7 +19,14 @@
 done
 
 MAIN_CLASS="cz.frantovo.alt2xml.cli.CLI";
-SAX_PARSER_FACTORY="cz.frantovo.alt2xml.ParserFactory";
 
-java -cp "$CLASS_PATH" -D"javax.xml.parsers.SAXParserFactory=$SAX_PARSER_FACTORY" $MAIN_CLASS "$@"
+SAX_PARSER_FACTORY_ALT="cz.frantovo.alt2xml.ParserFactory";                             # our alternative ParserFactory as default
+SAX_PARSER_FACTORY_XML="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl";  # former default factory as fallback 
 
+java \
+	-cp "$CLASS_PATH" \
+	-D"javax.xml.parsers.SAXParserFactory=$SAX_PARSER_FACTORY_ALT" \
+	-D"cz.frantovo.alt2xml.fallback.javax.xml.parsers.SAXParserFactory=$SAX_PARSER_FACTORY_XML" \
+	$MAIN_CLASS \
+	"$@"
+