Statistics
| Revision:

root / import / ext3D / trunk / install-extension3d / IzPack / src / lib / net / n3 / nanoxml / NonValidator.java @ 15280

History | View | Annotate | Download (21.4 KB)

1
/* NonValidator.java                                               NanoXML/Java
2
 *
3
 * $Revision: 1.1 $
4
 * $Date: 2006/06/14 07:29:07 $
5
 * $Name:  $
6
 *
7
 * This file is part of NanoXML 2 for Java.
8
 * Copyright (C) 2001 Marc De Scheemaecker, All Rights Reserved.
9
 *
10
 * This software is provided 'as-is', without any express or implied warranty.
11
 * In no event will the authors be held liable for any damages arising from the
12
 * use of this software.
13
 *
14
 * Permission is granted to anyone to use this software for any purpose,
15
 * including commercial applications, and to alter it and redistribute it
16
 * freely, subject to the following restrictions:
17
 *
18
 *  1. The origin of this software must not be misrepresented; you must not
19
 *     claim that you wrote the original software. If you use this software in
20
 *     a product, an acknowledgment in the product documentation would be
21
 *     appreciated but is not required.
22
 *
23
 *  2. Altered source versions must be plainly marked as such, and must not be
24
 *     misrepresented as being the original software.
25
 *
26
 *  3. This notice may not be removed or altered from any source distribution.
27
 */
28

    
29
package net.n3.nanoxml;
30

    
31

    
32
import java.io.Reader;
33
import java.io.StringReader;
34
import java.util.Enumeration;
35
import java.util.Hashtable;
36
import java.util.Properties;
37
import java.util.Stack;
38

    
39

    
40
/**
41
 * NonValidator processes the DTD and handles entity definitions.
42
 * It does not do any validation itself.
43
 *
44
 * @author Marc De Scheemaecker
45
 * @version $Name:  $, $Revision: 1.1 $
46
 */
47
public class NonValidator
48
    implements IXMLValidator
