1. /*
  2. * Copyright 2002-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.util;
  18. import java.io.File;
  19. import javax.xml.parsers.DocumentBuilder;
  20. import javax.xml.parsers.DocumentBuilderFactory;
  21. import javax.xml.parsers.FactoryConfigurationError;
  22. import javax.xml.parsers.ParserConfigurationException;
  23. import javax.xml.parsers.SAXParser;
  24. import javax.xml.parsers.SAXParserFactory;
  25. import org.apache.tools.ant.BuildException;
  26. import org.xml.sax.Parser;
  27. import org.xml.sax.SAXException;
  28. import org.xml.sax.XMLReader;
  29. /**
  30. * Collection of helper methods that retrieve a ParserFactory or
  31. * Parsers and Readers.
  32. *
  33. * <p>This class will create only a single factory instance.</p>
  34. *
  35. *
  36. * @since Ant 1.5
  37. */
  38. public class JAXPUtils {
  39. /**
  40. * Helper for systemId.
  41. *
  42. * @since Ant 1.6
  43. */
  44. private static final FileUtils fu = FileUtils.newFileUtils();
  45. /**
  46. * Parser factory to use to create parsers.
  47. * @see #getParserFactory
  48. *
  49. * @since Ant 1.5
  50. */
  51. private static SAXParserFactory parserFactory = null;
  52. /**
  53. * Parser Factory to create Namespace aware parsers.
  54. *
  55. * @since Ant 1.6
  56. */
  57. private static SAXParserFactory nsParserFactory = null;
  58. /**
  59. * Parser factory to use to create document builders.
  60. *
  61. * @since Ant 1.6
  62. */
  63. private static DocumentBuilderFactory builderFactory = null;
  64. /**
  65. * Returns the parser factory to use. Only one parser factory is
  66. * ever created by this method and is then cached for future use.
  67. *
  68. * @return a SAXParserFactory to use
  69. *
  70. * @since Ant 1.5
  71. */
  72. public static synchronized SAXParserFactory getParserFactory()
  73. throws BuildException {
  74. if (parserFactory == null) {
  75. parserFactory = newParserFactory();
  76. }
  77. return parserFactory;
  78. }
  79. /**
  80. * Returns the parser factory to use to create namespace aware parsers.
  81. *
  82. * @return a SAXParserFactory to use which supports manufacture of
  83. * namespace aware parsers
  84. *
  85. * @since Ant 1.6
  86. */
  87. public static synchronized SAXParserFactory getNSParserFactory()
  88. throws BuildException {
  89. if (nsParserFactory == null) {
  90. nsParserFactory = newParserFactory();
  91. nsParserFactory.setNamespaceAware(true);
  92. }
  93. return nsParserFactory;
  94. }
  95. /**
  96. * Returns a new parser factory instance.
  97. *
  98. * @since Ant 1.5
  99. */
  100. public static SAXParserFactory newParserFactory() throws BuildException {
  101. try {
  102. return SAXParserFactory.newInstance();
  103. } catch (FactoryConfigurationError e) {
  104. throw new BuildException("XML parser factory has not been "
  105. + "configured correctly: "
  106. + e.getMessage(), e);
  107. }
  108. }
  109. /**
  110. * Returns a newly created SAX 1 Parser, using the default parser
  111. * factory.
  112. *
  113. * @return a SAX 1 Parser.
  114. * @see #getParserFactory
  115. * @since Ant 1.5
  116. */
  117. public static Parser getParser() throws BuildException {
  118. try {
  119. return newSAXParser(getParserFactory()).getParser();
  120. } catch (SAXException e) {
  121. throw convertToBuildException(e);
  122. }
  123. }
  124. /**
  125. * Returns a newly created SAX 2 XMLReader, using the default parser
  126. * factory.
  127. *
  128. * @return a SAX 2 XMLReader.
  129. * @see #getParserFactory
  130. * @since Ant 1.5
  131. */
  132. public static XMLReader getXMLReader() throws BuildException {
  133. try {
  134. return newSAXParser(getParserFactory()).getXMLReader();
  135. } catch (SAXException e) {
  136. throw convertToBuildException(e);
  137. }
  138. }
  139. /**
  140. * Returns a newly created SAX 2 XMLReader, which is namespace aware
  141. *
  142. * @return a SAX 2 XMLReader.
  143. * @see #getParserFactory
  144. * @since Ant 1.6
  145. */
  146. public static XMLReader getNamespaceXMLReader() throws BuildException {
  147. try {
  148. return newSAXParser(getNSParserFactory()).getXMLReader();
  149. } catch (SAXException e) {
  150. throw convertToBuildException(e);
  151. }
  152. }
  153. /**
  154. * This is a best attempt to provide a URL.toExternalForm() from
  155. * a file URL. Some parsers like Crimson choke on uri that are made of
  156. * backslashed paths (ie windows) as it is does not conform
  157. * URI specifications.
  158. * @param file the file to create the system id from.
  159. * @return the systemid corresponding to the given file.
  160. * @since Ant 1.5.2
  161. */
  162. public static String getSystemId(File file) {
  163. return fu.toURI(file.getAbsolutePath());
  164. }
  165. /**
  166. * Returns a newly created DocumentBuilder.
  167. *
  168. * @return a DocumentBuilder
  169. * @since Ant 1.6
  170. */
  171. public static DocumentBuilder getDocumentBuilder() throws BuildException {
  172. try {
  173. return getDocumentBuilderFactory().newDocumentBuilder();
  174. } catch (ParserConfigurationException e) {
  175. throw new BuildException(e);
  176. }
  177. }
  178. /**
  179. * @return a new SAXParser instance as helper for getParser and
  180. * getXMLReader.
  181. *
  182. * @since Ant 1.5
  183. */
  184. private static SAXParser newSAXParser(SAXParserFactory factory)
  185. throws BuildException {
  186. try {
  187. return factory.newSAXParser();
  188. } catch (ParserConfigurationException e) {
  189. throw new BuildException("Cannot create parser for the given "
  190. + "configuration: " + e.getMessage(), e);
  191. } catch (SAXException e) {
  192. throw convertToBuildException(e);
  193. }
  194. }
  195. /**
  196. * Translate a SAXException into a BuildException
  197. *
  198. * @since Ant 1.5
  199. */
  200. private static BuildException convertToBuildException(SAXException e) {
  201. Exception nested = e.getException();
  202. if (nested != null) {
  203. return new BuildException(nested);
  204. } else {
  205. return new BuildException(e);
  206. }
  207. }
  208. /**
  209. * Obtains the default builder factory if not already.
  210. *
  211. * @since Ant 1.6
  212. */
  213. private static synchronized
  214. DocumentBuilderFactory getDocumentBuilderFactory()
  215. throws BuildException {
  216. if (builderFactory == null) {
  217. try {
  218. builderFactory = DocumentBuilderFactory.newInstance();
  219. } catch (FactoryConfigurationError e) {
  220. throw new BuildException("Document builder factory has not "
  221. + "been configured correctly: "
  222. + e.getMessage(), e);
  223. }
  224. }
  225. return builderFactory;
  226. }
  227. }