Skip to content

Commit 2fbbf47

Browse files
author
Niall Pemberton
committed
Replace BOM detection and XML guess logic with BOMInputStream
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1004092 13f79535-47bb-0310-9956-ffa450edef68
1 parent 5b75cf8 commit 2fbbf47

1 file changed

Lines changed: 29 additions & 65 deletions

File tree

src/java/org/apache/commons/io/input/XmlStreamReader.java

Lines changed: 29 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import java.util.regex.Matcher;
3333
import java.text.MessageFormat;
3434

35+
import org.apache.commons.io.ByteOrderMark;
36+
3537
/**
3638
* Character stream that handles all the necessary Voodo to figure out the
3739
* charset encoding of the XML document within the stream.
@@ -75,6 +77,12 @@ public class XmlStreamReader extends Reader {
7577

7678
private static final String EBCDIC = "CP1047";
7779

80+
private static final ByteOrderMark XML_UTF_8 = new ByteOrderMark(UTF_8, 0x3C, 0x3F, 0x78, 0x6D);
81+
private static final ByteOrderMark XML_UTF_16BE = new ByteOrderMark(UTF_16BE, 0x00, 0x3C, 0x00, 0x3F);
82+
private static final ByteOrderMark XML_UTF_16LE = new ByteOrderMark(UTF_16LE, 0x3C, 0x00, 0x3F, 0x00);
83+
private static final ByteOrderMark XML_EBCDIC = new ByteOrderMark(EBCDIC, 0x4C, 0x6F, 0xA7, 0x94);
84+
85+
7886
private static String staticDefaultEncoding = null;
7987

8088
private Reader reader;
@@ -406,27 +414,41 @@ public void close() throws IOException {
406414

407415
private void doRawStream(InputStream is, boolean lenient)
408416
throws IOException {
409-
BufferedInputStream pis = new BufferedInputStream(is, BUFFER_SIZE);
410-
String bomEnc = getBOMEncoding(pis);
411-
String xmlGuessEnc = getXMLGuessEncoding(pis);
417+
BOMInputStream bom = createBomStream(new BufferedInputStream(is, BUFFER_SIZE));
418+
BOMInputStream pis = createXmlStream(bom);
419+
String bomEnc = (bom.hasBOM() ? bom.getBOM().getCharsetName() : null);
420+
String xmlGuessEnc = (pis.hasBOM() ? pis.getBOM().getCharsetName() : null);
412421
String xmlEnc = getXmlProlog(pis, xmlGuessEnc);
413422
String encoding = calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc, pis);
414423
prepareReader(pis, encoding);
415424
}
416425

417426
private void doHttpStream(InputStream is, String httpContentType,
418427
boolean lenient) throws IOException {
419-
BufferedInputStream pis = new BufferedInputStream(is, BUFFER_SIZE);
428+
BOMInputStream bom = createBomStream(new BufferedInputStream(is, BUFFER_SIZE));
429+
BOMInputStream pis = createXmlStream(bom);
420430
String cTMime = getContentTypeMime(httpContentType);
421431
String cTEnc = getContentTypeEncoding(httpContentType);
422-
String bomEnc = getBOMEncoding(pis);
423-
String xmlGuessEnc = getXMLGuessEncoding(pis);
432+
String bomEnc = (bom.hasBOM() ? bom.getBOM().getCharsetName() : null);
433+
String xmlGuessEnc = (pis.hasBOM() ? pis.getBOM().getCharsetName() : null);
424434
String xmlEnc = getXmlProlog(pis, xmlGuessEnc);
425435
String encoding = calculateHttpEncoding(cTMime, cTEnc, bomEnc,
426436
xmlGuessEnc, xmlEnc, pis, lenient);
427437
prepareReader(pis, encoding);
428438
}
429439

440+
private BOMInputStream createBomStream(InputStream delegate) {
441+
BOMInputStream bis =
442+
new BOMInputStream(delegate, false, ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE);
443+
return bis;
444+
}
445+
446+
private BOMInputStream createXmlStream(InputStream delegate) {
447+
BOMInputStream bis =
448+
new BOMInputStream(delegate, true, XML_UTF_8, XML_UTF_16BE, XML_UTF_16LE, XML_EBCDIC);
449+
return bis;
450+
}
451+
430452
private void prepareReader(InputStream is, String encoding)
431453
throws IOException {
432454
reader = new InputStreamReader(is, encoding);
@@ -556,70 +578,12 @@ private static String getContentTypeEncoding(String httpContentType) {
556578
return encoding;
557579
}
558580

559-
// returns the BOM in the stream, NULL if not present,
560-
// if there was BOM the in the stream it is consumed
561-
private static String getBOMEncoding(BufferedInputStream is)
562-
throws IOException {
563-
String encoding = null;
564-
int[] bytes = new int[3];
565-
is.mark(3);
566-
bytes[0] = is.read();
567-
bytes[1] = is.read();
568-
bytes[2] = is.read();
569-
570-
if (bytes[0] == 0xFE && bytes[1] == 0xFF) {
571-
encoding = UTF_16BE;
572-
is.reset();
573-
is.read();
574-
is.read();
575-
} else if (bytes[0] == 0xFF && bytes[1] == 0xFE) {
576-
encoding = UTF_16LE;
577-
is.reset();
578-
is.read();
579-
is.read();
580-
} else if (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
581-
encoding = UTF_8;
582-
} else {
583-
is.reset();
584-
}
585-
return encoding;
586-
}
587-
588-
// returns the best guess for the encoding by looking the first bytes of the
589-
// stream, '<?'
590-
private static String getXMLGuessEncoding(BufferedInputStream is)
591-
throws IOException {
592-
String encoding = null;
593-
int[] bytes = new int[4];
594-
is.mark(4);
595-
bytes[0] = is.read();
596-
bytes[1] = is.read();
597-
bytes[2] = is.read();
598-
bytes[3] = is.read();
599-
is.reset();
600-
601-
if (bytes[0] == 0x00 && bytes[1] == 0x3C && bytes[2] == 0x00
602-
&& bytes[3] == 0x3F) {
603-
encoding = UTF_16BE;
604-
} else if (bytes[0] == 0x3C && bytes[1] == 0x00 && bytes[2] == 0x3F
605-
&& bytes[3] == 0x00) {
606-
encoding = UTF_16LE;
607-
} else if (bytes[0] == 0x3C && bytes[1] == 0x3F && bytes[2] == 0x78
608-
&& bytes[3] == 0x6D) {
609-
encoding = UTF_8;
610-
} else if (bytes[0] == 0x4C && bytes[1] == 0x6F && bytes[2] == 0xA7
611-
&& bytes[3] == 0x94) {
612-
encoding = EBCDIC;
613-
}
614-
return encoding;
615-
}
616-
617581
public static final Pattern ENCODING_PATTERN = Pattern.compile(
618582
"<\\?xml.*encoding[\\s]*=[\\s]*((?:\".[^\"]*\")|(?:'.[^']*'))",
619583
Pattern.MULTILINE);
620584

621585
// returns the encoding declared in the <?xml encoding=...?>, NULL if none
622-
private static String getXmlProlog(BufferedInputStream is, String guessedEnc)
586+
private static String getXmlProlog(InputStream is, String guessedEnc)
623587
throws IOException {
624588
String encoding = null;
625589
if (guessedEnc != null) {

0 commit comments

Comments
 (0)