/* * Copyright (c) 1998, 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. * * 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. */ /* @test * @bug 4099013 * @summary Enable substitution of String and Array by ObjectStreams. */ import java.io.*; import java.lang.reflect.Array; class A implements Serializable { String stringA; String stringB; String stringC; String[] arrayOfString; A() { stringA = "hello"; stringB = "goodbye"; stringC = stringA; arrayOfString = new String[2]; for (int i = 0; i < arrayOfString.length; i++) arrayOfString[i] = new String("array element " + i); } void report() { System.out.println("stringA = " + stringA); System.out.println("stringB = " + stringB); System.out.println("stringC = " + stringC); System.out.println("length of arrayOfString = " + arrayOfString.length); for (int i = 0; i < arrayOfString.length; i++) System.out.println("arrayOfString[" + i + "]= " + arrayOfString[i]); } } class SubstituteObjectOutputStream extends ObjectOutputStream { public int numStringsReplaced = 0; public int numArraysCounted = 0; public SubstituteObjectOutputStream(OutputStream out) throws IOException { super(out); enableReplaceObject(true); } protected Object replaceObject(Object obj) throws IOException { if (obj instanceof String) { numStringsReplaced++; return obj + "_WriteReplaced"; } if (obj.getClass().isArray()) { Object[] array = (Object[]) obj; /* Double the array. * Initialize new array elements with original array. */ Class arrayComponentType = array.getClass().getComponentType(); Object[] newarray = (Object[])Array.newInstance(arrayComponentType, array.length * 2); for (int i = 0; i < array.length; i++) newarray[i] = array[i]; for (int ni = array.length; ni < 2* array.length; ni++) newarray[ni] = array[ni - array.length]; numArraysCounted++; obj = newarray; } return obj; } } class SubstituteObjectInputStream extends ObjectInputStream { public int numStringsReplaced = 0; public int numArraysCounted = 0; public SubstituteObjectInputStream(InputStream in) throws IOException { super(in); enableResolveObject(true); } protected Object resolveObject(Object obj) throws IOException { if (obj instanceof String) { numStringsReplaced++; return obj + "_ReadResolved"; } if (obj.getClass().isArray()) { Object[] array = (Object[])obj; /* Double the array. * Initialize new array elements with original array. */ Class arrayComponentType = array.getClass().getComponentType(); Object[] newarray = (Object[])Array.newInstance(arrayComponentType, array.length * 2); for (int i = 0; i < array.length; i++) newarray[i] = array[i]; for (int ni = array.length; ni < 2* array.length; ni++) newarray[ni] = array[ni - array.length]; numArraysCounted++; obj = newarray; } return obj; } } public class ReplaceStringArray { public static void main(String args[]) throws IOException, ClassNotFoundException { boolean verbose = false; if (args.length >= 1 && args[0].compareTo("verbose") == 0) verbose = true; A a = new A(); if (verbose) { System.out.println("Value of Class A"); a.report(); System.out.println(""); } /* Serialize object a to bytestream. */ if (verbose) { System.out.println("Serialize A to SubstituteObjectOutputStream"); System.out.println(""); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); SubstituteObjectOutputStream out = new SubstituteObjectOutputStream(baos); out.writeObject(a); out.close(); a = null; /* Validate that writeReplace called by SubstituteObjectOutputStream.*/ boolean expectedResult = (out.numStringsReplaced == 4); if (!expectedResult) throw new Error("Expected " + 4 + " strings to be replaced during serialization;" + " only " + out.numStringsReplaced + " strings were replaced."); if (out.numArraysCounted != 1) throw new Error("Expected 1 array during serialization; only " + out.numArraysCounted + " arrays"); if (verbose) { System.out.println("DeSerialize A from SubstituteObjectInputStream"); System.out.println(""); } SubstituteObjectInputStream in = new SubstituteObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); a = (A)in.readObject(); in.close(); /* Validate that readResolve called by SubstituteObjectInputStream.*/ if (in.numStringsReplaced != 4) throw new Error("Expected 4 strings to be resolved during deserialization;" + " only " + in.numStringsReplaced + " strings were resolved."); if (in.numArraysCounted != 1) throw new Error("Expected 1 array during deserialization; only " + out.numArraysCounted + " arrays"); if (a.arrayOfString.length != 8) throw new Error("Expected a.arrayOfString.length to be 8, observed " + a.arrayOfString.length); if (verbose) { System.out.println("Value of Class A after serialize/deserialize with writeReplace/readResolve"); a.report(); } } }