Skip to content

Commit d19259a

Browse files
lucciomanPascalSchumacher
authored andcommitted
IO-557: UnsupportedEncodingException when opening an ISO-8859-1 XML stream with Turkish as the default locale (closes #51)
Perform locale independent upper case conversions. To handle properly lower cased character encoding name in XML prolog with any default system locale, notably Turkish.
1 parent d3fc1a2 commit d19259a

6 files changed

Lines changed: 42 additions & 8 deletions

File tree

src/main/java/org/apache/commons/io/ByteOrderMark.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.apache.commons.io;
1818

1919
import java.io.Serializable;
20+
import java.util.Locale;
2021

2122
/**
2223
* Byte Order Mark (BOM) representation - see {@link org.apache.commons.io.input.BOMInputStream}.
@@ -182,7 +183,7 @@ public String toString() {
182183
builder.append(",");
183184
}
184185
builder.append("0x");
185-
builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase());
186+
builder.append(Integer.toHexString(0xFF & bytes[i]).toUpperCase(Locale.ROOT));
186187
}
187188
builder.append(']');
188189
return builder.toString();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ static String getContentTypeEncoding(final String httpContentType) {
683683
final String postMime = httpContentType.substring(i + 1);
684684
final Matcher m = CHARSET_PATTERN.matcher(postMime);
685685
encoding = m.find() ? m.group(1) : null;
686-
encoding = encoding != null ? encoding.toUpperCase(Locale.US) : null;
686+
encoding = encoding != null ? encoding.toUpperCase(Locale.ROOT) : null;
687687
}
688688
}
689689
return encoding;
@@ -741,7 +741,7 @@ private static String getXmlProlog(final InputStream is, final String guessedEnc
741741
}
742742
final Matcher m = ENCODING_PATTERN.matcher(prolog);
743743
if (m.find()) {
744-
encoding = m.group(1).toUpperCase();
744+
encoding = m.group(1).toUpperCase(Locale.ROOT);
745745
encoding = encoding.substring(1, encoding.length() - 1);
746746
}
747747
}

src/main/java/org/apache/commons/io/output/XmlStreamWriter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.io.OutputStreamWriter;
2525
import java.io.StringWriter;
2626
import java.io.Writer;
27+
import java.util.Locale;
2728
import java.util.regex.Matcher;
2829
import java.util.regex.Pattern;
2930

@@ -168,7 +169,7 @@ private void detectEncoding(final char[] cbuf, final int off, final int len)
168169
final Matcher m = ENCODING_PATTERN.matcher(xmlProlog.substring(0,
169170
xmlPrologEnd));
170171
if (m.find()) {
171-
encoding = m.group(1).toUpperCase();
172+
encoding = m.group(1).toUpperCase(Locale.ROOT);
172173
encoding = encoding.substring(1, encoding.length() - 1);
173174
} else {
174175
// no encoding found in XML prolog: using default

src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,25 @@ public void testHttp() throws Exception {
276276
_testHttpLenient("text/html;charset=UTF-16BE", "no-bom", "US-ASCII", "UTF-8", "UTF-8");
277277
_testHttpLenient("text/html;charset=UTF-32BE", "no-bom", "US-ASCII", "UTF-8", "UTF-8");
278278
}
279+
280+
/**
281+
* Check lower case encoding names are properly handled. Should be successfull
282+
* with any system default locale, notably with Turkish language
283+
* (-Duser.language=tr JVM parameter), which has specific rules to convert dotted and dottless
284+
* i character.
285+
*/
286+
@Test
287+
public void testLowerCaseEncoding() throws Exception {
288+
final String[] encodings = { "iso8859-1", "us-ascii", "utf-8" };
289+
for (final String encoding : encodings) {
290+
final String xml = getXML("no-bom", XML3, encoding, encoding);
291+
try (final ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(encoding));
292+
final XmlStreamReader xmlReader = new XmlStreamReader(is);) {
293+
assertTrue("Check encoding : " + encoding, encoding.equalsIgnoreCase(xmlReader.getEncoding()));
294+
assertEquals("Check content", xml, IOUtils.toString(xmlReader));
295+
}
296+
}
297+
}
279298

280299
@Test
281300
public void testRawContent() throws Exception {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.net.URL;
3030
import java.net.URLConnection;
3131
import java.text.MessageFormat;
32+
import java.util.Locale;
3233
import java.util.regex.Matcher;
3334
import java.util.regex.Pattern;
3435

@@ -590,7 +591,7 @@ static String getContentTypeEncoding(final String httpContentType) {
590591
final String postMime = httpContentType.substring(i + 1);
591592
final Matcher m = CHARSET_PATTERN.matcher(postMime);
592593
encoding = m.find() ? m.group(1) : null;
593-
encoding = encoding != null ? encoding.toUpperCase() : null;
594+
encoding = encoding != null ? encoding.toUpperCase(Locale.ROOT) : null;
594595
}
595596
}
596597
return encoding;
@@ -699,7 +700,7 @@ private static String getXmlProlog(final BufferedInputStream is, final String gu
699700
}
700701
final Matcher m = ENCODING_PATTERN.matcher(prolog);
701702
if (m.find()) {
702-
encoding = m.group(1).toUpperCase();
703+
encoding = m.group(1).toUpperCase(Locale.ROOT);
703704
encoding = encoding.substring(1, encoding.length() - 1);
704705
}
705706
}

src/test/java/org/apache/commons/io/output/XmlStreamWriterTest.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
package org.apache.commons.io.output;
1818

19-
import static org.junit.Assert.assertEquals;
2019
import static org.junit.Assert.assertTrue;
2120

2221
import java.io.ByteArrayOutputStream;
@@ -56,7 +55,7 @@ private static void checkXmlContent(final String xml, final String encoding, fin
5655
writer.write(xml);
5756
writer.close();
5857
final byte[] xmlContent = out.toByteArray();
59-
assertEquals(encoding, writer.getEncoding());
58+
assertTrue(encoding.equalsIgnoreCase(writer.getEncoding()));
6059
assertTrue(Arrays.equals(xml.getBytes(encoding), xmlContent));
6160

6261
}
@@ -102,6 +101,19 @@ public void testDefaultEncoding() throws IOException {
102101
checkXmlWriter(TEXT_UNICODE, null, "UTF-16BE");
103102
checkXmlWriter(TEXT_UNICODE, null, "ISO-8859-1");
104103
}
104+
105+
/**
106+
* Check lower case encoding names are properly handled. Should be successfull
107+
* with any system default locale, notably with Turkish language
108+
* (-Duser.language=tr JVM parameter), which has specific rules to convert
109+
* dotted and dottless i character.
110+
*/
111+
@Test
112+
public void testLowerCaseEncoding() throws IOException {
113+
checkXmlWriter(TEXT_UNICODE, "utf-8");
114+
checkXmlWriter(TEXT_LATIN1, "iso-8859-1");
115+
checkXmlWriter(TEXT_LATIN7, "iso-8859-7");
116+
}
105117

106118
@Test
107119
public void testUTF8Encoding() throws IOException {

0 commit comments

Comments
 (0)