View Javadoc
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. */
80      public ParserConfigurationSettings() {
81          this(null);
82      } // <init>()
83  
84      /**
85       * Constructs a parser configuration settings object with a
86       * parent settings object.
87       */
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      */
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      */
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      */
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      */
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      */
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 
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 
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      */
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 
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 
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      */
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      */
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