001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.util;
019:
020: import java.io.File;
021: import javax.xml.parsers.DocumentBuilder;
022: import javax.xml.parsers.DocumentBuilderFactory;
023: import javax.xml.parsers.FactoryConfigurationError;
024: import javax.xml.parsers.ParserConfigurationException;
025: import javax.xml.parsers.SAXParser;
026: import javax.xml.parsers.SAXParserFactory;
027: import org.apache.tools.ant.BuildException;
028: import org.xml.sax.Parser;
029: import org.xml.sax.SAXException;
030: import org.xml.sax.XMLReader;
031:
032: // CheckStyle:HideUtilityClassConstructorCheck OFF - bc
033:
034: /**
035: * Collection of helper methods that retrieve a ParserFactory or
036: * Parsers and Readers.
037: *
038: * <p>This class will create only a single factory instance.</p>
039: *
040: * @since Ant 1.5
041: */
042: public class JAXPUtils {
043:
044: /**
045: * Helper for systemId.
046: *
047: * @since Ant 1.6
048: */
049: private static final FileUtils FILE_UTILS = FileUtils
050: .getFileUtils();
051:
052: /**
053: * Parser factory to use to create parsers.
054: * @see #getParserFactory
055: *
056: * @since Ant 1.5
057: */
058: private static SAXParserFactory parserFactory = null;
059:
060: /**
061: * Parser Factory to create Namespace aware parsers.
062: *
063: * @since Ant 1.6
064: */
065: private static SAXParserFactory nsParserFactory = null;
066:
067: /**
068: * Parser factory to use to create document builders.
069: *
070: * @since Ant 1.6
071: */
072: private static DocumentBuilderFactory builderFactory = null;
073:
074: /**
075: * Returns the parser factory to use. Only one parser factory is
076: * ever created by this method and is then cached for future use.
077: *
078: * @return a SAXParserFactory to use.
079: * @throws BuildException on error.
080: *
081: * @since Ant 1.5
082: */
083: public static synchronized SAXParserFactory getParserFactory()
084: throws BuildException {
085:
086: if (parserFactory == null) {
087: parserFactory = newParserFactory();
088: }
089: return parserFactory;
090: }
091:
092: /**
093: * Returns the parser factory to use to create namespace aware parsers.
094: *
095: * @return a SAXParserFactory to use which supports manufacture of
096: * namespace aware parsers.
097: * @throws BuildException on error.
098: *
099: * @since Ant 1.6
100: */
101: public static synchronized SAXParserFactory getNSParserFactory()
102: throws BuildException {
103:
104: if (nsParserFactory == null) {
105: nsParserFactory = newParserFactory();
106: nsParserFactory.setNamespaceAware(true);
107: }
108: return nsParserFactory;
109: }
110:
111: /**
112: * Returns a new parser factory instance.
113: *
114: * @return the parser factory.
115: * @throws BuildException on error.
116: * @since Ant 1.5
117: */
118: public static SAXParserFactory newParserFactory()
119: throws BuildException {
120:
121: try {
122: return SAXParserFactory.newInstance();
123: } catch (FactoryConfigurationError e) {
124: throw new BuildException("XML parser factory has not been "
125: + "configured correctly: " + e.getMessage(), e);
126: }
127: }
128:
129: /**
130: * Returns a newly created SAX 1 Parser, using the default parser
131: * factory.
132: *
133: * @return a SAX 1 Parser.
134: * @throws BuildException on error.
135: * @see #getParserFactory
136: * @since Ant 1.5
137: */
138: public static Parser getParser() throws BuildException {
139: try {
140: return newSAXParser(getParserFactory()).getParser();
141: } catch (SAXException e) {
142: throw convertToBuildException(e);
143: }
144: }
145:
146: /**
147: * Returns a newly created SAX 2 XMLReader, using the default parser
148: * factory.
149: *
150: * @return a SAX 2 XMLReader.
151: * @throws BuildException on error.
152: * @see #getParserFactory
153: * @since Ant 1.5
154: */
155: public static XMLReader getXMLReader() throws BuildException {
156: try {
157: return newSAXParser(getParserFactory()).getXMLReader();
158: } catch (SAXException e) {
159: throw convertToBuildException(e);
160: }
161: }
162:
163: /**
164: * Returns a newly created SAX 2 XMLReader, which is namespace aware
165: *
166: * @return a SAX 2 XMLReader.
167: * @throws BuildException on error.
168: * @see #getParserFactory
169: * @since Ant 1.6
170: */
171: public static XMLReader getNamespaceXMLReader()
172: throws BuildException {
173: try {
174: return newSAXParser(getNSParserFactory()).getXMLReader();
175: } catch (SAXException e) {
176: throw convertToBuildException(e);
177: }
178: }
179:
180: /**
181: * This is a best attempt to provide a URL.toExternalForm() from
182: * a file URL. Some parsers like Crimson choke on uri that are made of
183: * backslashed paths (ie windows) as it is does not conform
184: * URI specifications.
185: * @param file the file to create the system id from.
186: * @return the systemid corresponding to the given file.
187: * @since Ant 1.5.2
188: */
189: public static String getSystemId(File file) {
190: return FILE_UTILS.toURI(file.getAbsolutePath());
191: }
192:
193: /**
194: * Returns a newly created DocumentBuilder.
195: *
196: * @return a DocumentBuilder.
197: * @throws BuildException on error.
198: * @since Ant 1.6
199: */
200: public static DocumentBuilder getDocumentBuilder()
201: throws BuildException {
202: try {
203: return getDocumentBuilderFactory().newDocumentBuilder();
204: } catch (ParserConfigurationException e) {
205: throw new BuildException(e);
206: }
207: }
208:
209: /**
210: * @return a new SAXParser instance as helper for getParser and
211: * getXMLReader.
212: *
213: * @since Ant 1.5
214: */
215: private static SAXParser newSAXParser(SAXParserFactory factory)
216: throws BuildException {
217: try {
218: return factory.newSAXParser();
219: } catch (ParserConfigurationException e) {
220: throw new BuildException(
221: "Cannot create parser for the given "
222: + "configuration: " + e.getMessage(), e);
223: } catch (SAXException e) {
224: throw convertToBuildException(e);
225: }
226: }
227:
228: /**
229: * Translate a SAXException into a BuildException
230: *
231: * @since Ant 1.5
232: */
233: private static BuildException convertToBuildException(SAXException e) {
234: Exception nested = e.getException();
235: if (nested != null) {
236: return new BuildException(nested);
237: } else {
238: return new BuildException(e);
239: }
240: }
241:
242: /**
243: * Obtains the default builder factory if not already.
244: *
245: * @since Ant 1.6
246: */
247: private static synchronized DocumentBuilderFactory getDocumentBuilderFactory()
248: throws BuildException {
249: if (builderFactory == null) {
250: try {
251: builderFactory = DocumentBuilderFactory.newInstance();
252: } catch (FactoryConfigurationError e) {
253: throw new BuildException(
254: "Document builder factory has not "
255: + "been configured correctly: "
256: + e.getMessage(), e);
257: }
258: }
259: return builderFactory;
260: }
261:
262: }
|