diff --git a/README.md b/README.md
index 3ee3dd0..de6cfd6 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/example.png b/example.png
deleted file mode 100644
index 87962ed..0000000
Binary files a/example.png and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 02f2ab1..ce48f6a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
jar
0.1-SNAPSHOT
yooze
- www.cjib.nl
+ http://jssl.org/yooze
@@ -130,6 +130,12 @@
jackson-mapper-asl
1.9.10
+
+ org.mockito
+ mockito-core
+ 1.9.5
+ test
+
diff --git a/src/main/java/yooze/ClassModelBuilder.java b/src/main/java/yooze/ClassModelBuilder.java
index b25ef73..25ab100 100644
--- a/src/main/java/yooze/ClassModelBuilder.java
+++ b/src/main/java/yooze/ClassModelBuilder.java
@@ -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;
- }
+ return tryScan(className, model);
}
- 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 classNames = constPool.getClassNames();
for (String classResourcename : classNames) {
diff --git a/src/main/java/yooze/ClassesDirScanner.java b/src/main/java/yooze/ClassesDirScanner.java
deleted file mode 100644
index 724cddd..0000000
--- a/src/main/java/yooze/ClassesDirScanner.java
+++ /dev/null
@@ -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 scanArchive(String archiveName) throws IOException {
- return scanArchive(new File(archiveName));
- }
-
- @Override
- public List scanArchive(File file) throws IOException {
- List result = new ArrayList();
- result.add(new DirClassPath(file));
- return result;
- }
-
-}
diff --git a/src/main/java/yooze/DirClassPath.java b/src/main/java/yooze/DirClassPath.java
deleted file mode 100644
index bc1c88c..0000000
--- a/src/main/java/yooze/DirClassPath.java
+++ /dev/null
@@ -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 getClasses() {
- List classes = new ArrayList();
- getClasses(dir, dir, classes);
- return classes;
- }
-
- private void getClasses(File root, File dir, List 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);
- }
- }
-}
diff --git a/src/main/java/yooze/DotPrinter.java b/src/main/java/yooze/DotPrinter.java
deleted file mode 100644
index a0f809b..0000000
--- a/src/main/java/yooze/DotPrinter.java
+++ /dev/null
@@ -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 printedRelations;
-
- public DotPrinter(OutputStream out) {
- super(out);
- }
-
- public void print(Graph g) {
- printedRelations = new ArrayList();
- 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);
- }
- }
- }
- }
-
-}
diff --git a/src/main/java/yooze/GraphBuilder.java b/src/main/java/yooze/GraphBuilder.java
index 48b067a..b5b2e4f 100644
--- a/src/main/java/yooze/GraphBuilder.java
+++ b/src/main/java/yooze/GraphBuilder.java
@@ -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 cpList = scanner.scanArchive(archiveFile);
+ Graph buildClassDepencyGraph(File archiveFile, String className, IncludeDecision e) throws IOException {
+ List 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, String className) {
+ private Graph createClassDependencyGraph(ClassPool pool, List 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 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);
+ }
}
diff --git a/src/main/java/yooze/Inspectable.java b/src/main/java/yooze/Inspectable.java
deleted file mode 100644
index 07bb261..0000000
--- a/src/main/java/yooze/Inspectable.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package yooze;
-
-import java.util.List;
-
-public interface Inspectable {
- public String getResourceName();
- public List getClasses();
-}
diff --git a/src/main/java/yooze/JarClassPath.java b/src/main/java/yooze/JarClassPath.java
deleted file mode 100644
index 27712d6..0000000
--- a/src/main/java/yooze/JarClassPath.java
+++ /dev/null
@@ -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 getClasses() {
- List classes = new ArrayList();
- for (Enumeration 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);
- }
- }
-}
diff --git a/src/main/java/yooze/domain/MethodCallModel.java b/src/main/java/yooze/domain/MethodCallModel.java
index 5c1fccd..5887c42 100644
--- a/src/main/java/yooze/domain/MethodCallModel.java
+++ b/src/main/java/yooze/domain/MethodCallModel.java
@@ -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);
}
}
diff --git a/src/main/java/yooze/etc/ClassBuilder.java b/src/main/java/yooze/etc/ClassBuilder.java
deleted file mode 100644
index 2751b28..0000000
--- a/src/main/java/yooze/etc/ClassBuilder.java
+++ /dev/null
@@ -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 classes = new ConcurrentHashMap();
-
- private ClassPool pool = ClassPool.getDefault();
-
- private ClassBuilder(List 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;
-
- }
-}
diff --git a/src/main/java/yooze/etc/Neo4jDao.java b/src/main/java/yooze/etc/Neo4jDao.java
deleted file mode 100644
index ad08c2d..0000000
--- a/src/main/java/yooze/etc/Neo4jDao.java
+++ /dev/null
@@ -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 nodes = new ConcurrentHashMap();
-
- 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
-
- }
-}
diff --git a/src/main/java/yooze/etc/Yooze.java b/src/main/java/yooze/etc/Yooze.java
deleted file mode 100644
index b6c0ce9..0000000
--- a/src/main/java/yooze/etc/Yooze.java
+++ /dev/null
@@ -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);
- }
- }
-
-}
diff --git a/src/main/java/yooze/scanner/ArchiveScanner.java b/src/main/java/yooze/scanner/ArchiveScanner.java
index 6f14aa4..db300aa 100644
--- a/src/main/java/yooze/scanner/ArchiveScanner.java
+++ b/src/main/java/yooze/scanner/ArchiveScanner.java
@@ -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,147 +8,79 @@ 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 scanArchive(String archiveName) throws IOException {
+ public ArchiveScanner(WarScanner warScanner) {
+ this.warScanner = warScanner;
+ }
+
+ public List scanArchive(String archiveName) {
return scanArchive(new File(archiveName));
}
- public List scanArchive(File archiveFile) throws IOException {
- List result = new ArrayList();
+ public List scanArchive(File archiveFile) {
+ List result = new ArrayList();
if (!archiveFile.exists()) {
return result;
}
if (archiveFile.isDirectory()) {
- File[] list = archiveFile.listFiles();
- for (File entry : list) {
- if (entry.getName().endsWith(".jar")) {
- result.add(new JarClassPath(new JarFile(entry)));
- } else if (entry.getName().endsWith(".class")) {
- result.add(new DirClassPath(archiveFile));
- break;
- }
- }
+ 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;
}
+ }
- JarFile archive = new JarFile(archiveFile);
- if (archive.getName().endsWith(".ear")) {
- result.addAll(scanRoot(archive));
- result.addAll(scanWars(getWars(archive)));
+ private boolean isWarFile(JarFile archive) {
+ return archive.getName().endsWith(".war");
+ }
- } else if (archive.getName().endsWith(".war")) {
- result.addAll(scanWars(Arrays.asList(new JarFile[] { archive })));
- } else {
- // treat as jar file
- result.add(new JarClassPath(archive));
+ private boolean isEarFile(JarFile archive) {
+ return archive.getName().endsWith(".ear");
+ }
+
+ private List directoryAsClasspath(File archiveFile, List result) {
+ File[] list = archiveFile.listFiles();
+ for (File entry : list) {
+ if (entry.getName().endsWith(".jar")) {
+ result.add(new JarClassPath(createJar(entry)));
+ } else if (entry.getName().endsWith(".class")) {
+ result.add(new DirClassPath(archiveFile));
+ break;
+ }
}
+
return result;
}
- private List scanWars(List wars) {
- List classpaths = new ArrayList();
- for (JarFile war : wars) {
- classpaths.addAll(scanWar(war));
- }
- return classpaths;
- }
-
- private List scanWar(JarFile warfile) {
- List classpaths = new ArrayList();
- File classesDir = createTempLocation(classpaths);
- classpaths.add(new DirClassPath(classesDir));
- for (Enumeration entries = warfile.entries(); entries.hasMoreElements();) {
- JarEntry entry = (JarEntry) entries.nextElement();
- if (isArchive(entry)) {
- try {
- addToClasspath(warfile, classpaths, entry);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- } else {
- extractClass(warfile, entry, classesDir);
- }
- }
- return classpaths;
- }
-
- private File createTempLocation(List 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 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) {
+ private JarFile createJar(File archiveFile) {
try {
- FileOutputStream out = new FileOutputStream(classFile);
- IOUtils.copy(warfile.getInputStream(entry), out);
- return classFile;
+ return new JarFile(archiveFile);
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new JarCouldNotBeCreated(archiveFile.getAbsolutePath());
}
}
- 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 getWars(JarFile earfile) {
List wars = new ArrayList();
for (Enumeration entries = earfile.entries(); entries.hasMoreElements();) {
@@ -170,13 +101,13 @@ public class ArchiveScanner implements Scanner {
return entry.getName().endsWith(".war");
}
- private List scanRoot(JarFile earfile) {
- List classpaths = new ArrayList();
+ private List scanRoot(JarFile earfile) {
+ List classpaths = new ArrayList();
for (Enumeration 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);
+ }
+ }
}
diff --git a/src/main/java/yooze/scanner/LibScanner.java b/src/main/java/yooze/scanner/LibScanner.java
index bd0747d..68b1095 100644
--- a/src/main/java/yooze/scanner/LibScanner.java
+++ b/src/main/java/yooze/scanner/LibScanner.java
@@ -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 scanArchive(String archiveName) throws IOException {
+ public List scanArchive(String archiveName) throws IOException {
return scanArchive(new File(archiveName));
}
@Override
- public List scanArchive(File file) throws IOException {
- List classpaths = new ArrayList();
- return doScanArchive(classpaths,file);
+ public List scanArchive(File file) throws IOException {
+ List classpaths = new ArrayList();
+ return doScanArchive(classpaths, file);
}
- private List doScanArchive(List classpaths, File file)
+ /*
+ * return argument classpaths for sake of recursion
+ */
+ private List doScanArchive(List 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;
}
-
}
diff --git a/src/main/java/yooze/scanner/Scanner.java b/src/main/java/yooze/scanner/Scanner.java
deleted file mode 100644
index d7883ae..0000000
--- a/src/main/java/yooze/scanner/Scanner.java
+++ /dev/null
@@ -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 scanArchive(String archiveName) throws IOException;
-
- public List scanArchive(File file) throws IOException;
-}
diff --git a/src/main/java/yooze/scanner/TgzScanner.java b/src/main/java/yooze/scanner/TgzScanner.java
index bb9302d..3f8fd5d 100644
--- a/src/main/java/yooze/scanner/TgzScanner.java
+++ b/src/main/java/yooze/scanner/TgzScanner.java
@@ -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 scanArchive(String archiveName) throws IOException {
+ public List scanArchive(String archiveName) throws IOException {
return scanArchive(new File(archiveName));
}
- public List scanArchive(File file) throws IOException {
- List classpaths = new ArrayList();
- TarInputStream tarInputStream = new TarInputStream(new GZIPInputStream(
- new BufferedInputStream(new FileInputStream(file))));
+ public List scanArchive(File file) throws IOException {
+ List classpaths = new ArrayList();
+ 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);
diff --git a/src/test/java/yooze/AssTest.java b/src/test/java/yooze/AssTest.java
deleted file mode 100644
index 965b95b..0000000
--- a/src/test/java/yooze/AssTest.java
+++ /dev/null
@@ -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());
- }
-
- }
-}
diff --git a/src/test/java/yooze/DotPrinterTest.java b/src/test/java/yooze/DotPrinterTest.java
deleted file mode 100644
index ff3aac6..0000000
--- a/src/test/java/yooze/DotPrinterTest.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/src/test/java/yooze/EarScannerTest.java b/src/test/java/yooze/EarScannerTest.java
deleted file mode 100644
index 5371a74..0000000
--- a/src/test/java/yooze/EarScannerTest.java
+++ /dev/null
@@ -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 classpaths = new ArchiveScanner().scanArchive(config
- .getEarFile());
- for (ClassPath path : classpaths) {
- if (path instanceof DirClassPath) {
- List classes = ((Inspectable) path).getClasses();
- assertThat(classes.size(), is(49));
- }
- if (path instanceof JarClassPath) {
- String name = ((Inspectable) path).getResourceName();
- if (name.contains("standard")) {
- List classes = ((Inspectable) path).getClasses();
- assertTrue(classes.contains("org.apache.taglibs.standard.tag.common.sql.DataSourceUtil"));
- }
- }
- }
- }
-
- public void setConfig(Config config) {
- this.config = config;
- }
-
-}
diff --git a/src/test/java/yooze/GraphTest.java b/src/test/java/yooze/GraphTest.java
index bc0b6ab..10657f9 100644
--- a/src/test/java/yooze/GraphTest.java
+++ b/src/test/java/yooze/GraphTest.java
@@ -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("");
diff --git a/src/test/java/yooze/LargePackageTest.java b/src/test/java/yooze/LargePackageTest.java
index 8451fa8..4407ec3 100644
--- a/src/test/java/yooze/LargePackageTest.java
+++ b/src/test/java/yooze/LargePackageTest.java
@@ -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(),
diff --git a/src/test/java/yooze/MethodReferencesTest.java b/src/test/java/yooze/MethodReferencesTest.java
index f8cb25e..bfb8ae7 100644
--- a/src/test/java/yooze/MethodReferencesTest.java
+++ b/src/test/java/yooze/MethodReferencesTest.java
@@ -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 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();
}
diff --git a/src/test/java/yooze/TgzBuilderTest.java b/src/test/java/yooze/TgzBuilderTest.java
index ae3da15..baf4136 100644
--- a/src/test/java/yooze/TgzBuilderTest.java
+++ b/src/test/java/yooze/TgzBuilderTest.java
@@ -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(),