49
{
50

    
51
    /**
52
     * Delimiter for CDATA sections.
53
     */
54
    private static final char[] END_OF_CONDSECTION = { '>', ']', ']' };
55
    
56
    
57
    /**
58
     * The parameter entity resolver.
59
     */
60
    protected IXMLEntityResolver parameterEntityResolver;
61
    
62
    
63
    /**
64
     * The parameter entity level.
65
     */
66
    protected int peLevel;
67
    
68
    
69
    /**
70
     * Contains the default values for attributes for the different element
71
     * types.
72
     */
73
    protected Hashtable attributeDefaultValues;
74
    
75
    
76
    /**
77
     * The stack of elements to be processed.
78
     */
79
    protected Stack currentElements;
80
    
81
    
82
    /**
83
     * Creates the "validator".
84
     */
85
    public NonValidator()
86
    {
87
        this.attributeDefaultValues = new Hashtable();
88
        this.currentElements = new Stack();
89
        this.parameterEntityResolver = new XMLEntityResolver();
90
        this.peLevel = 0;
91
    }
92
    
93
    
94
    /**
95
     * Cleans up the object when it's destroyed.
96
     */
97
    protected void finalize()
98
        throws Throwable
99
    {
100
        this.parameterEntityResolver = null;
101
        this.attributeDefaultValues.clear();
102
        this.attributeDefaultValues = null;
103
        this.currentElements.clear();
104
        this.currentElements = null;
105
        super.finalize();
106
    }
107
    
108
    
109
    /**
110
     * Sets the parameter entity resolver.
111
     *
112
     * @param resolver the entity resolver.
113
     */
114
    public void setParameterEntityResolver(IXMLEntityResolver resolver)
115
    {
116
        this.parameterEntityResolver = resolver;
117
    }
118
    
119
    
120
    /**
121
     * Returns the parameter entity resolver.
122
     *
123
     * @return the entity resolver.
124
     */
125
    public IXMLEntityResolver getParameterEntityResolver()
126
    {
127
        return this.parameterEntityResolver;
128
    }
129
    
130
    
131
    /**
132
     * Parses the DTD. The validator object is responsible for reading the
133
     * full DTD.
134
     *
135
     * @param publicID       the public ID, which may be null.
136
     * @param reader         the reader to read the DTD from.
137
     * @param entityResolver the entity resolver.
138
     * @param external       true if the DTD is external.
139
     *
140
     * @throws java.lang.Exception
141
     *     if something went wrong.
142
     */
143
    public void parseDTD(String             publicID,
144
                         IXMLReader         reader,
145
                         IXMLEntityResolver entityResolver,
146
                         boolean            external)
147
        throws Exception
148
    {
149
        XMLUtil.skipWhitespace(reader, '%', null, null);
150
        
151
        for (;;) {
152
            char ch = XMLUtil.read(reader, null, '%',
153
                                   this.parameterEntityResolver);
154
            
155
            if (ch == '<') {
156
                this.processElement(reader, entityResolver);
157
            } else if (ch == ']') {
158
                return; // end internal DTD
159
            } else {
160
                XMLUtil.errorInvalidInput(reader.getSystemID(),
161
                                          reader.getLineNr(),
162
                                          "" + ch);
163
            }
164
            
165
            do {
166
                if (external
167
                        && (peLevel == 0)
168
                        && reader.atEOFOfCurrentStream()) {
169
                    return; // end external DTD
170
                }
171
                
172
                ch = reader.read();
173
            } while ((ch == ' ') || (ch == '\t') || (ch == '\n')
174
                     || (ch == '\r'));
175
                     
176
            reader.unread(ch);
177
            XMLUtil.skipWhitespace(reader, '%', null, null);
178
        }
179
    }
180
    
181

    
182
    /**
183
     * Processes an element in the DTD.
184
     *
185
     * @param reader         the reader to read data from
186
     * @param entityResolver the entity resolver
187
     *
188
     * @throws java.lang.Exception
189
     *     if something went wrong.
190
     */
191
    protected void processElement(IXMLReader         reader,
192
                                  IXMLEntityResolver entityResolver)
193
        throws Exception
194
    {
195
        char ch = XMLUtil.read(reader, null,'%', this.parameterEntityResolver);
196
        
197
        if (ch != '!') {
198
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
199
            return;
200
        }
201
        
202
        ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
203
        
204
        switch (ch) {
205
            case '-':
206
                XMLUtil.skipComment(reader, this.parameterEntityResolver);
207
                break;
208
                
209
            case '[':
210
                this.processConditionalSection(reader, entityResolver);
211
                break;
212
                
213
            case 'E':
214
                this.processEntity(reader, entityResolver);
215
                break;
216
                
217
            case 'A':
218
                this.processAttList(reader, entityResolver);
219
                break;
220
                
221
            default:
222
                XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
223
        }
224
    }
225
    
226
    
227
    /**
228
     * Processes a conditional section.
229
     *
230
     * @param reader         the reader to read data from
231
     * @param entityResolver the entity resolver
232
     *
233
     * @throws java.lang.Exception
234
     *     if something went wrong.
235
     */
236
    protected void processConditionalSection(IXMLReader         reader,
237
                                             IXMLEntityResolver entityResolver)
238
        throws Exception
239
    {
240
        XMLUtil.skipWhitespace(reader, '%', null, null);
241
        
242
        char ch = XMLUtil.read(reader, null,'%', this.parameterEntityResolver);
243
        
244
        if (ch != 'I') {
245
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
246
            return;
247
        }
248
        
249
        ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
250
        
251
        switch (ch) {
252
            case 'G':
253
                this.processIgnoreSection(reader, entityResolver);
254
                return;
255
                
256
            case 'N':
257
                break;
258
                
259
            default:
260
                XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
261
                return;
262
        }
263
        
264
        if (! XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver,
265
                                   "CLUDE")) {
266
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
267
            return;
268
        }
269
        
270
        XMLUtil.skipWhitespace(reader, '%', null, null);
271
        
272
        ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
273
        
274
        if (ch != '[') {
275
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
276
            return;
277
        }
278
        
279
        Reader subreader
280
                = new ContentReader(reader, this.parameterEntityResolver,
281
                                    '\0', NonValidator.END_OF_CONDSECTION,
282
                                    true, "");
283
        StringBuffer buf = new StringBuffer(1024);
284
        
285
        for (;;) {
286
            int ch2 = subreader.read();
287
            
288
            if (ch2 < 0) {
289
                break;
290
            }
291
            
292
            buf.append((char) ch2);
293
        }
294
        
295
        subreader.close();
296
        reader.startNewStream(new StringReader(buf.toString())); 
297
    }
298
        
299
    
300
    
301
    /**
302
     * Processes an ignore section.
303
     *
304
     * @param reader         the reader to read data from
305
     * @param entityResolver the entity resolver
306
     *
307
     * @throws java.lang.Exception
308
     *     if something went wrong.
309
     */
310
    protected void processIgnoreSection(IXMLReader         reader,
311
                                        IXMLEntityResolver entityResolver)
312
        throws Exception
313
    {
314
        if (! XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver,
315
                                   "NORE")) {
316
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
317
            return;
318
        }
319
        
320
        XMLUtil.skipWhitespace(reader, '%', null, null);
321
        
322
        char ch = XMLUtil.read(reader, null,'%', this.parameterEntityResolver);
323
        
324
        if (ch != '[') {
325
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
326
            return;
327
        }
328
        
329
        Reader subreader
330
                = new ContentReader(reader, this.parameterEntityResolver,
331
                                    '\0', NonValidator.END_OF_CONDSECTION,
332
                                    true, "");
