1 4 package com.tctest; 5 6 import org.apache.commons.io.IOUtils; 7 8 import com.tc.object.config.ConfigVisitor; 9 import com.tc.object.config.DSOClientConfigHelper; 10 import com.tc.object.config.TransparencyClassSpec; 11 import com.tc.process.LinkedJavaProcess; 12 import com.tc.process.StreamCollector; 13 import com.tc.simulator.app.ApplicationConfig; 14 import com.tc.simulator.listener.ListenerProvider; 15 import com.tc.util.Util; 16 import com.tctest.runner.AbstractTransparentApp; 17 18 import java.io.ByteArrayInputStream ; 19 import java.io.ByteArrayOutputStream ; 20 import java.io.FileInputStream ; 21 import java.io.FileOutputStream ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.ObjectInputStream ; 25 import java.io.ObjectOutputStream ; 26 import java.io.ObjectStreamClass ; 27 import java.io.OutputStream ; 28 import java.io.Serializable ; 29 import java.lang.reflect.Field ; 30 import java.lang.reflect.Modifier ; 31 import java.util.Arrays ; 32 import java.util.HashMap ; 33 import java.util.Map ; 34 35 public class SerialVersionUIDTestApp extends AbstractTransparentApp { 36 37 public static final String TEMP_FILE_KEY = "tempFile"; 38 39 private final Map map = new HashMap (); 40 private final String fileName; 41 42 public SerialVersionUIDTestApp(String appId, ApplicationConfig cfg, ListenerProvider listenerProvider) { 43 super(appId, cfg, listenerProvider); 44 this.fileName = cfg.getAttribute(TEMP_FILE_KEY); 45 } 46 47 public void run() { 48 final boolean first; 49 synchronized (map) { 50 first = map.isEmpty(); 51 if (first) { 52 map.put("with", new WithUID()); 53 map.put("without", new WithoutUID()); 54 } 55 } 56 57 WithUID with = (WithUID) map.get("with"); 58 WithoutUID without = (WithoutUID) map.get("without"); 59 60 checkUID(with, WithUID.serialVersionUID); 61 checkUID(without, WithoutUID.EXPECTED_UID); 62 63 doTheDance(with); 64 doTheDance(without); 65 66 verifyAddedField(without); 67 68 if (first) { 69 verifyExternal(); 71 } 72 } 73 74 private void verifyAddedField(WithoutUID without) { 75 Field field = getSerialUIDField(without); 76 77 if (field == null) { throw new RuntimeException ("Could not find the serialVersionUID field: " 78 + Arrays.asList(without.getClass().getDeclaredFields())); } 79 80 int access = field.getModifiers(); 81 if ((!Modifier.isStatic(access)) || (!Modifier.isFinal(access))) { 82 throw new RuntimeException ("Bad permissions: " + access); 84 } 85 86 Class type = field.getType(); 87 if (!Long.TYPE.equals(type)) { throw new RuntimeException ("Bad type: " + type); } 88 89 return; 91 } 92 93 private void verifyExternal() { 94 96 byte[] dataIn = null; 97 98 try { 99 OutputStream out = new FileOutputStream (fileName + ".in", false); 100 out.write(serialize(new WithoutUID())); 101 out.close(); 102 103 LinkedJavaProcess process = new LinkedJavaProcess(ExternalSerialize.class.getName(), new String [] { fileName }); 104 process.start(); 105 106 process.STDIN().close(); 107 StreamCollector stdout = new StreamCollector(process.STDOUT()); 108 stdout.start(); 109 StreamCollector stderr = new StreamCollector(process.STDERR()); 110 stderr.start(); 111 112 int exitCode = process.waitFor(); 113 114 stdout.join(); 115 stderr.join(); 116 117 if (exitCode != 0) { throw new RuntimeException ("Process exited with code " + exitCode + ", stdout: " 118 + stdout.toString() + ", stderr: " + stderr); } 119 120 InputStream in = new FileInputStream (fileName + ".out"); 121 dataIn = IOUtils.toByteArray(in); 122 if (dataIn.length == 0) { throw new RuntimeException ("No data read"); } 123 in.close(); 124 deserialize(dataIn); 125 } catch (Exception e) { 126 throw new RuntimeException (Util.enumerateArray(dataIn), e); 127 } 128 } 129 130 private static Field getSerialUIDField(Object obj) { 131 Field [] fields = obj.getClass().getDeclaredFields(); 132 for (int i = 0; i < fields.length; i++) { 133 Field f = fields[i]; 134 if ("serialVersionUID".equals(f.getName())) { return f; } 135 } 136 return null; 137 } 138 139 private void doTheDance(Object obj) { 140 try { 143 byte[] data = serialize(obj); 144 deserialize(data); 145 } catch (Exception e) { 146 notifyError(e); 147 } 148 } 149 150 private static Object deserialize(byte[] data) throws IOException , ClassNotFoundException { 151 ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (data)); 152 Object rv = ois.readObject(); 153 ois.close(); 154 return rv; 155 } 156 157 private static byte[] serialize(Object obj) throws IOException { 158 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 159 ObjectOutputStream oos = new ObjectOutputStream (baos); 160 oos.writeObject(obj); 161 oos.close(); 162 return baos.toByteArray(); 163 } 164 165 private void checkUID(Object obj, long expect) { 166 long uid = ObjectStreamClass.lookup(obj.getClass()).getSerialVersionUID(); 167 if (uid != expect) { throw new RuntimeException ("Unexpected UID: " + uid + ", expected " + expect); } 168 } 169 170 public static void visitL1DSOConfig(ConfigVisitor visitor, DSOClientConfigHelper config) { 171 String testClass = SerialVersionUIDTestApp.class.getName(); 172 TransparencyClassSpec spec = config.getOrCreateSpec(testClass); 173 spec.addRoot("map", "map"); 174 175 String methodExpression = "* " + testClass + ".*(..)"; 176 config.addWriteAutolock(methodExpression); 177 178 config.addIncludePattern(testClass + "$*"); 179 180 config.getOrCreateSpec(WithoutUID.class.getName()); 181 } 182 183 private static class WithUID implements Serializable { 184 static final long serialVersionUID = 0xDECAFBAD; 185 } 186 187 public static class ExternalSerialize { 188 189 public static void main(String args[]) throws Exception { 190 try { 191 if (args.length != 1) { 192 error("invalid number of args " + args.length); 193 } 194 195 String file = args[0]; 196 197 FileInputStream in = new FileInputStream (file + ".in"); 198 byte[] dataIn = IOUtils.toByteArray(in); 199 in.close(); 200 201 Object o = deserialize(dataIn); 202 203 verifyNoSerialUID(o); 204 205 FileOutputStream out = new FileOutputStream (file + ".out", false); 206 out.write(serialize(o)); 207 out.flush(); 208 out.close(); 209 System.exit(0); 210 } catch (Throwable t) { 211 t.printStackTrace(); 212 error(t.getMessage()); 213 } 214 215 } 216 217 private static void verifyNoSerialUID(Object o) { 218 Field f = getSerialUIDField(o); 219 if (f != null) { throw new RuntimeException ("Class has a serialVersionUID field: " + f); } 220 } 221 222 private static void error(String msg) { 223 System.err.println(msg); 224 System.err.flush(); 225 System.exit(1); 226 throw new RuntimeException (msg); 227 } 228 } 229 230 } 231 | Popular Tags |