Skip to content

Commit

Permalink
8316435: sun.util.calendar.CalendarSystem subclassing should be restr…
Browse files Browse the repository at this point in the history
…icted

Reviewed-by: naoto
  • Loading branch information
Justin Lu committed Sep 21, 2023
1 parent 1100dbc commit 496264c
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
* @since 1.5
*/

public abstract class AbstractCalendar extends CalendarSystem {
public sealed abstract class AbstractCalendar extends CalendarSystem
permits BaseCalendar {

// The constants assume no leap seconds support.
static final int SECOND_IN_MILLIS = 1000;
Expand All @@ -60,6 +61,7 @@ public abstract class AbstractCalendar extends CalendarSystem {
protected AbstractCalendar() {
}

@Override
public Era getEra(String eraName) {
if (eras != null) {
for (Era era : eras) {
Expand All @@ -71,6 +73,7 @@ public Era getEra(String eraName) {
return null;
}

@Override
public Era[] getEras() {
Era[] e = null;
if (eras != null) {
Expand All @@ -84,19 +87,23 @@ protected void setEras(Era[] eras) {
this.eras = eras;
}

@Override
public CalendarDate getCalendarDate() {
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
}

@Override
public CalendarDate getCalendarDate(long millis) {
return getCalendarDate(millis, newCalendarDate());
}

@Override
public CalendarDate getCalendarDate(long millis, TimeZone zone) {
CalendarDate date = newCalendarDate(zone);
return getCalendarDate(millis, date);
}

@Override
public CalendarDate getCalendarDate(long millis, CalendarDate date) {
int ms = 0; // time of day
int zoneOffset = 0;
Expand Down Expand Up @@ -156,6 +163,7 @@ public CalendarDate getCalendarDate(long millis, CalendarDate date) {
return date;
}

@Override
public long getTime(CalendarDate date) {
long gd = getFixedDate(date);
long ms = (gd - EPOCH_OFFSET) * DAY_IN_MILLIS + getTimeOfDay(date);
Expand Down Expand Up @@ -232,6 +240,7 @@ public CalendarDate setTimeOfDay(CalendarDate cdate, int fraction) {

protected abstract boolean isLeapYear(CalendarDate date);

@Override
public CalendarDate getNthDayOfWeek(int nth, int dayOfWeek, CalendarDate date) {
CalendarDate ndate = (CalendarDate) date.clone();
normalize(ndate);
Expand Down
15 changes: 12 additions & 3 deletions src/java.base/share/classes/sun/util/calendar/BaseCalendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
* @since 1.5
*/

public abstract class BaseCalendar extends AbstractCalendar {
public sealed abstract class BaseCalendar extends AbstractCalendar
permits Gregorian, JulianCalendar, LocalGregorianCalendar {

public static final int JANUARY = 1;
public static final int FEBRUARY = 2;
Expand Down Expand Up @@ -140,7 +141,8 @@ public abstract class BaseCalendar extends AbstractCalendar {
744365, // 2039
};

public abstract static class Date extends CalendarDate {
public sealed abstract static class Date extends CalendarDate
permits Gregorian.Date, ImmutableGregorianDate, JulianCalendar.Date, LocalGregorianCalendar.Date {
protected Date() {
super();
}
Expand Down Expand Up @@ -188,6 +190,7 @@ protected void setCache(int year, long jan1, int len) {
}
}

@Override
public boolean validate(CalendarDate date) {
Date bdate = (Date) date;
if (bdate.isNormalized()) {
Expand All @@ -214,6 +217,7 @@ public boolean validate(CalendarDate date) {
return true;
}

@Override
public boolean normalize(CalendarDate date) {
if (date.isNormalized()) {
return true;
Expand Down Expand Up @@ -303,6 +307,7 @@ void normalizeMonth(CalendarDate date) {
* @throws ClassCastException if the specified date is not a
* {@link BaseCalendar.Date}
*/
@Override
public int getYearLength(CalendarDate date) {
return isLeapYear(((Date)date).getNormalizedYear()) ? 366 : 365;
}
Expand All @@ -318,6 +323,7 @@ public int getYearLength(CalendarDate date) {
// 12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1
= { -30, 0, 31, 59+1, 90+1,120+1,151+1,181+1,212+1,243+1, 273+1, 304+1, 334+1};

@Override
public int getMonthLength(CalendarDate date) {
Date gdate = (Date) date;
int month = gdate.getMonth();
Expand Down Expand Up @@ -349,6 +355,7 @@ final long getDayOfYear(int year, int month, int dayOfMonth) {
}

// protected
@Override
public long getFixedDate(CalendarDate date) {
if (!date.isNormalized()) {
normalizeMonth(date);
Expand Down Expand Up @@ -415,6 +422,7 @@ public long getFixedDate(int year, int month, int dayOfMonth, BaseCalendar.Date
* {@code CalendarDate}.
*/
// should be 'protected'
@Override
public void getCalendarDateFromFixedDate(CalendarDate date,
long fixedDate) {
Date gdate = (Date) date;
Expand Down Expand Up @@ -473,7 +481,7 @@ public int getDayOfWeek(CalendarDate date) {
return getDayOfWeekFromFixedDate(fixedDate);
}

public static final int getDayOfWeekFromFixedDate(long fixedDate) {
public static int getDayOfWeekFromFixedDate(long fixedDate) {
// The fixed day 1 (January 1, 1 Gregorian) is Monday.
if (fixedDate >= 0) {
return (int)(fixedDate % 7) + SUNDAY;
Expand Down Expand Up @@ -525,6 +533,7 @@ final int getGregorianYearFromFixedDate(long fixedDate) {
* false otherwise.
* @see CalendarUtils#isGregorianLeapYear
*/
@Override
protected boolean isLeapYear(CalendarDate date) {
return isLeapYear(((Date)date).getNormalizedYear());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
* @author Masayoshi Okutsu
* @since 1.5
*/
public abstract class CalendarDate implements Cloneable {
public sealed abstract class CalendarDate implements Cloneable
permits BaseCalendar.Date {
public static final int FIELD_UNDEFINED = Integer.MIN_VALUE;
public static final long TIME_UNDEFINED = Long.MIN_VALUE;

Expand Down Expand Up @@ -340,6 +341,7 @@ public boolean equals(Object obj) {
&& zoneOffset == that.zoneOffset);
}

@Override
public int hashCode() {
// a pseudo (local standard) time stamp value in milliseconds
// from the Epoch, assuming Gregorian calendar fields.
Expand All @@ -362,6 +364,7 @@ public int hashCode() {
*
* @return a copy of this <code>CalendarDate</code>
*/
@Override
public Object clone() {
try {
return super.clone();
Expand All @@ -380,6 +383,7 @@ public Object clone() {
*
* @see java.text.SimpleDateFormat
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
CalendarUtils.sprintf0d(sb, year, 4).append('-');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
* @since 1.5
*/

public abstract class CalendarSystem {
public sealed abstract class CalendarSystem permits AbstractCalendar {

/////////////////////// Calendar Factory Methods /////////////////////////

Expand Down
31 changes: 17 additions & 14 deletions src/java.base/share/classes/sun/util/calendar/CalendarUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@

package sun.util.calendar;

public class CalendarUtils {
public final class CalendarUtils {

// Utility class should not be instantiated
private CalendarUtils() {}

/**
* Returns whether the specified year is a leap year in the Gregorian
Expand All @@ -36,9 +39,9 @@ public class CalendarUtils {
* calendar system.
* @see CalendarDate#isLeapYear
*/
public static final boolean isGregorianLeapYear(int gregorianYear) {
return (((gregorianYear % 4) == 0)
&& (((gregorianYear % 100) != 0) || ((gregorianYear % 400) == 0)));
public static boolean isGregorianLeapYear(int gregorianYear) {
return (((gregorianYear % 4) == 0) && (((gregorianYear % 100) != 0)
|| ((gregorianYear % 400) == 0)));
}

/**
Expand All @@ -51,7 +54,7 @@ public static final boolean isGregorianLeapYear(int gregorianYear) {
* calendar system.
* @see CalendarDate#isLeapYear
*/
public static final boolean isJulianLeapYear(int normalizedJulianYear) {
public static boolean isJulianLeapYear(int normalizedJulianYear) {
return (normalizedJulianYear % 4) == 0;
}

Expand All @@ -64,7 +67,7 @@ public static final boolean isJulianLeapYear(int normalizedJulianYear) {
* @param d a divisor that must be greater than 0
* @return the floor of the quotient
*/
public static final long floorDivide(long n, long d) {
public static long floorDivide(long n, long d) {
return ((n >= 0) ?
(n / d) : (((n + 1L) / d) - 1L));
}
Expand All @@ -78,7 +81,7 @@ public static final long floorDivide(long n, long d) {
* @param d a divisor that must be greater than 0
* @return the floor of the quotient
*/
public static final int floorDivide(int n, int d) {
public static int floorDivide(int n, int d) {
return ((n >= 0) ?
(n / d) : (((n + 1) / d) - 1));
}
Expand All @@ -96,7 +99,7 @@ public static final int floorDivide(int n, int d) {
* <code>mod(n, d)</code> is returned.
* @return the floor of the quotient.
*/
public static final int floorDivide(int n, int d, int[] r) {
public static int floorDivide(int n, int d, int[] r) {
if (n >= 0) {
r[0] = n % d;
return n / d;
Expand All @@ -106,28 +109,28 @@ public static final int floorDivide(int n, int d, int[] r) {
return q;
}

public static final long mod(long x, long y) {
public static long mod(long x, long y) {
return (x - y * floorDivide(x, y));
}

public static final int mod(int x, int y) {
public static int mod(int x, int y) {
return (x - y * floorDivide(x, y));
}

public static final int amod(int x, int y) {
public static int amod(int x, int y) {
int z = mod(x, y);
return (z == 0) ? y : z;
}

public static final long amod(long x, long y) {
public static long amod(long x, long y) {
long z = mod(x, y);
return (z == 0) ? y : z;
}

/**
* Mimics sprintf(buf, "%0*d", decaimal, width).
*/
public static final StringBuilder sprintf0d(StringBuilder sb, int value, int width) {
public static StringBuilder sprintf0d(StringBuilder sb, int value, int width) {
long d = value;
if (d < 0) {
sb.append('-');
Expand All @@ -146,7 +149,7 @@ public static final StringBuilder sprintf0d(StringBuilder sb, int value, int wid
return sb;
}

public static final StringBuffer sprintf0d(StringBuffer sb, int value, int width) {
public static StringBuffer sprintf0d(StringBuffer sb, int value, int width) {
long d = value;
if (d < 0) {
sb.append('-');
Expand Down
19 changes: 14 additions & 5 deletions src/java.base/share/classes/sun/util/calendar/Gregorian.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, 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
Expand Down Expand Up @@ -34,21 +34,23 @@
* @since 1.5
*/

public class Gregorian extends BaseCalendar {
public final class Gregorian extends BaseCalendar {

static class Date extends BaseCalendar.Date {
protected Date() {
static final class Date extends BaseCalendar.Date {
Date() {
super();
}

protected Date(TimeZone zone) {
Date(TimeZone zone) {
super(zone);
}

@Override
public int getNormalizedYear() {
return getYear();
}

@Override
public void setNormalizedYear(int normalizedYear) {
setYear(normalizedYear);
}
Expand All @@ -57,30 +59,37 @@ public void setNormalizedYear(int normalizedYear) {
Gregorian() {
}

@Override
public String getName() {
return "gregorian";
}

@Override
public Date getCalendarDate() {
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
}

@Override
public Date getCalendarDate(long millis) {
return getCalendarDate(millis, newCalendarDate());
}

@Override
public Date getCalendarDate(long millis, CalendarDate date) {
return (Date) super.getCalendarDate(millis, date);
}

@Override
public Date getCalendarDate(long millis, TimeZone zone) {
return getCalendarDate(millis, newCalendarDate(zone));
}

@Override
public Date newCalendarDate() {
return new Date();
}

@Override
public Date newCalendarDate(TimeZone zone) {
return new Date(zone);
}
Expand Down
Loading

1 comment on commit 496264c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.