2 *******************************************************************************
\r
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
9 package com.ibm.icu.dev.tool.serializable;
\r
11 import java.io.ByteArrayInputStream;
\r
12 import java.io.ByteArrayOutputStream;
\r
13 import java.io.File;
\r
14 import java.io.FileOutputStream;
\r
15 import java.io.IOException;
\r
16 import java.io.ObjectInputStream;
\r
17 import java.io.ObjectOutputStream;
\r
18 import java.lang.reflect.Modifier;
\r
19 import java.net.URL;
\r
20 import java.util.Arrays;
\r
21 import java.util.Iterator;
\r
22 import java.util.List;
\r
24 import com.ibm.icu.dev.test.serializable.SerializableTest;
\r
25 import com.ibm.icu.impl.URLHandler;
\r
28 * This class examines all the classes in a Jar file or a directory
\r
29 * and lists all those classes that implement <code>Serializable</code>. It also checks
\r
30 * to make sure that those classes have the <code>serialVersionUID</code>
\r
34 public class SerializableChecker implements URLHandler.URLVisitor
\r
36 private static Class serializable;
\r
37 //private static Class throwable;
\r
39 private String path = null;
\r
41 //private boolean write;
\r
43 public SerializableChecker(String path)
\r
48 File dir = new File(path);
\r
50 if (!dir.exists()) {
\r
58 serializable = Class.forName("java.io.Serializable");
\r
59 //throwable = Class.forName("java.lang.Throwable");
\r
60 } catch (Exception e) {
\r
61 // we're in deep trouble...
\r
62 System.out.println("Woops! Can't get class info for Serializable and Throwable.");
\r
66 private void writeFile(String className, byte bytes[])
\r
68 File file = new File(path + File.separator + className + ".dat");
\r
69 FileOutputStream stream;
\r
72 stream = new FileOutputStream(file);
\r
74 stream.write(bytes);
\r
76 } catch (Exception e) {
\r
77 System.out.print(" - can't write file!");
\r
81 public void visit(String str)
\r
83 int ix = str.lastIndexOf(".class");
\r
86 String className = "com.ibm.icu" + str.substring(0, ix).replace('/', '.');
\r
88 // Skip things in com.ibm.icu.dev; they're not relevant.
\r
89 if (className.startsWith("com.ibm.icu.dev.")) {
\r
94 Class c = Class.forName(className);
\r
95 int m = c.getModifiers();
\r
97 if (serializable.isAssignableFrom(c) /*&&
\r
98 (! throwable.isAssignableFrom(c) || c.getDeclaredFields().length > 0)*/) {
\r
101 System.out.print(className + " (" + Modifier.toString(m) + ") - ");
\r
103 if(!Modifier.isInterface(m)){
\r
106 c.getDeclaredField("serialVersionUID");
\r
107 } catch (Exception e) {
\r
108 System.out.print("no serialVersionUID - ");
\r
112 if (Modifier.isPublic(m)) {
\r
113 SerializableTest.Handler handler = SerializableTest.getHandler(className);
\r
115 if (!Modifier.isInterface(m) && handler != null) {
\r
116 Object objectsOut[] = handler.getTestObjects();
\r
117 Object objectsIn[];
\r
118 boolean passed = true;
\r
120 ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
\r
121 ObjectOutputStream out = new ObjectOutputStream(byteOut);
\r
124 out.writeObject(objectsOut);
\r
127 } catch (IOException e) {
\r
128 System.out.println("Eror writing test objects:" + e.toString());
\r
132 if (path != null) {
\r
133 writeFile(className, byteOut.toByteArray());
\r
136 ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
\r
137 ObjectInputStream in = new ObjectInputStream(byteIn);
\r
140 objectsIn = (Object[]) in.readObject();
\r
143 } catch (Exception e) {
\r
144 System.out.println("Error reading test objects:" + e.toString());
\r
148 for(int i = 0; i < objectsIn.length; i += 1) {
\r
149 if (! handler.hasSameBehavior(objectsIn[i], objectsOut[i])) {
\r
151 System.out.println("Object " + i + " failed behavior test.");
\r
156 System.out.print("test passed.");
\r
159 // it's OK to not have tests for abstract classes...
\r
160 if (! Modifier.isAbstract(m)) {
\r
161 System.out.print("no test.");
\r
166 System.out.println();
\r
168 } catch (Exception e) {
\r
169 System.out.println("Error processing " + className + ": " + e.toString());
\r
174 public static void main(String[] args)
\r
176 List argList = Arrays.asList(args);
\r
177 String path = null;
\r
179 for (Iterator it = argList.iterator(); it.hasNext(); /*anything?*/) {
\r
180 String arg = (String) it.next();
\r
182 if (arg.equals("-w")) {
\r
183 if (it.hasNext()) {
\r
184 path = (String) it.next();
\r
186 System.out.println("Missing directory name on -w command.");
\r
192 //URL jarURL = new URL("jar:file:/dev/eclipse/workspace/icu4j/icu4j.jar!/com/ibm/icu");
\r
193 //URL fileURL = new URL("file:/dev/eclipse/workspace/icu4j/classes/com/ibm/icu");
\r
194 URL url = new URL(arg);
\r
195 URLHandler handler = URLHandler.get(url);
\r
196 SerializableChecker checker = new SerializableChecker(path);
\r
198 System.out.println("Checking classes from " + arg + ":");
\r
199 handler.guide(checker, true, false);
\r
200 } catch (Exception e) {
\r
201 System.out.println("Error processing URL \"" + arg + "\" - " + e.getMessage());
\r