package gnu.xml.dom.ls;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Document;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMStringList;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSException;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSParserFilter;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import gnu.xml.dom.DomDocument;
import gnu.xml.dom.DomDOMException;
public class DomLSParser
implements LSParser, DOMConfiguration, DOMStringList, ErrorHandler
{
private static final List SUPPORTED_PARAMETERS
= Arrays.asList(new String[] { "cdata-sections",
"comments",
"element-content-whitespace",
"namespaces",
"expand-entity-references",
"coalescing",
"validating",
"xinclude-aware",
"entity-resolver",
"error-handler" });
private LSParserFilter filter;
private final boolean async;
private String schemaType;
private SAXEventSink eventSink;
private SAXParserFactory factory;
private XMLReader reader;
private boolean namespaceAware = true;
private boolean ignoreWhitespace;
private boolean expandEntityReferences;
private boolean ignoreComments;
private boolean coalescing;
private boolean validating;
private boolean xIncludeAware;
private EntityResolver entityResolver;
private ErrorHandler errorHandler;
public DomLSParser(short mode, String schemaType)
throws DOMException
{
switch (mode)
{
case DOMImplementationLS.MODE_ASYNCHRONOUS:
async = true;
break;
case DOMImplementationLS.MODE_SYNCHRONOUS:
async = false;
break;
default:
throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
}
this.schemaType = schemaType;
factory = SAXParserFactory.newInstance();
}
public DOMConfiguration getDomConfig()
{
return this;
}
public LSParserFilter getFilter()
{
return filter;
}
public void setFilter(LSParserFilter filter)
{
this.filter = filter;
}
public boolean getAsync()
{
return async;
}
public boolean getBusy()
{
return eventSink != null;
}
public Document parse(LSInput input)
throws DOMException, LSException
{
if (async)
{
return doParse(input);
}
else
{
synchronized (this)
{
return doParse(input);
}
}
}
public Document parseURI(String uri)
throws DOMException, LSException
{
LSInput input = new DomLSInput();
input.setSystemId(uri);
return parse(input);
}
public Node parseWithContext(LSInput input, Node context, short action)
throws DOMException, LSException
{
Document doc = (context.getNodeType() == Node.DOCUMENT_NODE) ?
(Document) context : context.getOwnerDocument();
input.setBaseURI(doc.getDocumentURI());
Document ret = parse(input);
Node root = ret.getDocumentElement();
root = doc.adoptNode(root);
switch (action)
{
case ACTION_APPEND_AS_CHILDREN:
context.appendChild(root);
break;
case ACTION_REPLACE_CHILDREN:
Node c1 = context.getFirstChild();
while (c1 != null)
{
Node next = c1.getNextSibling();
context.removeChild(c1);
c1 = next;
}
context.appendChild(root);
break;
case ACTION_INSERT_BEFORE:
Node p1 = context.getParentNode();
p1.insertBefore(root, context);
break;
case ACTION_INSERT_AFTER:
Node p2 = context.getParentNode();
Node r1 = context.getNextSibling();
if (r1 == null)
{
p2.appendChild(root);
}
else
{
p2.insertBefore(root, r1);
}
break;
case ACTION_REPLACE:
Node p3 = context.getParentNode();
Node r2 = context.getNextSibling();
p3.removeChild(context);
if (r2 == null)
{
p3.appendChild(root);
}
else
{
p3.insertBefore(root, r2);
}
break;
}
return root;
}
public void abort()
{
if (eventSink != null)
{
eventSink.interrupt();
}
}
private Document doParse(LSInput input)
throws DOMException, LSException
{
if (eventSink != null)
{
throw new LSException(LSException.PARSE_ERR, "parse in progress");
}
InputSource source = getInputSource(input);
eventSink = (filter == null) ? new SAXEventSink() :
new FilteredSAXEventSink(filter);
eventSink.namespaceAware = namespaceAware;
eventSink.ignoreWhitespace = ignoreWhitespace;
eventSink.expandEntityReferences = expandEntityReferences;
eventSink.ignoreComments = ignoreComments;
eventSink.coalescing = coalescing;
XMLReader reader = getXMLReader();
try
{
reader.setContentHandler(eventSink);
reader.setDTDHandler(eventSink);
reader.setProperty("http://xml.org/sax/properties/lexical-handler",
eventSink);
reader.setProperty("http://xml.org/sax/properties/declaration-handler",
eventSink);
reader.setFeature("http://xml.org/sax/features/namespaces",
namespaceAware);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
true);
reader.setFeature("http://xml.org/sax/features/validation",
validating);
try
{
reader.setFeature("http://xml.org/sax/features/use-attributes2",
true);
}
catch (SAXNotRecognizedException e)
{
}
try
{
reader.setFeature("http://xml.org/sax/features/external-general-entities",
true);
}
catch (SAXNotRecognizedException e)
{
}
reader.setEntityResolver(entityResolver);
reader.setErrorHandler(errorHandler);
reader.parse(source);
}
catch (DOMException e)
{
reader = null;
eventSink = null;
throw e;
}
catch (SAXException e)
{
reader = null;
eventSink = null;
throw new DomLSException(LSException.PARSE_ERR, e);
}
catch (IOException e)
{
reader = null;
eventSink = null;
throw new DomLSException(LSException.PARSE_ERR, e);
}
Document ret = eventSink.doc;
String systemId = input.getSystemId();
if (systemId != null && ret instanceof DomDocument)
{
((DomDocument) ret).setDocumentURI(systemId);
}
eventSink = null;
return ret;
}
private XMLReader getXMLReader()
throws LSException
{
if (reader == null)
{
factory.setNamespaceAware(namespaceAware);
factory.setValidating(validating);
factory.setXIncludeAware(xIncludeAware);
try
{
SAXParser parser = factory.newSAXParser();
reader = parser.getXMLReader();
}
catch (ParserConfigurationException e)
{
throw new DomLSException(LSException.PARSE_ERR, e);
}
catch (SAXException e)
{
throw new DomLSException(LSException.PARSE_ERR, e);
}
}
return reader;
}
private InputSource getInputSource(LSInput input)
throws LSException
{
InputSource source = null;
String systemId = input.getSystemId();
InputStream in = input.getByteStream();
if (in != null)
{
source = new InputSource(in);
source.setSystemId(systemId);
}
if (source == null && entityResolver != null)
{
String publicId = input.getPublicId();
try
{
source = entityResolver.resolveEntity(publicId, systemId);
}
catch (SAXException e)
{
throw new DomLSException(LSException.PARSE_ERR, e);
}
catch (IOException e)
{
throw new DomLSException(LSException.PARSE_ERR, e);
}
}
if (source == null)
{
URL url = null;
String base = input.getBaseURI();
try
{
try
{
URL baseURL = (base == null) ? null : new URL(base);
url = (baseURL == null) ? new URL(systemId) :
new URL(baseURL, systemId);
}
catch (MalformedURLException e)
{
File baseFile = (base == null) ? null : new File(base);
url = (baseFile == null) ? new File(systemId).toURL() :
new File(baseFile, systemId).toURL();
}
in = url.openStream();
systemId = url.toString();
source = new InputSource(in);
source.setSystemId(systemId);
}
catch (IOException e)
{
throw new DomLSException(LSException.PARSE_ERR, e);
}
}
return source;
}
public void setParameter(String name, Object value)
throws DOMException
{
name = name.toLowerCase();
if ("cdata-sections".equals(name))
{
coalescing = !((Boolean) value).booleanValue();
}
else if ("comments".equals(name))
{
ignoreComments = !((Boolean) value).booleanValue();
}
else if ("element-content-whitespace".equals(name))
{
ignoreWhitespace = !((Boolean) value).booleanValue();
}
else if ("namespaces".equals(name))
{
namespaceAware = ((Boolean) value).booleanValue();
}
else if ("expand-entity-references".equals(name))
{
expandEntityReferences = ((Boolean) value).booleanValue();
}
else if ("coalescing".equals(name))
{
coalescing = ((Boolean) value).booleanValue();
}
else if ("validating".equals(name))
{
validating = ((Boolean) value).booleanValue();
}
else if ("xinclude-aware".equals(name))
{
xIncludeAware = ((Boolean) value).booleanValue();
}
else if ("entity-resolver".equals(name))
{
entityResolver = (EntityResolver) value;
}
else if ("error-handler".equals(name))
{
errorHandler = (ErrorHandler) value;
}
else
{
throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
}
reader = null;
}
public Object getParameter(String name)
throws DOMException
{
name = name.toLowerCase();
if ("cdata-sections".equals(name))
{
return coalescing ? Boolean.FALSE : Boolean.TRUE;
}
else if ("comments".equals(name))
{
return ignoreComments ? Boolean.FALSE : Boolean.TRUE;
}
else if ("element-content-whitespace".equals(name))
{
return ignoreWhitespace ? Boolean.FALSE : Boolean.TRUE;
}
else if ("namespaces".equals(name))
{
return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
}
else if ("expand-entity-references".equals(name))
{
return expandEntityReferences ? Boolean.TRUE : Boolean.FALSE;
}
else if ("coalescing".equals(name))
{
return coalescing ? Boolean.TRUE : Boolean.FALSE;
}
else if ("validating".equals(name))
{
return validating ? Boolean.TRUE : Boolean.FALSE;
}
else if ("xinclude-aware".equals(name))
{
return xIncludeAware ? Boolean.TRUE : Boolean.FALSE;
}
else if ("entity-resolver".equals(name))
{
return entityResolver;
}
else if ("error-handler".equals(name))
{
return errorHandler;
}
else
{
throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
}
}
public boolean canSetParameter(String name, Object value)
{
return contains(name);
}
public DOMStringList getParameterNames()
{
return this;
}
public String item(int i)
{
return (String) SUPPORTED_PARAMETERS.get(i);
}
public int getLength()
{
return SUPPORTED_PARAMETERS.size();
}
public boolean contains(String str)
{
return SUPPORTED_PARAMETERS.contains(str);
}
public void warning(SAXParseException e)
throws SAXException
{
if (errorHandler != null)
{
errorHandler.warning(e);
}
}
public void error(SAXParseException e)
throws SAXException
{
if (errorHandler != null)
{
errorHandler.error(e);
}
}
public void fatalError(SAXParseException e)
throws SAXException
{
if (errorHandler != null)
{
errorHandler.fatalError(e);
}
abort();
}
}