OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [xml/] [aelfred2/] [SAXDriver.java] - Blame information for rev 858

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* SAXDriver.java --
2
   Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version.
37
 
38
Portions derived from code which carried the following notice:
39
 
40
  Copyright (c) 1997, 1998 by Microstar Software Ltd.
41
 
42
  AElfred is free for both commercial and non-commercial use and
43
  redistribution, provided that Microstar's copyright and disclaimer are
44
  retained intact.  You are free to modify AElfred for your own use and
45
  to redistribute AElfred with your modifications, provided that the
46
  modifications are clearly documented.
47
 
48
  This program is distributed in the hope that it will be useful, but
49
  WITHOUT ANY WARRANTY; without even the implied warranty of
50
  merchantability or fitness for a particular purpose.  Please use it AT
51
  YOUR OWN RISK.
52
*/
53
 
54
package gnu.xml.aelfred2;
55
 
56
import java.io.*;
57
 
58
import java.net.MalformedURLException;
59
import java.net.URL;
60
import java.util.Locale;
61
import java.util.Stack;
62
 
63
import java.util.ArrayList;
64
import java.util.Collections;
65
import java.util.Enumeration;
66
import java.util.Iterator;
67
import java.util.List;
68
 
69
import org.xml.sax.*;
70
import org.xml.sax.ext.*;
71
import org.xml.sax.helpers.NamespaceSupport;
72
 
73
 
74
/**
75
 * An enhanced SAX2 version of Microstar's Ælfred XML parser.
76
 * The enhancements primarily relate to significant improvements in
77
 * conformance to the XML specification, and SAX2 support.  Performance
78
 * has been improved.  See the package level documentation for more
79
 * information.
80
 *
81
 * <table border="1" width='100%' cellpadding='3' cellspacing='0'>
82
 * <tr bgcolor='#ccccff'>
83
 *      <th><font size='+1'>Name</font></th>
84
 *      <th><font size='+1'>Notes</font></th></tr>
85
 *
86
 * <tr><td colspan=2><center><em>Features ... URL prefix is
87
 * <b>http://xml.org/sax/features/</b></em></center></td></tr>
88
 *
89
 * <tr><td>(URL)/external-general-entities</td>
90
 *      <td>Value defaults to <em>true</em></td></tr>
91
 * <tr><td>(URL)/external-parameter-entities</td>
92
 *      <td>Value defaults to <em>true</em></td></tr>
93
 * <tr><td>(URL)/is-standalone</td>
94
 *      <td>(PRELIMINARY) Returns true iff the document's parsing
95
 *      has started (some non-error event after <em>startDocument()</em>
96
 *      was reported) and the document's standalone flag is set.</td></tr>
97
 * <tr><td>(URL)/namespace-prefixes</td>
98
 *      <td>Value defaults to <em>false</em> (but XML 1.0 names are
99
 *              always reported)</td></tr>
100
 * <tr><td>(URL)/lexical-handler/parameter-entities</td>
101
 *      <td>Value is fixed at <em>true</em></td></tr>
102
 * <tr><td>(URL)/namespaces</td>
103
 *      <td>Value defaults to <em>true</em></td></tr>
104
 * <tr><td>(URL)/resolve-dtd-uris</td>
105
 *      <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
106
 * <tr><td>(URL)/string-interning</td>
107
 *      <td>Value is fixed at <em>true</em></td></tr>
108
 * <tr><td>(URL)/use-attributes2</td>
109
 *      <td>(PRELIMINARY) Value is fixed at <em>true</em></td></tr>
110
 * <tr><td>(URL)/use-entity-resolver2</td>
111
 *      <td>(PRELIMINARY) Value defaults to <em>true</em></td></tr>
112
 * <tr><td>(URL)/validation</td>
113
 *      <td>Value is fixed at <em>false</em></td></tr>
114
 *
115
 * <tr><td colspan=2><center><em>Handler Properties ... URL prefix is
116
 * <b>http://xml.org/sax/properties/</b></em></center></td></tr>
117
 *
118
 * <tr><td>(URL)/declaration-handler</td>
119
 *      <td>A declaration handler may be provided.  </td></tr>
120
 * <tr><td>(URL)/lexical-handler</td>
121
 *      <td>A lexical handler may be provided.  </td></tr>
122
 * </table>
123
 *
124
 * <p>This parser currently implements the SAX1 Parser API, but
125
 * it may not continue to do so in the future.
126
 *
127
 * @author Written by David Megginson (version 1.2a from Microstar)
128
 * @author Updated by David Brownell &lt;dbrownell@users.sourceforge.net&gt;
129
 * @see org.xml.sax.Parser
130
 */
131
final public class SAXDriver
132
  implements Locator, Attributes2, XMLReader, Parser, AttributeList
