Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8273727

(prop) Canonical property storage

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P4
    • Resolution: Approved
    • Fix Version/s: 18
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      behavioral
    • Compatibility Risk:
      minimal
    • Compatibility Risk Description:
      Hide
      The change to the order in which the properties are written out shouldn't cause any compatibility risk to any applications because the previous order was neither specified nor deterministic. Steps also have been taken to preserve the order in which properties are written in the case where a subclass overrides Properties::entrySet() and return a different set than that returned by super::entrySet().
      The default date comment that gets written out won't be changed unless someone explicitly and intentionally sets the new system property to change the comment that gets added. In such cases, where the system property value that is being set doesn't represent a "EEE MMM dd HH:mm:ss zzz yyyy" formatted `java.util.Date`, there's a very small risk that any application that relied on this date comment would start to fail. This risk however is very minimal because the `java.util.Properties` APIs don't have any APIs to read or load comments and the only way these comments could be read is reading that file as a textual file, line by line, either using Java APIs or some external tool/script.
      Show
      The change to the order in which the properties are written out shouldn't cause any compatibility risk to any applications because the previous order was neither specified nor deterministic. Steps also have been taken to preserve the order in which properties are written in the case where a subclass overrides Properties::entrySet() and return a different set than that returned by super::entrySet(). The default date comment that gets written out won't be changed unless someone explicitly and intentionally sets the new system property to change the comment that gets added. In such cases, where the system property value that is being set doesn't represent a "EEE MMM dd HH:mm:ss zzz yyyy" formatted `java.util.Date`, there's a very small risk that any application that relied on this date comment would start to fail. This risk however is very minimal because the `java.util.Properties` APIs don't have any APIs to read or load comments and the only way these comments could be read is reading that file as a textual file, line by line, either using Java APIs or some external tool/script.
    • Interface Kind:
      Java API, System or security property
    • Scope:
      SE

      Description

      Summary

      java.util.Properties::store(Writer writer, String comments) and java.util.Properties::store(OutputStream out, String comments) must write the properties in a deterministic order and must allow for the default added date comment to be user controlled.

      Problem

      Applications, such as build tools, use the Properties::store methods to write out the application specific properties. In certain environments, like for generating reproducible builds (https://reproducible-builds.org/) these build tools expect the stored output to be exactly the same when the same set of property keys and values are provided as inputs to the store methods.

      The implementation of the Properties::store methods, currently writes out the properties in the iteration order of an internal hash based map. This order is not deterministic, and it may vary from run to run.

      Additionally, the Properties::store method implementations always write out a default comment which is the formatted string representation of the current date and time. Naturally, this also varies from run to run.

      Because of these two implementation semantics, applications cannot rely on Properties::store methods to produce reproducible output.

      Solution

      Change the implementation of Properties::store methods to write out the properties in the natural order of the property keys and also introduce a system property that can be set to control the default comment that gets written out by these methods.

      Multiple different options were discussed in the PR as well as a proposal thread before coming to this solution. The links to those threads are as follows:

      https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-August/080758.html

      https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-September/081113.html

      https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-September/081115.html

      Specification

      diff --git a/src/java.base/share/classes/java/util/Properties.java b/src/java.base/share/classes/java/util/Properties.java
      index 333b75f45b00..2955f65c20e8 100644
      --- a/src/java.base/share/classes/java/util/Properties.java
      +++ b/src/java.base/share/classes/java/util/Properties.java
      @@ -46,6 +46,7 @@
       import java.util.function.BiFunction;
       import java.util.function.Function;
      
      +import jdk.internal.util.StaticProperty;
       import sun.nio.cs.ISO_8859_1;
       import sun.nio.cs.UTF_8;
      
      @@ -807,17 +808,25 @@ public void save(OutputStream out, String comments)  {
            * If the comments argument is not null, then an ASCII {@code #}
            * character, the comments string, and a line separator are first written
            * to the output stream. Thus, the {@code comments} can serve as an
      -     * identifying comment. Any one of a line feed ('\n'), a carriage
      -     * return ('\r'), or a carriage return followed immediately by a line feed
      -     * in comments is replaced by a line separator generated by the {@code Writer}
      -     * and if the next character in comments is not character {@code #} or
      -     * character {@code !} then an ASCII {@code #} is written out
      -     * after that line separator.
      +     * identifying comment. Any one of a line feed ({@code \n}), a carriage
      +     * return ({@code \r}), or a carriage return followed immediately by a line feed
      +     * ({@code \r\n}) in comments is replaced by a
      +     * {@link System#lineSeparator() line separator} and if the next
      +     * character in comments is not character {@code #} or character {@code !} then
      +     * an ASCII {@code #} is written out after that line separator.
            * <p>
      -     * Next, a comment line is always written, consisting of an ASCII
      -     * {@code #} character, the current date and time (as if produced
      -     * by the {@code toString} method of {@code Date} for the
      -     * current time), and a line separator as generated by the {@code Writer}.
      +     * If the {@systemProperty java.properties.date} is set on the command line
      +     * and is non-empty (as determined by {@link String#isEmpty()  String.isEmpty}),
      +     * a comment line is written as follows.
      +     * First, a {@code #} character is written, followed by the contents
      +     * of the property, followed by a line separator. Any line terminator characters
      +     * in the value of the system property are treated the same way as noted above
      +     * for the comments argument.
      +     * If the system property is not set or is empty, a comment line is written
      +     * as follows.
      +     * First, a {@code #} character is written, followed by the current date and time
      +     * formatted as if by the {@link Date#toString() Date.toString} method,
      +     * followed by a line separator.
            * <p>
            * Then every entry in this {@code Properties} table is
            * written out, one per line. For each entry the key string is
      @@ -833,6 +842,10 @@ public void save(OutputStream out, String comments)  {
            * After the entries have been written, the output stream is flushed.
            * The output stream remains open after this method returns.
            *
      +     * @implSpec The keys and elements are written in the natural sort order
      +     * of the keys in the {@code entrySet()} unless {@code entrySet()} is
      +     * overridden by a subclass to return a different value than {@code super.entrySet()}.
      +     *
            * @param   writer      an output character stream writer.
            * @param   comments   a description of the property list.
            * @throws     IOException if writing this property list to the specified
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              jpai Jaikiran Pai
              Reporter:
              mr Mark Reinhold
              Reviewed By:
              Daniel Fuchs, Roger Riggs
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: