View Javadoc
1   /*
2    * Copyright 2007 Edward Kuns
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   *
14   * $Id: XMLReader.java 0000 2007-01-11 00:00:00Z ekuns $
15   */
16  package org.castor.xmlctf.xmldiff.xml;
17  
18  import java.io.File;
19  import java.io.FileReader;
20  import java.net.MalformedURLException;
21  
22  import javax.xml.parsers.SAXParser;
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.castor.core.util.Messages;
26  import org.castor.xmlctf.xmldiff.xml.nodes.Root;
27  import org.castor.xmlctf.xmldiff.xml.nodes.XMLNode;
28  import org.exolab.castor.util.NestedIOException;
29  import org.exolab.castor.xml.util.XMLParserUtils;
30  import org.xml.sax.InputSource;
31  import org.xml.sax.SAXException;
32  import org.xml.sax.SAXParseException;
33  import org.xml.sax.XMLReader;
34  
35  /**
36   * A Utility class to read an XML document from a file into the XMLNode tree used by the XMLDiff
37   * class.
38   *
39   * @author <a href="mailto:edward.kuns@aspect.com">Edward Kuns</a>
40   * @version $Revision: 0000 $ $Date: 2007-01-11 00:00:00 -0600 (Thu, 11 Jan 2007) $
41   * @see org.castor.xmlctf.xmldiff.XMLDiff
42   * @since Castor 1.1
43   */
44  public class XMLFileReader {
45  
46    /**
47     * The <a href="http://jakarta.apache.org/commons/logging/">Jakarta Commons Logging</a> instance
48     * used for all logging.
49     */
50    private static final Log LOG = LogFactory.getLog(XMLFileReader.class);
51  
52    /** The file we are reading. */
53    private final File _file;
54    /** URL for the document to be parsed. */
55    private final String _location;
56    /** A handle to the SAX parser. */
57    private XMLReader _parser;
58  
59    /**
60     * Creates a new XMLReader for the given URILocation.
61     *
62     * @param filename the URILocation to create this reader for.
63     */
64    public XMLFileReader(final String filename) {
65      if (filename == null) {
66        throw new IllegalArgumentException("You must give a non-null fliename");
67      }
68      _file = new File(filename);
69      if (!_file.exists()) {
70        throw new IllegalArgumentException("File '" + filename + "' does not exist");
71      }
72  
73      _location = getUrlFromFile();
74  
75      SAXParser saxParser = XMLParserUtils.getSAXParser(false, true);
76      try {
77        _parser = saxParser.getXMLReader();
78      } catch (org.xml.sax.SAXException sx) {
79        LOG.error(Messages.format("conf.configurationError", sx));
80      }
81  
82      if (_parser == null) {
83        _parser = XMLParserUtils.instantiateXMLReader("org.apache.xerces.parsers.SAXParser");
84      }
85    }
86  
87    /**
88     * Reads an XML Document into an BaseNode from the provided file.
89     *
90     * @return the BaseNode
91     * @throws java.io.IOException if any exception occurs during parsing
92     */
93    public XMLNode read() throws java.io.IOException {
94      XMLNode node = null;
95  
96      try {
97        InputSource source = new InputSource();
98        source.setSystemId(_location);
99        source.setCharacterStream(new FileReader(_file));
100 
101       XMLContentHandler builder = new XMLContentHandler();
102 
103       _parser.setContentHandler(builder);
104       _parser.parse(source);
105 
106       node = builder.getRoot();
107     } catch (SAXException sx) {
108       Exception nested = sx.getException();
109 
110       SAXParseException sxp = null;
111       if (sx instanceof SAXParseException) {
112         sxp = (SAXParseException) sx;
113       } else if (nested != null && (nested instanceof SAXParseException)) {
114         sxp = (SAXParseException) nested;
115       } else {
116         throw new NestedIOException(sx);
117       }
118 
119       String err = new StringBuilder(sxp.toString()).append("\n - ").append(sxp.getSystemId())
120           .append("; line: ").append(sxp.getLineNumber()).append(", column: ")
121           .append(sxp.getColumnNumber()).toString();
122       throw new NestedIOException(err, sx);
123     }
124 
125     Root root = (Root) node;
126     return root;
127   }
128 
129   /**
130    * Returns the absolute URL as a string.
131    * 
132    * @param file The URL to resolve
133    * @return the absolute URL as a string.
134    */
135   private String getUrlFromFile() {
136     try {
137       return _file.toURL().toString();
138     } catch (MalformedURLException e) {
139       // ignore -- cannot happen
140     }
141     return null;
142   }
143 
144 }