more tests

This commit is contained in:
snafu 2013-12-07 12:45:36 +01:00
parent 1083c9a4c7
commit ba53b67ccf
25 changed files with 154 additions and 838 deletions

View file

@ -2,3 +2,8 @@ yooze
=====
visualizes java class dependencies
=====
Not a finished project yet, just poking around with javassist.
It does build a model, and you you could pick up dot files to create pictures of the graph. It just isn't very pretty yet.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 MiB

View file

@ -8,7 +8,7 @@
<packaging>jar</packaging>
<version>0.1-SNAPSHOT</version>
<name>yooze</name>
<url>www.cjib.nl</url>
<url>http://jssl.org/yooze</url>
<build>
<plugins>
<plugin>
@ -130,6 +130,12 @@
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.10</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View file

@ -21,8 +21,7 @@ import yooze.domain.MethodModel;
* Builds a ClassModel.
*/
public class ClassModelBuilder {
private static Logger log = LoggerFactory
.getLogger(ClassModelBuilder.class);
private static Logger log = LoggerFactory.getLogger(ClassModelBuilder.class);
private Pattern[] packageIncludePatterns;
private Pattern[] packageExcludePatterns;
@ -47,17 +46,11 @@ public class ClassModelBuilder {
private ClassModel scan(String className) {
ClassModel model = new ClassModel(className);
ClassCache.add(className, model);
try {
return tryScan(className, model);
} catch (Exception e) {
log.warn("Loading class,", e);
return null;
}
}
private ClassModel tryScan(String className, ClassModel model)
throws NotFoundException {
CtClass ctClass = pool.get(className);
private ClassModel tryScan(String className, ClassModel model) {
CtClass ctClass = getClassFromJavassist(className);
if (isScannable(ctClass)) {
ConstPool constPool = ctClass.getClassFile().getConstPool();
@ -66,7 +59,15 @@ public class ClassModelBuilder {
resolveMethodReferences();
return model;
} else {
return null;
throw new ClassNotFound(className);
}
}
private CtClass getClassFromJavassist(String className) {
try {
return pool.get(className);
} catch (NotFoundException e) {
throw new ClassNotFound(className);
}
}
@ -88,11 +89,11 @@ public class ClassModelBuilder {
private void addMethods(ClassModel containingClass, CtClass ctClass) {
CtMethod[] methods = ctClass.getMethods();
for (CtMethod method : methods) {
containingClass.addMethod(MethodModel.create(containingClass,
method));
containingClass.addMethod(MethodModel.create(containingClass, method));
}
}
@SuppressWarnings("unchecked")
private void addClassReferences(ClassModel model, ConstPool constPool) {
Set<String> classNames = constPool.getClassNames();
for (String classResourcename : classNames) {

View file

@ -1,28 +0,0 @@
package yooze;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javassist.ClassPath;
import yooze.scanner.Scanner;
/**
* reads classes as .class files from a directory
*/
public class ClassesDirScanner implements Scanner {
@Override
public List<ClassPath> scanArchive(String archiveName) throws IOException {
return scanArchive(new File(archiveName));
}
@Override
public List<ClassPath> scanArchive(File file) throws IOException {
List<ClassPath> result = new ArrayList<ClassPath>();
result.add(new DirClassPath(file));
return result;
}
}

View file

@ -1,90 +0,0 @@
package yooze;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javassist.ClassPath;
import javassist.NotFoundException;
public class DirClassPath implements ClassPath, Inspectable {
private final File dir;
public DirClassPath(File dir) {
super();
this.dir = dir;
}
public void close() {
}
public URL find(String className) {
try {
return new URL("file:///" + dir.getCanonicalPath() + "/" + Util.toClassResource(className));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "DirectoryClasspath[" + dir + "]";
}
public List<String> getClasses() {
List<String> classes = new ArrayList<String>();
getClasses(dir, dir, classes);
return classes;
}
private void getClasses(File root, File dir, List<String> classes) {
File[] fileList = dir.listFiles();
for (File entry : fileList) {
if (entry.isDirectory()) {
// recurse deeper
getClasses(root, entry, classes);
} else if (isClassFile(entry)) {
classes.add(createQualifiedClassNameFromFileLocation(root, entry));
}
}
}
private boolean isClassFile(File entry) {
return entry.isFile() && entry.getName().endsWith(".class");
}
private String createQualifiedClassNameFromFileLocation(File root, File classFile) {
String absolutePath = classFile.getAbsolutePath();
String relativePath = absolutePath.substring(root.getAbsolutePath().length() + 1);
String packageFormat = relativePath.replaceAll("\\\\", ".").replaceAll("/", ".");
String substring = packageFormat.substring(0, packageFormat.length() - 6);
return substring;
}
@Override
public String getResourceName() {
return dir.getName();
}
@Override
public InputStream openClassfile(String className) throws NotFoundException {
File classFile = new File(dir, Util.toClassResource(className) + ".class");
if (!classFile.exists()) {
return null;
}
try {
return new ClassByteCountingInputStream(className, new FileInputStream(classFile));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -1,59 +0,0 @@
package yooze;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
/**
* prints the graph as a graphviz dot file. Takes care of circular dependencies. Not threadsafe.
*/
public class DotPrinter extends PrintStream {
private ArrayList<String> printedRelations;
public DotPrinter(OutputStream out) {
super(out);
}
public void print(Graph g) {
printedRelations = new ArrayList<String>();
println("digraph \"" + g.getName() + "\" {");
println("graph [size=100,100];");
for (ClassModel cm : g.getChildren()) {
print(cm);
}
println("}");
close();
}
private void print(ClassModel cm) {
double boxsize = Math.sqrt(Statistics.getByteCodeSizeForClass(cm.getName()));
print("\"");
print(cm.getName());
println("\" [shape=box, height=" + boxsize / 20 + "];");
if (cm.getReferences() == null || cm.getReferences().size() == 0) {
print("\"");
print(cm.getName());
println("\";");
} else {
for (ClassModel ref : cm.getReferences()) {
String relation = cm.getName() + "-" + ref.getName();
if (!printedRelations.contains(relation)) {
print("\"");
print(cm.getName());
print("\" -> \"");
print(ref.getName());
println("\"");
printedRelations.add(relation);
print(ref);
}
}
}
}
}

View file

@ -8,14 +8,9 @@ import javassist.ClassPath;
import javassist.ClassPool;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
import yooze.scanner.ArchiveScanner;
import yooze.scanner.LibScanner;
import yooze.scanner.Scanner;
import yooze.scanner.TgzScanner;
/**
* Builds a class dependency graph from given classpath. Delegates to
* ClassModelBuilder.
* Builds a class dependency graph from given classpath. Delegates to ClassModelBuilder.
*/
public class GraphBuilder {
private Scanner scanner;
@ -23,83 +18,67 @@ public class GraphBuilder {
private String[] packageIncludePatterns;
private String[] packageExcludePatterns;
/**
* Factory method for getting a builder that does earfiles
*/
public static GraphBuilder getEarBuilder() {
return new GraphBuilder(new ArchiveScanner());
}
/**
* Factory method for getting a builder that does (downloaded) .tar.gz files
*/
public static GraphBuilder getDefaultTgzBuilder() {
GraphBuilder tgzBuilder = new GraphBuilder(new TgzScanner());
tgzBuilder.setPackageExcludePatterns("java.*", "sun.*", "com.sun.*");
return tgzBuilder;
}
/**
* Factory method for getting a builder that scans a lib directory
* (containing jars)
*/
public static GraphBuilder getLibDirectoryBuilder() {
return new GraphBuilder(new LibScanner());
}
/**
* Factory method for getting a builder that scans a directory containing
* classes
*/
public static GraphBuilder getClassesDirectoryBuilder() {
return new GraphBuilder(new ClassesDirScanner());
}
private GraphBuilder(Scanner scanner) {
public GraphBuilder(Scanner scanner) {
this.scanner = scanner;
}
/**
* primary function for this class.
* Builds a graph from a give starting point(class)
*
* @param archiveFilename
* @param className
* the name of the class that is the starting point. Only classes referenced from here will be included.
* @return a Graph containing all calculated dependencies
* @throws IOException
* when file reading fails
*/
public Graph build(String archiveFilename, String className) throws IOException {
return buildClassDepencyGraph(new File(archiveFilename), className, new IncludeDecision() {
public boolean shouldIncludeClass(String name, String startingpointname) {
return name.equals(startingpointname);
}
});
}
/**
* Builds a graph for all classes (all included via package patterns and not excluded)
*
* @param archiveFilename
* @return a Graph containing all calculated dependencies
* @throws IOException
* when file reading fails
*/
public Graph build(String archiveFilename, String className)
throws IOException {
return buildClassDepencyGraph(new File(archiveFilename), className);
public Graph build(String archiveFilename) throws IOException {
return buildClassDepencyGraph(new File(archiveFilename), null, new IncludeDecision() {
public boolean shouldIncludeClass(String name, String startingpointname) {
return true;
}
});
}
Graph buildClassDepencyGraph(File archiveFile, String className)
throws IOException {
List<ClassPath> cpList = scanner.scanArchive(archiveFile);
Graph buildClassDepencyGraph(File archiveFile, String className, IncludeDecision e) throws IOException {
List<InspectableClasspath> cpList = scanner.scanArchive(archiveFile);
ClassPool pool = ClassPool.getDefault();
for (ClassPath cp : cpList) {
pool.appendClassPath(cp);
}
Graph graph = createClassDependencyGraph(pool, cpList, className);
Graph graph = createClassDependencyGraph(pool, cpList, className, e);
graph.setName(archiveFile.getName());
return graph;
}
private Graph createClassDependencyGraph(ClassPool pool,
List<ClassPath> classpath, String className) {
private Graph createClassDependencyGraph(ClassPool pool, List<InspectableClasspath> classpath, String className,
IncludeDecision decide) {
Graph graph = new Graph();
classModelBuilder = new ClassModelBuilder(pool);
classModelBuilder.setPackageExcludePatterns(packageExcludePatterns);
classModelBuilder.setPackageIncludePatterns(packageIncludePatterns);
for (ClassPath lib : classpath) {
assert (lib instanceof Inspectable);
List<String> classes = ((Inspectable) lib).getClasses();
for (String name : classes) {
if (name.equals(className)) {
ClassModel newModel = classModelBuilder
.scanClassOrSkip(className);
for (InspectableClasspath lib : classpath) {
for (String name : lib.getClasses()) {
if (decide.shouldIncludeClass(name, className)) {
ClassModel newModel = classModelBuilder.scanClassOrSkip(className);
if (newModel != null) {
graph.add(newModel);
}
@ -117,4 +96,7 @@ public class GraphBuilder {
this.packageExcludePatterns = packageExcludePatterns;
}
interface IncludeDecision {
boolean shouldIncludeClass(String name, String startingpointname);
}
}

View file

@ -1,8 +0,0 @@
package yooze;
import java.util.List;
public interface Inspectable {
public String getResourceName();
public List<String> getClasses();
}

View file

@ -1,78 +0,0 @@
package yooze;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import javassist.ClassPath;
import javassist.NotFoundException;
public class JarClassPath implements ClassPath, Inspectable {
private final JarFile jar;
public JarClassPath(JarFile jar) {
super();
this.jar = jar;
}
public void close() {
try {
jar.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public URL find(String className) {
try {
return new URL("file:///"+jar.getName()+"!"+Util.toClassResource(className));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return "JarClasspath[" + jar.getName() + "]";
}
public List<String> getClasses() {
List<String> classes = new ArrayList<String>();
for (Enumeration<JarEntry> entries = jar.entries(); entries
.hasMoreElements();) {
String name = entries.nextElement().getName().replaceAll("/", ".");
if (name.endsWith(".class")) {
classes.add(name.substring(0, name.length() - 6));
}
}
return classes;
}
public String getResourceName() {
return jar.getName();
}
@Override
public InputStream openClassfile(String className) throws NotFoundException {
ZipEntry entry = jar.getEntry(Util.toClassResource(className));
if (entry == null) {
return null;
}
try {
return new ClassByteCountingInputStream(className,jar.getInputStream(entry));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -19,10 +19,9 @@ public class MethodCallModel {
public MethodModel getCalledMethod() {
try {
ParameterList parameterList = ParameterList.create(methodCall.getMethod());
return MethodCache.getInstance().get(
createQualifiedMethodname(parameterList));
return MethodCache.getInstance().get(createQualifiedMethodname(parameterList));
} catch (NotFoundException e) {
throw new RuntimeException(e);
throw new MethodNotFound(e);
}
}

View file

@ -1,48 +0,0 @@
package yooze.etc;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import yooze.Util;
import yooze.domain.ClassModel;
import javassist.ClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.bytecode.ConstPool;
/**
* @deprecated does not seem to be in use
*
*/
public class ClassBuilder {
private final ConcurrentHashMap<String, ClassModel> classes = new ConcurrentHashMap<String, ClassModel>();
private ClassPool pool = ClassPool.getDefault();
private ClassBuilder(List<ClassPath> classpaths) {
super();
for (ClassPath cpEntry : classpaths) {
pool.appendClassPath(cpEntry);
}
}
public ClassModel load(String className) throws NotFoundException {
ClassModel model;
if ((model = classes.get(className)) != null) {
return model;
}
CtClass ctClass = pool.getCtClass(className);
model = new ClassModel(className);
ConstPool constPool = ctClass.getClassFile().getConstPool();
for (Iterator<?> classNames = constPool.getClassNames().iterator(); classNames.hasNext();) {
model.addReference(load(Util.toClassName(classNames.next().toString())));
}
return model;
}
}

View file

@ -1,89 +0,0 @@
package yooze.etc;
import java.util.concurrent.ConcurrentHashMap;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import yooze.domain.ClassModel;
public class Neo4jDao {
private GraphDatabaseService graphDb;
private Node rootNode;
private ConcurrentHashMap<String, Node> nodes = new ConcurrentHashMap<String, Node>();
public enum MyRelationshipTypes implements RelationshipType {
CONTAINS, REFERENCES
}
public Neo4jDao(String database) {
graphDb = new EmbeddedGraphDatabase(database);
Transaction tx = graphDb.beginTx();
try {
rootNode = graphDb.createNode();
rootNode.setProperty("name", "root");
tx.success();
} finally {
tx.finish();
}
}
public void insertClass(ClassModel classModel) {
Transaction tx = graphDb.beginTx();
try {
Node newNode = findOrCreateNode(classModel);
for (ClassModel ref : classModel.getReferences()) {
Node refNode = findOrCreateNode(ref);
newNode.createRelationshipTo(refNode,
MyRelationshipTypes.REFERENCES);
}
tx.success();
} finally {
tx.finish();
}
}
private Node findOrCreateNode(ClassModel classModel) {
Node newNode = findNode(classModel.getName());
if (newNode == null) {
Transaction tx = graphDb.beginTx();
try {
newNode = graphDb.createNode();
newNode.setProperty("name", classModel.getName());
tx.success();
} finally {
tx.finish();
}
}
return newNode;
}
public Node findNode(String className) {
Node node = nodes.get(className);
if (node != null) {
return node;
}
// do "tablescan". is there a better way?
Traverser classesTraverser = rootNode.traverse(
Traverser.Order.BREADTH_FIRST, StopEvaluator.DEPTH_ONE,
ReturnableEvaluator.ALL_BUT_START_NODE,
MyRelationshipTypes.CONTAINS, Direction.OUTGOING);
for (Node nextNode : classesTraverser) {
if (nextNode.getProperty("name").equals(className)) {
nodes.put(className, nextNode);
return nextNode;
}
}
return null;// not found
}
}

View file

@ -1,43 +0,0 @@
package yooze.etc;
import java.io.IOException;
import yooze.GraphBuilder;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
public class Yooze {
private String neo4jDb;
public static void main(String[] args) throws IOException {
String neoDb = args[0];
String earfile = args[1];
String in = args[2];
String ex = args[2];
String startingClassname = args[3];
new Yooze(neoDb).createNeoGraph(earfile, in, ex, startingClassname);
}
public Yooze(String neo4jDb) {
super();
this.neo4jDb = neo4jDb;
}
public void createNeoGraph(String archive, String packageIncludePatterns,
String packageExcludePatterns, String startingClass)
throws IOException {
GraphBuilder libDirectoryBuilder = GraphBuilder
.getLibDirectoryBuilder();
libDirectoryBuilder.setPackageExcludePatterns(packageExcludePatterns);
libDirectoryBuilder.setPackageIncludePatterns(packageIncludePatterns);
Graph graph = libDirectoryBuilder.build(archive, startingClass);
Neo4jDao neo4jDao = new Neo4jDao(neo4jDb);
for (ClassModel model : graph.getChildren()) {
neo4jDao.insertClass(model);
}
}
}

View file

@ -1,7 +1,6 @@
package yooze.scanner;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@ -9,40 +8,62 @@ import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import javassist.ClassPath;
import org.apache.commons.io.IOUtils;
import yooze.DirClassPath;
import yooze.JarClassPath;
import yooze.InspectableClasspath;
import yooze.Scanner;
import yooze.Util;
/**
* @author shautvast TODO separate models for wars
* TODO separate models for wars
*/
public class ArchiveScanner implements Scanner {
private final static Pattern classPattern = Pattern.compile("WEB-INF/classes/(.*)\\.class");
private final static Pattern packagePattern = Pattern.compile("(.+\\/+)(.+\\.class)");
private WarScanner warScanner;
public List<ClassPath> scanArchive(String archiveName) throws IOException {
public ArchiveScanner(WarScanner warScanner) {
this.warScanner = warScanner;
}
public List<InspectableClasspath> scanArchive(String archiveName) {
return scanArchive(new File(archiveName));
}
public List<ClassPath> scanArchive(File archiveFile) throws IOException {
List<ClassPath> result = new ArrayList<ClassPath>();
public List<InspectableClasspath> scanArchive(File archiveFile) {
List<InspectableClasspath> result = new ArrayList<InspectableClasspath>();
if (!archiveFile.exists()) {
return result;
}
if (archiveFile.isDirectory()) {
return directoryAsClasspath(archiveFile, result);
} else {
JarFile archive = createJar(archiveFile);
if (isEarFile(archive)) {
result.addAll(scanRoot(archive));
result.addAll(warScanner.scanWars(getWars(archive)));
} else if (isWarFile(archive)) {
result.addAll(warScanner.scanWars(Arrays.asList(new JarFile[] { archive })));
} else {
// treat as jar file
result.add(new JarClassPath(archive));
}
return result;
}
}
private boolean isWarFile(JarFile archive) {
return archive.getName().endsWith(".war");
}
private boolean isEarFile(JarFile archive) {
return archive.getName().endsWith(".ear");
}
private List<InspectableClasspath> directoryAsClasspath(File archiveFile, List<InspectableClasspath> result) {
File[] list = archiveFile.listFiles();
for (File entry : list) {
if (entry.getName().endsWith(".jar")) {
result.add(new JarClassPath(new JarFile(entry)));
result.add(new JarClassPath(createJar(entry)));
} else if (entry.getName().endsWith(".class")) {
result.add(new DirClassPath(archiveFile));
break;
@ -52,102 +73,12 @@ public class ArchiveScanner implements Scanner {
return result;
}
JarFile archive = new JarFile(archiveFile);
if (archive.getName().endsWith(".ear")) {
result.addAll(scanRoot(archive));
result.addAll(scanWars(getWars(archive)));
} else if (archive.getName().endsWith(".war")) {
result.addAll(scanWars(Arrays.asList(new JarFile[] { archive })));
} else {
// treat as jar file
result.add(new JarClassPath(archive));
}
return result;
}
private List<ClassPath> scanWars(List<JarFile> wars) {
List<ClassPath> classpaths = new ArrayList<ClassPath>();
for (JarFile war : wars) {
classpaths.addAll(scanWar(war));
}
return classpaths;
}
private List<ClassPath> scanWar(JarFile warfile) {
List<ClassPath> classpaths = new ArrayList<ClassPath>();
File classesDir = createTempLocation(classpaths);
classpaths.add(new DirClassPath(classesDir));
for (Enumeration<JarEntry> entries = warfile.entries(); entries.hasMoreElements();) {
JarEntry entry = (JarEntry) entries.nextElement();
if (isArchive(entry)) {
private JarFile createJar(File archiveFile) {
try {
addToClasspath(warfile, classpaths, entry);
return new JarFile(archiveFile);
} catch (IOException e) {
throw new RuntimeException(e);
throw new JarCouldNotBeCreated(archiveFile.getAbsolutePath());
}
} else {
extractClass(warfile, entry, classesDir);
}
}
return classpaths;
}
private File createTempLocation(List<ClassPath> classpaths) {
File classesDir = new File(new File(System.getProperty("java.io.tmpdir")), "classes"
+ System.currentTimeMillis());
boolean dirsMade = classesDir.mkdirs();
if (!dirsMade) {
throw new RuntimeException("Directory " + classesDir + " could not be created");
}
return classesDir;
}
private void addToClasspath(JarFile warfile, List<ClassPath> classpaths, JarEntry entry) throws IOException {
File jarFile = Util.extractFile(warfile, entry);
classpaths.add(new JarClassPath(new JarFile(jarFile)));
}
private boolean isArchive(JarEntry entry) {
String name = entry.getName();
return name.startsWith("WEB-INF/lib") && name.endsWith(".jar");
}
private File extractClass(JarFile warfile, ZipEntry entry, File classesDir) {
Matcher matcher = classPattern.matcher(entry.getName());
if (matcher.matches()) {
String className = matcher.group(1) + ".class";
Matcher matcher2 = packagePattern.matcher(className);
if (matcher2.matches()) {
String packageName = matcher2.group(1);
File classDir = createUnarchivedPackageDicectory(classesDir, packageName);
String simpleClassName = matcher2.group(2);
File classFile = new File(classDir, simpleClassName);
return createUnarchivedClassfile(warfile, entry, classFile);
}
}
return null;
}
private File createUnarchivedClassfile(JarFile warfile, ZipEntry entry, File classFile) {
try {
FileOutputStream out = new FileOutputStream(classFile);
IOUtils.copy(warfile.getInputStream(entry), out);
return classFile;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private File createUnarchivedPackageDicectory(File classesDir, String packageName) {
File classDir = new File(classesDir, packageName);
if (!classDir.exists()) {
boolean packageDirsMade = classDir.mkdirs();
if (!packageDirsMade) {
throw new RuntimeException("Directory " + classDir + " could not be created");
}
}
return classDir;
}
private List<JarFile> getWars(JarFile earfile) {
@ -170,13 +101,13 @@ public class ArchiveScanner implements Scanner {
return entry.getName().endsWith(".war");
}
private List<ClassPath> scanRoot(JarFile earfile) {
List<ClassPath> classpaths = new ArrayList<ClassPath>();
private List<InspectableClasspath> scanRoot(JarFile earfile) {
List<InspectableClasspath> classpaths = new ArrayList<InspectableClasspath>();
for (Enumeration<JarEntry> entries = earfile.entries(); entries.hasMoreElements();) {
JarEntry entry = (JarEntry) entries.nextElement();
if (isJarfile(entry)) {
try {
addToClasspath(earfile, classpaths, entry);
ClasspathAdder.addEntriesFromWarToClasspath(earfile, classpaths, entry);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -189,4 +120,10 @@ public class ArchiveScanner implements Scanner {
return entry.getName().endsWith(".jar");
}
@SuppressWarnings("serial")
private static class JarCouldNotBeCreated extends RuntimeException {
public JarCouldNotBeCreated(String name) {
super(name);
}
}
}

View file

@ -6,33 +6,30 @@ import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarFile;
import yooze.JarClassPath;
import javassist.ClassPath;
import yooze.InspectableClasspath;
import yooze.Scanner;
/**
* Scans a directory ("lib") recursively for jarfiles and adds them to the
* classpath
*
* @author sander
*
* Scans a directory ("lib") recursively for jarfiles and adds them to the classpath
*/
public class LibScanner implements Scanner {
@Override
public List<ClassPath> scanArchive(String archiveName) throws IOException {
public List<InspectableClasspath> scanArchive(String archiveName) throws IOException {
return scanArchive(new File(archiveName));
}
@Override
public List<ClassPath> scanArchive(File file) throws IOException {
List<ClassPath> classpaths = new ArrayList<ClassPath>();
public List<InspectableClasspath> scanArchive(File file) throws IOException {
List<InspectableClasspath> classpaths = new ArrayList<InspectableClasspath>();
return doScanArchive(classpaths, file);
}
private List<ClassPath> doScanArchive(List<ClassPath> classpaths, File file)
/*
* return argument classpaths for sake of recursion
*/
private List<InspectableClasspath> doScanArchive(List<InspectableClasspath> classpaths, File file)
throws IOException {
File[] entries = file.listFiles();
for (File entry : entries) {
if (entry.isDirectory()) {
@ -43,5 +40,4 @@ public class LibScanner implements Scanner {
}
return classpaths;
}
}

View file

@ -1,13 +0,0 @@
package yooze.scanner;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javassist.ClassPath;
public interface Scanner {
public List<ClassPath> scanArchive(String archiveName) throws IOException;
public List<ClassPath> scanArchive(File file) throws IOException;
}

View file

@ -11,34 +11,32 @@ import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.GZIPInputStream;
import javassist.ClassPath;
import org.xeustechnologies.jtar.TarEntry;
import org.xeustechnologies.jtar.TarInputStream;
import yooze.JarClassPath;
import yooze.InspectableClasspath;
import yooze.Scanner;
/**
* @author sander
*
*/
public class TgzScanner implements Scanner {
public List<ClassPath> scanArchive(String archiveName) throws IOException {
public List<InspectableClasspath> scanArchive(String archiveName) throws IOException {
return scanArchive(new File(archiveName));
}
public List<ClassPath> scanArchive(File file) throws IOException {
List<ClassPath> classpaths = new ArrayList<ClassPath>();
TarInputStream tarInputStream = new TarInputStream(new GZIPInputStream(
new BufferedInputStream(new FileInputStream(file))));
public List<InspectableClasspath> scanArchive(File file) throws IOException {
List<InspectableClasspath> classpaths = new ArrayList<InspectableClasspath>();
TarInputStream tarInputStream = new TarInputStream(new GZIPInputStream(new BufferedInputStream(
new FileInputStream(file))));
TarEntry entry;
while ((entry = tarInputStream.getNextEntry()) != null) {
if (entry.getName().endsWith(".jar")) {
int count;
byte data[] = new byte[2048];
File tempFile = File.createTempFile(
singleName(entry.getName()), ".jar");
File tempFile = File.createTempFile(singleName(entry.getName()), ".jar");
FileOutputStream fos = new FileOutputStream(tempFile);
BufferedOutputStream dest = new BufferedOutputStream(fos);

View file

@ -1,22 +0,0 @@
package yooze;
import java.util.Iterator;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.bytecode.ConstPool;
public class AssTest {
public static void main(String[] args) throws NotFoundException {
ClassPool pool = ClassPool.getDefault();
CtClass c1 = pool.get("yooze.Class1");
ConstPool constPool = c1.getClassFile().getConstPool();
for (Iterator iterator = constPool.getClassNames().iterator();iterator.hasNext();){
System.out.println(iterator.next());
}
}
}

View file

@ -1,80 +0,0 @@
package yooze;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.domain.Graph;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
public class DotPrinterTest {
@Before
public void clearClassCache() {
ClassCache.clear();
}
@Test
public void dotPrinting() throws IOException {
GraphBuilder directoryBuilder = GraphBuilder
.getClassesDirectoryBuilder();
directoryBuilder.setPackageExcludePatterns(".*?Class4");
directoryBuilder.setPackageIncludePatterns(".*?.Class.");
Graph graph = directoryBuilder.build("target/test-classes",
"yooze.Class1");
ByteArrayOutputStream bytes = new ByteArrayOutputStream(500);
DotPrinter d = new DotPrinter(bytes);
d.print(graph);
String dotText = new String(bytes.toByteArray());
d.close();
String[] expectedDotTextLines = { "digraph \"test-classes\" {",
"graph [size=100,100];",
"\"yooze.Class1\" [shape=box, height=0.0];",
"\"yooze.Class1\" -> \"yooze.Class2\"",
"\"yooze.Class2\" [shape=box, height=0.0];",
"\"yooze.Class2\" -> \"yooze.Class3\"",
"\"yooze.Class3\" [shape=box, height=0.0];",
"\"yooze.Class3\" -> \"yooze.Class1\"",
"\"yooze.Class1\" [shape=box, height=0.0];",
"\"yooze.Class2\" [shape=box, height=0.0];",
"\"yooze.Class3\" [shape=box, height=0.0];", "}" };
expectTextContainsLines(dotText, expectedDotTextLines);
}
private void expectTextContainsLines(String dotText,
String[] expectedDotTextLines) {
for (String line : expectedDotTextLines) {
Assert.assertTrue("Not found:" + line, dotText.contains(line));
}
}
@Test
public void noReference() throws IOException {
GraphBuilder directoryBuilder = GraphBuilder
.getClassesDirectoryBuilder();
directoryBuilder.setPackageExcludePatterns("");
directoryBuilder.setPackageIncludePatterns("yooze.Class4");
Graph graph = directoryBuilder.build("target/test-classes",
"yooze.Class4");
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
DotPrinter d = new DotPrinter(bytes);
d.print(graph);
String dotText = new String(bytes.toByteArray());
System.out.println(dotText);
String[] expectedDotTextLines = { "digraph \"test-classes\" {",
"graph [size=100,100];",
"\"yooze.Class4\" [shape=box, height=0.0];",
"\"yooze.Class4\";", "}" };
d.close();
expectTextContainsLines(dotText, expectedDotTextLines);
}
}

View file

@ -1,50 +0,0 @@
package yooze;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import javassist.ClassPath;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.scanner.ArchiveScanner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
public class EarScannerTest {
@Autowired
private Config config;
@Test
public void scanner() throws IOException {
List<ClassPath> classpaths = new ArchiveScanner().scanArchive(config
.getEarFile());
for (ClassPath path : classpaths) {
if (path instanceof DirClassPath) {
List<String> classes = ((Inspectable) path).getClasses();
assertThat(classes.size(), is(49));
}
if (path instanceof JarClassPath) {
String name = ((Inspectable) path).getResourceName();
if (name.contains("standard")) {
List<String> classes = ((Inspectable) path).getClasses();
assertTrue(classes.contains("org.apache.taglibs.standard.tag.common.sql.DataSourceUtil"));
}
}
}
}
public void setConfig(Config config) {
this.config = config;
}
}

View file

@ -12,6 +12,7 @@ import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.application.GraphBuilderFactory;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
@ -28,7 +29,7 @@ public class GraphTest {
public void buildGraph() throws IOException {
// new Yooze("/tmp/test").createNeoGraph("target/test-classes",
// ".*?.Class.");
GraphBuilder libDirectoryBuilder = GraphBuilder
GraphBuilder libDirectoryBuilder = GraphBuilderFactory
.getClassesDirectoryBuilder();
libDirectoryBuilder.setPackageIncludePatterns(".*?.Class.");
libDirectoryBuilder.setPackageExcludePatterns("");

View file

@ -9,7 +9,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.application.GraphBuilderFactory;
import yooze.domain.Graph;
import yooze.output.DotPrinter;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
@ -20,7 +22,7 @@ public class LargePackageTest {
@Test
public void largePackage() throws IOException {
GraphBuilder earBuilder = GraphBuilder.getEarBuilder();
GraphBuilder earBuilder = GraphBuilderFactory.getEarBuilder();
earBuilder.setPackageIncludePatterns("");
earBuilder.setPackageExcludePatterns("java.*");
Graph graph = earBuilder.buildClassDepencyGraph(config.getEarFile(),

View file

@ -13,7 +13,7 @@ import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.domain.Graph;
import yooze.application.GraphBuilderFactory;
import yooze.domain.MethodModel;
import yooze.dto.MethodDto;
@ -22,22 +22,18 @@ import yooze.dto.MethodDto;
public class MethodReferencesTest {
@Test
public void test() throws IOException {
GraphBuilder directoryBuilder = GraphBuilder
.getClassesDirectoryBuilder();
GraphBuilder directoryBuilder = GraphBuilderFactory.getClassesDirectoryBuilder();
directoryBuilder.setPackageIncludePatterns("yooze.Class.*");
Graph graph = directoryBuilder.build("target/test-classes",
"yooze.Class1");
MethodModel mm1 = MethodCache.getInstance()
.get("yooze.Class1.rup(int)");
directoryBuilder.build("target/test-classes", "yooze.Class1");
MethodModel mm1 = MethodCache.getInstance().get("yooze.Class1.rup(int)");
Assert.assertNotNull(mm1);
MethodModel mm2 = MethodCache.getInstance().get("yooze.Class3.dof()");
Assert.assertNotNull(mm2);
List<MethodModel> callers = mm1.getCallers();
Assert.assertTrue(callers.contains(mm2));
MethodDto dto = MethodDto.create(MethodCache.getInstance().get(
"yooze.Class1.zoef(yooze.Class2)"));
JsonGenerator jg = new ObjectMapper().getJsonFactory()
.createJsonGenerator(new FileOutputStream("c:\\ff\\out.json"));
MethodDto dto = MethodDto.create(MethodCache.getInstance().get("yooze.Class1.zoef(yooze.Class2)"));
JsonGenerator jg = new ObjectMapper().getJsonFactory().createJsonGenerator(
new FileOutputStream("c:\\ff\\out.json"));
jg.writeObject(dto);
jg.close();
}

View file

@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import yooze.application.GraphBuilderFactory;
import yooze.domain.ClassModel;
import yooze.domain.Graph;
@ -23,7 +24,7 @@ public class TgzBuilderTest {
@Test
public void tgzBuilder() throws IOException {
GraphBuilder tgzBuilder = GraphBuilder.getDefaultTgzBuilder();
GraphBuilder tgzBuilder = GraphBuilderFactory.getDefaultTgzBuilder();
tgzBuilder.setPackageIncludePatterns("nl.*");
tgzBuilder.setPackageExcludePatterns("");
Graph graph = tgzBuilder.buildClassDepencyGraph(config.getTgzFile(),