333
        subreader.close();
334
    }
335
        
336
    
337
    /**
338
     * Processes an ATTLIST element.
339
     *
340
     * @param reader         the reader to read data from
341
     * @param entityResolver the entity resolver
342
     *
343
     * @throws java.lang.Exception
344
     *     if something went wrong.
345
     */
346
    protected void processAttList(IXMLReader         reader,
347
                                  IXMLEntityResolver entityResolver)
348
        throws Exception
349
    {
350
        if (! XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver,
351
                                   "TTLIST")) {
352
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
353
            return;
354
        }
355
        
356
        XMLUtil.skipWhitespace(reader, '%', null, null);
357
        String elementName
358
                = XMLUtil.scanIdentifier(reader, '%',
359
                                         this.parameterEntityResolver);
360
        XMLUtil.skipWhitespace(reader, '%', null, null);
361
        char ch = XMLUtil.read(reader, null,'%', this.parameterEntityResolver);
362
        Properties props = new Properties();
363
        
364
        while (ch != '>') {
365
            reader.unread(ch);
366
            String attName
367
                    = XMLUtil.scanIdentifier(reader, '%',
368
                                             this.parameterEntityResolver);
369
            XMLUtil.skipWhitespace(reader, '%', null, null);
370
            ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
371
            
372
            if (ch == '(') {
373
                while (ch != ')') {
374
                    ch = XMLUtil.read(reader, null, '%',
375
                                      this.parameterEntityResolver);
376
                }
377
            } else {
378
                reader.unread(ch);
379
                XMLUtil.scanIdentifier(reader, '%',
380
                                       this.parameterEntityResolver);
381
            }
382
            
383
            XMLUtil.skipWhitespace(reader, '%', null, null);
384
            ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
385
            
386
            if (ch == '#') {
387
                String str
388
                        = XMLUtil.scanIdentifier(reader, '%',
389
                                                 this.parameterEntityResolver);
390
                XMLUtil.skipWhitespace(reader, '%', null, null);
391
                
392
                if (! str.equals("FIXED")) {
393
                    XMLUtil.skipWhitespace(reader, '%', null, null);
394
                    ch = XMLUtil.read(reader, null, '%',
395
                                      this.parameterEntityResolver);
396
                    continue;
397
                }
398
            } else {
399
                reader.unread(ch);
400
            }
401
            
402
            String value = XMLUtil.scanString(reader, '%', false,
403
                                              this.parameterEntityResolver);
404
            props.put(attName, value);
405
            XMLUtil.skipWhitespace(reader, '%', null, null);
406
            ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
407
        }
408
        
409
        if (! props.isEmpty()) {
410
            this.attributeDefaultValues.put(elementName, props);
411
        }
412
    }
413
    
414
    
415
    /**
416
     * Processes an ENTITY element.
417
     *
418
     * @param reader         the reader to read data from
419
     * @param entityResolver the entity resolver
420
     *
421
     * @throws java.lang.Exception
422
     *     if something went wrong.
423
     */
424
    protected void processEntity(IXMLReader         reader,
425
                                 IXMLEntityResolver entityResolver)
426
        throws Exception
427
    {
428
        if (! XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver,
429
                                   "NTITY")) {
430
            XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
431
            return;
432
        }
433
        
434
        XMLUtil.skipWhitespace(reader, '\0', null, null);
435
        char ch = XMLUtil.read(reader, null, '\0',
436
                               this.parameterEntityResolver);
437
        
438
        if (ch == '%') {
439
            XMLUtil.skipWhitespace(reader, '%', null, null);
440
            entityResolver = this.parameterEntityResolver;
441
        } else {
442
            reader.unread(ch);
443
        }
444
        
445
        String key = XMLUtil.scanIdentifier(reader, '%',
446
                                            this.parameterEntityResolver);
447
        XMLUtil.skipWhitespace(reader, '%', null, null);
448
        ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
449
        String systemID = null;
450
        String publicID = null;
451
        
