1 /* 2 * Copyright (c) 1998, 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 * @clean A SubstituteObjectOutputStream SubstituteObjectInputStream 26 * @bug 4099013 27 * @summary Enable substitution of String and Array by ObjectStreams. 28 */ 29 30 import java.io.*; 31 import java.lang.reflect.Array; 32 33 class A implements Serializable { 34 String stringA; 35 String stringB; 36 String stringC; 37 String[] arrayOfString; 38 39 A() { 40 stringA = "hello"; 41 stringB = "goodbye"; 42 stringC = stringA; 43 arrayOfString = new String[2]; 44 for (int i = 0; i < arrayOfString.length; i++) 45 arrayOfString[i] = new String("array element " + i); 46 } 47 48 void report() { 49 System.out.println("stringA = " + stringA); 50 System.out.println("stringB = " + stringB); 51 System.out.println("stringC = " + stringC); 52 System.out.println("length of arrayOfString = " + 53 arrayOfString.length); 54 for (int i = 0; i < arrayOfString.length; i++) 55 System.out.println("arrayOfString[" + i + "]= " + 56 arrayOfString[i]); 57 } 58 } 59 60 class SubstituteObjectOutputStream extends ObjectOutputStream { 61 public int numStringsReplaced = 0; 62 public int numArraysCounted = 0; 63 64 public SubstituteObjectOutputStream(OutputStream out) throws IOException { 65 super(out); 66 enableReplaceObject(true); 67 } 68 69 protected Object replaceObject(Object obj) throws IOException { 70 if (obj instanceof String) { 71 numStringsReplaced++; 72 return obj + "_WriteReplaced"; 73 } 74 if (obj.getClass().isArray()) { 75 Object[] array = (Object[]) obj; 76 /* Double the array. 77 * Initialize new array elements with original array. */ 78 Class arrayComponentType = array.getClass().getComponentType(); 79 Object[] newarray = 80 (Object[])Array.newInstance(arrayComponentType, 81 array.length * 2); 82 for (int i = 0; i < array.length; i++) 83 newarray[i] = array[i]; 84 for (int ni = array.length; ni < 2* array.length; ni++) 85 newarray[ni] = array[ni - array.length]; 86 numArraysCounted++; 87 obj = newarray; 88 } 89 return obj; 90 } 91 } 92 93 class SubstituteObjectInputStream extends ObjectInputStream { 94 public int numStringsReplaced = 0; 95 public int numArraysCounted = 0; 96 97 public SubstituteObjectInputStream(InputStream in) throws IOException { 98 super(in); 99 enableResolveObject(true); 100 } 101 102 protected Object resolveObject(Object obj) throws IOException { 103 if (obj instanceof String) { 104 numStringsReplaced++; 105 return obj + "_ReadResolved"; 106 } 107 if (obj.getClass().isArray()) { 108 Object[] array = (Object[])obj; 109 110 /* Double the array. 111 * Initialize new array elements with original array. */ 112 Class arrayComponentType = array.getClass().getComponentType(); 113 Object[] newarray = 114 (Object[])Array.newInstance(arrayComponentType, 115 array.length * 2); 116 for (int i = 0; i < array.length; i++) 117 newarray[i] = array[i]; 118 for (int ni = array.length; ni < 2* array.length; ni++) 119 newarray[ni] = array[ni - array.length]; 120 numArraysCounted++; 121 obj = newarray; 122 } 123 return obj; 124 } 125 } 126 127 public class ReplaceStringArray { 128 public static void main(String args[]) throws IOException, ClassNotFoundException { 129 boolean verbose = false; 130 if (args.length >= 1 && args[0].compareTo("verbose") == 0) 131 verbose = true; 132 133 134 A a = new A(); 135 if (verbose) { 136 System.out.println("Value of Class A"); 137 a.report(); 138 System.out.println(""); 139 } 140 141 142 /* Serialize object a to bytestream. */ 143 if (verbose) { 144 System.out.println("Serialize A to SubstituteObjectOutputStream"); 145 System.out.println(""); 146 } 147 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 148 SubstituteObjectOutputStream out = new SubstituteObjectOutputStream(baos); 149 out.writeObject(a); 150 out.close(); 151 a = null; 152 153 /* Validate that writeReplace called by SubstituteObjectOutputStream.*/ 154 boolean expectedResult = (out.numStringsReplaced == 4); 155 if (!expectedResult) 156 throw new Error("Expected " + 4 + " strings to be replaced during serialization;" + 157 " only " + out.numStringsReplaced + " strings were replaced."); 158 if (out.numArraysCounted != 1) 159 throw new Error("Expected 1 array during serialization; only " + 160 out.numArraysCounted + " arrays"); 161 162 if (verbose) { 163 System.out.println("DeSerialize A from SubstituteObjectInputStream"); 164 System.out.println(""); 165 } 166 SubstituteObjectInputStream in = 167 new SubstituteObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); 168 a = (A)in.readObject(); 169 in.close(); 170 171 /* Validate that readResolve called by SubstituteObjectInputStream.*/ 172 if (in.numStringsReplaced != 4) 173 throw new Error("Expected 4 strings to be resolved during deserialization;" + 174 " only " + in.numStringsReplaced + " strings were resolved."); 175 if (in.numArraysCounted != 1) 176 throw new Error("Expected 1 array during deserialization; only " + 177 out.numArraysCounted + " arrays"); 178 if (a.arrayOfString.length != 8) 179 throw new Error("Expected a.arrayOfString.length to be 8, observed " + 180 a.arrayOfString.length); 181 if (verbose) { 182 System.out.println("Value of Class A after serialize/deserialize with writeReplace/readResolve"); 183 a.report(); 184 } 185 } 186 }