new
This commit is contained in:
parent
85d2346835
commit
b24a3db5fd
48 changed files with 2061 additions and 0 deletions
BIN
example.png
Normal file
BIN
example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 MiB |
135
pom.xml
Normal file
135
pom.xml
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>nl.yooze</groupId>
|
||||
<artifactId>yooze</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>yooze</name>
|
||||
<url>www.cjib.nl</url>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-test-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>src/testdummies/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j</artifactId>
|
||||
<version>1.4.M06</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
<type>jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>3.0.5.RELEASE</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>3.0.5.RELEASE</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.0.5.RELEASE</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.12.1.GA</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>0.9.29</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.6.1</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>0.9.29</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xeustechnologies</groupId>
|
||||
<artifactId>jtar</artifactId>
|
||||
<version>1.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<version>1.9.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
BIN
src/._main
Normal file
BIN
src/._main
Normal file
Binary file not shown.
30
src/main/java/yooze/ClassByteCountingInputStream.java
Normal file
30
src/main/java/yooze/ClassByteCountingInputStream.java
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ClassByteCountingInputStream extends InputStream {
|
||||
|
||||
private InputStream nestedStream;
|
||||
private String className;
|
||||
private long count=0;
|
||||
|
||||
public ClassByteCountingInputStream(String className,
|
||||
InputStream inputStream) {
|
||||
this.className=className;
|
||||
this.nestedStream=inputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
count++;
|
||||
return nestedStream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
nestedStream.close();
|
||||
Statistics.addBytecodeSizeForClass(className, count);
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/yooze/ClassCache.java
Normal file
28
src/main/java/yooze/ClassCache.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package yooze;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import yooze.domain.ClassModel;
|
||||
|
||||
public class ClassCache {
|
||||
private final static Map<String, ClassModel> entries = new ConcurrentHashMap<String, ClassModel>();
|
||||
|
||||
public static boolean contains(String classname) {
|
||||
return entries.containsKey(classname);
|
||||
}
|
||||
|
||||
public static ClassModel createNewDummyModel(String name) {
|
||||
ClassModel classModel = new ClassModel(name);
|
||||
entries.put(name, classModel);
|
||||
return classModel;
|
||||
}
|
||||
|
||||
public static ClassModel get(String className) {
|
||||
return entries.get(className);
|
||||
}
|
||||
|
||||
public static void add(String className, ClassModel model) {
|
||||
entries.put(className, model);
|
||||
}
|
||||
}
|
||||
177
src/main/java/yooze/ClassModelBuilder.java
Normal file
177
src/main/java/yooze/ClassModelBuilder.java
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
package yooze;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
import javassist.NotFoundException;
|
||||
import javassist.bytecode.ConstPool;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import yooze.domain.ClassModel;
|
||||
import yooze.domain.MethodCallModel;
|
||||
import yooze.domain.MethodModel;
|
||||
|
||||
/**
|
||||
* Builds a ClassModel.
|
||||
*/
|
||||
public class ClassModelBuilder {
|
||||
private static Logger log = LoggerFactory.getLogger(ClassModelBuilder.class);
|
||||
|
||||
private Pattern[] packageIncludePatterns;
|
||||
private Pattern[] packageExcludePatterns;
|
||||
private ClassPool pool;
|
||||
|
||||
public ClassModelBuilder(ClassPool pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
|
||||
public ClassModel scanClassOrSkip(String className) {
|
||||
if (shouldSkip(className))
|
||||
return null;
|
||||
if (ClassCache.contains(className)) {
|
||||
return ClassCache.get(className);
|
||||
}
|
||||
log.info("scanning {}", className);
|
||||
|
||||
return scan(className);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
if (isScannable(ctClass)) {
|
||||
ConstPool constPool = ctClass.getClassFile().getConstPool();
|
||||
|
||||
addClassReferences(model, constPool);
|
||||
addMethods(model, ctClass);
|
||||
resolveMethodReferences();
|
||||
return model;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isScannable(CtClass ctClass) {
|
||||
return !ctClass.isFrozen();
|
||||
}
|
||||
|
||||
private void resolveMethodReferences() {
|
||||
for (MethodModel method : MethodCache.getInstance().getMethods()) {
|
||||
for (MethodCallModel methodCall : method.getMethodCalls()) {
|
||||
MethodModel calledMethod = methodCall.getCalledMethod();
|
||||
if (calledMethod != null && calledMethod != method) {
|
||||
calledMethod.addCaller(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMethods(ClassModel containingClass, CtClass ctClass) {
|
||||
CtMethod[] methods = ctClass.getMethods();
|
||||
for (CtMethod method : methods) {
|
||||
containingClass.addMethod(MethodModel.create(containingClass, method));
|
||||
}
|
||||
}
|
||||
|
||||
private void addClassReferences(ClassModel model, ConstPool constPool) {
|
||||
Set<String> classNames = constPool.getClassNames();
|
||||
for (String classResourcename : classNames) {
|
||||
String refClassName = Util.toClassName(classResourcename);
|
||||
addClassReference(model, refClassName);
|
||||
}
|
||||
}
|
||||
|
||||
private void addClassReference(ClassModel model, String refClassName) {
|
||||
/* recursive invocation */
|
||||
ClassModel scannedClass = scanClassOrSkip(refClassName);
|
||||
if (scannedClass != null && !scannedClass.equals(model)) {
|
||||
model.addReference(scannedClass);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldSkip(String className) {
|
||||
if (!isIncluded(className)) {
|
||||
log.debug("skipping {}", className);
|
||||
return true;
|
||||
}
|
||||
if (isExcluded(className)) {
|
||||
log.debug("skipping {}", className);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if (isInnerClass(className)) {
|
||||
// log.debug("skipping inner class {}", className);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// if (className.equals("java.lang.Object")) {
|
||||
// return true;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isInnerClass(String className) {
|
||||
return className.contains("$");
|
||||
}
|
||||
|
||||
private boolean isExcluded(String className) {
|
||||
if (packageExcludePatterns != null) {
|
||||
for (Pattern excludePattern : packageExcludePatterns) {
|
||||
Matcher matcher = excludePattern.matcher(className);
|
||||
if (matcher.matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isIncluded(String className) {
|
||||
if (packageIncludePatterns != null) {
|
||||
for (Pattern includePattern : packageIncludePatterns) {
|
||||
Matcher matcher = includePattern.matcher(className);
|
||||
if (matcher.matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPackageIncludePatterns(String... packageIncludePatterns) {
|
||||
if (packageIncludePatterns != null) {
|
||||
this.packageIncludePatterns = new Pattern[packageIncludePatterns.length];
|
||||
int i = 0;
|
||||
for (String pattern : packageIncludePatterns) {
|
||||
this.packageIncludePatterns[i++] = Pattern.compile(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPackageExcludePatterns(String... packageExcludePatterns) {
|
||||
if (packageExcludePatterns != null) {
|
||||
this.packageExcludePatterns = new Pattern[packageExcludePatterns.length];
|
||||
int i = 0;
|
||||
for (String pattern : packageExcludePatterns) {
|
||||
this.packageExcludePatterns[i++] = Pattern.compile(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/main/java/yooze/ClassesDirScanner.java
Normal file
28
src/main/java/yooze/ClassesDirScanner.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
90
src/main/java/yooze/DirClassPath.java
Normal file
90
src/main/java/yooze/DirClassPath.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/main/java/yooze/DotPrinter.java
Normal file
59
src/main/java/yooze/DotPrinter.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
105
src/main/java/yooze/GraphBuilder.java
Normal file
105
src/main/java/yooze/GraphBuilder.java
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
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.
|
||||
*/
|
||||
public class GraphBuilder {
|
||||
|
||||
private Scanner scanner;
|
||||
private ClassModelBuilder classModelBuilder;
|
||||
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) {
|
||||
super();
|
||||
this.scanner = scanner;
|
||||
}
|
||||
|
||||
public Graph build(String archive) throws IOException {
|
||||
return buildClassDepencyGraph(new File(archive));
|
||||
}
|
||||
|
||||
public Graph buildClassDepencyGraph(File archiveFile) throws IOException {
|
||||
List<ClassPath> cpList = scanner.scanArchive(archiveFile);
|
||||
|
||||
ClassPool pool = ClassPool.getDefault();
|
||||
for (ClassPath cp : cpList) {
|
||||
pool.appendClassPath(cp);
|
||||
}
|
||||
|
||||
Graph graph = createClassDependencyGraph(pool, cpList);
|
||||
graph.setName(archiveFile.getName());
|
||||
return graph;
|
||||
}
|
||||
|
||||
private Graph createClassDependencyGraph(ClassPool pool, List<ClassPath> classpath) {
|
||||
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 className : classes) {
|
||||
ClassModel newModel = classModelBuilder.scanClassOrSkip(className);
|
||||
if (newModel != null) {
|
||||
graph.add(newModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
|
||||
public void setPackageIncludePatterns(String... packageIncludePatterns) {
|
||||
this.packageIncludePatterns = packageIncludePatterns;
|
||||
}
|
||||
|
||||
public void setPackageExcludePatterns(String... packageExcludePatterns) {
|
||||
this.packageExcludePatterns = packageExcludePatterns;
|
||||
}
|
||||
|
||||
}
|
||||
8
src/main/java/yooze/Inspectable.java
Normal file
8
src/main/java/yooze/Inspectable.java
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package yooze;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Inspectable {
|
||||
public String getResourceName();
|
||||
public List<String> getClasses();
|
||||
}
|
||||
78
src/main/java/yooze/JarClassPath.java
Normal file
78
src/main/java/yooze/JarClassPath.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/main/java/yooze/MethodCache.java
Normal file
32
src/main/java/yooze/MethodCache.java
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package yooze;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import yooze.domain.MethodModel;
|
||||
|
||||
public class MethodCache {
|
||||
private final Map<String, MethodModel> entries = new ConcurrentHashMap<String, MethodModel>();
|
||||
private final static MethodCache instance = new MethodCache();
|
||||
|
||||
public static MethodCache getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public boolean contains(String classname) {
|
||||
return entries.containsKey(classname);
|
||||
}
|
||||
|
||||
public MethodModel get(String fullName) {
|
||||
return entries.get(fullName);
|
||||
}
|
||||
|
||||
public void add(MethodModel methodmodel) {
|
||||
entries.put(methodmodel.getFullname(), methodmodel);
|
||||
}
|
||||
|
||||
public Collection<MethodModel> getMethods() {
|
||||
return entries.values();
|
||||
}
|
||||
}
|
||||
16
src/main/java/yooze/Statistics.java
Normal file
16
src/main/java/yooze/Statistics.java
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package yooze;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Statistics {
|
||||
private static ConcurrentHashMap<String, Long> bytecodeSizes=new ConcurrentHashMap<String, Long>();
|
||||
|
||||
public static void addBytecodeSizeForClass(String className, long size){
|
||||
bytecodeSizes.put(className, size);
|
||||
}
|
||||
|
||||
public static Long getByteCodeSizeForClass(String className){
|
||||
Long value = bytecodeSizes.get(className);
|
||||
return value==null?0:value;
|
||||
}
|
||||
}
|
||||
39
src/main/java/yooze/Util.java
Normal file
39
src/main/java/yooze/Util.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
public class Util {
|
||||
private final static Pattern fileNamePattern = Pattern.compile(".+/(.+)");
|
||||
|
||||
public static File extractFile(ZipFile file, ZipEntry entry)
|
||||
throws IOException {
|
||||
String name=entry.getName();
|
||||
Matcher m = fileNamePattern.matcher(name);
|
||||
if (m.matches()){//chop off path
|
||||
name=m.group(1);
|
||||
}
|
||||
|
||||
File tempFile = File.createTempFile(name, ".file");
|
||||
InputStream in = file.getInputStream(entry);
|
||||
FileOutputStream out = new FileOutputStream(tempFile);
|
||||
IOUtils.copy(in, out);
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
public static String toClassResource(String className) {
|
||||
return className.replaceAll("\\.", "/")+".class";
|
||||
}
|
||||
|
||||
public static String toClassName(String classResource) {
|
||||
return classResource.replaceAll("/", ".");
|
||||
}
|
||||
}
|
||||
67
src/main/java/yooze/domain/ClassModel.java
Normal file
67
src/main/java/yooze/domain/ClassModel.java
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package yooze.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ClassModel {
|
||||
final private String name;
|
||||
|
||||
final private List<ClassModel> references = new ArrayList<ClassModel>();
|
||||
final private List<MethodModel> methods = new ArrayList<MethodModel>();
|
||||
|
||||
public ClassModel(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void addReference(ClassModel classModel) {
|
||||
references.add(classModel);
|
||||
}
|
||||
|
||||
public void addMethod(MethodModel method) {
|
||||
methods.add(method);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<ClassModel> getReferences() {
|
||||
return new ArrayList<ClassModel>(references);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "class " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ClassModel other = (ClassModel) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/yooze/domain/Graph.java
Normal file
28
src/main/java/yooze/domain/Graph.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package yooze.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Graph {
|
||||
private String name;
|
||||
|
||||
private final List<ClassModel> classes = new ArrayList<ClassModel>();
|
||||
|
||||
public void add(ClassModel model) {
|
||||
classes.add(model);
|
||||
}
|
||||
|
||||
public List<ClassModel> getChildren() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/java/yooze/domain/MethodCallModel.java
Normal file
32
src/main/java/yooze/domain/MethodCallModel.java
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package yooze.domain;
|
||||
|
||||
import javassist.NotFoundException;
|
||||
import javassist.expr.MethodCall;
|
||||
import yooze.ClassCache;
|
||||
import yooze.MethodCache;
|
||||
|
||||
public class MethodCallModel {
|
||||
private MethodCall methodCall;
|
||||
|
||||
public MethodCallModel(MethodCall m) {
|
||||
this.methodCall = m;
|
||||
}
|
||||
|
||||
public ClassModel getCalledClass() {
|
||||
return ClassCache.get(methodCall.getClassName());
|
||||
}
|
||||
|
||||
public MethodModel getCalledMethod() {
|
||||
try {
|
||||
ParameterList parameterList = ParameterList.create(methodCall.getMethod());
|
||||
return MethodCache.getInstance().get(
|
||||
createQualifiedMethodname(parameterList));
|
||||
} catch (NotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String createQualifiedMethodname(ParameterList parameterList) {
|
||||
return methodCall.getClassName() + "." + methodCall.getMethodName() + "(" + parameterList.asText() + ")";
|
||||
}
|
||||
}
|
||||
91
src/main/java/yooze/domain/MethodModel.java
Normal file
91
src/main/java/yooze/domain/MethodModel.java
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
package yooze.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.CtMethod;
|
||||
import javassist.expr.ExprEditor;
|
||||
import javassist.expr.MethodCall;
|
||||
import yooze.MethodCache;
|
||||
|
||||
public class MethodModel {
|
||||
private ClassModel containingClass;
|
||||
private String name;
|
||||
private ParameterList parameterList;
|
||||
private final List<MethodCallModel> methodCalls = new ArrayList<MethodCallModel>();
|
||||
private final Set<MethodModel> callers = new HashSet<MethodModel>();
|
||||
|
||||
public static MethodModel create(ClassModel containingClass, CtMethod method) {
|
||||
MethodModel methodModel = new MethodModel(containingClass, method);
|
||||
MethodCache.getInstance().add(methodModel);
|
||||
methodModel.scanSubsequentMethodCalls(method);
|
||||
return methodModel;
|
||||
}
|
||||
|
||||
private MethodModel(ClassModel containingClass, CtMethod method) {
|
||||
this.containingClass = containingClass;
|
||||
name = method.getName();
|
||||
parameterList = ParameterList.create(method);
|
||||
}
|
||||
|
||||
public void addCaller(MethodModel method) {
|
||||
callers.add(method);
|
||||
}
|
||||
|
||||
public List<MethodModel> getCallers() {
|
||||
return new ArrayList<MethodModel>(callers);
|
||||
}
|
||||
|
||||
public List<MethodCallModel> getMethodCalls() {
|
||||
return methodCalls;
|
||||
}
|
||||
|
||||
private void scanSubsequentMethodCalls(CtMethod method) {
|
||||
try {
|
||||
method.instrument(new ExprEditor() {
|
||||
@Override
|
||||
public void edit(MethodCall m) throws CannotCompileException {
|
||||
MethodCallModel methodCallModel = new MethodCallModel(m);
|
||||
methodCalls.add(methodCallModel);
|
||||
}
|
||||
});
|
||||
} catch (CannotCompileException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFullname() {
|
||||
return containingClass.getName() + "." + name + "(" + parameterList.asText() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getFullname();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof MethodModel)) {
|
||||
return false;
|
||||
}
|
||||
MethodModel other = (MethodModel) obj;
|
||||
return this.getFullname().equals(other.getFullname());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getFullname().hashCode();
|
||||
}
|
||||
}
|
||||
58
src/main/java/yooze/domain/ParameterList.java
Normal file
58
src/main/java/yooze/domain/ParameterList.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package yooze.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
import javassist.NotFoundException;
|
||||
|
||||
public class ParameterList {
|
||||
|
||||
private List<ParameterModel> parameters = new ArrayList<ParameterModel>();
|
||||
|
||||
public static ParameterList create(CtMethod method) {
|
||||
ParameterList parameterList = new ParameterList();
|
||||
parameterList.parameters = getParameters(method);
|
||||
return parameterList;
|
||||
}
|
||||
|
||||
private static List<ParameterModel> getParameters(CtMethod method) {
|
||||
try {
|
||||
List<ParameterModel> parameters = new ArrayList<ParameterModel>();
|
||||
CtClass[] parameterTypes = method.getParameterTypes();
|
||||
for (CtClass parameterType : parameterTypes) {
|
||||
parameters.add(new ParameterModel(parameterType));
|
||||
}
|
||||
return parameters;
|
||||
|
||||
} catch (NotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String asText() {
|
||||
String parameterText = "";
|
||||
int index = 0;
|
||||
int size = parameters.size();
|
||||
for (ParameterModel parameter : parameters) {
|
||||
parameterText = addType(parameterText, parameter);
|
||||
parameterText = addComma(parameterText, index, size);
|
||||
index++;
|
||||
}
|
||||
return parameterText;
|
||||
}
|
||||
|
||||
private String addComma(String parameterText, int i, int size) {
|
||||
if (i < (size - 1)) {
|
||||
parameterText += ", ";
|
||||
}
|
||||
return parameterText;
|
||||
}
|
||||
|
||||
private String addType(String parameterText, ParameterModel parameter) {
|
||||
parameterText += parameter.getType().getName();
|
||||
return parameterText;
|
||||
}
|
||||
|
||||
}
|
||||
22
src/main/java/yooze/domain/ParameterModel.java
Normal file
22
src/main/java/yooze/domain/ParameterModel.java
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package yooze.domain;
|
||||
|
||||
import yooze.ClassCache;
|
||||
import javassist.CtClass;
|
||||
|
||||
public class ParameterModel {
|
||||
private ClassModel type;
|
||||
private String name;
|
||||
|
||||
public ParameterModel(CtClass typeAsCtClass) {
|
||||
String classname = typeAsCtClass.getName();
|
||||
type = ClassCache.get(classname);
|
||||
if (type == null) {
|
||||
type = ClassCache.createNewDummyModel(classname);
|
||||
}
|
||||
name = "";// javassist doesn't give me this (?)
|
||||
}
|
||||
|
||||
public ClassModel getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
41
src/main/java/yooze/dto/MethodDto.java
Normal file
41
src/main/java/yooze/dto/MethodDto.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package yooze.dto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import yooze.domain.MethodModel;
|
||||
|
||||
public class MethodDto {
|
||||
private String name;
|
||||
private List<MethodDto> callers = new ArrayList<MethodDto>();
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<MethodDto> getCallers() {
|
||||
return callers;
|
||||
}
|
||||
|
||||
public void setCallers(List<MethodDto> callers) {
|
||||
this.callers = callers;
|
||||
}
|
||||
|
||||
public void addCaller(MethodDto caller) {
|
||||
callers.add(caller);
|
||||
}
|
||||
|
||||
public static MethodDto create(MethodModel startMethod) {
|
||||
MethodDto methodDto = new MethodDto();
|
||||
methodDto.setName(startMethod.getFullname());
|
||||
for (MethodModel caller : startMethod.getCallers()) {
|
||||
methodDto.addCaller(create(caller));
|
||||
}
|
||||
return methodDto;
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/java/yooze/etc/ClassBuilder.java
Normal file
48
src/main/java/yooze/etc/ClassBuilder.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
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;
|
||||
|
||||
}
|
||||
}
|
||||
89
src/main/java/yooze/etc/Neo4jDao.java
Normal file
89
src/main/java/yooze/etc/Neo4jDao.java
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
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
|
||||
|
||||
}
|
||||
}
|
||||
41
src/main/java/yooze/etc/Yooze.java
Normal file
41
src/main/java/yooze/etc/Yooze.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
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];
|
||||
new Yooze(neoDb).createNeoGraph(earfile, in,ex);
|
||||
|
||||
}
|
||||
|
||||
public Yooze(String neo4jDb) {
|
||||
super();
|
||||
this.neo4jDb = neo4jDb;
|
||||
}
|
||||
|
||||
public void createNeoGraph(String archive, String packageIncludePatterns, String packageExcludePatterns)
|
||||
throws IOException{
|
||||
GraphBuilder libDirectoryBuilder = GraphBuilder.getLibDirectoryBuilder();
|
||||
libDirectoryBuilder.setPackageExcludePatterns(packageExcludePatterns);
|
||||
libDirectoryBuilder.setPackageIncludePatterns(packageIncludePatterns);
|
||||
|
||||
Graph graph = libDirectoryBuilder.build(archive);
|
||||
|
||||
Neo4jDao neo4jDao = new Neo4jDao(neo4jDb);
|
||||
for (ClassModel model:graph.getChildren()){
|
||||
neo4jDao.insertClass(model);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
192
src/main/java/yooze/scanner/ArchiveScanner.java
Normal file
192
src/main/java/yooze/scanner/ArchiveScanner.java
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
package yooze.scanner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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.Util;
|
||||
|
||||
/**
|
||||
* @author shautvast 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)");
|
||||
|
||||
public List<ClassPath> scanArchive(String archiveName) throws IOException {
|
||||
return scanArchive(new File(archiveName));
|
||||
}
|
||||
|
||||
public List<ClassPath> scanArchive(File archiveFile) throws IOException {
|
||||
List<ClassPath> result = new ArrayList<ClassPath>();
|
||||
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 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)) {
|
||||
try {
|
||||
addToClasspath(warfile, classpaths, entry);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} 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) {
|
||||
List<JarFile> wars = new ArrayList<JarFile>();
|
||||
for (Enumeration<JarEntry> entries = earfile.entries(); entries.hasMoreElements();) {
|
||||
JarEntry entry = (JarEntry) entries.nextElement();
|
||||
if (isWarfile(entry)) {
|
||||
try {
|
||||
File warFile = Util.extractFile(earfile, entry);
|
||||
wars.add(new JarFile(warFile));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return wars;
|
||||
}
|
||||
|
||||
private boolean isWarfile(JarEntry entry) {
|
||||
return entry.getName().endsWith(".war");
|
||||
}
|
||||
|
||||
private List<ClassPath> scanRoot(JarFile earfile) {
|
||||
List<ClassPath> classpaths = new ArrayList<ClassPath>();
|
||||
for (Enumeration<JarEntry> entries = earfile.entries(); entries.hasMoreElements();) {
|
||||
JarEntry entry = (JarEntry) entries.nextElement();
|
||||
if (isJarfile(entry)) {
|
||||
try {
|
||||
addToClasspath(earfile, classpaths, entry);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return classpaths;
|
||||
}
|
||||
|
||||
private boolean isJarfile(JarEntry entry) {
|
||||
return entry.getName().endsWith(".jar");
|
||||
}
|
||||
|
||||
}
|
||||
47
src/main/java/yooze/scanner/LibScanner.java
Normal file
47
src/main/java/yooze/scanner/LibScanner.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package yooze.scanner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import yooze.JarClassPath;
|
||||
|
||||
import javassist.ClassPath;
|
||||
|
||||
/**
|
||||
* Scans a directory ("lib") recursively for jarfiles and adds them to the
|
||||
* classpath
|
||||
*
|
||||
* @author sander
|
||||
*
|
||||
*/
|
||||
public class LibScanner 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> classpaths = new ArrayList<ClassPath>();
|
||||
return doScanArchive(classpaths,file);
|
||||
}
|
||||
|
||||
private List<ClassPath> doScanArchive(List<ClassPath> classpaths, File file)
|
||||
throws IOException {
|
||||
|
||||
File[] entries = file.listFiles();
|
||||
for (File entry : entries) {
|
||||
if (entry.isDirectory()) {
|
||||
doScanArchive(classpaths, entry);
|
||||
} else if (entry.getName().endsWith(".jar")) {
|
||||
classpaths.add(new JarClassPath(new JarFile(entry)));
|
||||
}
|
||||
}
|
||||
return classpaths;
|
||||
}
|
||||
|
||||
}
|
||||
13
src/main/java/yooze/scanner/Scanner.java
Normal file
13
src/main/java/yooze/scanner/Scanner.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
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;
|
||||
}
|
||||
65
src/main/java/yooze/scanner/TgzScanner.java
Normal file
65
src/main/java/yooze/scanner/TgzScanner.java
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package yooze.scanner;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author sander
|
||||
*
|
||||
*/
|
||||
public class TgzScanner implements Scanner {
|
||||
public List<ClassPath> 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))));
|
||||
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");
|
||||
FileOutputStream fos = new FileOutputStream(tempFile);
|
||||
BufferedOutputStream dest = new BufferedOutputStream(fos);
|
||||
|
||||
while ((count = tarInputStream.read(data)) != -1) {
|
||||
dest.write(data, 0, count);
|
||||
}
|
||||
dest.flush();
|
||||
dest.close();
|
||||
classpaths.add(new JarClassPath(new JarFile(tempFile)));
|
||||
}
|
||||
}
|
||||
tarInputStream.close();
|
||||
return classpaths;
|
||||
}
|
||||
|
||||
private String singleName(String name) {
|
||||
int slash = name.lastIndexOf("/");
|
||||
if (slash > -1) {
|
||||
return name.substring(slash + 1);
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/test/java/yooze/AssTest.java
Normal file
22
src/test/java/yooze/AssTest.java
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
26
src/test/java/yooze/Config.java
Normal file
26
src/test/java/yooze/Config.java
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Config {
|
||||
private File earFile;
|
||||
private File tgzFile;
|
||||
|
||||
public void setEarFile(File earFile) {
|
||||
this.earFile = earFile;
|
||||
}
|
||||
|
||||
public File getEarFile() {
|
||||
return earFile;
|
||||
}
|
||||
|
||||
public File getTgzFile() {
|
||||
return tgzFile;
|
||||
}
|
||||
|
||||
public void setTgzFile(File tgzFile) {
|
||||
this.tgzFile = tgzFile;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
64
src/test/java/yooze/DotPrinterTest.java
Normal file
64
src/test/java/yooze/DotPrinterTest.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package yooze;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
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 {
|
||||
|
||||
@Test
|
||||
public void dotPrinting() throws IOException {
|
||||
GraphBuilder directoryBuilder = GraphBuilder.getClassesDirectoryBuilder();
|
||||
directoryBuilder.setPackageExcludePatterns(".*?Class4");
|
||||
directoryBuilder.setPackageIncludePatterns(".*?.Class.");
|
||||
Graph graph = directoryBuilder.build("target/test-classes");
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(500);
|
||||
DotPrinter d = new DotPrinter(bytes);
|
||||
d.print(graph);
|
||||
String dotText = new String(bytes.toByteArray());
|
||||
d.close();
|
||||
String expectedDotText = "digraph \"test-classes\" {\r\n" //
|
||||
+ "graph [size=100,100];\r\n"
|
||||
+ "\"yooze.Class1\" [shape=box, height=0.0];\r\n" //
|
||||
+ "\"yooze.Class1\" -> \"yooze.Class2\"\r\n"
|
||||
+ "\"yooze.Class2\" [shape=box, height=0.0];\r\n"
|
||||
+ "\"yooze.Class2\" -> \"yooze.Class3\"\r\n"
|
||||
+ "\"yooze.Class3\" [shape=box, height=0.0];\r\n"
|
||||
+ "\"yooze.Class3\" -> \"yooze.Class1\"\r\n"
|
||||
+ "\"yooze.Class1\" [shape=box, height=0.0];\r\n"
|
||||
+ "\"yooze.Class2\" [shape=box, height=0.0];\r\n" //
|
||||
+ "\"yooze.Class3\" [shape=box, height=0.0];\r\n" + "}\r\n";
|
||||
|
||||
assertEquals(expectedDotText, dotText);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noReference() throws IOException {
|
||||
GraphBuilder directoryBuilder = GraphBuilder.getClassesDirectoryBuilder();
|
||||
directoryBuilder.setPackageExcludePatterns("");
|
||||
directoryBuilder.setPackageIncludePatterns("yooze.Class4");
|
||||
Graph graph = directoryBuilder.build("target/test-classes");
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
|
||||
DotPrinter d = new DotPrinter(bytes);
|
||||
d.print(graph);
|
||||
String dotText = new String(bytes.toByteArray());
|
||||
String expectedDotText = "digraph \"test-classes\" {\r\n" //
|
||||
+ "graph [size=100,100];\r\n"//
|
||||
+ "\"yooze.Class4\" [shape=box, height=0.0];\r\n" //
|
||||
+ "\"yooze.Class4\";\r\n" //
|
||||
+ "}\r\n";
|
||||
d.close();
|
||||
assertEquals(expectedDotText, dotText);
|
||||
}
|
||||
}
|
||||
50
src/test/java/yooze/EarScannerTest.java
Normal file
50
src/test/java/yooze/EarScannerTest.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
40
src/test/java/yooze/GraphTest.java
Normal file
40
src/test/java/yooze/GraphTest.java
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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.ClassModel;
|
||||
import yooze.domain.Graph;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
|
||||
public class GraphTest {
|
||||
|
||||
@Test
|
||||
public void buildGraph() throws IOException{
|
||||
// new Yooze("/tmp/test").createNeoGraph("target/test-classes", ".*?.Class.");
|
||||
GraphBuilder libDirectoryBuilder = GraphBuilder.getLibDirectoryBuilder();
|
||||
libDirectoryBuilder.setPackageIncludePatterns(".*?.Class.");
|
||||
libDirectoryBuilder.setPackageExcludePatterns("");
|
||||
Graph graph = libDirectoryBuilder.build("target/test-classes");
|
||||
ClassModel class1=graph.getChildren().get(0);
|
||||
|
||||
assertTrue(class1!=null);
|
||||
ClassModel class2Dummy=new ClassModel("yooze.Class2");
|
||||
assertTrue(class1.getReferences().contains(class2Dummy));
|
||||
|
||||
ClassModel class2=class1.getReferences().get(0);
|
||||
assertTrue (class2.getName().equals("yooze.Class2"));
|
||||
ClassModel class3=class2.getReferences().get(0);
|
||||
assertTrue (class3.getName().equals("yooze.Class3"));
|
||||
|
||||
assertTrue(class2.getReferences().contains(class3));
|
||||
assertTrue(class3.getReferences().contains(class1));
|
||||
|
||||
}
|
||||
}
|
||||
40
src/test/java/yooze/LargePackageTest.java
Normal file
40
src/test/java/yooze/LargePackageTest.java
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
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.domain.Graph;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
|
||||
public class LargePackageTest {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
|
||||
@Test
|
||||
public void largePackage() throws IOException{
|
||||
GraphBuilder earBuilder = GraphBuilder.getEarBuilder();
|
||||
earBuilder.setPackageIncludePatterns("");
|
||||
earBuilder.setPackageExcludePatterns("java.*");
|
||||
Graph graph = earBuilder.buildClassDepencyGraph(config.getEarFile());
|
||||
new DotPrinter(new FileOutputStream("/tmp/example.dot")).print(graph);
|
||||
|
||||
}
|
||||
|
||||
public Config getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
40
src/test/java/yooze/MethodReferencesTest.java
Normal file
40
src/test/java/yooze/MethodReferencesTest.java
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
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;
|
||||
import yooze.domain.MethodModel;
|
||||
import yooze.dto.MethodDto;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
|
||||
public class MethodReferencesTest {
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
GraphBuilder directoryBuilder = GraphBuilder.getClassesDirectoryBuilder();
|
||||
directoryBuilder.setPackageIncludePatterns("yooze.Class.*");
|
||||
Graph graph = directoryBuilder.build("target/test-classes");
|
||||
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"));
|
||||
jg.writeObject(dto);
|
||||
jg.close();
|
||||
}
|
||||
}
|
||||
52
src/test/java/yooze/TgzBuilderTest.java
Normal file
52
src/test/java/yooze/TgzBuilderTest.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package yooze;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
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.domain.ClassModel;
|
||||
import yooze.domain.Graph;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
|
||||
public class TgzBuilderTest {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
|
||||
@Test
|
||||
public void tgzBuilder() throws IOException {
|
||||
GraphBuilder tgzBuilder = GraphBuilder.getDefaultTgzBuilder();
|
||||
tgzBuilder.setPackageIncludePatterns("nl.*");
|
||||
tgzBuilder.setPackageExcludePatterns("");
|
||||
Graph graph = tgzBuilder.buildClassDepencyGraph(config.getTgzFile());
|
||||
|
||||
ArrayList<String> names = new ArrayList<String>();
|
||||
|
||||
for (ClassModel cm : graph.getChildren()) {
|
||||
names.add(cm.getName());
|
||||
}
|
||||
assertTrue(names.contains("nl.jssl.jas.Main"));
|
||||
assertTrue(names.contains("nl.jssl.jas.agent.Agent"));
|
||||
assertTrue(names
|
||||
.contains("nl.jssl.jas.instrumentation.ClassTransformer"));
|
||||
assertTrue(names
|
||||
.contains("nl.jssl.jas.instrumentation.JavassistInstrumenter"));
|
||||
assertTrue(names.contains("nl.jssl.jas.measurement.Measurement"));
|
||||
assertTrue(names.contains("nl.jssl.jas.measurement.Stopwatch"));
|
||||
assertTrue(names.contains("nl.jssl.testjas.TestClass"));
|
||||
assertTrue(names.contains("nl.jssl.testjas.Instrument"));
|
||||
assertTrue(names.contains("nl.jssl.testjas.AgentTest"));
|
||||
|
||||
}
|
||||
|
||||
public void setConfig(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
}
|
||||
BIN
src/test/resources/.DS_Store
vendored
Normal file
BIN
src/test/resources/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/test/resources/._.DS_Store
Normal file
BIN
src/test/resources/._.DS_Store
Normal file
Binary file not shown.
BIN
src/test/resources/agent.tar.gz
Normal file
BIN
src/test/resources/agent.tar.gz
Normal file
Binary file not shown.
9
src/test/resources/applicationContext-test.xml
Normal file
9
src/test/resources/applicationContext-test.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
<bean id="config" class="yooze.Config">
|
||||
<property name="earFile" value="classpath:examples.ear"></property>
|
||||
<property name="tgzFile" value="classpath:agent.tar.gz"></property>
|
||||
</bean>
|
||||
</beans>
|
||||
BIN
src/test/resources/examples.ear
Normal file
BIN
src/test/resources/examples.ear
Normal file
Binary file not shown.
BIN
src/test/resources/examples.war
Normal file
BIN
src/test/resources/examples.war
Normal file
Binary file not shown.
12
src/test/resources/logback.xml
Normal file
12
src/test/resources/logback.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
15
src/testdummies/java/yooze/Class1.java
Normal file
15
src/testdummies/java/yooze/Class1.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package yooze;
|
||||
|
||||
public class Class1 {
|
||||
Class2 class2;
|
||||
|
||||
public void rup(int k) {
|
||||
System.out.println(k);
|
||||
class2.annoy();
|
||||
zoef(class2);
|
||||
}
|
||||
|
||||
public void zoef(Class2 envy) {
|
||||
System.out.println(envy);
|
||||
}
|
||||
}
|
||||
10
src/testdummies/java/yooze/Class2.java
Normal file
10
src/testdummies/java/yooze/Class2.java
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package yooze;
|
||||
|
||||
public class Class2 {
|
||||
public static Class3 class3=new Class3();
|
||||
|
||||
public void annoy() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
14
src/testdummies/java/yooze/Class3.java
Normal file
14
src/testdummies/java/yooze/Class3.java
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package yooze;
|
||||
|
||||
public class Class3 {
|
||||
public static Class1 class1 = new Class1();
|
||||
|
||||
public static void annoyStatic() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void dof() {
|
||||
class1.rup(1);
|
||||
}
|
||||
}
|
||||
8
src/testdummies/java/yooze/Class4.java
Normal file
8
src/testdummies/java/yooze/Class4.java
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package yooze;
|
||||
|
||||
public class Class4 {
|
||||
|
||||
public void fla() {
|
||||
new Class3().dof();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue