blob: 03d5d0367f49dd5aa7e32455612355068474ead7 [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 1996-2005, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
*/
package com.ibm.icu.dev.tool.serializable;
import com.ibm.icu.impl.URLHandler;
import com.ibm.icu.dev.test.serializable.SerializableTest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.Class;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* This class examines all the classes in a Jar file or a directory
* and lists all those classes that implement <code>Serializable</code>. It also checks
* to make sure that those classes have the <code>serialVersionUID</code>
* field define.
*
*/
public class SerializableChecker implements URLHandler.URLVisitor
{
private static Class serializable;
//private static Class throwable;
private String path = null;
private boolean write;
public SerializableChecker(String path)
{
this.path = path;
if (path != null) {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
}
}
static {
try {
serializable = Class.forName("java.io.Serializable");
//throwable = Class.forName("java.lang.Throwable");
} catch (Exception e) {
// we're in deep trouble...
System.out.println("Woops! Can't get class info for Serializable and Throwable.");
}
}
private void writeFile(String className, byte bytes[])
{
File file = new File(path + File.separator + className + ".dat");
FileOutputStream stream;
try {
stream = new FileOutputStream(file);
stream.write(bytes);
stream.close();
} catch (Exception e) {
System.out.print(" - can't write file!");
}
}
public void visit(String str)
{
int ix = str.lastIndexOf(".class");
if (ix >= 0) {
String className = "com.ibm.icu" + str.substring(0, ix).replace('/', '.');
// Skip things in com.ibm.icu.dev; they're not relevant.
if (className.startsWith("com.ibm.icu.dev.")) {
return;
}
try {
Class c = Class.forName(className);
int m = c.getModifiers();
if (serializable.isAssignableFrom(c) /*&&
(! throwable.isAssignableFrom(c) || c.getDeclaredFields().length > 0)*/) {
Field uid;
System.out.print(className + " (" + Modifier.toString(m) + ") - ");
try {
uid = c.getDeclaredField("serialVersionUID");
} catch (Exception e) {
System.out.print("no serialVersionUID - ");
}
if (Modifier.isPublic(m)) {
SerializableTest.Handler handler = SerializableTest.getHandler(className);
if (handler != null) {
Object objectsOut[] = handler.getTestObjects();
Object objectsIn[];
boolean passed = true;
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
try {
out.writeObject(objectsOut);
out.close();
byteOut.close();
} catch (IOException e) {
System.out.println("Eror writing test objects:" + e.toString());
return;
}
if (path != null) {
writeFile(className, byteOut.toByteArray());
}
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
try {
objectsIn = (Object[]) in.readObject();
in.close();
byteIn.close();
} catch (Exception e) {
System.out.println("Error reading test objects:" + e.toString());
return;
}
for(int i = 0; i < objectsIn.length; i += 1) {
if (! handler.hasSameBehavior(objectsIn[i], objectsOut[i])) {
passed = false;
System.out.println("Object " + i + " failed behavior test.");
}
}
if (passed) {
System.out.print("test passed.");
}
} else {
// it's OK to not have tests for abstract classes...
if (! Modifier.isAbstract(m)) {
System.out.print("no test.");
}
}
}
System.out.println();
}
} catch (Exception e) {
System.out.println("Error processing " + className + ": " + e.toString());
}
}
}
public static void main(String[] args) throws java.net.MalformedURLException
{
List argList = Arrays.asList(args);
String path = null;
for (Iterator it = argList.iterator(); it.hasNext(); /*anything?*/) {
String arg = (String) it.next();
if (arg.equals("-w")) {
if (it.hasNext()) {
path = (String) it.next();
} else {
System.out.println("Missing directory name on -w command.");
}
} else {
try {
//URL jarURL = new URL("jar:file:/dev/eclipse/workspace/icu4j/icu4j.jar!/com/ibm/icu");
//URL fileURL = new URL("file:/dev/eclipse/workspace/icu4j/classes/com/ibm/icu");
URL url = new URL(arg);
URLHandler handler = URLHandler.get(url);
SerializableChecker checker = new SerializableChecker(path);
System.out.println("Checking classes from " + arg + ":");
handler.guide(checker, true, false);
} catch (Exception e) {
System.out.println("Error processing URL \"" + arg + "\" - " + e.getMessage());
}
}
}
}
}