RFR: 8276766: Enable jar and jmod to produce deterministic timestamped content [v14]
John Neffenger
jgneff at openjdk.java.net
Thu Dec 2 01:09:33 UTC 2021
On Wed, 1 Dec 2021 18:02:05 GMT, Andrew Leonard <aleonard at openjdk.org> wrote:
>> Add a new --source-date <TIMESTAMP> (epoch seconds) option to jar and jmod to allow specification of time to use for created/updated jar/jmod entries. This then allows the ability to make the content deterministic.
>>
>> Signed-off-by: Andrew Leonard <anleonar at redhat.com>
>
> Andrew Leonard has updated the pull request incrementally with one additional commit since the last revision:
>
> Update src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java
>
> Co-authored-by: Magnus Ihse Bursie <mag at icus.se>
Mainly just two minor comments: (1) there's a better date and time parser, and (2) the current lower bound is a couple seconds off. I'll reply to your question about (2) separately.
The `DateTimeFormatter.ISO_ZONED_DATE_TIME` zoned date and time parser works better than the `ISO_DATE_TIME` local date and time parser when creating a `ZonedDateTime` instance. It catches the following error slightely earlier and provides a better error message.
Here's the current error using the local date and time parser:
$ jmod create --date 2011-12-03T10:15:30 ...
Error: --date 2011-12-03T10:15:30 is not a valid ISO 8601 date and time:
Text '2011-12-03T10:15:30' could not be parsed:
Unable to obtain ZonedDateTime from TemporalAccessor:
{},ISO resolved to 2011-12-03T10:15:30 of type java.time.format.Parsed
Here's the same error using the zoned date and time parser:
$ jmod create --date 2011-12-03T10:15:30 ...
Error: --date 2011-12-03T10:15:30 is not a valid ISO 8601 date and time:
Text '2021-11-29T09:36:06' could not be parsed at index 19
src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java line 199:
> 197: void process(Main jartool, String opt, String arg) throws BadArgs {
> 198: try {
> 199: jartool.date = ZonedDateTime.parse(arg, DateTimeFormatter.ISO_DATE_TIME)
The `ISO_ZONED_DATE_TIME` parser works better here.
src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java line 201:
> 199: jartool.date = ZonedDateTime.parse(arg, DateTimeFormatter.ISO_DATE_TIME)
> 200: .withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
> 201: if (jartool.date.getYear() < 1980 || jartool.date.getYear() > 2099) {
This `if` test actually compares down to the nanosecond, if present, but the wrong nanosecond. How about something like the following?
... ZonedDateTime TIME_MIN = ZonedDateTime.parse("1980-01-01T00:00:02Z");
... ZonedDateTime TIME_MAX = ZonedDateTime.parse("2099-12-31T23:59:59Z");
...
var zoned = ZonedDateTime.parse(date, DateTimeFormatter.ISO_ZONED_DATE_TIME);
if (zoned.isBefore(TIME_MIN) || zoned.isAfter(TIME_MAX)) {
....
src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties line 88:
> 86: date {0} is not a valid ISO 8601 date and time
> 87: error.date.out.of.range=\
> 88: date {0} is not within the valid year range 1980->2099
Maybe just define `date {0} is not within the valid range` and put the exact interval in the *man* pages and documentation?
src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java line 1164:
> 1162: public LocalDateTime convert(String value) {
> 1163: try {
> 1164: LocalDateTime date = ZonedDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME)
The `ISO_ZONED_DATE_TIME` parser works better here.
src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java line 1166:
> 1164: LocalDateTime date = ZonedDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME)
> 1165: .withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
> 1166: if (date.getYear() < 1980 || date.getYear() > 2099) {
See previous comment for this line in the `jar` tool.
src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod.properties line 111:
> 109: err.no.moduleToHash=No hashes recorded: no module matching {0} found to record hashes
> 110: err.invalid.date=--date {0} is not a valid ISO 8601 date and time: {1}
> 111: err.date.out.of.range=--date {0} is out of the valid year range 1980->2099
As before, perhaps refer to the exact range in the documentation? It's really an instant on the time line that is being compared and not the actual year digits that were provided in the command-line option.
test/jdk/tools/jar/JarEntryTime.java line 180:
> 178: "2022-03-15T00:00:00+06:00",
> 179: "2038-11-26T06:06:06+00:00",
> 180: "2098-02-18T00:00:00-08:00"};
It would be great to test just inside the exact boundaries of the permitted interval here.
test/jdk/tools/jar/JarEntryTime.java line 251:
> 249: // Negative Tests --date out of range source date
> 250: String[] badSourceDates = {"1976-06-24T01:02:03+00:00",
> 251: "2100-02-18T00:00:00-11:00"};
It would be great to test just outside the exact boundaries of the permitted interval here.
-------------
Changes requested by jgneff (no project role).
PR: https://git.openjdk.java.net/jdk/pull/6481
More information about the compiler-dev
mailing list