1 /*
2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
3  */
4 /*
5  * Licensed to the Apache Software Foundation (ASF) under one or more
6  * contributor license agreements.  See the NOTICE file distributed with
7  * this work for additional information regarding copyright ownership.
8  * The ASF licenses this file to You under the Apache License, Version 2.0
9  * (the "License"); you may not use this file except in compliance with
10  * the License.  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 package com.sun.org.apache.xerces.internal.jaxp;
22 
23 import com.sun.org.apache.xerces.internal.parsers.DOMParser;
24 import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
25 import java.util.HashMap;
26 import java.util.Map;
27 import javax.xml.XMLConstants;
28 import javax.xml.parsers.DocumentBuilder;
29 import javax.xml.parsers.DocumentBuilderFactory;
30 import javax.xml.parsers.ParserConfigurationException;
31 import javax.xml.validation.Schema;
32 import org.xml.sax.SAXException;
33 import org.xml.sax.SAXNotRecognizedException;
34 import org.xml.sax.SAXNotSupportedException;
35 
36 /**
37  * @author Rajiv Mordani
38  * @author Edwin Goei
39  */
40 public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory {
41     /** These are DocumentBuilderFactory attributes not DOM attributes */
42     private Map<String, Object> attributes;
43     private Map<String, Boolean> features;
44     private Schema grammar;
45     private boolean isXIncludeAware;
46 
47     /**
48      * State of the secure processing feature, initially <code>false</code>
49      */
50     private boolean fSecureProcess = true;
51 
52     /**
53      * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder}
54      * using the currently configured parameters.
55      */
newDocumentBuilder()56     public DocumentBuilder newDocumentBuilder()
57         throws ParserConfigurationException
58     {
59         /** Check that if a Schema has been specified that neither of the schema properties have been set. */
60         if (grammar != null && attributes != null) {
61             if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_LANGUAGE)) {
62                 throw new ParserConfigurationException(
63                         SAXMessageFormatter.formatMessage(null,
64                         "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_LANGUAGE}));
65             }
66             else if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_SOURCE)) {
67                 throw new ParserConfigurationException(
68                         SAXMessageFormatter.formatMessage(null,
69                         "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_SOURCE}));
70             }
71         }
72 
73         try {
74             return new DocumentBuilderImpl(this, attributes, features, fSecureProcess);
75         } catch (SAXException se) {
76             // Handles both SAXNotSupportedException, SAXNotRecognizedException
77             throw new ParserConfigurationException(se.getMessage());
78         }
79     }
80 
81     /**
82      * Allows the user to set specific attributes on the underlying
83      * implementation.
84      * @param name    name of attribute
85      * @param value   null means to remove attribute
86      */
setAttribute(String name, Object value)87     public void setAttribute(String name, Object value)
88         throws IllegalArgumentException
89     {
90         // This handles removal of attributes
91         if (value == null) {
92             if (attributes != null) {
93                 attributes.remove(name);
94             }
95             // Unrecognized attributes do not cause an exception
96             return;
97         }
98 
99         // This is ugly.  We have to collect the attributes and then
100         // later create a DocumentBuilderImpl to verify the attributes.
101 
102         // Create the Map if none existed before
103         if (attributes == null) {
104             attributes = new HashMap<>();
105         }
106 
107         attributes.put(name, value);
108 
109         // Test the attribute name by possibly throwing an exception
110         try {
111             new DocumentBuilderImpl(this, attributes, features);
112         } catch (Exception e) {
113             attributes.remove(name);
114             throw new IllegalArgumentException(e.getMessage());
115         }
116     }
117 
118     /**
119      * Allows the user to retrieve specific attributes on the underlying
120      * implementation.
121      */
getAttribute(String name)122     public Object getAttribute(String name)
123         throws IllegalArgumentException
124     {
125         // See if it's in the attributes Map
126         if (attributes != null) {
127             Object val = attributes.get(name);
128             if (val != null) {
129                 return val;
130             }
131         }
132 
133         DOMParser domParser = null;
134         try {
135             // We create a dummy DocumentBuilderImpl in case the attribute
136             // name is not one that is in the attributes map.
137             domParser =
138                 new DocumentBuilderImpl(this, attributes, features).getDOMParser();
139             return domParser.getProperty(name);
140         } catch (SAXException se1) {
141             // assert(name is not recognized or not supported), try feature
142             try {
143                 boolean result = domParser.getFeature(name);
144                 // Must have been a feature
145                 return result ? Boolean.TRUE : Boolean.FALSE;
146             } catch (SAXException se2) {
147                 // Not a property or a feature
148                 throw new IllegalArgumentException(se1.getMessage());
149             }
150         }
151     }
152 
getSchema()153     public Schema getSchema() {
154         return grammar;
155     }
156 
setSchema(Schema grammar)157     public void setSchema(Schema grammar) {
158         this.grammar = grammar;
159     }
160 
isXIncludeAware()161     public boolean isXIncludeAware() {
162         return this.isXIncludeAware;
163     }
164 
setXIncludeAware(boolean state)165     public void setXIncludeAware(boolean state) {
166         this.isXIncludeAware = state;
167     }
168 
getFeature(String name)169     public boolean getFeature(String name)
170         throws ParserConfigurationException {
171         if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
172             return fSecureProcess;
173         }
174         // See if it's in the features map
175         if (features != null) {
176             Boolean val = features.get(name);
177             if (val != null) {
178                 return val;
179             }
180         }
181         try {
182             DOMParser domParser = new DocumentBuilderImpl(this, attributes, features).getDOMParser();
183             return domParser.getFeature(name);
184         }
185         catch (SAXException e) {
186             throw new ParserConfigurationException(e.getMessage());
187         }
188     }
189 
setFeature(String name, boolean value)190     public void setFeature(String name, boolean value)
191         throws ParserConfigurationException {
192         if (features == null) {
193             features = new HashMap<>();
194         }
195         // If this is the secure processing feature, save it then return.
196         if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
197             if (System.getSecurityManager() != null && (!value)) {
198                 throw new ParserConfigurationException(
199                         SAXMessageFormatter.formatMessage(null,
200                         "jaxp-secureprocessing-feature", null));
201             }
202             fSecureProcess = value;
203             features.put(name, value ? Boolean.TRUE : Boolean.FALSE);
204             return;
205         }
206 
207         features.put(name, value ? Boolean.TRUE : Boolean.FALSE);
208         // Test the feature by possibly throwing SAX exceptions
209         try {
210             new DocumentBuilderImpl(this, attributes, features);
211         }
212         catch (SAXNotSupportedException e) {
213             features.remove(name);
214             throw new ParserConfigurationException(e.getMessage());
215         }
216         catch (SAXNotRecognizedException e) {
217             features.remove(name);
218             throw new ParserConfigurationException(e.getMessage());
219         }
220     }
221 }
222