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