8048124: Read hijra-config-umalqura.properties as a resource
8061533: HijrahChronology should use Integer.parseInt

Removed use of calendar.properties to configure calendars, move UmmAlQura calendar to resource; minor cleanup using parseInt

Reviewed-by: alanb, chegar
diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk
index 9ca5544..fd9a0ef 100644
--- a/jdk/make/copy/Copy-java.base.gmk
+++ b/jdk/make/copy/Copy-java.base.gmk
@@ -48,22 +48,6 @@
 
 ################################################################################
 
-CALENDARS_SRC := $(JDK_TOPDIR)/src/java.base/share/conf
-
-$(LIB_DST_DIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties
-	$(call install-file)
-
-BASE_CONF_FILES += $(LIB_DST_DIR)/calendars.properties
-
-$(LIB_DST_DIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
-
-BASE_CONF_FILES += $(LIB_DST_DIR)/hijrah-config-umalqura.properties
-
-################################################################################
-
 ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),)
 
   TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf
diff --git a/jdk/make/profile-includes.txt b/jdk/make/profile-includes.txt
index a3c7985..226b1ed 100644
--- a/jdk/make/profile-includes.txt
+++ b/jdk/make/profile-includes.txt
@@ -54,14 +54,12 @@
     $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/$(LIBRARY_PREFIX)jvm$(SHARED_LIBRARY_SUFFIX) \
     $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/$(LIBRARY_PREFIX)jvm.diz \
     $(OPENJDK_TARGET_CPU_LEGACY_LIB)/server/Xusage.txt \
-    calendars.properties \
     classlist \
     ext/localedata.jar \
     ext/meta-index \
     ext/sunec.jar \
     ext/sunjce_provider.jar \
     ext/sunpkcs11.jar \
-    hijrah-config-umalqura.properties \
     jce.jar \
     jsse.jar \
     logging.properties \
diff --git a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java
index 7c5005f..c6c6d4a 100644
--- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java
+++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java
@@ -61,13 +61,14 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+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.security.AccessController;
-import java.security.PrivilegedActionException;
+import java.security.PrivilegedAction;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Instant;
@@ -145,29 +146,7 @@
  * property resource that defines the {@code ID}, the {@code calendar type},
  * the start of the calendar, the alignment with the
  * ISO calendar, and the length of each month for a range of years.
