The source is attached. I've done some changes to compute
dependencies. So the result is a bit diferent.


On 12/28/05, Stefano Mazzocchi <[EMAIL PROTECTED]> wrote:
> Rodrigo Kumpera wrote:
> > Just for curiosity I've written a small program that enumerate all
> > graph cycles of packages dependencies in Java 1.4 (counting only
> > fields, methods and super types). This shows that for most packages
> > this won't be an issue and a packaging that have no cyclic dependencis
> > is possible.
> >
> > Given the criteria that dependencies are: fields, super class,
> > interfaces and method return/exception/parameters, one could have the
> > following bundles:
> >
> > [java.applet]
> > [java.awt.color]
> > [java.awt.datatransfer]
> > [java.awt.im.spi]
> > [java.awt.print]
> > [java.math]
> > [java.nio]
> > [java.rmi, java.rmi.registry]
> > [java.rmi.activation]
> > [java.rmi.dgc]
> > [java.rmi.server]
> > [java.security.acl]
> > [java.sql]
> > [java.io, java.lang, java.lang.ref, java.lang.reflect, java.net,
> > java.nio.channels, java.nio.channels.spi, java.nio.charset,
> > java.nio.charset.spi, java.security, java.security.cert,
> > java.security.interfaces, java.security.spec, java.text, java.util,
> > java.util.jar, javax.security.auth.x500]
> > [java.util.logging]
> > [java.util.prefs]
> > [java.util.regex]
> > [java.util.zip]
> > [javax.crypto]
> > [javax.crypto.interfaces]
> > [javax.crypto.spec]
> > [javax.imageio, javax.imageio.event, javax.imageio.metadata, 
> > javax.imageio.spi]
> > [javax.imageio.plugins.jpeg]
> > [javax.imageio.stream]
> > [javax.naming]
> > [javax.naming.directory]
> > [javax.naming.event]
> > [javax.naming.ldap]
> > [javax.naming.spi]
> > [javax.net]
> > [javax.net.ssl]
> > [javax.print, javax.print.event]
> > [javax.print.attribute]
> > [javax.print.attribute.standard]
> > [javax.rmi]
> > [javax.rmi.CORBA]
> > [javax.security.auth]
> > [javax.security.auth.callback]
> > [javax.security.auth.kerberos]
> > [javax.security.auth.login]
> > [javax.security.auth.spi]
> > [javax.security.cert]
> > [javax.sound.midi, javax.sound.midi.spi]
> > [javax.sound.sampled, javax.sound.sampled.spi]
> > [javax.sql]
> > [java.awt, java.awt.dnd, java.awt.dnd.peer, java.awt.event,
> > java.awt.font, java.awt.geom, java.awt.im, java.awt.image,
> > java.awt.image.renderable, java.awt.peer, java.beans,
> > java.beans.beancontext, javax.accessibility, javax.swing,
> > javax.swing.border, javax.swing.colorchooser, javax.swing.event,
> > javax.swing.filechooser, javax.swing.plaf, javax.swing.plaf.basic,
> > javax.swing.table, javax.swing.text, javax.swing.tree,
> > javax.swing.undo]
> > [javax.swing.plaf.metal]
> > [javax.swing.plaf.multi]
> > [javax.swing.text.html]
> > [javax.swing.text.html.parser]
> > [javax.swing.text.rtf]
> > [javax.transaction]
> > [javax.transaction.xa]
> > [javax.xml.parsers]
> > [javax.xml.transform]
> > [javax.xml.transform.dom]
> > [javax.xml.transform.sax]
> > [javax.xml.transform.stream]
> >
> > From that we can see that most of the GUI stuff should live in the
> > same package and the minimum set of classes for java.lang is not that
> > huge.
>
> Nice! awesome job!
>
> (is the source-code of this program available?)
>
> --
> Stefano.
>
>
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

public class Deps {

    static class Group implements Comparable {
        String name;
        Set packages = new TreeSet();
        Set deps = new TreeSet();

        public Group(Package p) {
            this.name = mkGroup();
            add(p);
        }

        public int compareTo(Object o) {
            return this.name.compareTo(((Group) o).name);
        }

        public void remark(Group from) {
            for (Iterator i = from.packages.iterator(); i.hasNext();)
                add((Package) i.next());
            groups.remove(from);
        }

        public void add(Package p) {
            p.group = this;
            this.packages.add(p);
        }

