diff --git a/src/share/classes/java/util/Properties.java b/src/share/classes/java/util/Properties.java index c8bdab7c2730773dbe2f707d2f56fddd9e4d93ff..e084479c6d96a87bc4e3c665a975cd8bbfe36eb7 100644 --- a/src/share/classes/java/util/Properties.java +++ b/src/share/classes/java/util/Properties.java @@ -81,8 +81,9 @@ import sun.util.spi.XmlPropertiesProvider; *

The {@link #loadFromXML(InputStream)} and {@link * #storeToXML(OutputStream, String, String)} methods load and store properties * in a simple XML format. By default the UTF-8 character encoding is used, - * however a specific encoding may be specified if required. An XML properties - * document has the following DOCTYPE declaration: + * however a specific encoding may be specified if required. Implementations + * are required to support UTF-8 and UTF-16 and may support other encodings. + * An XML properties document has the following DOCTYPE declaration: * *

  * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
@@ -853,23 +854,30 @@ class Properties extends Hashtable {
      * Furthermore, the document must satisfy the properties DTD described
      * above.
      *
+     * 

An implementation is required to read XML documents that use the + * "{@code UTF-8}" or "{@code UTF-16}" encoding. An implementation may + * support additional encodings. + * *

The specified stream is closed after this method returns. * * @param in the input stream from which to read the XML document. * @throws IOException if reading from the specified input stream * results in an IOException. + * @throws java.io.UnsupportedEncodingException if the document's encoding + * declaration can be read and it specifies an encoding that is not + * supported * @throws InvalidPropertiesFormatException Data on input stream does not * constitute a valid XML document with the mandated document type. * @throws NullPointerException if {@code in} is null. * @see #storeToXML(OutputStream, String, String) + * @see Character + * Encoding in Entities * @since 1.5 */ public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException { - if (in == null) - throw new NullPointerException(); - XmlSupport.load(this, in); + XmlSupport.load(this, Objects.requireNonNull(in)); in.close(); } @@ -896,8 +904,6 @@ class Properties extends Hashtable { public void storeToXML(OutputStream os, String comment) throws IOException { - if (os == null) - throw new NullPointerException(); storeToXML(os, comment, "UTF-8"); } @@ -910,9 +916,13 @@ class Properties extends Hashtable { * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> *

* - *

If the specified comment is {@code null} then no comment + *

If the specified comment is {@code null} then no comment * will be stored in the document. * + *

An implementation is required to support writing of XML documents + * that use the "{@code UTF-8}" or "{@code UTF-16}" encoding. An + * implementation may support additional encodings. + * *

The specified stream remains open after this method returns. * * @param os the output stream on which to emit the XML document. @@ -924,20 +934,23 @@ class Properties extends Hashtable { * * @throws IOException if writing to the specified output stream * results in an IOException. + * @throws java.io.UnsupportedEncodingException if the encoding is not + * supported by the implementation. * @throws NullPointerException if {@code os} is {@code null}, * or if {@code encoding} is {@code null}. * @throws ClassCastException if this {@code Properties} object * contains any keys or values that are not * {@code Strings}. * @see #loadFromXML(InputStream) + * @see Character + * Encoding in Entities * @since 1.5 */ public void storeToXML(OutputStream os, String comment, String encoding) throws IOException { - if (os == null) - throw new NullPointerException(); - XmlSupport.save(this, os, comment, encoding); + XmlSupport.save(this, Objects.requireNonNull(os), comment, + Objects.requireNonNull(encoding)); } /** diff --git a/src/share/classes/sun/util/spi/XmlPropertiesProvider.java b/src/share/classes/sun/util/spi/XmlPropertiesProvider.java index 42194daba294edc824ca8b8c2e6783909bb67a1b..3e4acddecfa4dd5fbfb06a0adc14a2e17738b658 100644 --- a/src/share/classes/sun/util/spi/XmlPropertiesProvider.java +++ b/src/share/classes/sun/util/spi/XmlPropertiesProvider.java @@ -55,6 +55,9 @@ public abstract class XmlPropertiesProvider { * @param props the properties table to populate * @param in the input stream from which to read the XML document * @throws IOException if reading from the specified input stream fails + * @throws java.io.UnsupportedEncodingException if the document's encoding + * declaration can be read and it specifies an encoding that is not + * supported * @throws InvalidPropertiesFormatException Data on input stream does not * constitute a valid XML document with the mandated document type. * @@ -73,6 +76,8 @@ public abstract class XmlPropertiesProvider { * @param encoding the name of a supported character encoding * * @throws IOException if writing to the specified output stream fails + * @throws java.io.UnsupportedEncodingException if the encoding is not + * supported by the implementation * @throws NullPointerException if {@code out} is null. * @throws ClassCastException if this {@code Properties} object * contains any keys or values that are not diff --git a/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java b/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java index f4e4010b28274d0b2b90d0c3bd03e27a4fb1f1c7..0878c3de9949980b30ea405727a453d6b113a9ad 100644 --- a/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java +++ b/src/share/classes/sun/util/xml/PlatformXmlPropertiesProvider.java @@ -27,6 +27,7 @@ package sun.util.xml; import java.io.*; import java.util.*; +import java.nio.charset.*; import org.xml.sax.*; import org.w3c.dom.*; import javax.xml.parsers.*; @@ -127,6 +128,13 @@ public class PlatformXmlPropertiesProvider extends XmlPropertiesProvider { String encoding) throws IOException { + // fast-fail for unsupported charsets as UnsupportedEncodingException may + // not be thrown later (see JDK-8000621) + try { + Charset.forName(encoding); + } catch (IllegalCharsetNameException | UnsupportedCharsetException x) { + throw new UnsupportedEncodingException(encoding); + } DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { diff --git a/test/java/util/Properties/LoadAndStoreXML.java b/test/java/util/Properties/LoadAndStoreXML.java index 8fc5e73ab44dd3ed2e3ffb28e736c9ae051e49d4..fd1d81f47e6be0cc3a946ebdc15b985149851972 100644 --- a/test/java/util/Properties/LoadAndStoreXML.java +++ b/test/java/util/Properties/LoadAndStoreXML.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8000354 + * @bug 8000354 8000685 * @summary Basic test of storeToXML and loadToXML */ @@ -66,13 +66,13 @@ public class LoadAndStoreXML { * Sanity test that properties saved with Properties#storeToXML can be * read with Properties#loadFromXML. */ - static void test() throws IOException { + static void testLoadAndStore(String encoding) throws IOException { Properties props = new Properties(); props.put("k1", "foo"); props.put("k2", "bar"); ByteArrayOutputStream out = new ByteArrayOutputStream(); - props.storeToXML(out, "no comment"); + props.storeToXML(out, null, encoding); Properties p = new Properties(); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); @@ -85,19 +85,74 @@ public class LoadAndStoreXML { } } + /** + * Test loadFromXML with a document that does not have an encoding declaration + */ + static void testLoadWithoutEncoding() throws IOException { + Properties expected = new Properties(); + expected.put("foo", "bar"); + + String s = "" + + "" + + "" + + "bar" + + ""; + ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes("UTF-8")); + Properties props = new Properties(); + props.loadFromXML(in); + + if (!props.equals(expected)) { + System.err.println("loaded: " + props + ", expected: " + expected); + throw new RuntimeException("Test failed"); + } + } + + /** + * Test loadFromXML with unsupported encoding + */ + static void testLoadWithBadEncoding() throws IOException { + String s = "" + + "" + + "" + + "bar" + + ""; + ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes("UTF-8")); + Properties props = new Properties(); + try { + props.loadFromXML(in); + throw new RuntimeException("UnsupportedEncodingException expected"); + } catch (UnsupportedEncodingException expected) { } + } + + /** + * Test storeToXML with unsupported encoding + */ + static void testStoreWithBadEncoding() throws IOException { + Properties props = new Properties(); + props.put("foo", "bar"); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + props.storeToXML(out, null, "BAD"); + throw new RuntimeException("UnsupportedEncodingException expected"); + } catch (UnsupportedEncodingException expected) { } + } + public static void main(String[] args) throws IOException { - // run test without security manager - test(); + testLoadAndStore("UTF-8"); + testLoadAndStore("UTF-16"); + testLoadWithoutEncoding(); + testLoadWithBadEncoding(); + testStoreWithBadEncoding(); - // re-run test with security manager + // re-run sanity test with security manager Policy orig = Policy.getPolicy(); Policy p = new SimplePolicy(new RuntimePermission("setSecurityManager"), new PropertyPermission("line.separator", "read")); Policy.setPolicy(p); System.setSecurityManager(new SecurityManager()); try { - test(); + testLoadAndStore("UTF-8"); } finally { // turn off security manager and restore policy System.setSecurityManager(null);