This commit is contained in:
unknown 2013-12-06 09:52:37 +01:00
parent 85d2346835
commit b24a3db5fd
48 changed files with 2061 additions and 0 deletions

BIN
example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 MiB

135
pom.xml Normal file
View 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

Binary file not shown.

View 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);
}
}

View 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);
}
}

View 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);
}
}
}
}

View 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;
}
}

View 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);
}
}
}

View 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);
}
}
}
}
}

View 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;
}
}

View file

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

View 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);
}
}
}

View 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();
}
}

View 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;
}
}

View 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("/", ".");
}
}

View 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;
}
}

View 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;
}
}

View 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() + ")";
}
}

View 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();
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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
}
}

View 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);
}
}
}

View 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");
}
}

View 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;
}
}

View 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;
}

View 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;
}
}
}

View 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());
}
}
}

View 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;
}
}

View 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);
}
}

View 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;
}
}

View 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));
}
}

View 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;
}
}

View 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();
}
}

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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>

Binary file not shown.

Binary file not shown.

View 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>

View 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);
}
}

View file

@ -0,0 +1,10 @@
package yooze;
public class Class2 {
public static Class3 class3=new Class3();
public void annoy() {
// TODO Auto-generated method stub
}
}

View 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);
}
}

View file

@ -0,0 +1,8 @@
package yooze;
public class Class4 {
public void fla() {
new Class3().dof();
}
}