FileDocCategorySizeDatePackage
ClassDep.javaAPI DocAndroid 1.5 API7424Wed May 06 22:41:16 BST 2009com.vladium.tools

ClassDep

public class ClassDep extends Object
TODO: doc
author
Vlad Roubtsov, (C) 2004

Fields Summary
private final String[]
m_rootSet
private final URL[]
m_classPath
Constructors Summary
public ClassDep(String[] rootSet, URL[] classPath)

        if (rootSet == null)
            throw new IllegalArgumentException ("null input: rootSet");
        
        if (classPath == null)
            throw new IllegalArgumentException ("null input: classPath");
        
        m_rootSet = rootSet;
        m_classPath = classPath;
    
Methods Summary
public static java.util.ListgetCONSTANT_Class_info(com.vladium.jcd.cls.ClassDef cls)

return
array of class VM names [may contain duplicates]

        if (cls == null)
            throw new IllegalArgumentException ("null input: cls");
        
        final IConstantCollection constants = cls.getConstants ();
        final IConstantCollection.IConstantIterator i = constants.iterator ();
        
        final List result = new ArrayList ();

        for (CONSTANT_info entry; (entry = i.nextConstant ()) != null; )
        {
            if (entry instanceof CONSTANT_Class_info)
            {
                result.add (((CONSTANT_Class_info) entry).getName (cls));
            }
        }
        
        return result;
    
public java.lang.String[]getDependencies(boolean includeRootSet)

        final Set /* class Java name:String */ _result = new HashSet ();
        final ClassLoader loader = new URLClassLoader (m_classPath, null);
        
        if (includeRootSet)
        {
            for (int i = 0; i < m_rootSet.length; ++ i)
            {
                _result.add (m_rootSet [i]);
            }
        }
        
        final LinkedList /* class VM name:String */ queue = new LinkedList ();
        for (int i = 0; i < m_rootSet.length; ++ i)
        {
            queue.add (Descriptors.javaNameToVMName (m_rootSet [i]));
        }
        
        final ByteArrayOStream baos = new ByteArrayOStream (8 * 1024);
        final byte [] readbuf = new byte [8 * 1024];
        
        while (! queue.isEmpty ())
        {
            final String classVMName = (String) queue.removeFirst ();
            
            // keep at most one file descriptor open:
            
            InputStream in = null;
            try
            {
                // NOTE: getResources() not used
                in = loader.getResourceAsStream (classVMName + ".class");
                
                if (in == null)
                {
                    throw new IllegalArgumentException ("class [" + Descriptors.vmNameToJavaName (classVMName) + "] not found in the input classpath");
                }
                else
                {
                    baos.reset ();
                    for (int read; (read = in.read (readbuf)) >= 0; baos.write (readbuf, 0, read));
                }
            }
            finally
            {
                if (in != null) try { in.close (); } catch (IOException ignore) { ignore.printStackTrace (); }
            }
            in = null;

            final ClassDef cls = ClassDefParser.parseClass (baos.getByteArray (), baos.size ());
            final List /* class VM name:String */ clsDeps  = getCONSTANT_Class_info (cls);
            
            for (Iterator i = clsDeps.iterator (); i.hasNext (); )
            {
                final String classDepVMName = (String) i.next ();
                
                if (classDepVMName.startsWith ("com/vladium/")) // TODO: generic filtering
                {
                    if (_result.add (Descriptors.vmNameToJavaName (classDepVMName)))
                    {
                        queue.addLast (classDepVMName);
                    }
                }
            }
        }
        
        final String [] result = new String [_result.size ()];
        _result.toArray (result);
        
        return result;
    
public static voidmain(java.lang.String[] args)

        if (args.length < 2)
            throw new IllegalArgumentException ("usage: classpath output_file rootset_classname_1 [rootset_classname_2 ...]");
            
        final String _classPath = args [0];
        final URL [] classPath;
        {
            final StringTokenizer tokenizer = new StringTokenizer (_classPath, File.pathSeparator);
            classPath = new URL [tokenizer.countTokens ()];
            
            for (int i = 0; tokenizer.hasMoreTokens (); ++ i)
            {
                classPath [i] = new File (tokenizer.nextToken ()).toURL ();
            }
        }
        
        final File outFile = new File (args [1]);
        
        final int offset = 2;
        final String [] rootSet = args.length > offset
            ? new String [args.length - offset]
            : new String [0];
        {
            for (int a = 0; a < rootSet.length; ++ a)
            {
                rootSet [a] = args [a + offset];
            }
        }
        
        final ClassDep _this = new ClassDep (rootSet, classPath);
        final String [] deps = _this.getDependencies (true);
        
        final StringBuffer s = new StringBuffer (); 
        for (int d = deps.length - 1; d >= 0; -- d) // reverse topological order
        {
            s.append (deps [d]);
            if (d > 0) s.append (',");
        }
        
        final File parent = outFile.getParentFile ();
        if (parent != null) parent.mkdirs ();
        
        final FileOutputStream out = new FileOutputStream (outFile);
        
        final Properties result = new Properties ();
        result.setProperty ("closure", s.toString ());
        
        result.store (out, "this file is auto-generated, do not edit");
        
        out.close ();