1 /*
2 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.xml.internal.dtdparser;
27
28 import org.xml.sax.InputSource;
29 import org.xml.sax.SAXException;
30 import org.xml.sax.SAXParseException;
31
32 import java.io.CharConversionException;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.InputStreamReader;
36 import java.io.Reader;
37 import java.io.UnsupportedEncodingException;
38 import java.net.URL;
39 import java.util.Locale;
40
41 /**
42 * This is how the parser talks to its input entities, of all kinds.
43 * The entities are in a stack.
44 * <p/>
45 * <P> For internal entities, the character arrays are referenced here,
46 * and read from as needed (they're read-only). External entities have
47 * mutable buffers, that are read into as needed.
48 * <p/>
49 * <P> <em>Note:</em> This maps CRLF (and CR) to LF without regard for
50 * whether it's in an external (parsed) entity or not. The XML 1.0 spec
51 * is inconsistent in explaining EOL handling; this is the sensible way.
52 *
53 * @author David Brownell
54 * @author Janet Koenig
55 * @version 1.4 00/08/05
56 */
57 public class InputEntity {
58 private int start, finish;
59 private char buf [];
60 private int lineNumber = 1;
61 private boolean returnedFirstHalf = false;
62 private boolean maybeInCRLF = false;
63
64 // name of entity (never main document or unnamed DTD PE)
65 private String name;
66
67 private InputEntity next;
68
131 //
132 public String getName() {
133 return name;
134 }
135
136 //
137 // use this for an external parsed entity
138 //
139 public void init(InputSource in, String name, InputEntity stack,
140 boolean isPE)
141 throws IOException, SAXException {
142
143 input = in;
144 this.isPE = isPE;
145 reader = in.getCharacterStream();
146
147 if (reader == null) {
148 InputStream bytes = in.getByteStream();
149
150 if (bytes == null)
151 reader = XmlReader.createReader(new URL(in.getSystemId())
152 .openStream());
153 else if (in.getEncoding() != null)
154 reader = XmlReader.createReader(in.getByteStream(),
155 in.getEncoding());
156 else
157 reader = XmlReader.createReader(in.getByteStream());
158 }
159 next = stack;
160 buf = new char[BUFSIZ];
161 this.name = name;
162 checkRecursion(stack);
163 }
164
165 //
166 // use this for an internal parsed entity; buffer is readonly
167 //
168 public void init(char b [], String name, InputEntity stack, boolean isPE)
169 throws SAXException {
170
171 next = stack;
172 buf = b;
173 finish = b.length;
174 this.name = name;
175 this.isPE = isPE;
176 checkRecursion(stack);
177 }
178
179 private void checkRecursion(InputEntity stack)
180 throws SAXException {
181
182 if (stack == null)
183 return;
184 for (stack = stack.next; stack != null; stack = stack.next) {
185 if (stack.name != null && stack.name.equals(name))
186 fatal("P-069", new Object[]{name});
187 }
188 }
189
190 public InputEntity pop() throws IOException {
191
192 // caller has ensured there's nothing left to read
367 //
368 if ((c == '\n' || c == '\r') && !isInternal()) {
369 if (!(c == '\n' && sawCR)) {
370 lineNumber++;
371 sawCR = false;
372 }
373 if (c == '\r')
374 sawCR = true;
375 }
376 } else {
377 start--;
378 return isSpace;
379 }
380 }
381 }
382
383
384 /**
385 * normal content; whitespace in markup may be handled
386 * specially if the parser uses the content model.
387 * <p/>
388 * <P> content terminates with markup delimiter characters,
389 * namely ampersand (&amp;) and left angle bracket (&lt;).
390 * <p/>
391 * <P> the document handler's characters() method is called
392 * on all the content found
393 */
394 public boolean parsedContent(DTDEventListener docHandler
395 /*ElementValidator validator*/)
396 throws IOException, SAXException {
397
398 // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
399
400 int first; // first char to return
401 int last; // last char to return
402 boolean sawContent; // sent any chars?
403 char c;
404
405 // deliver right out of the buffer, until delimiter, EOF,
406 // or error, refilling as we go
407 for (first = last = start, sawContent = false; ; last++) {
408
409 // buffer empty?
410 if (last >= finish) {
530 else {
531 last--;
532 // also terminate on surrogate pair oddities
533 break;
534 }
535 continue;
536 }
537
538 fatal("P-071", new Object[]{Integer.toHexString(c)});
539 }
540 if (last == first)
541 return sawContent;
542 // validator.text ();
543 docHandler.characters(buf, first, last - first);
544 start = last;
545 return true;
546 }
547
548
549 /**
550 * CDATA -- character data, terminated by "]]>" and optionally
551 * including unescaped markup delimiters (ampersand and left angle
552 * bracket). This should otherwise be exactly like character data,
553 * modulo differences in error report details.
554 * <p/>
555 * <P> The document handler's characters() or ignorableWhitespace()
556 * methods are invoked on all the character data found
557 *
558 * @param docHandler gets callbacks for character data
559 * @param ignorableWhitespace if true, whitespace characters will
560 * be reported using docHandler.ignorableWhitespace(); implicitly,
561 * non-whitespace characters will cause validation errors
562 * @param whitespaceInvalidMessage if true, ignorable whitespace
563 * causes a validity error report as well as a callback
564 */
565 public boolean unparsedContent(DTDEventListener docHandler,
566 /*ElementValidator validator,*/
567 boolean ignorableWhitespace,
568 String whitespaceInvalidMessage)
569 throws IOException, SAXException {
570
571 // [18] CDSect ::= CDStart CData CDEnd
572 // [19] CDStart ::= '<![CDATA['
573 // [20] CData ::= (Char* - (Char* ']]>' Char*))
574 // [21] CDEnd ::= ']]>'
603 continue;
604 } else {
605 last--;
606 break;
607 }
608 }
609 fatal("P-071", new Object[]
610 {Integer.toHexString(buf[last])});
611 }
612 if (c == '\n') {
613 if (!isInternal())
614 lineNumber++;
615 continue;
616 }
617 if (c == '\r') {
618 // As above, we can't repeat CR/CRLF --> LF mapping
619 if (isInternal())
620 continue;
621
622 if (white) {
623 if (whitespaceInvalidMessage != null)
624 errHandler.error(new SAXParseException(DTDParser.messages.getMessage(locale,
625 whitespaceInvalidMessage), null));
626 docHandler.ignorableWhitespace(buf, start,
627 last - start);
628 docHandler.ignorableWhitespace(newline, 0, 1);
629 } else {
630 // validator.text ();
631 docHandler.characters(buf, start, last - start);
632 docHandler.characters(newline, 0, 1);
633 }
634 lineNumber++;
635 if (finish > (last + 1)) {
636 if (buf[last + 1] == '\n')
637 last++;
638 } else { // CR at end of buffer
639 // XXX case not yet handled ... as above
640 }
641 start = last + 1;
642 continue;
643 }
644 if (c != ']') {
645 if (c != ' ' && c != '\t')
646 white = false;
647 continue;
648 }
649 if ((last + 2) < finish) {
650 if (buf[last + 1] == ']' && buf[last + 2] == '>') {
651 done = true;
652 break;
653 }
654 white = false;
655 continue;
656 } else {
657 //last--;
658 break;
659 }
660 }
661 if (white) {
662 if (whitespaceInvalidMessage != null)
663 errHandler.error(new SAXParseException(DTDParser.messages.getMessage(locale,
664 whitespaceInvalidMessage), null));
665 docHandler.ignorableWhitespace(buf, start, last - start);
666 } else {
667 // validator.text ();
668 docHandler.characters(buf, start, last - start);
669 }
670 if (done) {
671 start = last + 3;
672 break;
673 }
674 start = last;
675 if (isEOF())
676 fatal("P-073", null);
677 }
678 docHandler.endCDATA();
679 return true;
680 }
681
682 // return false to backstep at end of buffer)
684 throws SAXException {
685
686 if ((offset + 1) >= finish)
687 return false;
688
689 char c1 = buf[offset++];
690 char c2 = buf[offset];
691
692 if ((c1 >= 0xd800 && c1 < 0xdc00) && (c2 >= 0xdc00 && c2 <= 0xdfff))
693 return true;
694 fatal("P-074", new Object[]{
695 Integer.toHexString(c1 & 0x0ffff),
696 Integer.toHexString(c2 & 0x0ffff)
697 });
698 return false;
699 }
700
701
702 /**
703 * whitespace in markup (flagged to app, discardable)
704 * <p/>
705 * <P> the document handler's ignorableWhitespace() method
706 * is called on all the whitespace found
707 */
708 public boolean ignorableWhitespace(DTDEventListener handler)
709 throws IOException, SAXException {
710
711 char c;
712 boolean isSpace = false;
713 int first;
714
715 // [3] S ::= #20 | #09 | #0D | #0A
716 for (first = start; ;) {
717 if (finish <= start) {
718 if (isSpace)
719 handler.ignorableWhitespace(buf, first, start - first);
720 fillbuf();
721 first = start;
722 }
723 if (finish <= start)
724 return isSpace;
742 handler.ignorableWhitespace(buf, first,
743 (start - 1) - first);
744 handler.ignorableWhitespace(newline, 0, 1);
745 if (start < finish && buf[start] == '\n')
746 ++start;
747 first = start;
748 continue;
749
750 default:
751 ungetc();
752 if (isSpace)
753 handler.ignorableWhitespace(buf, first, start - first);
754 return isSpace;
755 }
756 }
757 }
758
759 /**
760 * returns false iff 'next' string isn't as provided,
761 * else skips that text and returns true.
762 * <p/>
763 * <P> NOTE: two alternative string representations are
764 * both passed in, since one is faster.
765 */
766 public boolean peek(String next, char chars [])
767 throws IOException, SAXException {
768
769 int len;
770 int i;
771
772 if (chars != null)
773 len = chars.length;
774 else
775 len = next.length();
776
777 // buffer should hold the whole thing ... give it a
778 // chance for the end-of-buffer case and cope with EOF
779 // by letting fillbuf compact and fill
780 if (finish <= start || (finish - start) < len)
781 fillbuf();
782
793 } else {
794 for (i = 0; i < len && (start + i) < finish; i++) {
795 if (buf[start + i] != next.charAt(i))
796 return false;
797 }
798 }
799
800 // if the first fillbuf didn't get enough data, give
801 // fillbuf another chance to read
802 if (i < len) {
803 if (reader == null || isClosed)
804 return false;
805
806 //
807 // This diagnostic "knows" that the only way big strings would
808 // fail to be peeked is where it's a symbol ... e.g. for an
809 // </EndTag> construct. That knowledge could also be applied
810 // to get rid of the symbol length constraint, since having
811 // the wrong symbol is a fatal error anyway ...
812 //
813 if (len > buf.length)
814 fatal("P-077", new Object[]{new Integer(buf.length)});
815
816 fillbuf();
817 return peek(next, chars);
818 }
819
820 start += len;
821 return true;
822 }
823
824
825 //
826 // Support for reporting the internal DTD subset, so <!DOCTYPE...>
827 // declarations can be recreated. This is collected as a single
828 // string; such subsets are normally small, and many applications
829 // don't even care about this.
830 //
831 public void startRemembering() {
832
833 if (startRemember != 0)
834 throw new InternalError();
967
968 public void close() {
969
970 try {
971 if (reader != null && !isClosed)
972 reader.close();
973 isClosed = true;
974 } catch (IOException e) {
975 /* NOTHING */
976 }
977 }
978
979
980 private void fatal(String messageId, Object params [])
981 throws SAXException {
982
983 SAXParseException x = new SAXParseException(DTDParser.messages.getMessage(locale, messageId, params), null);
984
985 // not continuable ... e.g. WF errors
986 close();
987 errHandler.fatalError(x);
988 throw x;
989 }
990 }
|
1 /*
2 * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.xml.internal.dtdparser;
27
28 import org.xml.sax.InputSource;
29 import org.xml.sax.SAXException;
30 import org.xml.sax.SAXParseException;
31
32 import java.io.CharConversionException;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.InputStreamReader;
36 import java.io.Reader;
37 import java.io.UnsupportedEncodingException;
38 import java.net.URL;
39 import java.util.Arrays;
40 import java.util.Locale;
41
42 /**
43 * This is how the parser talks to its input entities, of all kinds.
44 * The entities are in a stack.
45 * <p>
46 * <P> For internal entities, the character arrays are referenced here,
47 * and read from as needed (they're read-only). External entities have
48 * mutable buffers, that are read into as needed.
49 * <p>
50 * <P> <em>Note:</em> This maps CRLF (and CR) to LF without regard for
51 * whether it's in an external (parsed) entity or not. The XML 1.0 spec
52 * is inconsistent in explaining EOL handling; this is the sensible way.
53 *
54 * @author David Brownell
55 * @author Janet Koenig
56 * @version 1.4 00/08/05
57 */
58 public class InputEntity {
59 private int start, finish;
60 private char buf [];
61 private int lineNumber = 1;
62 private boolean returnedFirstHalf = false;
63 private boolean maybeInCRLF = false;
64
65 // name of entity (never main document or unnamed DTD PE)
66 private String name;
67
68 private InputEntity next;
69
132 //
133 public String getName() {
134 return name;
135 }
136
137 //
138 // use this for an external parsed entity
139 //
140 public void init(InputSource in, String name, InputEntity stack,
141 boolean isPE)
142 throws IOException, SAXException {
143
144 input = in;
145 this.isPE = isPE;
146 reader = in.getCharacterStream();
147
148 if (reader == null) {
149 InputStream bytes = in.getByteStream();
150
151 if (bytes == null)
152 if (Boolean.valueOf(System.getProperty("enableExternalEntityProcessing")))
153 reader = XmlReader.createReader(new URL(in.getSystemId()).openStream());
154 else
155 fatal("P-082", new Object[] {in.getSystemId()});
156 else if (in.getEncoding() != null)
157 reader = XmlReader.createReader(in.getByteStream(), in.getEncoding());
158 else
159 reader = XmlReader.createReader(in.getByteStream());
160 }
161 next = stack;
162 buf = new char[BUFSIZ];
163 this.name = name;
164 checkRecursion(stack);
165 }
166
167 //
168 // use this for an internal parsed entity; buffer is readonly
169 //
170 public void init(char b [], String name, InputEntity stack, boolean isPE)
171 throws SAXException {
172
173 next = stack;
174 buf = Arrays.copyOf(b, b.length);
175 finish = b.length;
176 this.name = name;
177 this.isPE = isPE;
178 checkRecursion(stack);
179 }
180
181 private void checkRecursion(InputEntity stack)
182 throws SAXException {
183
184 if (stack == null)
185 return;
186 for (stack = stack.next; stack != null; stack = stack.next) {
187 if (stack.name != null && stack.name.equals(name))
188 fatal("P-069", new Object[]{name});
189 }
190 }
191
192 public InputEntity pop() throws IOException {
193
194 // caller has ensured there's nothing left to read
369 //
370 if ((c == '\n' || c == '\r') && !isInternal()) {
371 if (!(c == '\n' && sawCR)) {
372 lineNumber++;
373 sawCR = false;
374 }
375 if (c == '\r')
376 sawCR = true;
377 }
378 } else {
379 start--;
380 return isSpace;
381 }
382 }
383 }
384
385
386 /**
387 * normal content; whitespace in markup may be handled
388 * specially if the parser uses the content model.
389 * <p>
390 * <P> content terminates with markup delimiter characters,
391 * namely ampersand (&amp;) and left angle bracket (&lt;).
392 * <p>
393 * <P> the document handler's characters() method is called
394 * on all the content found
395 */
396 public boolean parsedContent(DTDEventListener docHandler
397 /*ElementValidator validator*/)
398 throws IOException, SAXException {
399
400 // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
401
402 int first; // first char to return
403 int last; // last char to return
404 boolean sawContent; // sent any chars?
405 char c;
406
407 // deliver right out of the buffer, until delimiter, EOF,
408 // or error, refilling as we go
409 for (first = last = start, sawContent = false; ; last++) {
410
411 // buffer empty?
412 if (last >= finish) {
532 else {
533 last--;
534 // also terminate on surrogate pair oddities
535 break;
536 }
537 continue;
538 }
539
540 fatal("P-071", new Object[]{Integer.toHexString(c)});
541 }
542 if (last == first)
543 return sawContent;
544 // validator.text ();
545 docHandler.characters(buf, first, last - first);
546 start = last;
547 return true;
548 }
549
550
551 /**
552 * CDATA -- character data, terminated by {@code "]]>"} and optionally
553 * including unescaped markup delimiters (ampersand and left angle
554 * bracket). This should otherwise be exactly like character data,
555 * modulo differences in error report details.
556 * <p>
557 * <P> The document handler's characters() or ignorableWhitespace()
558 * methods are invoked on all the character data found
559 *
560 * @param docHandler gets callbacks for character data
561 * @param ignorableWhitespace if true, whitespace characters will
562 * be reported using docHandler.ignorableWhitespace(); implicitly,
563 * non-whitespace characters will cause validation errors
564 * @param whitespaceInvalidMessage if true, ignorable whitespace
565 * causes a validity error report as well as a callback
566 */
567 public boolean unparsedContent(DTDEventListener docHandler,
568 /*ElementValidator validator,*/
569 boolean ignorableWhitespace,
570 String whitespaceInvalidMessage)
571 throws IOException, SAXException {
572
573 // [18] CDSect ::= CDStart CData CDEnd
574 // [19] CDStart ::= '<![CDATA['
575 // [20] CData ::= (Char* - (Char* ']]>' Char*))
576 // [21] CDEnd ::= ']]>'
605 continue;
606 } else {
607 last--;
608 break;
609 }
610 }
611 fatal("P-071", new Object[]
612 {Integer.toHexString(buf[last])});
613 }
614 if (c == '\n') {
615 if (!isInternal())
616 lineNumber++;
617 continue;
618 }
619 if (c == '\r') {
620 // As above, we can't repeat CR/CRLF --> LF mapping
621 if (isInternal())
622 continue;
623
624 if (white) {
625 if (whitespaceInvalidMessage != null && errHandler != null)
626 errHandler.error(new SAXParseException(DTDParser.messages.getMessage(locale,
627 whitespaceInvalidMessage), null));
628 docHandler.ignorableWhitespace(buf, start,
629 last - start);
630 docHandler.ignorableWhitespace(newline, 0, 1);
631 } else {
632 // validator.text ();
633 docHandler.characters(buf, start, last - start);
634 docHandler.characters(newline, 0, 1);
635 }
636 lineNumber++;
637 if (finish > (last + 1)) {
638 if (buf[last + 1] == '\n')
639 last++;
640 } else { // CR at end of buffer
641 // XXX case not yet handled ... as above
642 }
643 start = last + 1;
644 continue;
645 }
646 if (c != ']') {
647 if (c != ' ' && c != '\t')
648 white = false;
649 continue;
650 }
651 if ((last + 2) < finish) {
652 if (buf[last + 1] == ']' && buf[last + 2] == '>') {
653 done = true;
654 break;
655 }
656 white = false;
657 continue;
658 } else {
659 //last--;
660 break;
661 }
662 }
663 if (white) {
664 if (whitespaceInvalidMessage != null && errHandler != null)
665 errHandler.error(new SAXParseException(DTDParser.messages.getMessage(locale,
666 whitespaceInvalidMessage), null));
667 docHandler.ignorableWhitespace(buf, start, last - start);
668 } else {
669 // validator.text ();
670 docHandler.characters(buf, start, last - start);
671 }
672 if (done) {
673 start = last + 3;
674 break;
675 }
676 start = last;
677 if (isEOF())
678 fatal("P-073", null);
679 }
680 docHandler.endCDATA();
681 return true;
682 }
683
684 // return false to backstep at end of buffer)
686 throws SAXException {
687
688 if ((offset + 1) >= finish)
689 return false;
690
691 char c1 = buf[offset++];
692 char c2 = buf[offset];
693
694 if ((c1 >= 0xd800 && c1 < 0xdc00) && (c2 >= 0xdc00 && c2 <= 0xdfff))
695 return true;
696 fatal("P-074", new Object[]{
697 Integer.toHexString(c1 & 0x0ffff),
698 Integer.toHexString(c2 & 0x0ffff)
699 });
700 return false;
701 }
702
703
704 /**
705 * whitespace in markup (flagged to app, discardable)
706 * <p>
707 * <P> the document handler's ignorableWhitespace() method
708 * is called on all the whitespace found
709 */
710 public boolean ignorableWhitespace(DTDEventListener handler)
711 throws IOException, SAXException {
712
713 char c;
714 boolean isSpace = false;
715 int first;
716
717 // [3] S ::= #20 | #09 | #0D | #0A
718 for (first = start; ;) {
719 if (finish <= start) {
720 if (isSpace)
721 handler.ignorableWhitespace(buf, first, start - first);
722 fillbuf();
723 first = start;
724 }
725 if (finish <= start)
726 return isSpace;
744 handler.ignorableWhitespace(buf, first,
745 (start - 1) - first);
746 handler.ignorableWhitespace(newline, 0, 1);
747 if (start < finish && buf[start] == '\n')
748 ++start;
749 first = start;
750 continue;
751
752 default:
753 ungetc();
754 if (isSpace)
755 handler.ignorableWhitespace(buf, first, start - first);
756 return isSpace;
757 }
758 }
759 }
760
761 /**
762 * returns false iff 'next' string isn't as provided,
763 * else skips that text and returns true.
764 * <p>
765 * <P> NOTE: two alternative string representations are
766 * both passed in, since one is faster.
767 */
768 public boolean peek(String next, char chars [])
769 throws IOException, SAXException {
770
771 int len;
772 int i;
773
774 if (chars != null)
775 len = chars.length;
776 else
777 len = next.length();
778
779 // buffer should hold the whole thing ... give it a
780 // chance for the end-of-buffer case and cope with EOF
781 // by letting fillbuf compact and fill
782 if (finish <= start || (finish - start) < len)
783 fillbuf();
784
795 } else {
796 for (i = 0; i < len && (start + i) < finish; i++) {
797 if (buf[start + i] != next.charAt(i))
798 return false;
799 }
800 }
801
802 // if the first fillbuf didn't get enough data, give
803 // fillbuf another chance to read
804 if (i < len) {
805 if (reader == null || isClosed)
806 return false;
807
808 //
809 // This diagnostic "knows" that the only way big strings would
810 // fail to be peeked is where it's a symbol ... e.g. for an
811 // </EndTag> construct. That knowledge could also be applied
812 // to get rid of the symbol length constraint, since having
813 // the wrong symbol is a fatal error anyway ...
814 //
815 if (len > buf.length) {
816 fatal("P-077", new Object[]{Integer.valueOf(buf.length)});
817 }
818
819 fillbuf();
820 return peek(next, chars);
821 }
822
823 start += len;
824 return true;
825 }
826
827
828 //
829 // Support for reporting the internal DTD subset, so <!DOCTYPE...>
830 // declarations can be recreated. This is collected as a single
831 // string; such subsets are normally small, and many applications
832 // don't even care about this.
833 //
834 public void startRemembering() {
835
836 if (startRemember != 0)
837 throw new InternalError();
970
971 public void close() {
972
973 try {
974 if (reader != null && !isClosed)
975 reader.close();
976 isClosed = true;
977 } catch (IOException e) {
978 /* NOTHING */
979 }
980 }
981
982
983 private void fatal(String messageId, Object params [])
984 throws SAXException {
985
986 SAXParseException x = new SAXParseException(DTDParser.messages.getMessage(locale, messageId, params), null);
987
988 // not continuable ... e.g. WF errors
989 close();
990 if (errHandler != null) {
991 errHandler.fatalError(x);
992 }
993 throw x;
994 }
995 }
|