8187987: Add a mechanism to configure custom variants in HijrahChronology
Reviewed-by: joehw, rriggs
This commit is contained in:
parent
f129cc4328
commit
0ae7207e95
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,7 +39,7 @@ $(eval $(call IncludeCustomExtension, CompileJavaModules.gmk))
|
||||
# Module specific build settings
|
||||
|
||||
java.base_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference,-accessibility '-Xdoclint/package:java.*,javax.*' -XDstringConcat=inline
|
||||
java.base_COPY += .icu .dat .spp .nrm content-types.properties hijrah-config-islamic-umalqura.properties
|
||||
java.base_COPY += .icu .dat .spp .nrm content-types.properties hijrah-config-Hijrah-umalqura_islamic-umalqura.properties
|
||||
java.base_CLEAN += intrinsic.properties
|
||||
|
||||
java.base_EXCLUDE_FILES += \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -60,10 +60,15 @@ package java.time.chrono;
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.time.Clock;
|
||||
@ -189,6 +194,11 @@ import sun.util.logging.PlatformLogger;
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* <p>
|
||||
* Additional variants may be added by providing configuration properties files in
|
||||
* {@code <JAVA_HOME>/conf/chronology} directory. The properties
|
||||
* files should follow the naming convention of
|
||||
* {@code hijrah-config-<chronology id>_<calendar type>.properties}.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@ -278,6 +288,11 @@ public final class HijrahChronology extends AbstractChronology implements Serial
|
||||
// Register it by its aliases
|
||||
AbstractChronology.registerChrono(INSTANCE, "Hijrah");
|
||||
AbstractChronology.registerChrono(INSTANCE, "islamic");
|
||||
|
||||
// custom config chronologies
|
||||
CONF_PATH = Path.of(AccessController.doPrivileged((PrivilegedAction<String>)
|
||||
() -> System.getProperty("java.home")), "conf", "chronology");
|
||||
registerCustomChrono();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -800,27 +815,40 @@ public final class HijrahChronology extends AbstractChronology implements Serial
|
||||
private static final String KEY_TYPE = "type";
|
||||
private static final String KEY_VERSION = "version";
|
||||
private static final String KEY_ISO_START = "iso-start";
|
||||
private static final Path CONF_PATH;
|
||||
|
||||
/**
|
||||
* Return the configuration properties from the resource.
|
||||
* <p>
|
||||
* The location of the variant configuration resource is:
|
||||
* <pre>
|
||||
* "/java/time/chrono/hijrah-config-" + calendarType + ".properties"
|
||||
* "/java/time/chrono/" (for "islamic-umalqura" type), or
|
||||
* "<JAVA_HOME>/conf/chronology/" +
|
||||
* "hijrah-config-" + chronologyId + "_" + calendarType + ".properties"
|
||||
* </pre>
|
||||
*
|
||||
* @param chronologyId the chronology ID of the calendar variant
|
||||
* @param calendarType the calendarType of the calendar variant
|
||||
* @return a Properties containing the properties read from the resource.
|
||||
* @throws Exception if access to the property resource fails
|
||||
*/
|
||||
private Properties readConfigProperties(final String calendarType) throws Exception {
|
||||
String resourceName = RESOURCE_PREFIX + calendarType + RESOURCE_SUFFIX;
|
||||
PrivilegedAction<InputStream> getResourceAction = () -> HijrahChronology.class.getResourceAsStream(resourceName);
|
||||
private static Properties readConfigProperties(final String chronologyId, final String calendarType) throws Exception {
|
||||
String resourceName = RESOURCE_PREFIX + chronologyId + "_" + calendarType + RESOURCE_SUFFIX;
|
||||
PrivilegedAction<InputStream> getResourceAction = calendarType.equals("islamic-umalqura") ?
|
||||
() -> HijrahChronology.class.getResourceAsStream(resourceName) :
|
||||
() -> {
|
||||
try {
|
||||
return Files.newInputStream(CONF_PATH.resolve(resourceName),
|
||||
StandardOpenOption.READ);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
};
|
||||
FilePermission perm1 = new FilePermission("<<ALL FILES>>", "read");
|
||||
RuntimePermission perm2 = new RuntimePermission("accessSystemModules");
|
||||
try (InputStream is = AccessController.doPrivileged(getResourceAction, null, perm1, perm2)) {
|
||||
if (is == null) {
|
||||
throw new RuntimeException("Hijrah calendar resource not found: /java/time/chrono/" + resourceName);
|
||||
throw new RuntimeException("Hijrah calendar resource not found: " + resourceName);
|
||||
}
|
||||
Properties props = new Properties();
|
||||
props.load(is);
|
||||
@ -841,7 +869,7 @@ public final class HijrahChronology extends AbstractChronology implements Serial
|
||||
*/
|
||||
private void loadCalendarData() {
|
||||
try {
|
||||
Properties props = readConfigProperties(calendarType);
|
||||
Properties props = readConfigProperties(typeId, calendarType);
|
||||
|
||||
Map<Integer, int[]> years = new HashMap<>();
|
||||
int minYear = Integer.MAX_VALUE;
|
||||
@ -1009,6 +1037,44 @@ public final class HijrahChronology extends AbstractChronology implements Serial
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for Hijrah chronology variant properties files in
|
||||
* <JAVA_HOME>/conf/chronology directory. Then register its chronology, if any.
|
||||
*/
|
||||
private static void registerCustomChrono() {
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<Void>)() -> {
|
||||
if (Files.isDirectory(CONF_PATH)) {
|
||||
try {
|
||||
Files.list(CONF_PATH)
|
||||
.map(p -> p.getFileName().toString())
|
||||
.filter(fn -> fn.matches("hijrah-config-[^\\.]+\\.properties"))
|
||||
.map(fn -> fn.replaceAll("(hijrah-config-|\\.properties)", ""))
|
||||
.forEach(idtype -> {
|
||||
int delimiterPos = idtype.indexOf('_');
|
||||
// '_' should be somewhere in the middle of idtype
|
||||
if (delimiterPos > 1 && delimiterPos < idtype.length() - 1) {
|
||||
AbstractChronology.registerChrono(
|
||||
new HijrahChronology(
|
||||
idtype.substring(0, delimiterPos),
|
||||
idtype.substring(delimiterPos + 1)));
|
||||
} else {
|
||||
PlatformLogger.getLogger("java.time.chrono")
|
||||
.warning("Hijrah custom config init failed." +
|
||||
"'<id>_<type>' name convention not followed: " + idtype);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
PlatformLogger.getLogger("java.time.chrono")
|
||||
.warning("Hijrah custom config init failed.", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
null,
|
||||
new FilePermission("<<ALL FILES>>", "read"));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Writes the Chronology using a
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.util.Locale;
|
||||
|
||||
public class HijrahConfigCheck {
|
||||
private static final String CALTYPE = "islamic-test";
|
||||
|
||||
public static void main(String... args) {
|
||||
// Availability test
|
||||
if (Chronology.getAvailableChronologies().stream()
|
||||
.filter(c -> c.getCalendarType().equals(CALTYPE))
|
||||
.count() != 1) {
|
||||
throw new RuntimeException(CALTYPE + " chronology was not found, or " +
|
||||
"appeared more than once in Chronology.getAvailableChronologies()");
|
||||
}
|
||||
|
||||
// Instantiation tests
|
||||
Chronology c1 = Chronology.of(CALTYPE);
|
||||
Chronology c2 = Chronology.ofLocale(Locale.forLanguageTag("und-u-ca-" + CALTYPE ));
|
||||
if (!c1.equals(c2)) {
|
||||
throw new RuntimeException(CALTYPE + " chronologies differ. c1: " + c1 +
|
||||
", c2: " + c2);
|
||||
}
|
||||
|
||||
// Date test
|
||||
// 2020-01-10 is AH 1000-01-10 in islamic-test config
|
||||
LocalDateTime iso = LocalDateTime.of(LocalDate.of(2020, 1, 10), LocalTime.MIN);
|
||||
ChronoLocalDateTime hijrah = c1.date(1000, 1, 10).atTime(LocalTime.MIN);
|
||||
if (!iso.toInstant(ZoneOffset.UTC).equals(hijrah.toInstant(ZoneOffset.UTC))) {
|
||||
throw new RuntimeException("test Hijrah date is incorrect. LocalDate: " +
|
||||
iso + ", test date: " + hijrah);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import tests.Helper;
|
||||
import tests.JImageGenerator;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Tests whether a custom Hijrah configuration properties file works correctly
|
||||
* @bug 8187987
|
||||
* @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g)
|
||||
* @library /tools/lib
|
||||
* @modules java.base/jdk.internal.jimage
|
||||
* jdk.jdeps/com.sun.tools.classfile
|
||||
* jdk.jlink/jdk.tools.jimage
|
||||
* jdk.compiler
|
||||
* @build HijrahConfigCheck tests.*
|
||||
* @run main/othervm -Xmx1g HijrahConfigTest
|
||||
*/
|
||||
public class HijrahConfigTest {
|
||||
|
||||
private static final String TEST_CONFIG = "hijrah-config-Hijrah-test_islamic-test.properties";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Helper helper = Helper.newHelper();
|
||||
if (helper == null) {
|
||||
System.err.println("Test not run");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the test JDK image
|
||||
Path outputPath = helper.createNewImageDir("HijrahConfigTest");
|
||||
JImageGenerator.getJLinkTask()
|
||||
.output(outputPath)
|
||||
.addMods("java.base")
|
||||
.call().assertSuccess();
|
||||
|
||||
// Install the test hijrah configuration properties
|
||||
Path confPath = outputPath.resolve("conf").resolve("chronology");
|
||||
Files.createDirectory(confPath);
|
||||
Files.copy(Path.of(System.getProperty("test.src"), TEST_CONFIG),
|
||||
confPath.resolve(TEST_CONFIG));
|
||||
|
||||
// Run tests
|
||||
Path launcher = outputPath.resolve("bin").resolve("java");
|
||||
ProcessBuilder builder = new ProcessBuilder(
|
||||
launcher.toAbsolutePath().toString(), "-ea", "-esa", "HijrahConfigCheck");
|
||||
Process p = builder.inheritIO().start();
|
||||
p.waitFor();
|
||||
int exitValue = p.exitValue();
|
||||
if (exitValue != 0) {
|
||||
throw new RuntimeException("HijrahConfigTest failed. Exit value: " + exitValue);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
|
||||
# A test configuration properties file for a custom Hijrah chronology.
|
||||
# The data here are solely hypothetical and do not represent any of
|
||||
# the actual Hijrah variants.
|
||||
|
||||
# Version of this definition
|
||||
version=0.1
|
||||
|
||||
# Java chronology ID
|
||||
id=Hijrah-test
|
||||
|
||||
# Standard calendar type specification
|
||||
type=islamic-test
|
||||
|
||||
# defines the corresponding ISO date to the earliest Hijrah date
|
||||
iso-start=2020-01-01
|
||||
|
||||
# 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
1000=29 30 29 29 30 29 30 29 30 30 30 29
|
||||
1001=30 29 30 29 29 30 29 29 30 30 30 30
|
||||
1002=29 30 29 30 29 29 29 30 29 30 30 30
|
||||
1003=29 30 30 29 30 29 29 29 30 29 30 30
|
||||
1004=29 30 30 29 30 29 30 29 29 30 29 30
|
||||
1005=30 29 30 29 30 30 29 30 29 30 29 30
|
||||
1006=29 29 30 29 30 30 29 30 29 30 30 29
|
||||
1007=30 29 29 30 29 30 29 30 30 29 30 30
|
||||
1008=29 30 29 29 30 29 29 30 30 30 29 30
|
||||
1009=30 29 30 29 29 30 29 29 30 30 29 30
|
||||
1010=30 30 29 30 29 29 30 29 29 30 30 29
|
@ -1,5 +1,5 @@
|
||||
# java.time tests use TestNG
|
||||
TestNG.dirs = ..
|
||||
othervm.dirs = java/time/chrono
|
||||
lib.dirs = /test/lib
|
||||
lib.dirs = /test/lib /test/jdk/tools/lib
|
||||
lib.build = jdk.test.lib.RandomFactory
|
||||
|
@ -1,5 +1,5 @@
|
||||
# java.time tests use TestNG
|
||||
TestNG.dirs = ..
|
||||
othervm.dirs = java/time/chrono java/time/format
|
||||
lib.dirs = /test/lib
|
||||
lib.dirs = /test/lib /test/jdk/tools/lib
|
||||
lib.build = jdk.test.lib.RandomFactory
|
||||
|
Loading…
x
Reference in New Issue
Block a user