452
        switch (ch) {
453
            case 'P':
454
                if (! XMLUtil.checkLiteral(reader, '%',
455
                                           this.parameterEntityResolver,
456
                                           "UBLIC")) {
457
                    XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
458
                    return;
459
                }
460
                
461
                XMLUtil.skipWhitespace(reader, '%', null, null);
462
                publicID = XMLUtil.scanString(reader, '%', false,
463
                                              this.parameterEntityResolver);
464
                XMLUtil.skipWhitespace(reader, '%', null, null);
465
                systemID = XMLUtil.scanString(reader, '%', false,
466
                                              this.parameterEntityResolver);
467
                XMLUtil.skipWhitespace(reader, '%', null, null);
468
                XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
469
                break;
470
                
471
            case 'S':
472
                if (! XMLUtil.checkLiteral(reader, '%',
473
                                           this.parameterEntityResolver,
474
                                           "YSTEM")) {
475
                    XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
476
                    return;
477
                }
478
        
479
                XMLUtil.skipWhitespace(reader, '%', null, null);
480
                systemID = XMLUtil.scanString(reader, '%', false,
481
                                              this.parameterEntityResolver);
482
                XMLUtil.skipWhitespace(reader, '%', null, null);
483
                XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
484
                break;
485
                
486
            case '"':
487
            case '\'':
488
                reader.unread(ch);
489
                String value = XMLUtil.scanString(reader, '%', false,
490
                                                 this.parameterEntityResolver);
491
                entityResolver.addInternalEntity(key, value);
492
                XMLUtil.skipWhitespace(reader, '%', null, null);
493
                XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
494
                break;
495
            default:
496
                XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
497
        }
498
        
499
        if (systemID != null) {
500
            entityResolver.addExternalEntity(key, publicID, systemID);
501
        }
502
    }
503
     
504

    
505
    /**
506
     * Indicates that an element has been started.
507
     *
508
     * @param name       the name of the element.
509
     * @param nsPrefix   the prefix used to identify the namespace
510
     * @param nsSystemId the system ID associated with the namespace
511
     * @param systemId   the system ID of the XML data of the element.
512
     * @param lineNr     the line number in the XML data of the element.
513
     */
514
    public void elementStarted(String name,
515
                               String nsPrefix,
516
                               String nsSystemId,
517
                               String systemId,
518
                               int    lineNr)
519
    {
520
        Properties attribs
521
                = (Properties) this.attributeDefaultValues.get(name);
522
        
523
        if (attribs == null) {
524
            attribs = new Properties();
525
        } else {
526
            attribs = (Properties) attribs.clone();
527
        }
528
        
529
        this.currentElements.push(attribs);
530
    }
531
    
532
                             
533
    /**
534
     * Indicates that the current element has ended.
535
     *
536
     * @param name       the name of the element.
537
     * @param nsPrefix   the prefix used to identify the namespace
538
     * @param nsSystemId the system ID associated with the namespace
539
     * @param systemId   the system ID of the XML data of the element.
540
     * @param lineNr     the line number in the XML data of the element.
541
     */
542
    public void elementEnded(String name,
543
                             String nsPrefix,
544
                             String nsSystemId,
545
                             String systemId,
546
                             int    lineNr)
547
    {
548
        // nothing to do
549
    }
550
    
551
    
552
    /**
553
     * This method is called when the attributes of an XML element have been
554
     * processed.
555
     * If there are attributes with a default value which have not been
556
     * specified yet, they have to be put into <I>extraAttributes</I>.
557
     *
558
     * @param name            the name of the element.
559
     * @param nsPrefix        the prefix used to identify the namespace
560
     * @param nsSystemId      the system ID associated with the namespace
561
     * @param extraAttributes where to put extra attributes.
562
     * @param systemId        the system ID of the XML data of the element.
563
     * @param lineNr          the line number in the XML data of the element.
564
     */
565
    public void elementAttributesProcessed(String     name,
566
                                           String     nsPrefix,
567
                                           String     nsSystemId,
568
                                           Properties extraAttributes,
569
                                           String     systemId,
570
                                           int        lineNr)
571
    {
572
        Properties props = (Properties) this.currentElements.pop();
573
        Enumeration enum = props.keys();
574
        
575
        while (enum.hasMoreElements()) {
576
            String key = (String) enum.nextElement();
577
            extraAttributes.put(key, props.get(key));
578
        }
579
    }
580
    
581
    
582
    /**
583
     * Indicates that an attribute has been added to the current element.
584
     *
585
     * @param key        the name of the attribute.
586
     * @param nsPrefix   the prefix used to identify the namespace
587
     * @param nsSystemId the system ID associated with the namespace
588
     * @param value      the value of the attribute.
589
     * @param systemId   the system ID of the XML data of the element.
590
     * @param lineNr     the line number in the XML data of the element.
591
     */
592
    public void attributeAdded(String key,
593
                               String nsPrefix,
594
                               String nsSystemId,
595
                               String value,
596
                               String systemId,
597
                               int    lineNr)
598
    {
599
        Properties props = (Properties) this.currentElements.peek();
600
        
601
        if (props.containsKey(key)) {
602
            props.remove(key);
603
        }
604
    }
605
    
606
                             
607
    /**
608
     * Indicates that a new #PCDATA element has been encountered.
609
     *
610
     * @param systemId the system ID of the XML data of the element.
611
     * @param lineNr   the line number in the XML data of the element.
612
     */
613
    public void PCDataAdded(String systemId,
614
                            int    lineNr)
615
    {
616
        // nothing to do
617
    }
618
   
619
}