package org.caudexorigo.xom;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import nu.xom.XMLException;
import org.apache.commons.lang3.StringUtils;
import org.caudexorigo.jpt.JptConfiguration;
import org.caudexorigo.jpt.JptNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public final class XomDocumentBuilder
{
private static final Logger log = LoggerFactory.getLogger(XomDocumentBuilder.class);
// These are stored in the order of preference.
private static String[] parsers = { "org.apache.xerces.parsers.SAXParser", "com.sun.org.apache.xerces.internal.parsers.SAXParser", "gnu.xml.aelfred2.XmlReader", "org.apache.crimson.parser.XMLReaderImpl", "com.bluecast.xml.Piccolo", "oracle.xml.parser.v2.SAXParser", "com.jclark.xml.sax.SAX2Driver", "net.sf.saxon.aelfred.SAXDriver", "com.icl.saxon.aelfred.SAXDriver", "org.dom4j.io.aelfred2.SAXDriver", "org.dom4j.io.aelfred.SAXDriver" };
private static final XMLReader reader;
static
{
if (StringUtils.isBlank(JptConfiguration.xmlReaderClass()))
{
reader = findParser();
}
else
{
reader = createParser(JptConfiguration.xmlReaderClass());
}
if (reader == null)
{
throw new RuntimeException("Unable to create XMLReader");
}
else
{
reader.setEntityResolver(new XhtmlEntityResolver());
}
}
static XMLReader createParser(String parserClass)
{
XMLReader parser;
try
{
parser = XMLReaderFactory.createXMLReader(parserClass);
return parser;
}
catch (Exception ex)
{
throw new XMLException(parserClass + " not found or not a a suitable SAX2 parser", ex);
}
}
static XMLReader findParser()
{
// first look for Xerces; we only trust Xerces if
// we set it up; and we need to configure it specially
// so we can't load it with the XMLReaderFactory
XMLReader parser;
// XMLReaderFactory.createXMLReader never returns
// null. If it can't locate the parser, it throws
// a SAXException.
for (int i = 0; i < parsers.length; i++)
{
try
{
parser = XMLReaderFactory.createXMLReader(parsers[i]);
try
{
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", true);
parser.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
parser.setFeature("http://xml.org/sax/features/external-general-entities", false);
parser.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
}
catch (Exception e)
{
// ignore, we can live without this.
}
return parser;
}
catch (SAXException ex)
{
// try the next one
}
catch (NoClassDefFoundError err)
{
// try the next one
}
}
try
{ // default
parser = XMLReaderFactory.createXMLReader();
return parser;
}
catch (SAXException ex)
{
throw new XMLException("Could not find a suitable SAX2 parser", ex);
}
}
public static Document getDocument(InputStream in) throws ValidityException, ParsingException, IOException
{
synchronized (reader)
{
if (reader == null)
{
XMLReader singularity_reader = findParser();
Builder builder = new Builder(singularity_reader, false);
return builder.build(in);
}
Builder builder = new Builder(reader, false);
return builder.build(in);
}
}
public static Document getDocument(URI templateUri) throws ValidityException, ParsingException, IOException
{
if (log.isDebugEnabled())
{
log.debug("building document: {}", templateUri.toString());
}
// File ftemplate = new File(JptUtil.resolvePath(templatePath));
File ftemplate = new File(templateUri);
FileInputStream fis;
try
{
fis = new FileInputStream(ftemplate);
}
catch (FileNotFoundException e)
{
throw new JptNotFoundException(e);
}
synchronized (reader)
{
Builder builder = new Builder(reader, false);
return builder.build(fis);
}
}
private XomDocumentBuilder()
{
}
}