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.xerces.jaxp;
019:
020: import java.util.Hashtable;
021:
022: import javax.xml.XMLConstants;
023: import javax.xml.parsers.DocumentBuilder;
024: import javax.xml.parsers.DocumentBuilderFactory;
025: import javax.xml.parsers.ParserConfigurationException;
026: import javax.xml.validation.Schema;
027:
028: import org.apache.xerces.impl.Constants;
029: import org.apache.xerces.parsers.DOMParser;
030: import org.apache.xerces.util.SAXMessageFormatter;
031: import org.xml.sax.SAXException;
032: import org.xml.sax.SAXNotRecognizedException;
033: import org.xml.sax.SAXNotSupportedException;
034:
035: /**
036: * @author Rajiv Mordani
037: * @author Edwin Goei
038: * @version $Id: DocumentBuilderFactoryImpl.java 447237 2006-09-18 05:03:10Z mrglavas $
039: */
040: public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
041:
042: /** Feature identifier: namespaces. */
043: private static final String NAMESPACES_FEATURE = Constants.SAX_FEATURE_PREFIX
044: + Constants.NAMESPACES_FEATURE;
045:
046: /** Feature identifier: validation */
047: private static final String VALIDATION_FEATURE = Constants.SAX_FEATURE_PREFIX
048: + Constants.VALIDATION_FEATURE;
049:
050: /** Feature identifier: XInclude processing */
051: private static final String XINCLUDE_FEATURE = Constants.XERCES_FEATURE_PREFIX
052: + Constants.XINCLUDE_FEATURE;
053:
054: /** Feature identifier: include ignorable white space. */
055: private static final String INCLUDE_IGNORABLE_WHITESPACE = Constants.XERCES_FEATURE_PREFIX
056: + Constants.INCLUDE_IGNORABLE_WHITESPACE;
057:
058: /** Feature identifier: create entiry ref nodes feature. */
059: private static final String CREATE_ENTITY_REF_NODES_FEATURE = Constants.XERCES_FEATURE_PREFIX
060: + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
061:
062: /** Feature identifier: include comments feature. */
063: private static final String INCLUDE_COMMENTS_FEATURE = Constants.XERCES_FEATURE_PREFIX
064: + Constants.INCLUDE_COMMENTS_FEATURE;
065:
066: /** Feature identifier: create cdata nodes feature. */
067: private static final String CREATE_CDATA_NODES_FEATURE = Constants.XERCES_FEATURE_PREFIX
068: + Constants.CREATE_CDATA_NODES_FEATURE;
069:
070: /** These are DocumentBuilderFactory attributes not DOM attributes */
071: private Hashtable attributes;
072: private Hashtable features;
073: private Schema grammar;
074: private boolean isXIncludeAware;
075:
076: /**
077: * State of the secure processing feature, initially <code>false</code>
078: */
079: private boolean fSecureProcess = false;
080:
081: /**
082: * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder}
083: * using the currently configured parameters.
084: */
085: public DocumentBuilder newDocumentBuilder()
086: throws ParserConfigurationException {
087: /** Check that if a Schema has been specified that neither of the schema properties have been set. */
088: if (grammar != null && attributes != null) {
089: if (attributes
090: .containsKey(JAXPConstants.JAXP_SCHEMA_LANGUAGE)) {
091: throw new ParserConfigurationException(
092: SAXMessageFormatter
093: .formatMessage(
094: null,
095: "schema-already-specified",
096: new Object[] { JAXPConstants.JAXP_SCHEMA_LANGUAGE }));
097: } else if (attributes
098: .containsKey(JAXPConstants.JAXP_SCHEMA_SOURCE)) {
099: throw new ParserConfigurationException(
100: SAXMessageFormatter
101: .formatMessage(
102: null,
103: "schema-already-specified",
104: new Object[] { JAXPConstants.JAXP_SCHEMA_SOURCE }));
105: }
106: }
107:
108: try {
109: return new DocumentBuilderImpl(this , attributes, features,
110: fSecureProcess);
111: } catch (SAXException se) {
112: // Handles both SAXNotSupportedException, SAXNotRecognizedException
113: throw new ParserConfigurationException(se.getMessage());
114: }
115: }
116:
117: /**
118: * Allows the user to set specific attributes on the underlying
119: * implementation.
120: * @param name name of attribute
121: * @param value null means to remove attribute
122: */
123: public void setAttribute(String name, Object value)
124: throws IllegalArgumentException {
125: // This handles removal of attributes
126: if (value == null) {
127: if (attributes != null) {
128: attributes.remove(name);
129: }
130: // Unrecognized attributes do not cause an exception
131: return;
132: }
133:
134: // This is ugly. We have to collect the attributes and then
135: // later create a DocumentBuilderImpl to verify the attributes.
136:
137: // Create Hashtable if none existed before
138: if (attributes == null) {
139: attributes = new Hashtable();
140: }
141:
142: attributes.put(name, value);
143:
144: // Test the attribute name by possibly throwing an exception
145: try {
146: new DocumentBuilderImpl(this , attributes, features);
147: } catch (Exception e) {
148: attributes.remove(name);
149: throw new IllegalArgumentException(e.getMessage());
150: }
151: }
152:
153: /**
154: * Allows the user to retrieve specific attributes on the underlying
155: * implementation.
156: */
157: public Object getAttribute(String name)
158: throws IllegalArgumentException {
159: // See if it's in the attributes Hashtable
160: if (attributes != null) {
161: Object val = attributes.get(name);
162: if (val != null) {
163: return val;
164: }
165: }
166:
167: DOMParser domParser = null;
168: try {
169: // We create a dummy DocumentBuilderImpl in case the attribute
170: // name is not one that is in the attributes hashtable.
171: domParser = new DocumentBuilderImpl(this , attributes,
172: features).getDOMParser();
173: return domParser.getProperty(name);
174: } catch (SAXException se1) {
175: // assert(name is not recognized or not supported), try feature
176: try {
177: boolean result = domParser.getFeature(name);
178: // Must have been a feature
179: return result ? Boolean.TRUE : Boolean.FALSE;
180: } catch (SAXException se2) {
181: // Not a property or a feature
182: throw new IllegalArgumentException(se1.getMessage());
183: }
184: }
185: }
186:
187: public Schema getSchema() {
188: return grammar;
189: }
190:
191: public void setSchema(Schema grammar) {
192: this .grammar = grammar;
193: }
194:
195: public boolean isXIncludeAware() {
196: return this .isXIncludeAware;
197: }
198:
199: public void setXIncludeAware(boolean state) {
200: this .isXIncludeAware = state;
201: }
202:
203: public boolean getFeature(String name)
204: throws ParserConfigurationException {
205: if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
206: return fSecureProcess;
207: } else if (name.equals(NAMESPACES_FEATURE)) {
208: return isNamespaceAware();
209: } else if (name.equals(VALIDATION_FEATURE)) {
210: return isValidating();
211: } else if (name.equals(XINCLUDE_FEATURE)) {
212: return isXIncludeAware();
213: } else if (name.equals(INCLUDE_IGNORABLE_WHITESPACE)) {
214: return !isIgnoringElementContentWhitespace();
215: } else if (name.equals(CREATE_ENTITY_REF_NODES_FEATURE)) {
216: return !isExpandEntityReferences();
217: } else if (name.equals(INCLUDE_COMMENTS_FEATURE)) {
218: return !isIgnoringComments();
219: } else if (name.equals(CREATE_CDATA_NODES_FEATURE)) {
220: return !isCoalescing();
221: }
222: // See if it's in the features Hashtable
223: if (features != null) {
224: Object val = features.get(name);
225: if (val != null) {
226: return ((Boolean) val).booleanValue();
227: }
228: }
229: try {
230: DOMParser domParser = new DocumentBuilderImpl(this ,
231: attributes, features).getDOMParser();
232: return domParser.getFeature(name);
233: } catch (SAXException e) {
234: throw new ParserConfigurationException(e.getMessage());
235: }
236: }
237:
238: public void setFeature(String name, boolean value)
239: throws ParserConfigurationException {
240: // If this is the secure processing feature, save it then return.
241: if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
242: fSecureProcess = value;
243: return;
244: }
245: // Keep built-in settings in synch with the feature values.
246: else if (name.equals(NAMESPACES_FEATURE)) {
247: setNamespaceAware(value);
248: return;
249: } else if (name.equals(VALIDATION_FEATURE)) {
250: setValidating(value);
251: return;
252: } else if (name.equals(XINCLUDE_FEATURE)) {
253: setXIncludeAware(value);
254: return;
255: } else if (name.equals(INCLUDE_IGNORABLE_WHITESPACE)) {
256: setIgnoringElementContentWhitespace(!value);
257: return;
258: } else if (name.equals(CREATE_ENTITY_REF_NODES_FEATURE)) {
259: setExpandEntityReferences(!value);
260: return;
261: } else if (name.equals(INCLUDE_COMMENTS_FEATURE)) {
262: setIgnoringComments(!value);
263: return;
264: } else if (name.equals(CREATE_CDATA_NODES_FEATURE)) {
265: setCoalescing(!value);
266: return;
267: }
268:
269: if (features == null) {
270: features = new Hashtable();
271: }
272: features.put(name, value ? Boolean.TRUE : Boolean.FALSE);
273: // Test the feature by possibly throwing SAX exceptions
274: try {
275: new DocumentBuilderImpl(this , attributes, features);
276: } catch (SAXNotSupportedException e) {
277: features.remove(name);
278: throw new ParserConfigurationException(e.getMessage());
279: } catch (SAXNotRecognizedException e) {
280: features.remove(name);
281: throw new ParserConfigurationException(e.getMessage());
282: }
283: }
284: }
|