~ubuntu-branches/ubuntu/karmic/libxerces2-java/karmic

« back to all changes in this revision

Viewing changes to src/org/apache/xerces/impl/dtd/XMLDTDLoader.java

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Gybas
  • Date: 2004-06-06 18:00:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040606180026-a3vh56uc95hjbyfh
Tags: upstream-2.6.2
ImportĀ upstreamĀ versionĀ 2.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The Apache Software License, Version 1.1
 
3
 *
 
4
 *
 
5
 * Copyright (c) 1999-2003 The Apache Software Foundation.  
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 *
 
12
 * 1. Redistributions of source code must retain the above copyright
 
13
 *    notice, this list of conditions and the following disclaimer. 
 
14
 *
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in
 
17
 *    the documentation and/or other materials provided with the
 
18
 *    distribution.
 
19
 *
 
20
 * 3. The end-user documentation included with the redistribution,
 
21
 *    if any, must include the following acknowledgment:  
 
22
 *       "This product includes software developed by the
 
23
 *        Apache Software Foundation (http://www.apache.org/)."
 
24
 *    Alternately, this acknowledgment may appear in the software itself,
 
25
 *    if and wherever such third-party acknowledgments normally appear.
 
26
 *
 
27
 * 4. The names "Xerces" and "Apache Software Foundation" must
 
28
 *    not be used to endorse or promote products derived from this
 
29
 *    software without prior written permission. For written 
 
30
 *    permission, please contact apache@apache.org.
 
31
 *
 
32
 * 5. Products derived from this software may not be called "Apache",
 
33
 *    nor may "Apache" appear in their name, without prior written
 
34
 *    permission of the Apache Software Foundation.
 
35
 *
 
36
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 
37
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
38
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
39
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 
40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
42
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 
43
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
44
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
45
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 
46
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
47
 * SUCH DAMAGE.
 
48
 * ====================================================================
 
49
 *
 
50
 * This software consists of voluntary contributions made by many
 
51
 * individuals on behalf of the Apache Software Foundation and was
 
52
 * originally based on software copyright (c) 1999, International
 
53
 * Business Machines, Inc., http://www.apache.org.  For more
 
54
 * information on the Apache Software Foundation, please see
 
55
 * <http://www.apache.org/>.
 
56
 */
 
57
 
 
58
package org.apache.xerces.impl.dtd;
 
59
 
 
60
import org.apache.xerces.impl.Constants;
 
61
import org.apache.xerces.impl.XMLDTDScannerImpl;
 
62
import org.apache.xerces.impl.XMLErrorReporter;
 
63
import org.apache.xerces.impl.XMLEntityManager;
 
64
import org.apache.xerces.impl.msg.XMLMessageFormatter;
 
65
 
 
66
import org.apache.xerces.util.SymbolTable;
 
67
import org.apache.xerces.util.DefaultErrorHandler;
 
68
 
 
69
import org.apache.xerces.xni.XNIException;
 
70
import org.apache.xerces.xni.grammars.XMLGrammarPool;
 
71
import org.apache.xerces.xni.grammars.XMLGrammarLoader;
 
72
import org.apache.xerces.xni.grammars.Grammar;
 
73
import org.apache.xerces.xni.parser.XMLConfigurationException;
 
74
import org.apache.xerces.xni.parser.XMLErrorHandler;
 
75
import org.apache.xerces.xni.parser.XMLEntityResolver;
 
76
import org.apache.xerces.xni.parser.XMLInputSource;
 
77
 
 
78
import java.util.Locale;
 
79
import java.io.IOException;
 
80
import java.io.EOFException;
 
81
 
 
82
/**
 
83
 * The DTD loader. The loader knows how to build grammars from XMLInputSources.
 
84
 * It extends the DTD processor in order to do this; it's
 
85
 * a separate class because DTD processors don't need to know how
 
86
 * to talk to the outside world in their role as instance-document
 
87
 * helpers.
 
88
 * <p>
 
89
 * This component requires the following features and properties.  It
 
90
 * know ho to set them if no one else does:from the
 
91
 * <ul>
 
92
 *  <li>http://xml.org/sax/features/namespaces</li>
 
93
 *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
 
94
 *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
 
95
 *  <li>http://apache.org/xml/properties/internal/grammar-pool</li>
 
96
 *  <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
 
97
 * </ul>
 
98
 *
 
99
 * @author Neil Graham, IBM
 
100
 *
 
101
 * @version $Id: XMLDTDLoader.java,v 1.9 2003/10/14 14:34:26 mrglavas Exp $
 
102
 */
 
103
public class XMLDTDLoader
 
104
        extends XMLDTDProcessor 
 
105
        implements XMLGrammarLoader {
 
106
 
 
107
    //
 
108
    // Constants
 
109
    //
 
110
 
 
111
    // feature identifiers
 
112
 
 
113
    /** Feature identifier: standard uri conformant feature. */
 
114
    protected static final String STANDARD_URI_CONFORMANT_FEATURE =
 
115
        Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
 
116
 
 
117
    // recognized features:
 
118
    private static final String[] RECOGNIZED_FEATURES = {
 
119
        VALIDATION,
 
120
        WARN_ON_DUPLICATE_ATTDEF,
 
121
        NOTIFY_CHAR_REFS,
 
122
        STANDARD_URI_CONFORMANT_FEATURE
 
123
    };
 
124
 
 
125
    // property identifiers
 
126
 
 
127
    /** Property identifier: error handler. */
 
128
    protected static final String ERROR_HANDLER =
 
129
        Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
 
130
 
 
131
    /** Property identifier: entity resolver. */
 
132
    public static final String ENTITY_RESOLVER =
 
133
        Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 
134
 
 
135
    /** Recognized properties. */
 
136
    private static final String[] LOADER_RECOGNIZED_PROPERTIES = {
 
137
        SYMBOL_TABLE,       
 
138
        ERROR_REPORTER,
 
139
        ERROR_HANDLER,
 
140
        ENTITY_RESOLVER,
 
141
        GRAMMAR_POOL,       
 
142
        DTD_VALIDATOR,
 
143
    };
 
144
 
 
145
    // enforcing strict uri?
 
146
    private boolean fStrictURI = false;
 
147
 
 
148
    /** Entity resolver . */
 
149
    protected XMLEntityResolver fEntityResolver;
 
150
 
 
151
    // the scanner we use to actually read the DTD
 
152
    protected XMLDTDScannerImpl fDTDScanner;
 
153
 
 
154
    // the entity manager the scanner needs.  
 
155
    protected XMLEntityManager fEntityManager;
 
156
 
 
157
    // what's our Locale?
 
158
    protected Locale fLocale;
 
159
 
 
160
    //
 
161
    // Constructors
 
162
    //
 
163
 
 
164
    /** Deny default construction; we need a SymtolTable! */
 
165
    public XMLDTDLoader() {
 
166
        this(new SymbolTable());
 
167
    } // <init>()
 
168
 
 
169
    public XMLDTDLoader(SymbolTable symbolTable) {
 
170
        this(symbolTable, null);
 
171
    } // init(SymbolTable)
 
172
 
 
173
    public XMLDTDLoader(SymbolTable symbolTable,
 
174
                XMLGrammarPool grammarPool) {
 
175
        this(symbolTable, grammarPool, null, new XMLEntityManager());
 
176
    } // init(SymbolTable, XMLGrammarPool)
 
177
 
 
178
    XMLDTDLoader(SymbolTable symbolTable,
 
179
                XMLGrammarPool grammarPool, XMLErrorReporter errorReporter, 
 
180
                XMLEntityResolver entityResolver) {
 
181
        fSymbolTable = symbolTable;
 
182
        fGrammarPool = grammarPool;
 
183
        if(errorReporter == null) {
 
184
            errorReporter = new XMLErrorReporter();
 
185
            errorReporter.setProperty(ERROR_HANDLER, new DefaultErrorHandler());
 
186
        }
 
187
        fErrorReporter = errorReporter;
 
188
        // Add XML message formatter if there isn't one.
 
189
        if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 
190
            XMLMessageFormatter xmft = new XMLMessageFormatter();
 
191
            fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 
192
            fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 
193
        }
 
194
        fEntityResolver = entityResolver;
 
195
        if(fEntityResolver instanceof XMLEntityManager) {
 
196
            fEntityManager = (XMLEntityManager)fEntityResolver;
 
197
        } else {
 
198
            fEntityManager = new XMLEntityManager();
 
199
        }
 
200
        fEntityManager.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY, errorReporter);
 
201
        fDTDScanner = new XMLDTDScannerImpl(fSymbolTable, fErrorReporter, fEntityManager);
 
202
        fDTDScanner.setDTDHandler(this);
 
203
        fDTDScanner.setDTDContentModelHandler(this);
 
204
        reset();
 
205
    } // init(SymbolTable, XMLGrammarPool, XMLErrorReporter, XMLEntityResolver)
 
