1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Copyright 2001, 2002,2004 The Apache Software Foundation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * 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.util;
22 
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Set;
28 
29 import com.sun.org.apache.xerces.internal.impl.Constants;
30 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
31 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
32 
33 /**
34  * This class implements the basic operations for managing parser
35  * configuration features and properties. This utility class can
36  * be used as a base class for parser configurations or separately
37  * to encapsulate a number of parser settings as a component
38  * manager.
39  * <p>
40  * This class can be constructed with a "parent" settings object
41  * (in the form of an <code>XMLComponentManager</code>) that allows
42  * parser configuration settings to be "chained" together.
43  *
44  * @author Andy Clark, IBM
45  *
46  * @version $Id: ParserConfigurationSettings.java,v 1.6 2010-11-01 04:40:14 joehw Exp $
47  */
48 public class ParserConfigurationSettings
49     implements XMLComponentManager {
50 
51         protected static final String PARSER_SETTINGS =
52                         Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
53 
54     //
55     // Data
56     //
57 
58     // data
59 
60     /** Recognized properties. */
61     protected Set<String> fRecognizedProperties;
62 
63     /** Properties. */
64     protected Map<String, Object> fProperties;
65 
66     /** Recognized features. */
67     protected Set<String> fRecognizedFeatures;
68 
69     /** Features. */
70     protected Map<String, Boolean> fFeatures;
71 
72     /** Parent parser configuration settings. */
73     protected XMLComponentManager fParentSettings;
74 
75     //
76     // Constructors
77     //
78 
79     /** Default Constructor. */
ParserConfigurationSettings()80     public ParserConfigurationSettings() {
81         this(null);
82     } // <init>()
83 
84     /**
85      * Constructs a parser configuration settings object with a
86      * parent settings object.
87      */
ParserConfigurationSettings(XMLComponentManager parent)88     public ParserConfigurationSettings(XMLComponentManager parent) {
89 
90         // create storage for recognized features and properties
91         fRecognizedFeatures = new HashSet<String>();
92         fRecognizedProperties = new HashSet<String>();
93 
94         // create table for features and properties
95         fFeatures = new HashMap<String, Boolean>();
96         fProperties = new HashMap<String, Object>();
97 
98         // save parent
99         fParentSettings = parent;
100 
101     } // <init>(XMLComponentManager)
102 
103     //
104     // XMLParserConfiguration methods
105     //
106 
107     /**
108      * Allows a parser to add parser specific features to be recognized
109      * and managed by the parser configuration.
110      *
111      * @param featureIds An array of the additional feature identifiers
112      *                   to be recognized.
113      */
addRecognizedFeatures(String[] featureIds)114     public void addRecognizedFeatures(String[] featureIds) {
115 
116         // add recognized features
117         int featureIdsCount = featureIds != null ? featureIds.length : 0;
118         for (int i = 0; i < featureIdsCount; i++) {
119             String featureId = featureIds[i];
120             if (!fRecognizedFeatures.contains(featureId)) {
121                 fRecognizedFeatures.add(featureId);
122             }
123         }
124 
125     } // addRecognizedFeatures(String[])
126 
127     /**
128      * Set the state of a feature.
129      *
130      * Set the state of any feature in a SAX2 parser.  The parser
131      * might not recognize the feature, and if it does recognize
132      * it, it might not be able to fulfill the request.
133      *
134      * @param featureId The unique identifier (URI) of the feature.
135      * @param state The requested state of the feature (true or false).
136      *
137      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
138      *            requested feature is not known.
139      */
setFeature(String featureId, boolean state)140     public void setFeature(String featureId, boolean state)
141         throws XMLConfigurationException {
142 
143         // check and store
144         FeatureState checkState = checkFeature(featureId);
145         if (checkState.isExceptional()) {
146             throw new XMLConfigurationException(checkState.status, featureId);
147         }
148 
149         fFeatures.put(featureId, state);
150     } // setFeature(String,boolean)
151 
152     /**
153      * Allows a parser to add parser specific properties to be recognized
154      * and managed by the parser configuration.
155      *
156      * @param propertyIds An array of the additional property identifiers
157      *                    to be recognized.
158      */
addRecognizedProperties(String[] propertyIds)159     public void addRecognizedProperties(String[] propertyIds) {
160         fRecognizedProperties.addAll(Arrays.asList(propertyIds));
161     } // addRecognizedProperties(String[])
162 
163     /**
164      * setProperty
165      *
166      * @param propertyId
167      * @param value
168      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
169      *            requested feature is not known.
170      */
setProperty(String propertyId, Object value)171     public void setProperty(String propertyId, Object value)
172         throws XMLConfigurationException {
173 
174         // check and store
175         PropertyState checkState = checkProperty(propertyId);
176         if (checkState.isExceptional()) {
177             throw new XMLConfigurationException(checkState.status, propertyId);
178         }
179         fProperties.put(propertyId, value);
180 
181     } // setProperty(String,Object)
182 
183     //
184     // XMLComponentManager methods
185     //
186 
187     /**
188      * Returns the state of a feature.
189      *
190      * @param featureId The feature identifier.
191                  * @return true if the feature is supported
192      *
193      * @throws XMLConfigurationException Thrown for configuration error.
194      *                                   In general, components should
195      *                                   only throw this exception if
196      *                                   it is <strong>really</strong>
197      *                                   a critical error.
198      */
getFeature(String featureId)199     public final boolean getFeature(String featureId)
200         throws XMLConfigurationException {
201 
202         FeatureState state = getFeatureState(featureId);
203         if (state.isExceptional()) {
204             throw new XMLConfigurationException(state.status, featureId);
205         }
206         return state.state;
207     } // getFeature(String):boolean
208 
getFeature(String featureId, boolean defaultValue)209     public final boolean getFeature(String featureId, boolean defaultValue) {
210         FeatureState state = getFeatureState(featureId);
211         if (state.isExceptional()) {
212             return defaultValue;
213         }
214         return state.state;
215     }
216 
getFeatureState(String featureId)217     public FeatureState getFeatureState(String featureId) {
218         Boolean state = (Boolean) fFeatures.get(featureId);
219 
220         if (state == null) {
221             FeatureState checkState = checkFeature(featureId);
222             if (checkState.isExceptional()) {
223                 return checkState;
224             }
225             return FeatureState.is(false);
226         }
227         return FeatureState.is(state);
228     }
229 
230     /**
231      * Returns the value of a property.
232      *
233      * @param propertyId The property identifier.
234                  * @return the value of the property
235      *
236      * @throws XMLConfigurationException Thrown for configuration error.
237      *                                   In general, components should
238      *                                   only throw this exception if
239      *                                   it is <strong>really</strong>
240      *                                   a critical error.
241      */
getProperty(String propertyId)242     public final Object getProperty(String propertyId)
243         throws XMLConfigurationException {
244 
245         PropertyState state = getPropertyState(propertyId);
246         if (state.isExceptional()) {
247             throw new XMLConfigurationException(state.status, propertyId);
248         }
249 
250         return state.state;
251     } // getProperty(String):Object
252 
getProperty(String propertyId, Object defaultValue)253     public final Object getProperty(String propertyId, Object defaultValue) {
254         PropertyState state = getPropertyState(propertyId);
255         if (state.isExceptional()) {
256             return defaultValue;
257         }
258 
259         return state.state;
260     }
261 
getPropertyState(String propertyId)262     public PropertyState getPropertyState(String propertyId) {
263         Object propertyValue = fProperties.get(propertyId);
264 
265         if (propertyValue == null) {
266             PropertyState state = checkProperty(propertyId);
267             if (state.isExceptional()) {
268                 return state;
269             }
270         }
271 
272         return PropertyState.is(propertyValue);
273     }
274 
275     //
276     // Protected methods
277     //
278 
279     /**
280      * Check a feature. If feature is known and supported, this method simply
281      * returns. Otherwise, the appropriate exception is thrown.
282      *
283      * @param featureId The unique identifier (URI) of the feature.
284      *
285      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
286      *            requested feature is not known.
287      */
checkFeature(String featureId)288     protected FeatureState checkFeature(String featureId)
289         throws XMLConfigurationException {
290 
291         // check feature
292         if (!fRecognizedFeatures.contains(featureId)) {
293             if (fParentSettings != null) {
294                 return fParentSettings.getFeatureState(featureId);
295             }
296             else {
297                 return FeatureState.NOT_RECOGNIZED;
298             }
299         }
300 
301         // TODO: reasonable default?
302         return FeatureState.RECOGNIZED;
303     } // checkFeature(String)
304 
305     /**
306      * Check a property. If the property is known and supported, this method
307      * simply returns. Otherwise, the appropriate exception is thrown.
308      *
309      * @param propertyId The unique identifier (URI) of the property
310      *                   being set.
311      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
312      *            requested feature is not known.
313      */
checkProperty(String propertyId)314     protected PropertyState checkProperty(String propertyId)
315         throws XMLConfigurationException {
316 
317         // check property
318         if (!fRecognizedProperties.contains(propertyId)) {
319             if (fParentSettings != null) {
320                 PropertyState state = fParentSettings.getPropertyState(propertyId);
321                 if (state.isExceptional()) {
322                     return state;
323                 }
324             }
325             else {
326                 return PropertyState.NOT_RECOGNIZED;
327             }
328         }
329         return PropertyState.RECOGNIZED;
330     } // checkProperty(String)
331 
332 } // class ParserConfigurationSettings
333