        public String toString() {
            StringBuffer buff = new StringBuffer();
            buff.append("group [").append(this.name).append("] ")
                    .append(this.packages).append(" -> [ ");
            for(Iterator i = this.deps.iterator(); i.hasNext(); ){
                Group g = (Group) i.next();
                buff.append(g.name);
                if(i.hasNext())
                    buff.append(", ");
            }
            buff.append(" ]");
            return buff.toString();
        }

        public void computeDeps() {
            this.deps.clear();
            for (Iterator i = this.packages.iterator(); i.hasNext();) {
                final Package p = (Package) i.next();
                for (Iterator j = p.deps.iterator(); j.hasNext();) {
                    Package dep = (Package) pkg.get(j.next());
                    if (dep.group != null)
                        this.deps.add(dep.group);
                }
            }

        }
    }

    static class Package implements Comparable {
        Group group;
        String name;
        Set deps = new TreeSet();

        public Package(String name) {
            this.name = name;
        }

        public int compareTo(Object o) {
            return this.name.compareTo(((Package) o).name);
        }

        public String toString() {
            return name;
        }

        public void digest(Class cl) {
            dep(cl.getSuperclass());

            Class[] interfaces = cl.getInterfaces();
            dep(interfaces);

            Field[] declaredFields = cl.getDeclaredFields();
            for (int i = 0; i < declaredFields.length; ++i)
                dep(declaredFields[i].getType());

            Method[] declaredMethods = cl.getDeclaredMethods();
            for (int i = 0; i < declaredMethods.length; ++i) {
                Method m = declaredMethods[i];
                dep(m.getReturnType());
                dep(m.getParameterTypes());
                dep(m.getExceptionTypes());
            }
        }

        private void dep(Class[] cl) {
            if (cl == null)
                return;
            for (int i = 0; i < cl.length; ++i)
                dep(cl[i]);
        }

        private void dep(Class cl) {
            if (cl == null)
                return;
            while (cl.isArray())
                cl = cl.getComponentType();
            if (cl.isPrimitive())
                return;
            if (cl.getPackage() == null)
                System.out.println(cl);
            final String pkgName = cl.getPackage().getName();
            if (isApi(pkgName) && !pkgName.equals(this.name))
                deps.add(pkgName);
        }

        public void mark() {
            if (this.group == null)
                groups.add(this.group = new Group(this));

            for (Iterator i = this.deps.iterator(); i.hasNext();) {
                final Object key = i.next();
                Package p = (Package) pkg.get(key);
                if (p == null) {
                    System.out.println("#### " + key);
                    continue;
                }
                if (p.group == this.group)
                    continue;
                if (p.deps.contains(this.name)) {
                    if (p.group == null)
                        this.group.add(p);
                    else
                        this.group.remark(p.group);
                }
            }
        }
    }

    static Map pkg = new TreeMap();
    static char nextGroup = 'a';
    static Set groups = new TreeSet();

    static String mkGroup() {
        return String.valueOf(nextGroup++);
    }

    public static boolean isApi(String str) {
        return str.startsWith("java.") || str.startsWith("javax.");
    }

    private static Package getPkg(Class cl) {
        String key = cl.getPackage().getName();
        Package r = (Package) pkg.get(key);
        if (r == null)
            pkg.put(key, r = new Package(key));
        return r;
    }

    public static void main(String[] args) throws Exception {
        collect("C:/j2sdk/jre/lib/rt.jar");
        collect("C:/j2sdk/jre/lib/jce.jar");
        collect("C:/j2sdk/jre/lib/jsse.jar");

        for (Iterator i = pkg.values().iterator(); i.hasNext();) {
            Package p = (Package) i.next();
            System.out.println("package " + p + " depends on " + p.deps);
        }

        for (Iterator i = pkg.values().iterator(); i.hasNext();)
            ((Package) i.next()).mark();

        nextGroup = 'A';

        for (Iterator i = groups.iterator(); i.hasNext();) {
            Group g = (Group) i.next();
            g.name = mkGroup();
            g.computeDeps();
        }

        for (Iterator i = groups.iterator(); i.hasNext();) 
            System.out.println(i.next());
    }

    private static void collect(String file) throws ZipException, IOException,
            ClassNotFoundException {
        ZipFile zip = new ZipFile(new File(file));
        for (Enumeration e = zip.entries(); e.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            String name = entry.getName();
            if ((!name.startsWith("java/") && !name.startsWith("javax/"))
                    || !name.endsWith(".class"))
                continue;
            name = name.substring(0, name.length() - 6).replace('/', '.');
            Class cl = Class.forName(name, false, null);
            Package p = getPkg(cl);
            p.digest(cl);
        }
        zip.close();
    }
}

Reply via email to