TypeSafeEnum.java revision 2362
1037N/A/*
1037N/A * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
1037N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1037N/A *
1037N/A * This code is free software; you can redistribute it and/or modify it
1037N/A * under the terms of the GNU General Public License version 2 only, as
1037N/A * published by the Free Software Foundation.
1037N/A *
1037N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1037N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1037N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1037N/A * version 2 for more details (a copy is included in the LICENSE file that
1037N/A * accompanied this code).
1037N/A *
1037N/A * You should have received a copy of the GNU General Public License version
1037N/A * 2 along with this work; if not, write to the Free Software Foundation,
1037N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1037N/A *
1037N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1037N/A * or visit www.oracle.com if you need additional information or have any
1037N/A * questions.
1037N/A */
1037N/A
1037N/A/* @test
1037N/A * @bug 4140729
1037N/A * @summary Verify that writeReplace & readResolve are called by serialization.
1037N/A * readResolve is used to maintain the invariant that the enums
1037N/A * of TypeSafeEnum are singletons.
1037N/A */
1037N/Aimport java.io.*;
1037N/A
1037N/Apublic class TypeSafeEnum implements Serializable, ObjectInputValidation {
1037N/A private static int numWriteObject = 0;
1037N/A private static int numReadObject = 0;
1037N/A
1037N/A
1037N/A private String value;
1037N/A private TypeSafeEnum(String value) {
1037N/A this.value = value;
1037N/A }
1037N/A
1037N/A final public static TypeSafeEnum FIRST = new TypeSafeEnum("First");
1037N/A final public static TypeSafeEnum SECOND = new TypeSafeEnum("Second");
1037N/A final public static TypeSafeEnum THIRD = new TypeSafeEnum("Third");
1037N/A static int numReadResolve = 0;
1037N/A static int numWriteReplace = 0;
1037N/A static boolean verbose = false;
1037N/A
1037N/A
1037N/A private Object writeReplace() throws IOException {
1037N/A numWriteReplace++;
1037N/A if (verbose) {
1037N/A System.out.println("TypeSafeEnum.writeReplace() " +
1037N/A this.toString());
1037N/A }
1037N/A return this;
1037N/A }
1037N/A
1037N/A private Object readResolve() throws IOException {
1037N/A numReadResolve++;
1037N/A if (verbose) {
1037N/A System.out.println("readResolve called on " + this.toString());
1037N/A }
1037N/A if (value.equals(FIRST.value)) {
1037N/A return FIRST;
1037N/A } else if (value.equals(SECOND.value)) {
1037N/A return SECOND;
1037N/A } else if (value.equals(THIRD.value)) {
1037N/A return THIRD;
1037N/A } else {
1037N/A //unknown type safe enum
1037N/A return this;
1037N/A }
1037N/A }
1037N/A
1037N/A private void readObject(ObjectInputStream in)
1037N/A throws IOException, ClassNotFoundException
1037N/A {
1037N/A numReadObject++;
1037N/A in.defaultReadObject();
1037N/A if (verbose) {
1037N/A System.out.println("TypeSafeEnum.readObject() " + this.toString());
1037N/A }
1037N/A if (value == null) {
1037N/A in.registerValidation(this, 0);
1037N/A }
1037N/A }
1037N/A
1037N/A public void validateObject() throws InvalidObjectException {
1037N/A // only top level case has null for value, validate.
1037N/A if (numWriteObject != 4) {
1037N/A throw new Error("Expected 4 calls to writeObject, only " +
1037N/A numWriteObject + " made");
1037N/A }
1037N/A if (numReadObject != 4) {
1037N/A throw new Error("Expected 4 calls to readObject, only " +
1037N/A numReadObject + " made");
1037N/A }
1037N/A if (numWriteReplace != 4) {
1037N/A throw new Error("Expected 4 calls to writeReplace, only " +
1037N/A numWriteReplace + " made");
1037N/A }
1037N/A if (numReadResolve != 4) {
1037N/A throw new Error("Expected 4 calls to readResolve, only " +
1037N/A numReadResolve + " made");
1037N/A }
1037N/A }
1037N/A
private void writeObject(ObjectOutputStream out) throws IOException
{
numWriteObject++;
out.defaultWriteObject();
if (verbose) {
System.out.println("TypeSafeEnum.writeObject() " +
this.toString());
}
}
public String toString() {
return super.toString() + " value=" + value;
}
public static void main(String args[])
throws IOException, ClassNotFoundException
{
if (args.length > 0 && args[0].equals("-verbose"))
verbose = true;
TypeSafeEnum[] writeArray = new TypeSafeEnum[7];
writeArray[0] = FIRST;
writeArray[1] = SECOND;
writeArray[2] = THIRD;
writeArray[3] = FIRST;
writeArray[4] = SECOND;
writeArray[5] = THIRD;
writeArray[6] = new TypeSafeEnum("Third");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(baos);
os.writeObject(writeArray);
os.close();
TypeSafeEnum[] readArray;
ObjectInputStream in =
new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
readArray = (TypeSafeEnum[])in.readObject();
in.close();
for (int i= 0; i < writeArray.length - 1 ; i++) {
if (writeArray[i] != readArray[i]) {
throw new Error("Serializa/deserialize did not preserve " +
"singleton for " +
readArray[i].toString() +
" and " + writeArray[i].toString());
}
}
}
};