Jdep-grapher: make a dependency tree of your Java projects

Oh, my first english post ... so amazing (isn't it ?). Well, I present a little (and awful) bash dependency graph generator for Java projects.

One goal of my job is to maintain the Quercus project. It is currently highly dependent of Resin, another Caucho's project, and a removal is needed. To know what I need to remove first, I wanted a graphical representation of all links between projects. We can consider that dependencies could be computed with 'import' Java keyword. Yes I know, it's not a perfect dependencies representation but it's currently the best way I found (and faster). Finally, we need a graph generation tool ... I found GraphViz which can be directly used in CLI and we use DOT format file to make the graph specifications. One day after ... Jdep-grapher is released.

How does it work ?

It will first get the list of files to parse (with find) and extract all lines beginning with 'import' and 'package' (we use temp files with mktemp) :

find $DIR -type f -name "*.java" > $FILES
grep -E "^package|^import" $(< $FILES) | awk -F':' '{print $2}' > $GREP

Next it creates links between packages and uses DOT format :

while read type name
do
    name=`echo $name | tr -d ";"`
    pkg=`echo $name | tr -d "."`
    if [[ "$type" == "package" ]]; then
        echo "$pkg [label=\"$name\", style = filled, shape = box];"
        CPKG=$pkg
    else
        ALL=`echo $pkg | grep "\*" | wc -l`
        SUP=""
        LNK=""
        if [[ $ALL -eq 1 ]]; then
            pkg=`echo $pkg | sed s/"*"/"allpkg"/`
            SUP=", color=red, style = filled"
                        LNK=" [color=red]"
        fi
        echo "$pkg [label=\"$name\"$SUP];"
        echo "$CPKG -> $pkg $LNK;"
    fi
done < $GREP | sort -u > $COMPUTE

sort -u at the end of loop will automatically remove duplicates and send the result to a new temp file. All-inclusion packages (with *) are filled in red.

We can exclude useless links (eg. internal dependencies) with :

grep -vE "$EXCLUDE" $COMPUTE > $TMPDOT

To reduce the weight of graph, it removes single nodes :

CT=`grep -E "$rpkg( |;)" $TMPDOT | wc -l`
    if [[ $CT -gt 1 ]]; then
        echo $rpkg $rop $rchild >> $TMPDOT2
    fi

Finally, the script closes the DOT file and launches graphviz ...

echo "digraph G {" > $DOT
cat $TMPDOT2 >> $DOT
echo "}" >> $DOT

fdp -Tpng < $DOT > $GRAPH

Enjoy

Example : Resin Dependency Graph of Quercus

Note : the script currently uses 'fdp' from graphviz which is not fully optimized for this kind of graph. Tell me if you have any other solution ;-)

More information on GitHub.