1/* 2 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* @test 25 * @bug 4099013 26 * @summary Enable substitution of String and Array by ObjectStreams. 27 */ 28 29import java.io.*; 30import java.lang.reflect.Array; 31 32class A implements Serializable { 33 String stringA; 34 String stringB; 35 String stringC; 36 String[] arrayOfString; 37 38 A() { 39 stringA = "hello"; 40 stringB = "goodbye"; 41 stringC = stringA; 42 arrayOfString = new String[2]; 43 for (int i = 0; i < arrayOfString.length; i++) 44 arrayOfString[i] = new String("array element " + i); 45 } 46 47 void report() { 48 System.out.println("stringA = " + stringA); 49 System.out.println("stringB = " + stringB); 50 System.out.println("stringC = " + stringC); 51 System.out.println("length of arrayOfString = " + 52 arrayOfString.length); 53 for (int i = 0; i < arrayOfString.length; i++) 54 System.out.println("arrayOfString[" + i + "]= " + 55 arrayOfString[i]); 56 } 57} 58 59class SubstituteObjectOutputStream extends ObjectOutputStream { 60 public int numStringsReplaced = 0; 61 public int numArraysCounted = 0; 62 63 public SubstituteObjectOutputStream(OutputStream out) throws IOException { 64 super(out); 65 enableReplaceObject(true); 66 } 67 68 protected Object replaceObject(Object obj) throws IOException { 69 if (obj instanceof String) { 70 numStringsReplaced++; 71 return obj + "_WriteReplaced"; 72 } 73 if (obj.getClass().isArray()) { 74 Object[] array = (Object[]) obj; 75 /* Double the array. 76 * Initialize new array elements with original array. */ 77 Class arrayComponentType = array.getClass().getComponentType(); 78 Object[] newarray = 79 (Object[])Array.newInstance(arrayComponentType, 80 array.length * 2); 81 for (int i = 0; i < array.length; i++) 82 newarray[i] = array[i]; 83 for (int ni = array.length; ni < 2* array.length; ni++) 84 newarray[ni] = array[ni - array.length]; 85 numArraysCounted++; 86 obj = newarray; 87 } 88 return obj; 89 } 90} 91 92class SubstituteObjectInputStream extends ObjectInputStream { 93 public int numStringsReplaced = 0; 94 public int numArraysCounted = 0; 95 96 public SubstituteObjectInputStream(InputStream in) throws IOException { 97 super(in); 98 enableResolveObject(true); 99 } 100 101 protected Object resolveObject(Object obj) throws IOException { 102 if (obj instanceof String) { 103 numStringsReplaced++; 104 return obj + "_ReadResolved"; 105 } 106 if (obj.getClass().isArray()) { 107 Object[] array = (Object[])obj; 108 109 /* Double the array. 110 * Initialize new array elements with original array. */ 111 Class arrayComponentType = array.getClass().getComponentType(); 112 Object[] newarray = 113 (Object[])Array.newInstance(arrayComponentType, 114 array.length * 2); 115 for (int i = 0; i < array.length; i++) 116 newarray[i] = array[i]; 117 for (int ni = array.length; ni < 2* array.length; ni++) 118 newarray[ni] = array[ni - array.length]; 119 numArraysCounted++; 120 obj = newarray; 121 } 122 return obj; 123 } 124} 125 126public class ReplaceStringArray { 127 public static void main(String args[]) throws IOException, ClassNotFoundException { 128 boolean verbose = false; 129 if (args.length >= 1 && args[0].compareTo("verbose") == 0) 130 verbose = true; 131 132 133 A a = new A(); 134 if (verbose) { 135 System.out.println("Value of Class A"); 136 a.report(); 137 System.out.println(""); 138 } 139 140 141 /* Serialize object a to bytestream. */ 142 if (verbose) { 143 System.out.println("Serialize A to SubstituteObjectOutputStream"); 144 System.out.println(""); 145 } 146 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 147 SubstituteObjectOutputStream out = new SubstituteObjectOutputStream(baos); 148 out.writeObject(a); 149 out.close(); 150 a = null; 151 152 /* Validate that writeReplace called by SubstituteObjectOutputStream.*/ 153 boolean expectedResult = (out.numStringsReplaced == 4); 154 if (!expectedResult) 155 throw new Error("Expected " + 4 + " strings to be replaced during serialization;" + 156 " only " + out.numStringsReplaced + " strings were replaced."); 157 if (out.numArraysCounted != 1) 158 throw new Error("Expected 1 array during serialization; only " + 159 out.numArraysCounted + " arrays"); 160 161 if (verbose) { 162 System.out.println("DeSerialize A from SubstituteObjectInputStream"); 163 System.out.println(""); 164 } 165 SubstituteObjectInputStream in = 166 new SubstituteObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); 167 a = (A)in.readObject(); 168 in.close(); 169 170 /* Validate that readResolve called by SubstituteObjectInputStream.*/ 171 if (in.numStringsReplaced != 4) 172 throw new Error("Expected 4 strings to be resolved during deserialization;" + 173 " only " + in.numStringsReplaced + " strings were resolved."); 174 if (in.numArraysCounted != 1) 175 throw new Error("Expected 1 array during deserialization; only " + 176 out.numArraysCounted + " arrays"); 177 if (a.arrayOfString.length != 8) 178 throw new Error("Expected a.arrayOfString.length to be 8, observed " + 179 a.arrayOfString.length); 180 if (verbose) { 181 System.out.println("Value of Class A after serialize/deserialize with writeReplace/readResolve"); 182 a.report(); 183 } 184 } 185} 186