206
 
 
207
    // XMLGrammarLoader methods
 
208
 
 
209
    /**
 
210
     * Sets the state of a feature. This method is called by the component
 
211
     * manager any time after reset when a feature changes state. 
 
212
     * <p>
 
213
     * <strong>Note:</strong> Components should silently ignore features
 
214
     * that do not affect the operation of the component.
 
215
     * 
 
216
     * @param featureId The feature identifier.
 
217
     * @param state     The state of the feature.
 
218
     *
 
219
     * @throws SAXNotRecognizedException The component should not throw
 
220
     *                                   this exception.
 
221
     * @throws SAXNotSupportedException The component should not throw
 
222
     *                                  this exception.
 
223
     */
 
224
    public void setFeature(String featureId, boolean state)
 
225
            throws XMLConfigurationException {
 
226
        if(featureId.equals(VALIDATION)) {
 
227
            fValidation = state;
 
228
        } else if(featureId.equals(WARN_ON_DUPLICATE_ATTDEF)) {
 
229
            fWarnDuplicateAttdef = state;
 
230
        } else if(featureId.equals(NOTIFY_CHAR_REFS)) {
 
231
            fDTDScanner.setFeature(featureId, state);
 
232
        } else if(featureId.equals(STANDARD_URI_CONFORMANT_FEATURE)) {
 
233
            fStrictURI = state;
 
234
        }  else {
 
235
            throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId);
 
236
        }
 
