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();
}
}