/*
* Copyright, Aspect Security, Inc.
*
* This file is part of JavaSnoop.
*
* JavaSnoop is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JavaSnoop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JavaSnoop. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aspect.snoop.ui.choose.process;
import com.aspect.snoop.util.IOUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javassist.ByteArrayClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
public class ClasspathTreeModel extends DefaultTreeModel {
List<ClasspathEntry> entries = new ArrayList<ClasspathEntry>();
List<String> classesSeen;
private static Comparator alphabeticComparator = new Comparator() {
public int compare(Object o1, Object o2) {
String s1 = ((ClasspathEntry)o1).getStringEntry();
String s2 = ((ClasspathEntry)o2).getStringEntry();
return s1.toLowerCase().compareTo(s2.toLowerCase());
}
};
public ClasspathTreeModel(TreeNode root) {
super(root);
}
@Override
public boolean isLeaf(Object node) {
return node instanceof CtMethod;
}
private boolean hasEntry(String file) {
for(ClasspathEntry entry : entries) {
if ( entry.getStringEntry().equals(file) ) {
return true;
}
}
return false;
}
public void addEntry(ClasspathEntry entry) {
String file = entry.getStringEntry();
File f = new File(file);
/*
* If it's a dupe of an existing jar, throw it out.
*/
if ( f.isFile() && hasEntry(file) )
return;
/*
* If it's a directory that is beneath an already-listed directory
* then throw it out.
*/
else if(f.isDirectory()) {
for(ClasspathEntry existingEntry : entries) {
File existing = new File(existingEntry.getStringEntry());
if ( f.getAbsolutePath().startsWith(existing.getAbsolutePath()))
return;
}
}
entries.add(entry);
Collections.sort(entries,alphabeticComparator);
}
public void removeEntry(ClasspathEntry entry) {
entries.remove(entry);
Collections.sort(entries,alphabeticComparator);
}
public List<ClasspathEntry> getEntries() {
return entries;
}
public int getSize() {
return entries.size();
}
@Override
public void reload() {
DefaultMutableTreeNode top = (DefaultMutableTreeNode)root;
top.removeAllChildren();
classesSeen = new ArrayList<String>();
ClassPool pool = new ClassPool();
for(ClasspathEntry entry : entries) {
DefaultMutableTreeNode jarNode = new DefaultMutableTreeNode(entry);
pool.insertClassPath(entry.getEntry());
if ( entry.isJar() ) {
try {
JarFile jar = new JarFile(entry.getStringEntry());
Enumeration<JarEntry> jarEntries = jar.entries();
while(jarEntries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry)jarEntries.nextElement();
if ( jarEntry.isDirectory() )
continue;
String entryName = jarEntry.getName();
if ( entryName.endsWith(".class") ) {
try {
String cls = jarEntry.getName().replaceAll("/", "\\.");
String shortendCls = cls.substring(0,cls.length()-6);
classesSeen.add(shortendCls);
byte[] bytecode = IOUtil.getBytesFromStream(jar.getInputStream(jarEntry));
pool.insertClassPath(new ByteArrayClassPath(shortendCls,bytecode));
CtClass clazz = pool.get(shortendCls);
DefaultMutableTreeNode classNode = new DefaultMutableTreeNode(clazz);
for(CtMethod method : clazz.getDeclaredMethods()) {
DefaultMutableTreeNode methodNode = new DefaultMutableTreeNode(method);
classNode.add(methodNode);
}
jarNode.add(classNode);
} catch(NotFoundException e) {
e.printStackTrace();
}
} else {
DefaultMutableTreeNode resourceNode = new DefaultMutableTreeNode(entryName);
jarNode.add(resourceNode);
}
}
top.add(jarNode);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
List<String> getClassesSeen() {
return classesSeen;
}
}