Java dependencies
Thu, Nov 10, 2011
One-minute read
A little python snippet for creating dot-representation of the dependencies in a java app.
Let this little baby chew on your target/classes dir and you will get a dot-file on stdout.
#!/usr/bin/env python
import re
import os
import sys
from os.path import join, basename
LIB_REG_EXP = re.compile('[,+L#][a-z][A-Za-z0-9/]+')
PACKAGE_FILTER = ''
CLASS_PREFIX_REMOVE = ''
if len(sys.argv) > 2:
PACKAGE_FILTER = sys.argv[2]
if len(sys.argv) > 3:
CLASS_PREFIX_REMOVE = sys.argv[3]
def get_class_dependecies(class_file_contents):
libraries = set(map(lambda x: x.replace('/','.'), [l[1:] for l in LIB_REG_EXP.findall(class_file_contents)]))
return filter(lambda x: PACKAGE_FILTER in x, libraries)
class_dependecies = {}
for root, dirs, files in os.walk(sys.argv[1]):
if '.svn' in dirs:
dirs.remove('.svn')
class_files = [f for f in files if f.endswith('.class') and '$' not in f]
for class_file in class_files:
class_content = open(join(root, class_file)).read()
class_name = join(root, class_file).replace('/','.')[len(CLASS_PREFIX_REMOVE):-6]
if PACKAGE_FILTER not in class_name:
continue
class_dependecies[class_name] = []
for dep in get_class_dependecies(class_content):
if dep == class_name:
continue
class_dependecies[class_name].append(dep)
print "digraph G {"
for key, deps in class_dependecies.items():
for dep in deps:
print '"%s" -> "%s";' % (key, dep)
print "}"
The second argument creates a basic filter for the class-names you want. The third parameter is used for removing the folder-names (target.classes. in usual cases)
Example:
python dotclass.py target/classes us.klette.myproject target.classes. > deps.dot
Have fun