/*
* Copyright 2007 Edward Kuns
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id: XMLReader.java 0000 2007-01-11 00:00:00Z ekuns $
*/
package org.castor.xmlctf.xmldiff.xml;
import java.io.File;
import java.io.FileReader;
import java.net.MalformedURLException;
import javax.xml.parsers.SAXParser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.castor.core.util.Messages;
import org.castor.xmlctf.xmldiff.xml.nodes.Root;
import org.castor.xmlctf.xmldiff.xml.nodes.XMLNode;
import org.exolab.castor.util.NestedIOException;
import org.exolab.castor.xml.util.XMLParserUtils;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
/**
* A Utility class to read an XML document from a file into the XMLNode tree
* used by the XMLDiff class.
*
* @author <a href="mailto:edward.kuns@aspect.com">Edward Kuns</a>
* @version $Revision: 0000 $ $Date: 2007-01-11 00:00:00 -0600 (Thu, 11 Jan 2007) $
* @see org.castor.xmlctf.xmldiff.XMLDiff
* @since Castor 1.1
*/
public class XMLFileReader {
/**
* The <a href="http://jakarta.apache.org/commons/logging/">Jakarta
* Commons Logging</a> instance used for all logging.
*/
private static final Log LOG = LogFactory.getLog(XMLFileReader.class);
/** The file we are reading. */
private final File _file;
/** URL for the document to be parsed. */
private final String _location;
/** A handle to the SAX parser. */
private XMLReader _parser;
/**
* Creates a new XMLReader for the given URILocation.
*
* @param filename the URILocation to create this reader for.
*/
public XMLFileReader(final String filename) {
if (filename == null) {
throw new IllegalArgumentException("You must give a non-null fliename");
}
_file = new File(filename);
if (!_file.exists()) {
throw new IllegalArgumentException("File '" + filename + "' does not exist");
}
_location = getUrlFromFile();
SAXParser saxParser = XMLParserUtils.getSAXParser(false, true);
try {
_parser = saxParser.getXMLReader();
}
catch(org.xml.sax.SAXException sx) {
LOG.error(Messages.format("conf.configurationError", sx));
}
if (_parser == null) {
_parser = XMLParserUtils.instantiateXMLReader("org.apache.xerces.parsers.SAXParser");
}
}
/**
* Reads an XML Document into an BaseNode from the provided file.
*
* @return the BaseNode
* @throws java.io.IOException if any exception occurs during parsing
*/
public XMLNode read() throws java.io.IOException {
XMLNode node = null;
try {
InputSource source = new InputSource();
source.setSystemId(_location);
source.setCharacterStream(new FileReader(_file));
XMLContentHandler builder = new XMLContentHandler();
_parser.setContentHandler(builder);
_parser.parse(source);
node = builder.getRoot();
} catch (SAXException sx) {
Exception nested = sx.getException();
SAXParseException sxp = null;
if (sx instanceof SAXParseException) {
sxp = (SAXParseException) sx;
} else if (nested != null && (nested instanceof SAXParseException)) {
sxp = (SAXParseException) nested;
} else {
throw new NestedIOException(sx);
}
StringBuffer err = new StringBuffer(sxp.toString());
err.append("\n - ");
err.append(sxp.getSystemId());
err.append("; line: ");
err.append(sxp.getLineNumber());
err.append(", column: ");
err.append(sxp.getColumnNumber());
throw new NestedIOException(err.toString(), sx);
}
Root root = (Root) node;
return root;
}
/**
* Returns the absolute URL as a string.
* @param file The URL to resolve
* @return the absolute URL as a string.
*/
private String getUrlFromFile() {
try {
return _file.toURL().toString();
} catch (MalformedURLException e) {
// ignore -- cannot happen
}
return null;
}
}