251 lines · 5.7 KB · Java
RawDownload
package javal;// Copyright (c) Lucent Technologies 1997// Revisions copyright (c) Vita Nuova Holdings Limited 2004 import java.lang.reflect.*;import java.io.FileInputStream;import java.io.File;import java.io.IOException;  publicclass javal{ 	private static java.io.PrintStream out = System.out; 	private static boolean opt_verbose   = false;	private static boolean opt_classinfo = false;   //dump class info	private static boolean opt_module    = false;   //create Limbo mod (.m)	private static boolean opt_impl      = false;   //create Limbo impl skeleton (.b)  	public static void main( String[] args )	{		int args_len = args.length; 		if ( (args_len < 1) || (args_len > 2) )			error( "wrong args", true ); 		if ( args_len == 2 )			SetArgs( args[0] ); 		// class to create limbo module for		String targ_name  = args[args_len-1];		Class  targ_class = null; 		try		{			TargetLoader tl = new TargetLoader( opt_verbose );			targ_class = tl.loadClass( targ_name, false );		}		catch ( NoClassDefFoundError ee )		{			ee.printStackTrace();			error( "ERROR: Class "+ targ_name +" not found.", false );		}		catch ( ClassNotFoundException ee )		{			error( "Error: Class "+ targ_name +" not found: "+ ee.getMessage(), false );		}		catch ( Exception ee )		{			error( "Error: Could not load class "+ targ_name +".", false );		} 		out.println( "Class Name: "+ targ_class ); 		Field[]   fields  = GetFields( targ_class );		Method[]  methods = GetMethods( targ_class); 		if ( opt_classinfo )		{			Dump( "Fields", fields );			Dump( "Methods", methods );		} 		if ( opt_module || opt_impl )		{			try			{				LimboGen limbogen = new LimboGen( targ_class, fields, methods, opt_verbose ); 				if ( opt_module )					limbogen.DotM(); 				if ( opt_impl )					limbogen.DotB();			}			catch ( RuntimeException ee )			{				System.err.println( "Error: internal error: "+ ee );				ee.printStackTrace();				error( "...too bad.", false );			}			catch ( Exception ee )			{				error( "Error: could not generate limbo file: "+ ee, false );			}					} 	}  	/**	 * Get all data fields for the class and	 * all of his ancestors.	 */	private static Field[] GetFields( Class c )	{		if ( c == null ) return( new Field[0] ); 		Class sup = c.getSuperclass();		Field[] sup_f = GetFields( sup );						Field[] f = c.getDeclaredFields(); 		return( (Field[])ConcatArray( sup_f, f ) );	}  	/**	 * Get methods for the specified class 	 * only (i.e. don't care about ancestor's)	 */	private static Method[] GetMethods( Class c )	{		return( c.getDeclaredMethods() );	}  	private static Object ConcatArray( Object[] a1, Object[] a2 )	{		if ( (a2 == null) || (a2.length==0) ) return( a1 );		if ( (a1 == null) || (a1.length==0) ) return( a2 );				int[] dim = {a1.length+a2.length};		Object a = Array.newInstance( a1[0].getClass(), dim );  		System.arraycopy( a1, 0, a, 0, a1.length );		System.arraycopy( a2, 0, a, a1.length, a2.length ); 		return( a );	}  	private static void Dump( String title, Object[] ary )	{		System.out.println( title );		for(int x=0; x<ary.length; x++ )		{			System.out.println( "\t"+ ary[x] );		}	} 	private static void SetArgs( String opts )	{				if ( (opts.length() > 5) || 		     (opts.length() < 2) ||			 (! opts.startsWith("-")) )			 error( "Error: bad options", true ); 		opt_verbose   = opts.indexOf( "v" ) != -1;		opt_classinfo = opts.indexOf( "c" ) != -1;		opt_module    = opts.indexOf( "m" ) != -1;		opt_impl      = opts.indexOf( "b" ) != -1; 		if ( opt_verbose )			Runtime.getRuntime().traceMethodCalls(true);	}  	private static void error( String msg, boolean usage )	{		out.println( msg );		if ( usage )		{			out.println( "  javal [-vcmb] <class name>" );		}		System.exit(1);	}}			/** * This loader simply reads from a disk based * .class file in the "current" directory. It * only accepts the base name of the class, * appends ".class" and reads the file. The * purpose is to allow classes like "String.java" * to be read and queried, where the class * is different then the one used by this * program.  This tool is used to develop a * new java class library and this class loader * avoids the conflics of using a java based * tool to develop java classes, etc. */class TargetLoader extends ClassLoader{	private boolean verbose;  	private String  class_name = null; 	TargetLoader( boolean verbose )	{		this.verbose = verbose;	} 	public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException	{ 		// if we have already been here once		// then load all other classes from the system		if ( class_name != null )		{			return( findSystemClass( name ) );		} 		if ( name.startsWith("java/") )		{			System.out.println( "Warning: we can't load " + name + " due to java security policy" );			System.out.println( "Warning: we will use the system (already loaded) class instead" );			return( findSystemClass( name.replaceAll("/", ".") ) );		} 		// otherwise do our one time load from a disk file 		// read from the current directory the file "name".java		class_name = name +".class"; 		try		{			FileInputStream fin = new FileInputStream( class_name );						int len = fin.available();  // how big is the file 			if ( len == 0 )				throw new ClassNotFoundException( class_name ); 			byte[] buf = new byte[len];						fin.read( buf );  //read the .class file 			if ( verbose )			{				System.out.println( "loading class ["+ class_name +"]("+ len +")" );			} 			// create class object and return it			return( defineClass( buf, 0, buf.length ) );		}		catch ( IOException ee )		{			File f = new File( class_name );			throw new ClassNotFoundException( "(path:"+f.getAbsolutePath() +")" );		}		catch ( Exception ee )		{			throw new ClassNotFoundException( ee.getMessage() );		}	}}