1 // This file is part of TagSoup and is Copyright 2002-2008 by John Cowan. 2 // 3 // TagSoup is licensed under the Apache License, 4 // Version 2.0. You may obtain a copy of this license at 5 // http://www.apache.org/licenses/LICENSE-2.0 . You may also have 6 // additional legal rights not granted by this license. 7 // 8 // TagSoup is distributed in the hope that it will be useful, but 9 // unless required by applicable law or agreed to in writing, TagSoup 10 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 11 // OF ANY KIND, either express or implied; not even the implied warranty 12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 14 package org.ccil.cowan.tagsoup.jaxp; 15 16 import java.util.*; 17 import javax.xml.parsers.*; 18 19 import org.xml.sax.*; 20 21 /** 22 * This is a simple implementation of JAXP {@link SAXParserFactory}, 23 * to allow easier integration of TagSoup with the default JDK 24 * xml processing stack. 25 * 26 * @author Tatu Saloranta (cowtowncoder@yahoo.com) 27 */ 28 public class SAXFactoryImpl 29 extends SAXParserFactory 30 { 31 /** 32 * The easiest way to test validity of features to set is to use 33 * a prototype object. Currently this is actually not a real prototype, 34 * in the sense that the configuration is actually passed separately 35 * (as opposed to instantiating new readers from this prototype), but 36 * this could be changed in future, if TagSoup parser object allowed 37 * cloning. 38 */ 39 private SAXParserImpl prototypeParser = null; 40 41 /** 42 * This Map contains explicitly set features that can be succesfully 43 * set for XMLReader instances. Temporary storage is needed due to 44 * JAXP design: multiple readers can be instantiated from a single 45 * factory, and settings can be changed between instantiations. 46 *<p> 47 * Note that we wouldn't need this map if we could create instances 48 * directly using the prototype instance. 49 */ 50 private HashMap features = null; 51 SAXFactoryImpl()52 public SAXFactoryImpl() 53 { 54 super(); 55 } 56 57 // // // JAXP API implementation: 58 59 /** 60 * Creates a new instance of <code>SAXParser</code> using the currently 61 * configured factory parameters. 62 */ newSAXParser()63 public SAXParser newSAXParser() 64 throws ParserConfigurationException 65 { 66 try { 67 return SAXParserImpl.newInstance(features); 68 } catch (SAXException se) { 69 // Translate to ParserConfigurationException 70 throw new ParserConfigurationException(se.getMessage()); 71 } 72 } 73 74 /** 75 * Defines that the specified feature is to enabled/disabled (as 76 * per second argument) on reader instances created by this 77 * factory. 78 */ setFeature(String name, boolean value)79 public void setFeature(String name, boolean value) 80 throws ParserConfigurationException, SAXNotRecognizedException, 81 SAXNotSupportedException 82 { 83 // First, let's see if it's a valid call 84 getPrototype().setFeature(name, value); 85 86 // If not, exception was thrown: so we are good now: 87 if (features == null) { 88 // Let's retain the ordering as well 89 features = new LinkedHashMap(); 90 } 91 features.put(name, value ? Boolean.TRUE : Boolean.FALSE); 92 } 93 94 /** 95 * Returns whether the specified property will be enabled or disabled 96 * on reader instances constructed by this factory. 97 */ getFeature(String name)98 public boolean getFeature(String name) 99 throws ParserConfigurationException, SAXNotRecognizedException, 100 SAXNotSupportedException 101 { 102 return getPrototype().getFeature(name); 103 } 104 105 // // // Internal methods 106 getPrototype()107 private SAXParserImpl getPrototype() 108 { 109 if (prototypeParser == null) { 110 prototypeParser = new SAXParserImpl(); 111 } 112 return prototypeParser; 113 } 114 } 115