J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1998 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 21 | * have any 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 | } |