133
{
134
 
135
  private final DefaultHandler2 base = new DefaultHandler2();
136
  private XmlParser parser;
137
 
138
  private EntityResolver entityResolver = base;
139
  private EntityResolver2 resolver2 = null;
140
  private ContentHandler contentHandler = base;
141
  private DTDHandler dtdHandler = base;
142
  private ErrorHandler errorHandler = base;
143
  private DeclHandler declHandler = base;
144
  private LexicalHandler lexicalHandler = base;
145
 
146
  private String elementName;
147
  private Stack entityStack;
148
 
149
  // one vector (of object/struct): faster, smaller
150
  private List attributesList;
151
 
152
  private boolean namespaces = true;
153
  private boolean xmlNames = false;
154
  private boolean extGE = true;
155
  private boolean extPE = true;
156
  private boolean resolveAll = true;
157
  private boolean useResolver2 = true;
158
 
159
  // package private to allow (read-only) access in XmlParser
160
  boolean stringInterning = true;
161
 
162
  private int attributeCount;
163
  private boolean attributes;
164
  private String[] nsTemp;
165
  private NamespaceSupport prefixStack;
166
 
167
  //
168
  // Constructor.
169
  //
170
 
171
  /**
172
   * Constructs a SAX Parser.
173
   */
174
  public SAXDriver()
175
  {
176
    reset();
177
  }
178
 
179
  private void reset()
180
  {
181
    elementName = null;
182
    entityStack = new Stack();
183
    attributesList = Collections.synchronizedList(new ArrayList());
184
    attributeCount = 0;
185
    attributes = false;
186
    nsTemp = new String[3];
187
    prefixStack = null;
188
  }
189
 
190
 
191
  //
192
  // Implementation of org.xml.sax.Parser.
193
  //
194
 
195
  /**
196
   * <b>SAX1</b>: Sets the locale used for diagnostics; currently,
197
   * only locales using the English language are supported.
198
   * @param locale The locale for which diagnostics will be generated
199
   */
200
  public void setLocale(Locale locale)
201
    throws SAXException
202
  {
203
    if ("en".equals(locale.getLanguage()))
204
      {
205
        return;
206
      }
207
    throw new SAXException ("AElfred2 only supports English locales.");
208
  }
209
 
210
  /**
211
   * <b>SAX2</b>: Returns the object used when resolving external
212
   * entities during parsing (both general and parameter entities).
213
   */
214
  public EntityResolver getEntityResolver()
215
  {
216
    return (entityResolver == base) ? null : entityResolver;
217
  }
218
 
219
  /**
220
   * <b>SAX1, SAX2</b>: Set the entity resolver for this parser.
221
   * @param handler The object to receive entity events.
222
   */
223
  public void setEntityResolver(EntityResolver resolver)
224
  {
225
    if (resolver instanceof EntityResolver2)
226
      {
227
        resolver2 = (EntityResolver2) resolver;
228
      }
229
    else
230
      {
231
        resolver2 = null;
232
      }
233
    if (resolver == null)
234
      {
235
        resolver = base;
236
      }
237
    entityResolver = resolver;
238
  }
239
 
240
  /**
241
   * <b>SAX2</b>: Returns the object used to process declarations related
242
   * to notations and unparsed entities.
243
   */
244
  public DTDHandler getDTDHandler()
245
  {
246
    return (dtdHandler == base) ? null : dtdHandler;
247
  }
248
 
249
  /**
250
   * <b>SAX1, SAX2</b>: Set the DTD handler for this parser.
251
   * @param handler The object to receive DTD events.
252
   */
253
  public void setDTDHandler(DTDHandler handler)
254
  {
255
    if (handler == null)
256
      {
257
        handler = base;
258
      }
259
    this.dtdHandler = handler;
260
  }
261
 
262
 
263
  /**
264
   * <b>SAX1</b>: Set the document handler for this parser.  If a
265
   * content handler was set, this document handler will supplant it.
266
   * The parser is set to report all XML 1.0 names rather than to
267
   * filter out "xmlns" attributes (the "namespace-prefixes" feature
268
   * is set to true).
269
   *
270
   * @deprecated SAX2 programs should use the XMLReader interface
271
   *  and a ContentHandler.
272
   *
273
   * @param handler The object to receive document events.
274
   */
275
  public void setDocumentHandler(DocumentHandler handler)
276
  {
277
    contentHandler = new Adapter(handler);
278
    xmlNames = true;
279
  }
280
 
281
  /**
282
   * <b>SAX2</b>: Returns the object used to report the logical
283
   * content of an XML document.
284
   */
285
  public ContentHandler getContentHandler()
286
  {
287
    return (contentHandler == base) ? null : contentHandler;
288
  }
289
 
290
  /**
291
   * <b>SAX2</b>: Assigns the object used to report the logical
292
   * content of an XML document.  If a document handler was set,
293
   * this content handler will supplant it (but XML 1.0 style name
294
   * reporting may remain enabled).
295
   */
296
  public void setContentHandler(ContentHandler handler)
297
  {
298
    if (handler == null)
299
      {
300
        handler = base;
301
      }
302
    contentHandler = handler;
303
  }
304
 
305
  /**
306
   * <b>SAX1, SAX2</b>: Set the error handler for this parser.
307
   * @param handler The object to receive error events.
308
   */
309
  public void setErrorHandler(ErrorHandler handler)
310
  {
311
    if (handler == null)
312
      {
313
        handler = base;
314
      }
315
    this.errorHandler = handler;
316
  }
317
 
318
  /**
319
   * <b>SAX2</b>: Returns the object used to receive callbacks for XML
320
   * errors of all levels (fatal, nonfatal, warning); this is never null;
321
   */
322
  public ErrorHandler getErrorHandler()
323
  {
324
    return (errorHandler == base) ? null : errorHandler;
325
  }
326
 
327
  /**
328
   * <b>SAX1, SAX2</b>: Auxiliary API to parse an XML document, used mostly
329
   * when no URI is available.
330
   * If you want anything useful to happen, you should set
331
   * at least one type of handler.
332
   * @param source The XML input source.  Don't set 'encoding' unless
333
   *  you know for a fact that it's correct.
334
   * @see #setEntityResolver
335
   * @see #setDTDHandler
336
   * @see #setContentHandler
337
   * @see #setErrorHandler
338
   * @exception SAXException The handlers may throw any SAXException,
339
   *  and the parser normally throws SAXParseException objects.
340
   * @exception IOException IOExceptions are normally through through
341
   *  the parser if there are problems reading the source document.
342
   */
343
  public void parse(InputSource source)
344
    throws SAXException, IOException
345
  {
346
    synchronized (base)
347
      {
348
        parser = new XmlParser();
349
        if (namespaces)
350
          {
351
            prefixStack = new NamespaceSupport();
352
          }
353
        else if (!xmlNames)
354
          {
355
            throw new IllegalStateException();
356
          }
357
        parser.setHandler(this);
358
 
359
        try
360
          {
361
            Reader r = source.getCharacterStream();
362
            InputStream in = source.getByteStream();
363
 
364
            parser.doParse(source.getSystemId(),
365
                           source.getPublicId(),
366
                           r,
367
                           in,
368
                           source.getEncoding());
369
          }
370
        catch (SAXException e)
371
          {
372
            throw e;
373
          }
374
        catch (IOException e)
375
          {
376
            throw e;
377
          }
378
        catch (RuntimeException e)
379
          {
380
            throw e;
381
          }
382
        catch (Exception e)
383
          {
384
            throw new SAXParseException(e.getMessage(), this, e);
385
          }
386
        finally
387
          {
388
            contentHandler.endDocument();
389
            reset();
390
          }
391
      }
392
  }
393
 
394
  /**
395
   * <b>SAX1, SAX2</b>: Preferred API to parse an XML document, using a
396
   * system identifier (URI).
397
   */
398
  public void parse(String systemId)
399
    throws SAXException, IOException
400
  {
401
    parse(new InputSource(systemId));
402
  }
403
 
404
  //
405
  // Implementation of SAX2 "XMLReader" interface
406
  //
407
  static final String FEATURE = "http://xml.org/sax/features/";
408
  static final String PROPERTY = "http://xml.org/sax/properties/";
409
 
410
  /**
411
   * <b>SAX2</b>: Tells the value of the specified feature flag.
412
   *
413
   * @exception SAXNotRecognizedException thrown if the feature flag
414
   *  is neither built in, nor yet assigned.
415
   */
416
  public boolean getFeature(String featureId)
417
    throws SAXNotRecognizedException, SAXNotSupportedException
418
  {
419
    if ((FEATURE + "validation").equals(featureId))
420
      {
421
        return false;
422
      }
423
 
424
    // external entities (both types) are optionally included
425
    if ((FEATURE + "external-general-entities").equals(featureId))
426
      {
427
        return extGE;
428
      }
429
    if ((FEATURE + "external-parameter-entities").equals(featureId))
430
      {
431
        return extPE;
432
      }
433
 
434
    // element/attribute names are as written in document; no mangling
435
    if ((FEATURE + "namespace-prefixes").equals(featureId))
436
      {
437
        return xmlNames;
438
      }
439
 
440
    // report element/attribute namespaces?
441
    if ((FEATURE + "namespaces").equals(featureId))
442
      {
443
        return namespaces;
444
      }
445
 
446
    // all PEs and GEs are reported
447
    if ((FEATURE + "lexical-handler/parameter-entities").equals(featureId))
448
      {
449
        return true;
450
      }
451
 
452
    // default is true
453
    if ((FEATURE + "string-interning").equals(featureId))
454
      {
455
        return stringInterning;
456
      }
457
 
458
    // EXTENSIONS 1.1
459
 
460
    // always returns isSpecified info
461
    if ((FEATURE + "use-attributes2").equals(featureId))
462
      {
463
        return true;
464
      }
465
 
466
    // meaningful between startDocument/endDocument
467
    if ((FEATURE + "is-standalone").equals(featureId))
468
      {
469
        if (parser == null)
470
          {
471
            throw new SAXNotSupportedException(featureId);
472
          }
473
        return parser.isStandalone();
474
      }
475
 
476
    // optionally don't absolutize URIs in declarations
477
    if ((FEATURE + "resolve-dtd-uris").equals(featureId))
478
      {
479
        return resolveAll;
480
      }
481
 
482
    // optionally use resolver2 interface methods, if possible
483
    if ((FEATURE + "use-entity-resolver2").equals(featureId))
484
      {
485
        return useResolver2;
486
      }
487
 
488
    throw new SAXNotRecognizedException(featureId);
489
  }
490
 
491
  // package private
492
  DeclHandler getDeclHandler()
493
  {
494
    return declHandler;
495
  }
496
 
497
  // package private
498
  boolean resolveURIs()
499
  {
500
    return resolveAll;
501
  }
502
 
503
  /**
504
   * <b>SAX2</b>:  Returns the specified property.
505
   *
506
   * @exception SAXNotRecognizedException thrown if the property value
507
   *  is neither built in, nor yet stored.
508
   */
509
  public Object getProperty(String propertyId)
510
    throws SAXNotRecognizedException
511
  {
512
    if ((PROPERTY + "declaration-handler").equals(propertyId))
513
      {
514
        return (declHandler == base) ? null : declHandler;
515
      }
516
 
517
    if ((PROPERTY + "lexical-handler").equals(propertyId))
518
      {
519
        return (lexicalHandler == base) ? null : lexicalHandler;
520
      }
521
 
522
    // unknown properties
523
    throw new SAXNotRecognizedException(propertyId);
524
  }
525
 
526
  /**
527
   * <b>SAX2</b>:  Sets the state of feature flags in this parser.  Some
528
   * built-in feature flags are mutable.
529
   */
530
  public void setFeature(String featureId, boolean value)
531
    throws SAXNotRecognizedException, SAXNotSupportedException
532
  {
533
    boolean state;
534
 
535
    // Features with a defined value, we just change it if we can.
536
    state = getFeature (featureId);
537
 
538
    if (state == value)
539
      {
540
        return;
541
      }
542
    if (parser != null)
543
      {
544
        throw new SAXNotSupportedException("not while parsing");
545
      }
546
 
547
    if ((FEATURE + "namespace-prefixes").equals(featureId))
548
      {
549
        // in this implementation, this only affects xmlns reporting
550
        xmlNames = value;
551
        // forcibly prevent illegal parser state
552
        if (!xmlNames)
553
          {
554
            namespaces = true;
555
          }
556
        return;
557
      }
558
 
559
    if ((FEATURE + "namespaces").equals(featureId))
560
      {
561
        namespaces = value;
562
        // forcibly prevent illegal parser state
563
        if (!namespaces)
564
          {
565
            xmlNames = true;
566
          }
567
        return;
568
      }
569
 
570
    if ((FEATURE + "external-general-entities").equals(featureId))
571
      {
572
        extGE = value;
573
        return;
574
      }
575
    if ((FEATURE + "external-parameter-entities").equals(featureId))
576
      {
577
        extPE = value;
578
        return;
579
      }
580
    if ((FEATURE + "resolve-dtd-uris").equals(featureId))
581
      {
582
        resolveAll = value;
583
        return;
584
      }
585
 
586
    if ((FEATURE + "use-entity-resolver2").equals(featureId))
587
      {
588
        useResolver2 = value;
589
        return;
590
      }
591
 
592
    throw new SAXNotRecognizedException(featureId);
593
  }
594
 
595
  /**
596
   * <b>SAX2</b>:  Assigns the specified property.  Like SAX1 handlers,
597
   * these may be changed at any time.
598
   */
599
  public void setProperty(String propertyId, Object value)
600
    throws SAXNotRecognizedException, SAXNotSupportedException
601
  {
602
    // see if the property is recognized
603
    getProperty(propertyId);
604
 
605
    // Properties with a defined value, we just change it if we can.
606
 
607
    if ((PROPERTY + "declaration-handler").equals(propertyId))
608
      {
609
        if (value == null)
610
          {
611
            declHandler = base;
612
          }
613
        else if (!(value instanceof DeclHandler))
614
          {
615
            throw new SAXNotSupportedException(propertyId);
616
          }
617
        else
618
          {
619
            declHandler = (DeclHandler) value;
620
          }
621
        return ;
622
      }
623
 
624
    if ((PROPERTY + "lexical-handler").equals(propertyId))
625
      {
626
        if (value == null)
627
          {
628
            lexicalHandler = base;
629
          }
630
        else if (!(value instanceof LexicalHandler))
631
          {
632
            throw new SAXNotSupportedException(propertyId);
633
          }
634
        else
635
          {
636
            lexicalHandler = (LexicalHandler) value;
637
          }
638
        return;
639
      }
640
 
641
    throw new SAXNotSupportedException(propertyId);
642
  }
643
 
644
  //
645
  // This is where the driver receives XmlParser callbacks and translates
646
  // them into SAX callbacks.  Some more callbacks have been added for
647
  // SAX2 support.
648
  //
649
 
650
  void startDocument()
651
    throws SAXException
652
  {
653
    contentHandler.setDocumentLocator(this);
654
    contentHandler.startDocument();
655
    attributesList.clear();
656
  }
657
 
658
  void skippedEntity(String name)
659
    throws SAXException
660
  {
661
    contentHandler.skippedEntity(name);
662
  }
663
 
664
  InputSource getExternalSubset(String name, String baseURI)
665
    throws SAXException, IOException
666
  {
667
    if (resolver2 == null || !useResolver2 || !extPE)
668
      {
669
        return null;
670
      }
671
    return resolver2.getExternalSubset(name, baseURI);
672
  }
673
 
674
  InputSource resolveEntity(boolean isPE, String name,
675
                            InputSource in, String baseURI)
676
    throws SAXException, IOException
677
  {
678
    InputSource  source;
679
 
680
    // external entities might be skipped
681
    if (isPE && !extPE)
682
      {
683
        return null;
684
      }
685
    if (!isPE && !extGE)
686
      {
687
        return null;
688
      }
689
 
690
    // ... or not
691
    lexicalHandler.startEntity(name);
692
    if (resolver2 != null && useResolver2)
693
      {
694
        source = resolver2.resolveEntity(name, in.getPublicId(),
695
                                         baseURI, in.getSystemId());
696
        if (source == null)
697
          {
698
            in.setSystemId(absolutize(baseURI,
699
                                      in.getSystemId(), false));
700
            source = in;
701
          }
702
      }
703
    else
704
      {
705
        in.setSystemId(absolutize(baseURI,
706
                                  in.getSystemId(),
707
                                  entityResolver != base));
708
        source = entityResolver.resolveEntity(in.getPublicId(),
709
                                              in.getSystemId());
710
        if (source == null)
711
          {
712
            source = in;
713
          }
714
      }
715
    startExternalEntity(name, source.getSystemId(), true);
716
    return source;
717
  }
718
 
719
  // absolutize a system ID relative to the specified base URI
720
  // (temporarily) package-visible for external entity decls
721
  String absolutize(String baseURI, String systemId, boolean nice)
722
    throws MalformedURLException, SAXException
723
  {
724
    // FIXME normalize system IDs -- when?
725
    // - Convert to UTF-8
726
    // - Map reserved and non-ASCII characters to %HH
727
 
728
    try
729
      {
730
        if (baseURI == null)
731
          {
732
            if (XmlParser.uriWarnings)
733
              {
734
                warn ("No base URI; hope this SYSTEM id is absolute: "
735
                      + systemId);
736
              }
737
            return new URL(systemId).toString();
738
          }
739
        else
740
          {
741
            return new URL(new URL(baseURI), systemId).toString();
742
          }
743
      }
744
    catch (MalformedURLException e)
745
      {
746
        // Let unknown URI schemes pass through unless we need
747
        // the JVM to map them to i/o streams for us...
748
        if (!nice)
749
          {
750
            throw e;
751
          }
752
 
753
        // sometimes sysids for notations or unparsed entities
754
        // aren't really URIs...
755
        warn("Can't absolutize SYSTEM id: " + e.getMessage());
756
        return systemId;
757
      }
758
  }
759
 
760
  void startExternalEntity(String name, String systemId, boolean stackOnly)
761
    throws SAXException
762
  {
763
    // The following warning was deleted because the application has the
764
    // option of not setting systemId. Sun's JAXP or Xerces seems to
765
    // ignore this case.
766
    /*
767
       if (systemId == null)
768
       warn ("URI was not reported to parser for entity " + name);
769
     */
770
    if (!stackOnly)  // spliced [dtd] needs startEntity
771
      {
772
        lexicalHandler.startEntity(name);
773
      }
774
    entityStack.push(systemId);
775
  }
776
 
777
  void endExternalEntity(String name)
778
    throws SAXException
779
  {
780
    if (!"[document]".equals(name))
781
      {
782
        lexicalHandler.endEntity(name);
783
      }
784
    entityStack.pop();
785
  }
786
 
787
  void startInternalEntity(String name)
788
    throws SAXException
789
  {
790
    lexicalHandler.startEntity(name);
791
  }
792
 
793
  void endInternalEntity(String name)
794
    throws SAXException
795
  {
796
    lexicalHandler.endEntity(name);
797
  }
798
 
799
  void doctypeDecl(String name, String publicId, String systemId)
800
    throws SAXException
801
  {
802
    lexicalHandler.startDTD(name, publicId, systemId);
803
 
804
    // ... the "name" is a declaration and should be given
805
    // to the DeclHandler (but sax2 doesn't).
806
 
807
    // the IDs for the external subset are lexical details,
808
    // as are the contents of the internal subset; but sax2
809
    // doesn't provide the internal subset "pre-parse"
810
  }
811
 
812
  void notationDecl(String name, String publicId, String systemId,
813
                    String baseUri)
814
    throws SAXException
815
  {
816
    try
817
      {
818
        dtdHandler.notationDecl(name, publicId,
819
                                (resolveAll && systemId != null)
820
                                ? absolutize(baseUri, systemId, true)
821
                                : systemId);
822
      }
823
    catch (IOException e)
824
      {
825
        // "can't happen"
826
        throw new SAXParseException(e.getMessage(), this, e);
827
      }
828
  }
829
 
830
  void unparsedEntityDecl(String name, String publicId, String systemId,
831
                          String baseUri, String notation)
832
    throws SAXException
833
  {
834
    try
835
      {
836
        dtdHandler.unparsedEntityDecl(name, publicId,
837
                                      resolveAll
838
                                      ? absolutize(baseUri, systemId, true)
839
                                      : systemId,
840
                                      notation);
841
      }
842
    catch (IOException e)
843
      {
844
        // "can't happen"
845
        throw new SAXParseException(e.getMessage(), this, e);
846
      }
847
  }
848
 
849
  void endDoctype()
850
    throws SAXException
851
  {
852
    lexicalHandler.endDTD();
853
  }
854
 
855
  private void declarePrefix(String prefix, String uri)
856
    throws SAXException
857
  {
858
    int index = uri.indexOf(':');
859
 
860
    // many versions of nwalsh docbook stylesheets
861
    // have bogus URLs; so this can't be an error...
862
    if (index < 1 && uri.length() != 0)
863
      {
864
        warn("relative URI for namespace: " + uri);
865
      }
866
 
867
    // FIXME:  char [0] must be ascii alpha; chars [1..index]
868
    // must be ascii alphanumeric or in "+-." [RFC 2396]
869
 
870
    //Namespace Constraints
871
    //name for xml prefix must be http://www.w3.org/XML/1998/namespace
872
    boolean prefixEquality = prefix.equals("xml");
873
    boolean uriEquality = uri.equals("http://www.w3.org/XML/1998/namespace");
874
    if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
875
      {
876
        fatal("xml is by definition bound to the namespace name " +
877
              "http://www.w3.org/XML/1998/namespace");
878
      }
879
 
880
    //xmlns prefix declaration is illegal but xml prefix declaration is llegal...
881
    if (prefixEquality && uriEquality)
882
      {
883
        return;
884
      }
885
 
886
    //name for xmlns prefix must be http://www.w3.org/2000/xmlns/
887
    prefixEquality = prefix.equals("xmlns");
888
    uriEquality = uri.equals("http://www.w3.org/2000/xmlns/");
889
    if ((prefixEquality || uriEquality) && !(prefixEquality && uriEquality))
890
      {
891
        fatal("http://www.w3.org/2000/xmlns/ is by definition bound" +
892
              " to prefix xmlns");
893
      }
894
 
895
    //even if the uri is http://www.w3.org/2000/xmlns/
896
    // it is illegal to declare it
897
    if (prefixEquality && uriEquality)
898
      {
899
        fatal ("declaring the xmlns prefix is illegal");
900
      }
901
 
902
    uri = uri.intern();
903
    prefixStack.declarePrefix(prefix, uri);
904
    contentHandler.startPrefixMapping(prefix, uri);
905
  }
906
 
907
  void attribute(String qname, String value, boolean isSpecified)
908
    throws SAXException
909
  {
910
    if (!attributes)
911
      {
912
        attributes = true;
913
        if (namespaces)
914
          {
915
            prefixStack.pushContext();
916
          }
917
      }
918
 
919
    // process namespace decls immediately;
920
    // then maybe forget this as an attribute
921
    if (namespaces)
922
      {
923
        int index;
924
 
925
        // default NS declaration?
926
        if (stringInterning)
927
          {
928
            if ("xmlns" == qname)
929
              {
930
                declarePrefix("", value);
931
                if (!xmlNames)
932
                  {
933
                    return;
934
                  }
935
              }
936
            // NS prefix declaration?
937
            else if ((index = qname.indexOf(':')) == 5
938
                     && qname.startsWith("xmlns"))
939
              {
940
                String prefix = qname.substring(6);
941
 
942
                if (prefix.equals(""))
943
                  {
944
                    fatal("missing prefix " +
945
                          "in namespace declaration attribute");
946
                  }
947
                if (value.length() == 0)
948
                  {
949
                    verror("missing URI in namespace declaration attribute: "
950
                           + qname);
951
                  }
952
                else
953
                  {
954
                    declarePrefix(prefix, value);
955
                  }
956
                if (!xmlNames)
957
                  {
958
                    return;
959
                  }
960
              }
961
          }
962
        else
963
          {
964
            if ("xmlns".equals(qname))
965
              {
966
                declarePrefix("", value);
967
                if (!xmlNames)
968
                  {
969
                    return;
970
                  }
971
              }
972
            // NS prefix declaration?
973
            else if ((index = qname.indexOf(':')) == 5
974
                     && qname.startsWith("xmlns"))
975
              {
976
                String prefix = qname.substring(6);
977
 
978
                if (value.length() == 0)
979
                  {
980
                    verror("missing URI in namespace decl attribute: "
981
                           + qname);
982
                  }
983
                else
984
                  {
985
                    declarePrefix(prefix, value);
986
                  }
987
                if (!xmlNames)
988
                  {
989
                    return;
990
                  }
991
              }
992
          }
993
      }
994
    // remember this attribute ...
995
    attributeCount++;
996
 
997
    // attribute type comes from querying parser's DTD records
998
    attributesList.add(new Attribute(qname, value, isSpecified));
999
 
1000
  }
1001
 
1002
  void startElement(String elname)
1003
    throws SAXException
1004
  {
1005
    ContentHandler handler = contentHandler;
1006
 
1007
    //
1008
    // NOTE:  this implementation of namespace support adds something
1009
    // like six percent to parsing CPU time, in a large (~50 MB)
1010
    // document that doesn't use namespaces at all.  (Measured by PC
1011
    // sampling, with a bug where endElement processing was omitted.)
1012
    // [Measurement referred to older implementation, older JVM ...]
1013
    //
1014
    // It ought to become notably faster in such cases.  Most
1015
    // costs are the prefix stack calling Hashtable.get() (2%),
1016
    // String.hashCode() (1.5%) and about 1.3% each for pushing
1017
    // the context, and two chunks of name processing.
1018
    //
1019
 
1020
    if (!attributes)
1021
      {
1022
        if (namespaces)
1023
          {
1024
            prefixStack.pushContext();
1025
          }
1026
      }
1027
    else if (namespaces)
1028
      {
1029
 
1030
        // now we can patch up namespace refs; we saw all the
1031
        // declarations, so now we'll do the Right Thing
1032
        Iterator itt = attributesList.iterator();
1033
        while (itt.hasNext())
1034
          {
1035
            Attribute attribute = (Attribute) itt.next();
1036
            String qname = attribute.name;
1037
            int index;
1038
 
1039
            // default NS declaration?
1040
            if (stringInterning)
1041
              {
1042
                if ("xmlns" == qname)
1043
                  {
1044
                    continue;
1045
                  }
1046
              }
1047
            else
1048
              {
1049
                if ("xmlns".equals(qname))
1050
                  {
1051
                    continue;
1052
                  }
1053
              }
1054
            //Illegal in the new Namespaces Draft
1055
            //should it be only in 1.1 docs??
1056
            if (qname.equals (":"))
1057
              {
1058
                fatal("namespace names consisting of a single colon " +
1059
                      "character are invalid");
1060
              }
1061
            index = qname.indexOf(':');
1062
 
1063
            // NS prefix declaration?
1064
            if (index == 5 && qname.startsWith("xmlns"))
1065
              {
1066
                continue;
1067
              }
1068
 
1069
            // it's not a NS decl; patch namespace info items
1070
            if (prefixStack.processName(qname, nsTemp, true) == null)
1071
              {
1072
                fatal("undeclared attribute prefix in: " + qname);
1073
              }
1074
            else
1075
              {
1076
                attribute.nameSpace = nsTemp[0];
1077
                attribute.localName = nsTemp[1];
1078
              }
1079
          }
1080
      }
1081
 
1082
    // save element name so attribute callbacks work
1083
    elementName = elname;
1084
    if (namespaces)
1085
      {
1086
        if (prefixStack.processName(elname, nsTemp, false) == null)
1087
          {
1088
            fatal("undeclared element prefix in: " + elname);
1089
            nsTemp[0] = nsTemp[1] = "";
1090
          }
1091
        handler.startElement(nsTemp[0], nsTemp[1], elname, this);
1092
      }
1093
    else
1094
      {
1095
        handler.startElement("", "", elname, this);
1096
      }
1097
    // elementName = null;
1098
 
1099
    // elements with no attributes are pretty common!
1100
    if (attributes)
1101
      {
1102
        attributesList.clear();
1103
        attributeCount = 0;
1104
        attributes = false;
1105
      }
1106
  }
1107
 
1108
  void endElement(String elname)
1109
    throws SAXException
1110
  {
1111
    ContentHandler handler = contentHandler;
1112
 
1113
    if (!namespaces)
1114
      {
1115
        handler.endElement("", "", elname);
1116
        return;
1117
      }
1118
    prefixStack.processName(elname, nsTemp, false);
1119
    handler.endElement(nsTemp[0], nsTemp[1], elname);
1120
 
1121
    Enumeration prefixes = prefixStack.getDeclaredPrefixes();
1122
 
1123
    while (prefixes.hasMoreElements())
1124
      {
1125
        handler.endPrefixMapping((String) prefixes.nextElement());
1126
      }
1127
    prefixStack.popContext();
1128
  }
1129
 
1130
  void startCDATA()
1131
    throws SAXException
1132
  {
1133
    lexicalHandler.startCDATA();
1134
  }
1135
 
1136
  void charData(char[] ch, int start, int length)
1137
    throws SAXException
1138
  {
1139
    contentHandler.characters(ch, start, length);
1140
  }
1141
 
1142
  void endCDATA()
1143
    throws SAXException
1144
  {
1145
    lexicalHandler.endCDATA();
1146
  }
1147
 
1148
  void ignorableWhitespace(char[] ch, int start, int length)
1149
    throws SAXException
1150
  {
1151
    contentHandler.ignorableWhitespace(ch, start, length);
1152
  }
1153
 
1154
  void processingInstruction(String target, String data)
1155
    throws SAXException
1156
  {
1157
    contentHandler.processingInstruction(target, data);
1158
  }
1159
 
1160
  void comment(char[] ch, int start, int length)
1161
    throws SAXException
1162
  {
1163
    if (lexicalHandler != base)
1164
      {
1165
        lexicalHandler.comment(ch, start, length);
1166
      }
1167
  }
1168
 
1169
  void fatal(String message)
1170
    throws SAXException
1171
  {
1172
    SAXParseException fatal;
1173
 
1174
    fatal = new SAXParseException(message, this);
1175
    errorHandler.fatalError(fatal);
1176
 
1177
    // Even if the application can continue ... we can't!
1178
    throw fatal;
1179
  }
1180
 
1181
  // We can safely report a few validity errors that
1182
  // make layered SAX2 DTD validation more conformant
1183
  void verror(String message)
1184
    throws SAXException
1185
  {
1186
    SAXParseException err;
1187
 
1188
    err = new SAXParseException(message, this);
1189
    errorHandler.error(err);
1190
  }
1191
 
1192
  void warn(String message)
1193
    throws SAXException
1194
  {
1195
    SAXParseException err;
1196
 
1197
    err = new SAXParseException(message, this);
1198
    errorHandler.warning(err);
1199
  }
1200
 
1201
  //
1202
  // Implementation of org.xml.sax.Attributes.
1203
  //
1204
 
1205
  /**
1206
   * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1207
   * (don't invoke on parser);
1208
   */
1209
  public int getLength()
1210
  {
1211
    return attributesList.size();
1212
  }
1213
 
1214
  /**
1215
   * <b>SAX2 Attributes</b> method (don't invoke on parser);
1216
   */
1217
  public String getURI(int index)
1218
  {
1219
    if (index < 0 || index >= attributesList.size())
1220
      {
1221
        return null;
1222
      }
1223
    return ((Attribute) attributesList.get(index)).nameSpace;
1224
  }
1225
 
1226
  /**
1227
   * <b>SAX2 Attributes</b> method (don't invoke on parser);
1228
   */
1229
  public String getLocalName(int index)
1230
  {
1231
    if (index < 0 || index >= attributesList.size())
1232
      {
1233
        return null;
1234
      }
1235
    Attribute attr = (Attribute) attributesList.get(index);
1236
    // FIXME attr.localName is sometimes null, why?
1237
    if (namespaces && attr.localName == null)
1238
      {
1239
        // XXX fix this here for now
1240
        int ci = attr.name.indexOf(':');
1241
        attr.localName = (ci == -1) ? attr.name :
1242
          attr.name.substring(ci + 1);
1243
      }
1244
    return (attr.localName == null) ? "" : attr.localName;
1245
  }
1246
 
1247
  /**
1248
   * <b>SAX2 Attributes</b> method (don't invoke on parser);
1249
   */
1250
  public String getQName(int index)
1251
  {
1252
    if (index < 0 || index >= attributesList.size())
1253
      {
1254
      return null;
1255
      }
1256
    Attribute attr = (Attribute) attributesList.get(index);
1257
    return (attr.name == null) ? "" : attr.name;
1258
  }
1259
 
1260
  /**
1261
   * <b>SAX1 AttributeList</b> method (don't invoke on parser);
1262
   */
1263
  public String getName(int index)
1264
  {
1265
    return getQName(index);
1266
  }
1267
 
1268
  /**
1269
   * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1270
   * (don't invoke on parser);
1271
   */
1272
  public String getType(int index)
1273
  {
1274
    if (index < 0 || index >= attributesList.size())
1275
      {
1276
        return null;
1277
      }
1278
    String type = parser.getAttributeType(elementName, getQName(index));
1279
    if (type == null)
1280
      {
1281
        return "CDATA";
1282
      }
1283
    // ... use DeclHandler.attributeDecl to see enumerations
1284
    if (type == "ENUMERATION")
1285
      {
1286
        return "NMTOKEN";
1287
      }
1288
    return type;
1289
  }
1290
 
1291
  /**
1292
   * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1293
   * (don't invoke on parser);
1294
   */
1295
  public String getValue(int index)
1296
  {
1297
    if (index < 0 || index >= attributesList.size())
1298
      {
1299
        return null;
1300
      }
1301
    return ((Attribute) attributesList.get(index)).value;
1302
  }
1303
 
1304
  /**
1305
   * <b>SAX2 Attributes</b> method (don't invoke on parser);
1306
   */
1307
  public int getIndex(String uri, String local)
1308
    {
1309
      int length = getLength();
1310
 
1311
      for (int i = 0; i < length; i++)
1312
        {
1313
          if (!getURI(i).equals(uri))
1314
            {
1315
              continue;
1316
            }
1317
          if (getLocalName(i).equals(local))
1318
            {
1319
              return i;
1320
            }
1321
        }
1322
      return -1;
1323
  }
1324
 
1325
  /**
1326
   * <b>SAX2 Attributes</b> method (don't invoke on parser);
1327
   */
1328
  public int getIndex(String xmlName)
1329
  {
1330
    int length = getLength();
1331
 
1332
    for (int i = 0; i < length; i++)
1333
      {
1334
        if (getQName(i).equals(xmlName))
1335
          {
1336
            return i;
1337
          }
1338
      }
1339
    return -1;
1340
  }
1341
 
1342
  /**
1343
   * <b>SAX2 Attributes</b> method (don't invoke on parser);
1344
   */
1345
  public String getType(String uri, String local)
1346
  {
1347
    int index = getIndex(uri, local);
1348
 
1349
    if (index < 0)
1350
      {
1351
        return null;
1352
      }
1353
    return getType(index);
1354
  }
1355
 
1356
  /**
1357
   * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1358
   * (don't invoke on parser);
1359
   */
1360
  public String getType(String xmlName)
1361
  {
1362
    int index = getIndex(xmlName);
1363
 
1364
    if (index < 0)
1365
      {
1366
        return null;
1367
      }
1368
    return getType(index);
1369
  }
1370
 
1371
  /**
1372
   * <b>SAX Attributes</b> method (don't invoke on parser);
1373
   */
1374
  public String getValue(String uri, String local)
1375
  {
1376
    int index = getIndex(uri, local);
1377
 
1378
    if (index < 0)
1379
      {
1380
        return null;
1381
      }
1382
    return getValue(index);
1383
  }
1384
 
1385
  /**
1386
   * <b>SAX1 AttributeList, SAX2 Attributes</b> method
1387
   * (don't invoke on parser);
1388
   */
1389
  public String getValue(String xmlName)
1390
  {
1391
    int index = getIndex(xmlName);
1392
 
1393
    if (index < 0)
1394
      {
1395
        return null;
1396
      }
1397
    return getValue(index);
1398
  }
1399
 
1400
  //
1401
  // Implementation of org.xml.sax.ext.Attributes2
1402
  //
1403
 
1404
  /** @return false unless the attribute was declared in the DTD.
1405
   * @throws java.lang.ArrayIndexOutOfBoundsException
1406
   *   When the supplied index does not identify an attribute.
1407
   */
1408
  public boolean isDeclared(int index)
1409
  {
1410
    if (index < 0 || index >= attributeCount)
1411
      {
1412
        throw new ArrayIndexOutOfBoundsException();
1413
      }
1414
    String type = parser.getAttributeType(elementName, getQName(index));
1415
    return (type != null);
1416
  }
1417
 
1418
  /** @return false unless the attribute was declared in the DTD.
1419
   * @throws java.lang.IllegalArgumentException
1420
   *   When the supplied names do not identify an attribute.
1421
   */
1422
  public boolean isDeclared(String qName)
1423
  {
1424
    int index = getIndex(qName);
1425
    if (index < 0)
1426
      {
1427
        throw new IllegalArgumentException();
1428
      }
1429
    String type = parser.getAttributeType(elementName, qName);
1430
    return (type != null);
1431
  }
1432
 
1433
  /** @return false unless the attribute was declared in the DTD.
1434
   * @throws java.lang.IllegalArgumentException
1435
   *   When the supplied names do not identify an attribute.
1436
   */
1437
  public boolean isDeclared(String uri, String localName)
1438
  {
1439
    int index = getIndex(uri, localName);
1440
    return isDeclared(index);
1441
  }
1442
 
1443
  /**
1444
   * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
1445
   */
1446
  public boolean isSpecified(int index)
1447
  {
1448
    return ((Attribute) attributesList.get(index)).specified;
1449
  }
1450
 
1451
  /**
1452
   * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
1453
   */
1454
  public boolean isSpecified(String uri, String local)
1455
  {
1456
    int index = getIndex (uri, local);
1457
    return isSpecified(index);
1458
  }
1459
 
1460
  /**
1461
   * <b>SAX-ext Attributes2</b> method (don't invoke on parser);
1462
   */
1463
  public boolean isSpecified(String xmlName)
1464
  {
1465
    int index = getIndex (xmlName);
1466
    return isSpecified(index);
1467
  }
1468
 
1469
  //
1470
  // Implementation of org.xml.sax.Locator.
1471
  //
1472
 
1473
  /**
1474
   * <b>SAX Locator</b> method (don't invoke on parser);
1475
   */
1476
  public String getPublicId()
1477
  {
1478
    return null;   // FIXME track public IDs too
1479
  }
1480
 
1481
  /**
1482
   * <b>SAX Locator</b> method (don't invoke on parser);
1483
   */
1484
  public String getSystemId()
1485
  {
1486
    if (entityStack.empty())
1487
      {
1488
        return null;
1489
      }
1490
    else
1491
      {
1492
        return (String) entityStack.peek();
1493
      }
1494
  }
1495
 
1496
  /**
1497
   * <b>SAX Locator</b> method (don't invoke on parser);
1498
   */
1499
  public int getLineNumber()
1500
  {
1501
    return parser.getLineNumber();
1502
  }
1503
 
1504
  /**
1505
   * <b>SAX Locator</b> method (don't invoke on parser);
1506
   */
1507
  public int getColumnNumber()
1508
  {
1509
    return parser.getColumnNumber();
1510
  }
1511
 
1512
  // adapter between SAX2 content handler and SAX1 document handler callbacks
1513
  private static class Adapter
1514
    implements ContentHandler
1515
  {
1516
 
1517
    private DocumentHandler docHandler;
1518
 
1519
    Adapter(DocumentHandler dh)
1520
    {
1521
      docHandler = dh;
1522
    }
1523
 
1524
    public void setDocumentLocator(Locator l)
1525
    {
1526
      docHandler.setDocumentLocator(l);
1527
    }
1528
 
1529
    public void startDocument()
1530
      throws SAXException
1531
    {
1532
      docHandler.startDocument();
1533
    }
1534
 
1535
    public void processingInstruction(String target, String data)
1536
      throws SAXException
1537
    {
1538
      docHandler.processingInstruction(target, data);
1539
    }
1540
 
1541
    public void startPrefixMapping(String prefix, String uri)
1542
    {
1543
      /* ignored */
1544
    }
1545
 
1546
    public void startElement(String namespace,
1547
                             String local,
1548
                             String name,
1549
                             Attributes attrs)
1550
      throws SAXException
1551
    {
1552
      docHandler.startElement(name, (AttributeList) attrs);
1553
    }
1554
 
1555
    public void characters(char[] buf, int offset, int len)
1556
      throws SAXException
1557
    {
1558
      docHandler.characters(buf, offset, len);
1559
    }
1560
 
1561
    public void ignorableWhitespace(char[] buf, int offset, int len)
1562
      throws SAXException
1563
    {
1564
      docHandler.ignorableWhitespace(buf, offset, len);
1565
    }
1566
 
1567
    public void skippedEntity(String name)
1568
    {
1569
      /* ignored */
1570
    }
1571
 
1572
    public void endElement(String u, String l, String name)
1573
      throws SAXException
1574
    {
1575
      docHandler.endElement(name);
1576
    }
1577
 
1578
    public void endPrefixMapping(String prefix)
1579
    {
1580
      /* ignored */
1581
    }
1582
 
1583
    public void endDocument()
1584
      throws SAXException
1585
    {
1586
      docHandler.endDocument();
1587
    }
1588
  }
1589
 
1590
  private static class Attribute
1591
  {
1592
 
1593
    String name;
1594
    String value;
1595
    String nameSpace;
1596
    String localName;
1597
    boolean specified;
1598
 
1599
    Attribute(String name, String value, boolean specified)
1600
    {
1601
      this.name = name;
1602
      this.value = value;
1603
      this.nameSpace = "";
1604
      this.specified = specified;
1605
    }
1606
 
1607
  }
1608
 
1609
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.