237
    } // setFeature(String,boolean)
 
238
 
 
239
    /**
 
240
     * Returns a list of property identifiers that are recognized by
 
241
     * this component. This method may return null if no properties
 
242
     * are recognized by this component.
 
243
     */
 
244
    public String[] getRecognizedProperties() {
 
245
        return (String[])(LOADER_RECOGNIZED_PROPERTIES.clone());
 
246
    } // getRecognizedProperties():String[]
 
247
 
 
248
    /**
 
249
     * Returns the state of a property.
 
250
     * 
 
251
     * @param propertyId The property identifier.
 
252
     * 
 
253
     * @throws XMLConfigurationException Thrown on configuration error.
 
254
     */
 
255
    public Object getProperty(String propertyId) 
 
256
            throws XMLConfigurationException {
 
257
        if(propertyId.equals( SYMBOL_TABLE)) {
 
258
            return fSymbolTable;
 
259
        } else if(propertyId.equals( ERROR_REPORTER)) {
 
260
            return fErrorReporter;
 
261
        } else if(propertyId.equals( ERROR_HANDLER)) {
 
262
            return fErrorReporter.getErrorHandler();
 
263
        } else if(propertyId.equals( ENTITY_RESOLVER)) {
 
264
            return fEntityResolver;
 
265
        } else if(propertyId.equals( GRAMMAR_POOL)) {
 
266
            return fGrammarPool;
 
267
        } else if(propertyId.equals( DTD_VALIDATOR)) {
 
268
            return fValidator;
 
269
        } 
 
270
        throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, propertyId);
 
271
    } // getProperty(String):  Object
 
272
 
 
273
    /**
 
274
     * Sets the value of a property. This method is called by the component
 
275
     * manager any time after reset when a property changes value. 
 
276
     * <p>
 
277
     * <strong>Note:</strong> Components should silently ignore properties
 
278
     * that do not affect the operation of the component.
 
279
     * 
 
280
     * @param propertyId The property identifier.
 
281
     * @param value      The value of the property.
 
282
     *
 
283
     * @throws SAXNotRecognizedException The component should not throw
 
284
     *                                   this exception.
 
285
     * @throws SAXNotSupportedException The component should not throw
 
286
     *                                  this exception.
 
287
     */
 
288
    public void setProperty(String propertyId, Object value)
 
289
            throws XMLConfigurationException {
 
290
        if(propertyId.equals( SYMBOL_TABLE)) {
 
291
            fSymbolTable = (SymbolTable)value;
 
292
            fDTDScanner.setProperty(propertyId, value);
 
293
            fEntityManager.setProperty(propertyId, value);
 
294
        } else if(propertyId.equals( ERROR_REPORTER)) {
 
295
            fErrorReporter = (XMLErrorReporter)value;
 
296
            // Add XML message formatter if there isn't one.
 
297
            if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 
298
                XMLMessageFormatter xmft = new XMLMessageFormatter();
 
299
                fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 
300
                fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 
301
            }
 
302
            fDTDScanner.setProperty(propertyId, value);
 
303
            fEntityManager.setProperty(propertyId, value);
 
304
        } else if(propertyId.equals( ERROR_HANDLER)) {
 
305
            fErrorReporter.setProperty(propertyId, value);
 
306
        } else if(propertyId.equals( ENTITY_RESOLVER)) {
 
307
            fEntityResolver = (XMLEntityResolver)value;
 
308
        } else if(propertyId.equals( GRAMMAR_POOL)) {
 
309
            fGrammarPool = (XMLGrammarPool)value;
 
310
        } else {
 
311
            throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, propertyId);
 
312
        }
 
313
    } // setProperty(String,Object)
 
314
 
 
315
    /**
 
316
     * Returns the state of a feature.
 
317
     * 
 
318
     * @param featureId The feature identifier.
 
319
     * 
 
320
     * @throws XMLConfigurationException Thrown on configuration error.
 
321
     */
 
322
    public boolean getFeature(String featureId) 
 
