001: /*
002: *******************************************************************************
003: * Copyright (C) 1996-2006, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: *
007: */
008:
009: package com.ibm.icu.dev.tool.serializable;
010:
011: import com.ibm.icu.impl.URLHandler;
012: import com.ibm.icu.dev.test.serializable.SerializableTest;
013: import java.io.ByteArrayInputStream;
014: import java.io.ByteArrayOutputStream;
015: import java.io.File;
016: import java.io.FileOutputStream;
017: import java.io.IOException;
018: import java.io.ObjectInputStream;
019: import java.io.ObjectOutputStream;
020: import java.lang.Class;
021: import java.lang.reflect.Field;
022: import java.lang.reflect.Modifier;
023: import java.net.URL;
024: import java.util.Arrays;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: /**
029: * This class examines all the classes in a Jar file or a directory
030: * and lists all those classes that implement <code>Serializable</code>. It also checks
031: * to make sure that those classes have the <code>serialVersionUID</code>
032: * field define.
033: *
034: */
035: public class SerializableChecker implements URLHandler.URLVisitor {
036: private static Class serializable;
037: //private static Class throwable;
038:
039: private String path = null;
040:
041: private boolean write;
042:
043: public SerializableChecker(String path) {
044: this .path = path;
045:
046: if (path != null) {
047: File dir = new File(path);
048:
049: if (!dir.exists()) {
050: dir.mkdirs();
051: }
052: }
053: }
054:
055: static {
056: try {
057: serializable = Class.forName("java.io.Serializable");
058: //throwable = Class.forName("java.lang.Throwable");
059: } catch (Exception e) {
060: // we're in deep trouble...
061: System.out
062: .println("Woops! Can't get class info for Serializable and Throwable.");
063: }
064: }
065:
066: private void writeFile(String className, byte bytes[]) {
067: File file = new File(path + File.separator + className + ".dat");
068: FileOutputStream stream;
069:
070: try {
071: stream = new FileOutputStream(file);
072:
073: stream.write(bytes);
074: stream.close();
075: } catch (Exception e) {
076: System.out.print(" - can't write file!");
077: }
078: }
079:
080: public void visit(String str) {
081: int ix = str.lastIndexOf(".class");
082:
083: if (ix >= 0) {
084: String className = "com.ibm.icu"
085: + str.substring(0, ix).replace('/', '.');
086:
087: // Skip things in com.ibm.icu.dev; they're not relevant.
088: if (className.startsWith("com.ibm.icu.dev.")) {
089: return;
090: }
091:
092: try {
093: Class c = Class.forName(className);
094: int m = c.getModifiers();
095:
096: if (serializable.isAssignableFrom(c) /*&&
097: (! throwable.isAssignableFrom(c) || c.getDeclaredFields().length > 0)*/) {
098: Field uid;
099:
100: System.out.print(className + " ("
101: + Modifier.toString(m) + ") - ");
102:
103: try {
104: uid = c.getDeclaredField("serialVersionUID");
105: } catch (Exception e) {
106: System.out.print("no serialVersionUID - ");
107: }
108:
109: if (Modifier.isPublic(m)) {
110: SerializableTest.Handler handler = SerializableTest
111: .getHandler(className);
112:
113: if (handler != null) {
114: Object objectsOut[] = handler
115: .getTestObjects();
116: Object objectsIn[];
117: boolean passed = true;
118:
119: ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
120: ObjectOutputStream out = new ObjectOutputStream(
121: byteOut);
122:
123: try {
124: out.writeObject(objectsOut);
125: out.close();
126: byteOut.close();
127: } catch (IOException e) {
128: System.out
129: .println("Eror writing test objects:"
130: + e.toString());
131: return;
132: }
133:
134: if (path != null) {
135: writeFile(className, byteOut
136: .toByteArray());
137: }
138:
139: ByteArrayInputStream byteIn = new ByteArrayInputStream(
140: byteOut.toByteArray());
141: ObjectInputStream in = new ObjectInputStream(
142: byteIn);
143:
144: try {
145: objectsIn = (Object[]) in.readObject();
146: in.close();
147: byteIn.close();
148: } catch (Exception e) {
149: System.out
150: .println("Error reading test objects:"
151: + e.toString());
152: return;
153: }
154:
155: for (int i = 0; i < objectsIn.length; i += 1) {
156: if (!handler.hasSameBehavior(
157: objectsIn[i], objectsOut[i])) {
158: passed = false;
159: System.out.println("Object " + i
160: + " failed behavior test.");
161: }
162: }
163:
164: if (passed) {
165: System.out.print("test passed.");
166: }
167: } else {
168: // it's OK to not have tests for abstract classes...
169: if (!Modifier.isAbstract(m)) {
170: System.out.print("no test.");
171: }
172: }
173: }
174:
175: System.out.println();
176: }
177: } catch (Exception e) {
178: System.out.println("Error processing " + className
179: + ": " + e.toString());
180: }
181: }
182: }
183:
184: public static void main(String[] args)
185: throws java.net.MalformedURLException {
186: List argList = Arrays.asList(args);
187: String path = null;
188:
189: for (Iterator it = argList.iterator(); it.hasNext(); /*anything?*/) {
190: String arg = (String) it.next();
191:
192: if (arg.equals("-w")) {
193: if (it.hasNext()) {
194: path = (String) it.next();
195: } else {
196: System.out
197: .println("Missing directory name on -w command.");
198: }
199: } else {
200:
201: try {
202: //URL jarURL = new URL("jar:file:/dev/eclipse/workspace/icu4j/icu4j.jar!/com/ibm/icu");
203: //URL fileURL = new URL("file:/dev/eclipse/workspace/icu4j/classes/com/ibm/icu");
204: URL url = new URL(arg);
205: URLHandler handler = URLHandler.get(url);
206: SerializableChecker checker = new SerializableChecker(
207: path);
208:
209: System.out.println("Checking classes from " + arg
210: + ":");
211: handler.guide(checker, true, false);
212: } catch (Exception e) {
213: System.out.println("Error processing URL \"" + arg
214: + "\" - " + e.getMessage());
215: }
216: }
217: }
218: }
219: }
|