1 /*
2  * Copyright (c) 2002 World Wide Web Consortium,
3  * (Massachusetts Institute of Technology, Institut National de
4  * Recherche en Informatique et en Automatique, Keio University). All
5  * Rights Reserved. This program is distributed under the W3C's Software
6  * Intellectual Property License. This program is distributed in the
7  * hope that it will be useful, but WITHOUT ANY WARRANTY; without even
8  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9  * PURPOSE.
10  * See W3C License http://www.w3.org/Consortium/Legal/ for more details.
11  */
12 
13 package org.w3c.domts;
14 
15 import java.lang.reflect.Constructor;
16 import java.lang.reflect.InvocationTargetException;
17 import java.lang.reflect.Method;
18 
19 import javax.xml.parsers.ParserConfigurationException;
20 import javax.xml.parsers.SAXParser;
21 import javax.xml.parsers.SAXParserFactory;
22 
23 import org.w3c.dom.DOMImplementation;
24 import org.w3c.dom.Document;
25 import org.xml.sax.AttributeList;
26 import org.xml.sax.Attributes;
27 import org.xml.sax.DocumentHandler;
28 import org.xml.sax.SAXException;
29 import org.xml.sax.helpers.DefaultHandler;
30 
31 /**
32  *   This class implements the generic parser and configuation
33  *   class for the HTML DOM L2 implementation in Xerces-J
34  */
35 public class XercesHTML2DocumentBuilderFactory
36     extends DOMTestDocumentBuilderFactory {
37 
38   private SAXParserFactory factory;
39   private Constructor htmlBuilderConstructor;
40   private Method getHTMLDocumentMethod;
41   private DOMImplementation domImpl;
42   private static final Class[] NO_CLASSES = new Class[0];
43   private static final Object[] NO_OBJECTS = new Object[0];
44 
45   /**
46    * Creates a implementation of DOMTestDocumentBuilderFactory
47    * using org.apache.html.dom.HTMLBuilder
48    * @param settings array of settings, may be null.
49    */
XercesHTML2DocumentBuilderFactory(DocumentBuilderSetting[] settings)50   public XercesHTML2DocumentBuilderFactory(DocumentBuilderSetting[] settings) throws
51       DOMTestIncompatibleException {
52     super(settings);
53 
54     try {
55       ClassLoader classLoader = ClassLoader.getSystemClassLoader();
56       Class htmlBuilderClass =
57           classLoader.loadClass("org.apache.html2.dom.HTMLBuilder");
58 
59       htmlBuilderConstructor =
60           htmlBuilderClass.getConstructor(NO_CLASSES);
61 
62       getHTMLDocumentMethod =
63           htmlBuilderClass.getMethod("getHTMLDocument", NO_CLASSES);
64 
65       Class htmlDOMImpl =
66           classLoader.loadClass(
67           "org.apache.html2.dom.HTMLDOMImplementationImpl");
68       Method method =
69           htmlDOMImpl.getMethod("getHTMLDOMImplementation", NO_CLASSES);
70       domImpl = (DOMImplementation) method.invoke(null, NO_OBJECTS);
71 
72       Class saxFactoryClass =
73           classLoader.loadClass(
74           "org.apache.xerces.jaxp.SAXParserFactoryImpl");
75       factory = (SAXParserFactory) saxFactoryClass.newInstance();
76     }
77     catch (InvocationTargetException ex) {
78       throw new DOMTestIncompatibleException(
79           ex.getTargetException(),
80           null);
81     }
82     catch (Exception ex) {
83       throw new DOMTestIncompatibleException(ex, null);
84     }
85 
86     //
87     //    apply settings to selected document builder
88     //         may throw exception if incompatible
89     if (settings != null) {
90       for (int i = 0; i < settings.length; i++) {
91         //        settings[i].applySetting(factory);
92       }
93     }
94     try {
95       factory.newSAXParser();
96     }
97     catch (ParserConfigurationException ex) {
98       throw new DOMTestIncompatibleException(ex, null);
99     }
100     catch (SAXException ex) {
101       throw new DOMTestIncompatibleException(ex, null);
102     }
103   }
104 
newInstance(DocumentBuilderSetting[] newSettings)105   public DOMTestDocumentBuilderFactory newInstance(DocumentBuilderSetting[]
106       newSettings) throws DOMTestIncompatibleException {
107     if (newSettings == null) {
108       return this;
109     }
110     DocumentBuilderSetting[] mergedSettings = mergeSettings(newSettings);
111     return new XercesHTML2DocumentBuilderFactory(mergedSettings);
112   }
113 
114   private class HTMLHandler
115       extends DefaultHandler
116       implements AttributeList {
117     private final DocumentHandler htmlBuilder;
118     private final Method getHTMLDocumentMethod;
119     private Attributes currentAttributes;
120 
HTMLHandler( Constructor htmlBuilderConstructor, Method getHTMLDocumentMethod)121     public HTMLHandler(
122         Constructor htmlBuilderConstructor,
123         Method getHTMLDocumentMethod) throws Exception {
124       htmlBuilder =
125           (DocumentHandler) htmlBuilderConstructor.newInstance(
126           new Object[0]);
127       this.getHTMLDocumentMethod = getHTMLDocumentMethod;
128     }
129 
startDocument()130     public void startDocument() throws SAXException {
131       htmlBuilder.startDocument();
132     }
133 
endDocument()134     public void endDocument() throws SAXException {
135       htmlBuilder.endDocument();
136     }
137 
startElement( String uri, String localName, String qName, Attributes attributes)138     public void startElement(
139         String uri,
140         String localName,
141         String qName,
142         Attributes attributes) throws SAXException {
143       currentAttributes = attributes;
144       htmlBuilder.startElement(qName, this);
145     }
146 
endElement(String uri, String localName, String qName)147     public void endElement(String uri, String localName, String qName) throws
148         SAXException {
149       htmlBuilder.endElement(qName);
150     }
151 
characters(char ch[], int start, int length)152     public void characters(char ch[], int start, int length) throws
153         SAXException {
154       htmlBuilder.characters(ch, start, length);
155     }
156 
ignorableWhitespace(char ch[], int start, int length)157     public void ignorableWhitespace(char ch[], int start, int length) throws
158         SAXException {
159       htmlBuilder.ignorableWhitespace(ch, start, length);
160     }
161 
processingInstruction(String target, String data)162     public void processingInstruction(String target, String data) throws
163         SAXException {
164       htmlBuilder.processingInstruction(target, data);
165     }
166 
getHTMLDocument()167     public Document getHTMLDocument() throws Exception {
168       return (Document) getHTMLDocumentMethod.invoke(
169           htmlBuilder,
170           NO_OBJECTS);
171     }
172 
getLength()173     public int getLength() {
174       return currentAttributes.getLength();
175     }
176 
getName(int i)177     public String getName(int i) {
178       return currentAttributes.getQName(i);
179     }
180 
getType(int i)181     public String getType(int i) {
182       return currentAttributes.getType(i);
183     }
184 
getValue(int i)185     public String getValue(int i) {
186       return currentAttributes.getValue(i);
187     }
188 
getType(String name)189     public String getType(String name) {
190       return currentAttributes.getType(name);
191     }
192 
getValue(String name)193     public String getValue(String name) {
194       return currentAttributes.getValue(name);
195     }
196 
197   }
198 
load(java.net.URL url)199   public Document load(java.net.URL url) throws DOMTestLoadException {
200     Document doc = null;
201     try {
202       SAXParser parser = factory.newSAXParser();
203       HTMLHandler handler =
204           new HTMLHandler(htmlBuilderConstructor, getHTMLDocumentMethod);
205       parser.parse(url.toString(), handler);
206       doc = handler.getHTMLDocument();
207     }
208     catch (Exception ex) {
209       throw new DOMTestLoadException(ex);
210     }
211     return doc;
212   }
213 
getDOMImplementation()214   public DOMImplementation getDOMImplementation() {
215     return domImpl;
216   }
217 
hasFeature(String feature, String version)218   public boolean hasFeature(String feature, String version) {
219     return domImpl.hasFeature(feature, version);
220   }
221 
isCoalescing()222   public boolean isCoalescing() {
223     return false;
224   }
225 
isExpandEntityReferences()226   public boolean isExpandEntityReferences() {
227     return false;
228   }
229 
isIgnoringElementContentWhitespace()230   public boolean isIgnoringElementContentWhitespace() {
231     return false;
232   }
233 
isNamespaceAware()234   public boolean isNamespaceAware() {
235     return factory.isNamespaceAware();
236   }
237 
isValidating()238   public boolean isValidating() {
239     return factory.isValidating();
240   }
241 
getConfiguration1()242   public static DocumentBuilderSetting[] getConfiguration1() {
243     return new DocumentBuilderSetting[] {
244         DocumentBuilderSetting.notCoalescing,
245         DocumentBuilderSetting.notExpandEntityReferences,
246         DocumentBuilderSetting.notIgnoringElementContentWhitespace,
247         DocumentBuilderSetting.notNamespaceAware,
248         DocumentBuilderSetting.notValidating};
249   }
250 
getConfiguration2()251   public static DocumentBuilderSetting[] getConfiguration2() {
252     return new DocumentBuilderSetting[] {
253         DocumentBuilderSetting.notCoalescing,
254         DocumentBuilderSetting.expandEntityReferences,
255         DocumentBuilderSetting.ignoringElementContentWhitespace,
256         DocumentBuilderSetting.namespaceAware,
257         DocumentBuilderSetting.validating};
258 
259   }
260 
261 }
262