323
            throws XMLConfigurationException {
 
324
        if(featureId.equals( VALIDATION)) {
 
325
            return fValidation;
 
326
        } else if(featureId.equals( WARN_ON_DUPLICATE_ATTDEF)) {
 
327
            return fWarnDuplicateAttdef;
 
328
        } else if(featureId.equals( NOTIFY_CHAR_REFS)) {
 
329
            return fDTDScanner.getFeature(featureId);
 
330
        }
 
331
        throw new XMLConfigurationException(XMLConfigurationException.NOT_RECOGNIZED, featureId);
 
332
    } //getFeature(String):  boolean
 
333
 
 
334
    /**
 
335
     * Set the locale to use for messages.
 
336
     *
 
337
     * @param locale The locale object to use for localization of messages.
 
338
     *
 
339
     * @exception XNIException Thrown if the parser does not support the
 
340
     *                         specified locale.
 
341
     */
 
342
    public void setLocale(Locale locale) {
 
343
        fLocale = locale;
 
344
    } // setLocale(Locale)
 
345
 
 
346
    /** Return the Locale the XMLGrammarLoader is using. */
 
347
    public Locale getLocale() {
 
348
        return fLocale;
 
349
    } // getLocale():  Locale
 
350
 
 
351
 
 
352
    /**
 
353
     * Sets the error handler.
 
354
     *
 
355
     * @param errorHandler The error handler.
 
356
     */
 
357
    public void setErrorHandler(XMLErrorHandler errorHandler) {
 
358
        fErrorReporter.setProperty(ERROR_HANDLER, errorHandler);
 
359
    } // setErrorHandler(XMLErrorHandler)
 
360
 
 
361
    /** Returns the registered error handler.  */
 
362
    public XMLErrorHandler getErrorHandler() {
 
363
        return fErrorReporter.getErrorHandler();
 
364
    } // getErrorHandler():  XMLErrorHandler
 
365
 
 
366
    /**
 
367
     * Sets the entity resolver.
 
368
     *
 
369
     * @param entityResolver The new entity resolver.
 
370
     */
 
371
    public void setEntityResolver(XMLEntityResolver entityResolver) {
 
372
        fEntityResolver = entityResolver;
 
373
    } // setEntityResolver(XMLEntityResolver)
 
374
 
 
375
    /** Returns the registered entity resolver.  */
 
376
    public XMLEntityResolver getEntityResolver() {
 
377
        return fEntityResolver;
 
378
    } // getEntityResolver():  XMLEntityResolver
 
379
 
 
380
    /**
 
381
     * Returns a Grammar object by parsing the contents of the
 
382
     * entity pointed to by source.
 
383
     *
 
384
     * @param source        the location of the entity which forms
 
385
     *                          the starting point of the grammar to be constructed.
 
386
     * @throws IOException      When a problem is encountered reading the entity
 
387
     *          XNIException    When a condition arises (such as a FatalError) that requires parsing
 
388
     *                              of the entity be terminated.
 
389
     */
 
390
    public Grammar loadGrammar(XMLInputSource source)
 
391
            throws IOException, XNIException {
 
392
        reset();
 
393
        // First chance checking strict URI
 
394
        String eid = XMLEntityManager.expandSystemId(source.getSystemId(), source.getBaseSystemId(), fStrictURI);
 
395
        fDTDGrammar = new DTDGrammar(fSymbolTable, new XMLDTDDescription(source.getPublicId(), source.getSystemId(), source.getBaseSystemId(), eid, null));
 
396
        fGrammarBucket = new DTDGrammarBucket();
 
397
        fGrammarBucket.setStandalone(false);
 
398
        fGrammarBucket.setActiveGrammar(fDTDGrammar); 
 
399
        // no reason to use grammar bucket's "put" method--we
 
400
        // know which grammar it is, and we don't know the root name anyway...
 
401
 
 
402
        // actually start the parsing!
 
403
        try {
 
404
            fDTDScanner.setInputSource(source);
 
405
            fDTDScanner.scanDTDExternalSubset(true);
 
406
        } catch (EOFException e) {
 
407
            // expected behaviour...
 
408
        }
 
409
        finally {
 
410
            // Close all streams opened by the parser.
 
411
            fEntityManager.closeReaders();
 
412
        }
 
413
        if(fDTDGrammar != null && fGrammarPool != null) {
 
414
            fGrammarPool.cacheGrammars(XMLDTDDescription.XML_DTD, new Grammar[] {fDTDGrammar});
 
415
        }
 
416
        return fDTDGrammar;
 
417
    } // loadGrammar(XMLInputSource):  Grammar
 
418
 
 
419
    // reset all the components that we rely upon
 
420
    protected void reset() {
 
421
        super.reset();
 
422
        fDTDScanner.reset();
 
423
        fEntityManager.reset();
 
424
        fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
 
425
    }
 
426
 
 
427
} // class XMLDTDLoader