1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.xerces.jaxp;
19
20 import java.util.Hashtable;
21
22 import javax.xml.XMLConstants;
23 import javax.xml.parsers.DocumentBuilder;
24 import javax.xml.parsers.DocumentBuilderFactory;
25 import javax.xml.parsers.ParserConfigurationException;
26 import javax.xml.validation.Schema;
27
28 import org.apache.xerces.impl.Constants;
29 import org.apache.xerces.parsers.DOMParser;
30 import org.apache.xerces.util.SAXMessageFormatter;
31 import org.xml.sax.SAXException;
32 import org.xml.sax.SAXNotRecognizedException;
33 import org.xml.sax.SAXNotSupportedException;
34
35 /**
36 * @author Rajiv Mordani
37 * @author Edwin Goei
38 * @version $Id: DocumentBuilderFactoryImpl.java 447237 2006-09-18 05:03:10Z mrglavas $
39 */
40 public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
41
42 /** Feature identifier: namespaces. */
43 private static final String NAMESPACES_FEATURE =
44 Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
45
46 /** Feature identifier: validation */
47 private static final String VALIDATION_FEATURE =
48 Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
49
50 /** Feature identifier: XInclude processing */
51 private static final String XINCLUDE_FEATURE =
52 Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FEATURE;
53
54 /** Feature identifier: include ignorable white space. */
55 private static final String INCLUDE_IGNORABLE_WHITESPACE =
56 Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
57
58 /** Feature identifier: create entiry ref nodes feature. */
59 private static final String CREATE_ENTITY_REF_NODES_FEATURE =
60 Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
61
62 /** Feature identifier: include comments feature. */
63 private static final String INCLUDE_COMMENTS_FEATURE =
64 Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
65
66 /** Feature identifier: create cdata nodes feature. */
67 private static final String CREATE_CDATA_NODES_FEATURE =
68 Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
69
70 /** These are DocumentBuilderFactory attributes not DOM attributes */
71 private Hashtable attributes;
72 private Hashtable features;
73 private Schema grammar;
74 private boolean isXIncludeAware;
75
76 /**
77 * State of the secure processing feature, initially <code>false</code>
78 */
79 private boolean fSecureProcess = false;
80
81 /**
82 * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder}
83 * using the currently configured parameters.
84 */
85 public DocumentBuilder newDocumentBuilder()
86 throws ParserConfigurationException
87 {
88 /** Check that if a Schema has been specified that neither of the schema properties have been set. */
89 if (grammar != null && attributes != null) {
90 if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_LANGUAGE)) {
91 throw new ParserConfigurationException(
92 SAXMessageFormatter.formatMessage(null,
93 "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_LANGUAGE}));
94 }
95 else if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_SOURCE)) {
96 throw new ParserConfigurationException(
97 SAXMessageFormatter.formatMessage(null,
98 "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_SOURCE}));
99 }
100 }
101
102 try {
103 return new DocumentBuilderImpl(this, attributes, features, fSecureProcess);
104 } catch (SAXException se) {
105 // Handles both SAXNotSupportedException, SAXNotRecognizedException
106 throw new ParserConfigurationException(se.getMessage());
107 }
108 }
109
110 /**
111 * Allows the user to set specific attributes on the underlying
112 * implementation.
113 * @param name name of attribute
114 * @param value null means to remove attribute
115 */
116 public void setAttribute(String name, Object value)
117 throws IllegalArgumentException
118 {
119 // This handles removal of attributes
120 if (value == null) {
121 if (attributes != null) {
122 attributes.remove(name);
123 }
124 // Unrecognized attributes do not cause an exception
125 return;
126 }
127
128 // This is ugly. We have to collect the attributes and then
129 // later create a DocumentBuilderImpl to verify the attributes.
130
131 // Create Hashtable if none existed before
132 if (attributes == null) {
133 attributes = new Hashtable();
134 }
135
136 attributes.put(name, value);
137
138 // Test the attribute name by possibly throwing an exception
139 try {
140 new DocumentBuilderImpl(this, attributes, features);
141 } catch (Exception e) {
142 attributes.remove(name);
143 throw new IllegalArgumentException(e.getMessage());
144 }
145 }
146
147 /**
148 * Allows the user to retrieve specific attributes on the underlying
149 * implementation.
150 */
151 public Object getAttribute(String name)
152 throws IllegalArgumentException
153 {
154 // See if it's in the attributes Hashtable
155 if (attributes != null) {
156 Object val = attributes.get(name);
157 if (val != null) {
158 return val;
159 }
160 }
161
162 DOMParser domParser = null;
163 try {
164 // We create a dummy DocumentBuilderImpl in case the attribute
165 // name is not one that is in the attributes hashtable.
166 domParser =
167 new DocumentBuilderImpl(this, attributes, features).getDOMParser();
168 return domParser.getProperty(name);
169 } catch (SAXException se1) {
170 // assert(name is not recognized or not supported), try feature
171 try {
172 boolean result = domParser.getFeature(name);
173 // Must have been a feature
174 return result ? Boolean.TRUE : Boolean.FALSE;
175 } catch (SAXException se2) {
176 // Not a property or a feature
177 throw new IllegalArgumentException(se1.getMessage());
178 }
179 }
180 }
181
182 public Schema getSchema() {
183 return grammar;
184 }
185
186 public void setSchema(Schema grammar) {
187 this.grammar = grammar;
188 }
189
190 public boolean isXIncludeAware() {
191 return this.isXIncludeAware;
192 }
193
194 public void setXIncludeAware(boolean state) {
195 this.isXIncludeAware = state;
196 }
197
198 public boolean getFeature(String name)
199 throws ParserConfigurationException {
200 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
201 return fSecureProcess;
202 }
203 else if (name.equals(NAMESPACES_FEATURE)) {
204 return isNamespaceAware();
205 }
206 else if (name.equals(VALIDATION_FEATURE)) {
207 return isValidating();
208 }
209 else if (name.equals(XINCLUDE_FEATURE)) {
210 return isXIncludeAware();
211 }
212 else if (name.equals(INCLUDE_IGNORABLE_WHITESPACE)) {
213 return !isIgnoringElementContentWhitespace();
214 }
215 else if (name.equals(CREATE_ENTITY_REF_NODES_FEATURE)) {
216 return !isExpandEntityReferences();
217 }
218 else if (name.equals(INCLUDE_COMMENTS_FEATURE)) {
219 return !isIgnoringComments();
220 }
221 else if (name.equals(CREATE_CDATA_NODES_FEATURE)) {
222 return !isCoalescing();
223 }
224 // See if it's in the features Hashtable
225 if (features != null) {
226 Object val = features.get(name);
227 if (val != null) {
228 return ((Boolean) val).booleanValue();
229 }
230 }
231 try {
232 DOMParser domParser = new DocumentBuilderImpl(this, attributes, features).getDOMParser();
233 return domParser.getFeature(name);
234 }
235 catch (SAXException e) {
236 throw new ParserConfigurationException(e.getMessage());
237 }
238 }
239
240 public void setFeature(String name, boolean value)
241 throws ParserConfigurationException {
242 // If this is the secure processing feature, save it then return.
243 if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
244 fSecureProcess = value;
245 return;
246 }
247 // Keep built-in settings in synch with the feature values.
248 else if (name.equals(NAMESPACES_FEATURE)) {
249 setNamespaceAware(value);
250 return;
251 }
252 else if (name.equals(VALIDATION_FEATURE)) {
253 setValidating(value);
254 return;
255 }
256 else if (name.equals(XINCLUDE_FEATURE)) {
257 setXIncludeAware(value);
258 return;
259 }
260 else if (name.equals(INCLUDE_IGNORABLE_WHITESPACE)) {
261 setIgnoringElementContentWhitespace(!value);
262 return;
263 }
264 else if (name.equals(CREATE_ENTITY_REF_NODES_FEATURE)) {
265 setExpandEntityReferences(!value);
266 return;
267 }
268 else if (name.equals(INCLUDE_COMMENTS_FEATURE)) {
269 setIgnoringComments(!value);
270 return;
271 }
272 else if (name.equals(CREATE_CDATA_NODES_FEATURE)) {
273 setCoalescing(!value);
274 return;
275 }
276
277 if (features == null) {
278 features = new Hashtable();
279 }
280 features.put(name, value ? Boolean.TRUE : Boolean.FALSE);
281 // Test the feature by possibly throwing SAX exceptions
282 try {
283 new DocumentBuilderImpl(this, attributes, features);
284 }
285 catch (SAXNotSupportedException e) {
286 features.remove(name);
287 throw new ParserConfigurationException(e.getMessage());
288 }
289 catch (SAXNotRecognizedException e) {
290 features.remove(name);
291 throw new ParserConfigurationException(e.getMessage());
292 }
293 }
294 }