From 0d1388172ab1a10ab8abbcf14c1a9eac9ed0cbe3 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Fri, 24 Aug 2007 00:17:00 +0000 Subject: [PATCH] ICU-3474 serialization fix for icu4j calendar X-SVN-Rev: 22500 --- .../dev/test/calendar/CalendarRegression.java | 107 ++++++++++++++++++ icu4j/src/com/ibm/icu/util/Calendar.java | 20 +--- 2 files changed, 111 insertions(+), 16 deletions(-) diff --git a/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java b/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java index 311c01c88dc..907517cb2a8 100755 --- a/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java +++ b/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java @@ -7,6 +7,11 @@ package com.ibm.icu.dev.test.calendar; import com.ibm.icu.util.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Date; import java.util.Locale; import java.util.MissingResourceException; @@ -1949,6 +1954,108 @@ public class CalendarRegression extends com.ibm.icu.dev.test.TestFmwk { */ } + /** + * test serialize-and-modify. + * @throws ClassNotFoundException + */ + public void TestSerialization3474() { + try { + ByteArrayOutputStream icuStream = new ByteArrayOutputStream(); + + logln("icu Calendar"); + + com.ibm.icu.util.GregorianCalendar icuCalendar = + new com.ibm.icu.util.GregorianCalendar(); + + icuCalendar.setTimeInMillis(1187912555931L); + long expectMillis = 1187912520931L; // with seconds (not ms) cleared. + + logln("instantiated: "+icuCalendar); + logln("getMillis: "+icuCalendar.getTimeInMillis()); + icuCalendar.set(com.ibm.icu.util.GregorianCalendar.SECOND, 0); + logln("setSecond=0: "+icuCalendar); + { + long gotMillis = icuCalendar.getTimeInMillis(); + if(gotMillis != expectMillis) { + errln("expect millis "+expectMillis+" but got "+gotMillis); + } else { + logln("getMillis: "+gotMillis); + } + } + ObjectOutputStream icuOut = + new ObjectOutputStream(icuStream); + icuOut.writeObject(icuCalendar); + icuOut.flush(); + icuOut.close(); + + ObjectInputStream icuIn = + new ObjectInputStream(new ByteArrayInputStream(icuStream.toByteArray())); + icuCalendar = null; + icuCalendar = (com.ibm.icu.util.GregorianCalendar)icuIn.readObject(); + + logln("serialized back in: "+icuCalendar); + { + long gotMillis = icuCalendar.getTimeInMillis(); + if(gotMillis != expectMillis) { + errln("expect millis "+expectMillis+" but got "+gotMillis); + } else { + logln("getMillis: "+gotMillis); + } + } + + icuCalendar.set(com.ibm.icu.util.GregorianCalendar.SECOND, 0); + + logln("setSecond=0: "+icuCalendar); + { + long gotMillis = icuCalendar.getTimeInMillis(); + if(gotMillis != expectMillis) { + errln("expect millis "+expectMillis+" after stream and setSecond but got "+gotMillis); + } else { + logln("getMillis after stream and setSecond: "+gotMillis); + } + } + } catch(IOException e) { + errln(e.toString()); + e.printStackTrace(); + } catch(ClassNotFoundException cnf) { + errln(cnf.toString()); + cnf.printStackTrace(); + } + + // JDK works correctly, etc etc. +// ByteArrayOutputStream jdkStream = new ByteArrayOutputStream(); + +// logln("\nSUN Calendar"); +// +// java.util.GregorianCalendar sunCalendar = +// new java.util.GregorianCalendar(); +// +// logln("instanzieren: "+sunCalendar); +// logln("getMillis: "+sunCalendar.getTimeInMillis()); +// sunCalendar.set(java.util.GregorianCalendar.SECOND, 0); +// logln("setSecond=0: "+sunCalendar); +// logln("getMillis: "+sunCalendar.getTimeInMillis()); +// +// ObjectOutputStream sunOut = +// new ObjectOutputStream(jdkStream); +// sunOut.writeObject(sunCalendar); +// sunOut.flush(); +// sunOut.close(); +// +// ObjectInputStream sunIn = +// new ObjectInputStream(new ByteArrayInputStream(jdkStream.toByteArray())); +// sunCalendar = null; +// sunCalendar = (java.util.GregorianCalendar)sunIn.readObject(); +// +// logln("serialized: "+sunCalendar); +// logln("getMillis: "+sunCalendar.getTimeInMillis()); +// +// sunCalendar.set(java.util.GregorianCalendar.SECOND, 0); +// logln("setSecond=0: "+sunCalendar); +// logln("getMillis: "+sunCalendar.getTimeInMillis()); + + } + } //eof diff --git a/icu4j/src/com/ibm/icu/util/Calendar.java b/icu4j/src/com/ibm/icu/util/Calendar.java index d92b0773310..bbbe5c6fa89 100755 --- a/icu4j/src/com/ibm/icu/util/Calendar.java +++ b/icu4j/src/com/ibm/icu/util/Calendar.java @@ -1310,9 +1310,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable { /** * True if all fields have been virtually set, but have not yet been - * computed. This occurs only in setTimeInMillis(). A calendar set - * to this state will compute all fields from the time if it becomes - * necessary, but otherwise will delay such computation. + * computed. This occurs only in setTimeInMillis(), or after readObject(). + * A calendar set to this state will compute all fields from the time if it + * becomes necessary, but otherwise will delay such computation. */ private transient boolean areFieldsVirtuallySet; @@ -1416,9 +1416,6 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable { /** * The next available value for stamp[], an internal array. - * This actually should not be written out to the stream, and will probably - * be removed from the stream in the near future. In the meantime, - * a value of MINIMUM_USER_STAMP should be used. * @serial */ private transient int nextStamp = MINIMUM_USER_STAMP; @@ -3968,16 +3965,6 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable { /** * Save the state of this object to a stream (i.e., serialize it). - * - * Ideally, Calendar would only write out its state data and - * the current time, and not write any field data out, such as - * fields[], isTimeSet, areFieldsSet, - * and isSet[]. nextStamp also should not be part - * of the persistent state. Unfortunately, this didn't happen before JDK 1.1 - * shipped. To be compatible with JDK 1.1, we will always have to write out - * the field values and state flags. However, nextStamp can be - * removed from the serialization stream; this will probably happen in the - * near future. */ private void writeObject(ObjectOutputStream stream) throws IOException @@ -4007,6 +3994,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable { isTimeSet = true; areFieldsSet = areAllFieldsSet = false; + areFieldsVirtuallySet = true; // cause fields to be recalculated if requested. nextStamp = MINIMUM_USER_STAMP; }