- * The variants are identified in the {@code calendars.properties} file.
- * The new properties are prefixed with {@code "calendars.hijrah."}:
- * <table cellpadding="2" border="0" summary="Configuration of Hijrah Calendar Variants">
- * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left">Property Name</th>
- * <th class="colFirst" align="left">Property value</th>
- * <th class="colLast" align="left">Description </th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr class="altColor">
- * <td>calendars.hijrah.{ID}</td>
- * <td>The property resource defining the {@code {ID}} variant</td>
- * <td>The property resource is located with the {@code calendars.properties} file</td>
- * </tr>
- * <tr class="rowColor">
- * <td>calendars.hijrah.{ID}.type</td>
- * <td>The calendar type</td>
- * <td>LDML defines the calendar type names</td>
- * </tr>
- * </tbody>
- * </table>
+ * The variants are loaded by HijrahChronology as a resource from hijrah-config-<calendar-type>.properties.
  * <p>
  * The Hijrah property resource is a set of properties that describe the calendar.
  * The syntax is defined by {@code java.util.Properties#load(Reader)}.
@@ -279,91 +258,41 @@
      * Computed by {@link #createEpochMonths}.
      */
     private transient int maxYearLength;
-    /**
-     * A reference to the properties stored in
-     * ${java.home}/lib/calendars.properties
-     */
-    private final transient static Properties calendarProperties;
 
     /**
-     * Prefix of property names for Hijrah calendar variants.
+     * Prefix of resource names for Hijrah calendar variants.
      */
-    private static final String PROP_PREFIX = "calendar.hijrah.";
-    /**
-     * Suffix of property names containing the calendar type of a variant.
-     */
-    private static final String PROP_TYPE_SUFFIX = ".type";
+    private static final String RESOURCE_PREFIX = "hijrah-config-";
 
     /**
-     * Static initialization of the predefined calendars found in the
-     * lib/calendars.properties file.
+     * Suffix of resource names for Hijrah calendar variants.
+     */
+    private static final String RESOURCE_SUFFIX = ".properties";
+
+    /**
+     * Static initialization of the built-in calendars.
+     * The data is not loaded until it is used.
      */
     static {
-        try {
-            calendarProperties = sun.util.calendar.BaseCalendar.getCalendarProperties();
-        } catch (IOException ioe) {
-            throw new InternalError("Can't initialize lib/calendars.properties", ioe);
-        }
-
-        try {
-            INSTANCE = new HijrahChronology("Hijrah-umalqura");
-            // Register it by its aliases
-            AbstractChronology.registerChrono(INSTANCE, "Hijrah");
-            AbstractChronology.registerChrono(INSTANCE, "islamic");
-        } catch (DateTimeException ex) {
-            // Absence of Hijrah calendar is fatal to initializing this class.
-            PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
-            logger.severe("Unable to initialize Hijrah calendar: Hijrah-umalqura", ex);
-            throw new RuntimeException("Unable to initialize Hijrah-umalqura calendar", ex.getCause());
-        }
-        registerVariants();
+        INSTANCE = new HijrahChronology("Hijrah-umalqura", "islamic-umalqura");
+        // Register it by its aliases
+        AbstractChronology.registerChrono(INSTANCE, "Hijrah");
+        AbstractChronology.registerChrono(INSTANCE, "islamic");
     }
 
     /**
-     * For each Hijrah variant listed, create the HijrahChronology and register it.
-     * Exceptions during initialization are logged but otherwise ignored.
-     */
-    private static void registerVariants() {
-        for (String name : calendarProperties.stringPropertyNames()) {
-            if (name.startsWith(PROP_PREFIX)) {
-                String id = name.substring(PROP_PREFIX.length());
-                if (id.indexOf('.') >= 0) {
-                    continue;   // no name or not a simple name of a calendar
-                }
-                if (id.equals(INSTANCE.getId())) {
-                    continue;           // do not duplicate the default
-                }
-                try {
-                    // Create and register the variant
-                    HijrahChronology chrono = new HijrahChronology(id);
-                    AbstractChronology.registerChrono(chrono);
-                } catch (DateTimeException ex) {
-                    // Log error and continue
-                    PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
-                    logger.severe("Unable to initialize Hijrah calendar: " + id, ex);
-                }
-            }
-        }
-    }
-
-    /**
-     * Create a HijrahChronology for the named variant.
-     * The resource and calendar type are retrieved from properties
-     * in the {@code calendars.properties}.
-     * The property names are {@code "calendar.hijrah." + id}
-     * and  {@code "calendar.hijrah." + id + ".type"}
+     * Create a HijrahChronology for the named variant and type.
+     *
      * @param id the id of the calendar
-     * @throws DateTimeException if the calendar type is missing from the properties file.
-     * @throws IllegalArgumentException if the id is empty
+     * @param calType the typeId of the calendar
+     * @throws IllegalArgumentException if the id or typeId is empty
      */
-    private HijrahChronology(String id) throws DateTimeException {
+    private HijrahChronology(String id, String calType) {
         if (id.isEmpty()) {
             throw new IllegalArgumentException("calendar id is empty");
         }
-        String propName = PROP_PREFIX + id + PROP_TYPE_SUFFIX;
-        String calType = calendarProperties.getProperty(propName);
-        if (calType == null || calType.isEmpty()) {
-            throw new DateTimeException("calendarType is missing or empty for: " + propName);
+        if (calType.isEmpty()) {
+            throw new IllegalArgumentException("calendar typeId is empty");
         }
         this.typeId = id;
         this.calendarType = calType;
@@ -866,30 +795,26 @@
     /**
      * Return the configuration properties from the resource.
      * <p>
-     * The default location of the variant configuration resource is:
+     * The location of the variant configuration resource is:
      * <pre>
-     *   "$java.home/lib/" + resource-name
+     *   "/java/time/chrono/hijrah-config-" + calendarType + ".properties"
      * </pre>
      *
-     * @param resource the name of the calendar property resource
+     * @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 static Properties readConfigProperties(final String resource) throws Exception {
-        try {
-            return AccessController
-                    .doPrivileged((java.security.PrivilegedExceptionAction<Properties>)
-                        () -> {
-                        String libDir = System.getProperty("java.home") + File.separator + "lib";
-                        File file = new File(libDir, resource);
-                        Properties props = new Properties();
-                        try (InputStream is = new FileInputStream(file)) {
-                            props.load(is);
-                        }
-                        return props;
-                    });
-        } catch (PrivilegedActionException pax) {
-            throw pax.getException();
+    private Properties readConfigProperties(final String calendarType) throws Exception {
+        String resourceName = RESOURCE_PREFIX + calendarType + RESOURCE_SUFFIX;
+        PrivilegedAction<InputStream> getResourceAction =  () -> HijrahChronology.class.getResourceAsStream(resourceName);
+        FilePermission perm = new FilePermission("<<ALL FILES>>", "read");
+        try (InputStream is = AccessController.doPrivileged(getResourceAction, null, perm)) {
+            if (is == null) {
+                throw new RuntimeException("Hijrah calendar resource not found: /java/time/chrono/" + resourceName);
+            }
+            Properties props = new Properties();
+            props.load(is);
+            return props;
         }
     }
 
@@ -906,9 +831,7 @@
      */
     private void loadCalendarData() {
         try {
-            String resourceName = calendarProperties.getProperty(PROP_PREFIX + typeId);
-            Objects.requireNonNull(resourceName, "Resource missing for calendar: " + PROP_PREFIX + typeId);
-            Properties props = readConfigProperties(resourceName);
+            Properties props = readConfigProperties(calendarType);
 
             Map<Integer, int[]> years = new HashMap<>();
             int minYear = Integer.MAX_VALUE;
@@ -937,7 +860,7 @@
                     default:
                         try {
                             // Everything else is either a year or invalid
-                            int year = Integer.valueOf(key);
+                            int year = Integer.parseInt(key);
                             int[] months = parseMonths((String) entry.getValue());
                             years.put(year, months);
                             maxYear = Math.max(maxYear, year);
@@ -1045,7 +968,7 @@
         }
         for (int i = 0; i < 12; i++) {
             try {
-                months[i] = Integer.valueOf(numbers[i]);
+                months[i] = Integer.parseInt(numbers[i]);
             } catch (NumberFormatException nfe) {
                 throw new IllegalArgumentException("bad key: " + numbers[i]);
             }
@@ -1067,9 +990,9 @@
                 throw new IllegalArgumentException("date must be yyyy-MM-dd");
             }
             int[] ymd = new int[3];
-            ymd[0] = Integer.valueOf(string.substring(0, 4));
-            ymd[1] = Integer.valueOf(string.substring(5, 7));
-            ymd[2] = Integer.valueOf(string.substring(8, 10));
+            ymd[0] = Integer.parseInt(string, 0, 4, 10);
+            ymd[1] = Integer.parseInt(string, 5, 7, 10);
+            ymd[2] = Integer.parseInt(string, 8, 10, 10);
             return ymd;
         } catch (NumberFormatException ex) {
             throw new IllegalArgumentException("date must be yyyy-MM-dd", ex);
diff --git a/jdk/src/java.base/share/conf/hijrah-config-umalqura.properties b/jdk/src/java.base/share/classes/java/time/chrono/hijrah-config-islamic-umalqura.properties
similarity index 100%
rename from jdk/src/java.base/share/conf/hijrah-config-umalqura.properties
rename to jdk/src/java.base/share/classes/java/time/chrono/hijrah-config-islamic-umalqura.properties
diff --git a/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java b/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java
index 81b769a..c66518a 100644
--- a/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java
+++ b/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java
@@ -97,8 +97,7 @@
      *
      * This implementation uses
      * sun.util.calendar.LocalGregorianCalendar to perform most of the
-     * calendar calculations. LocalGregorianCalendar is configurable
-     * and reads <JRE_HOME>/lib/calendars.properties at the start-up.
+     * calendar calculations.
      */
 
     /**
diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java
index 589f552..811eae7 100644
--- a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java
@@ -177,44 +177,6 @@
         return (cs == null) ? cal : cs;
     }
 
-    /**
-     * Returns a {@link Properties} loaded from lib/calendars.properties.
-     *
-     * @return a {@link Properties} loaded from lib/calendars.properties
-     * @throws IOException if an error occurred when reading from the input stream
-     * @throws IllegalArgumentException if the input stream contains any malformed
-     *                                  Unicode escape sequences
-     */
-    public static Properties getCalendarProperties() throws IOException {
-        Properties calendarProps = null;
-        try {
-            String homeDir = AccessController.doPrivileged(
-                new sun.security.action.GetPropertyAction("java.home"));
-            final String fname = homeDir + File.separator + "lib" + File.separator
-                                 + "calendars.properties";
-            calendarProps = AccessController.doPrivileged(new PrivilegedExceptionAction<Properties>() {
-                @Override
-                public Properties run() throws IOException {
-                    Properties props = new Properties();
-                    try (FileInputStream fis = new FileInputStream(fname)) {
-                        props.load(fis);
-                    }
-                    return props;
-                }
-            });
-        } catch (PrivilegedActionException e) {
-            Throwable cause = e.getCause();
-            if (cause instanceof IOException) {
-                throw (IOException) cause;
-            } else if (cause instanceof IllegalArgumentException) {
-                throw (IllegalArgumentException) cause;
-            }
-            // Should not happen
-            throw new InternalError(cause);
-        }
-        return calendarProps;
-    }
-
     //////////////////////////////// Calendar API //////////////////////////////////
 
     /**
diff --git a/jdk/src/java.base/share/conf/calendars.properties b/jdk/src/java.base/share/conf/calendars.properties
deleted file mode 100644
index 46bb0e2..0000000
--- a/jdk/src/java.base/share/conf/calendars.properties
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2005, 2014, 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.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-#
-# Hijrah calendars
-#
-calendar.hijrah.Hijrah-umalqura: hijrah-config-umalqura.properties
-calendar.hijrah.Hijrah-umalqura.type: islamic-umalqura