faster loading. (please fix this fucking code, it's too bad) -Bibl
This commit is contained in:
parent
db3b4083cf
commit
8a6e6c0542
21 changed files with 1498 additions and 404 deletions
198
src/the/bytecode/club/bootloader/Boot.java
Normal file
198
src/the/bytecode/club/bootloader/Boot.java
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import me.konloch.kontainer.io.HTTPRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 19 Jul 2015 03:22:37
|
||||||
|
*/
|
||||||
|
public class Boot {
|
||||||
|
|
||||||
|
private static InitialBootScreen screen;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ILoader loader = findLoader();
|
||||||
|
|
||||||
|
screen = new InitialBootScreen();
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
screen.setVisible(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
create(loader, args.length > 0 ? Boolean.valueOf(args[0]) : true);
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
screen.setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Class<?> klass = loader.loadClass("the.bytecode.club.bytecodeviewer.BytecodeViewer");
|
||||||
|
klass.getDeclaredMethod("main", new Class<?>[] { String[].class }).invoke(null, new Object[] { args });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void create(ILoader loader, boolean clean) throws Exception {
|
||||||
|
setState("Bytecode Viewer Boot Screen - Checking Libraries...");
|
||||||
|
|
||||||
|
final File libsDirectory = libsDir();
|
||||||
|
|
||||||
|
List<String> urlList = new ArrayList<String>();
|
||||||
|
HTTPRequest req = new HTTPRequest(new URL("https://github.com/Konloch/bytecode-viewer/tree/master/libs"));
|
||||||
|
for (String s : req.read())
|
||||||
|
if (s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/")) {
|
||||||
|
urlList.add("https://github.com" + s.split("<a href=")[1].split("\"")[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urlList.isEmpty()) {
|
||||||
|
JOptionPane
|
||||||
|
.showMessageDialog(
|
||||||
|
null,
|
||||||
|
"Bytecode Viewer ran into an issue, for some reason github is not returning what we're expecting. Please try rebooting, if this issue persists please contact @Konloch.",
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clean)
|
||||||
|
libsDirectory.delete();
|
||||||
|
|
||||||
|
if (!libsDirectory.exists())
|
||||||
|
libsDirectory.mkdir();
|
||||||
|
|
||||||
|
List<String> libsList = new ArrayList<String>();
|
||||||
|
List<String> libsFileList = new ArrayList<String>();
|
||||||
|
for (File f : libsDirectory.listFiles()) {
|
||||||
|
libsList.add(f.getName());
|
||||||
|
libsFileList.add(f.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.getProgressBar().setMaximum(urlList.size() * 2);
|
||||||
|
|
||||||
|
int completedCheck = 0;
|
||||||
|
|
||||||
|
for (String s : urlList) {
|
||||||
|
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length());
|
||||||
|
if (!libsList.contains(fileName)) {
|
||||||
|
setState("Bytecode Viewer Boot Screen - Downloading " + fileName);
|
||||||
|
System.out.println("Downloading " + fileName);
|
||||||
|
boolean passed = false;
|
||||||
|
while (!passed) {
|
||||||
|
InputStream is = null;
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream();
|
||||||
|
fos = new FileOutputStream(new File(libsDirectory, fileName));
|
||||||
|
System.out.println("Downloading from " + s);
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int len;
|
||||||
|
int downloaded = 0;
|
||||||
|
boolean flag = false;
|
||||||
|
while ((len = is.read(buffer)) > 0) {
|
||||||
|
fos.write(buffer, 0, len);
|
||||||
|
fos.flush();
|
||||||
|
downloaded += 8192;
|
||||||
|
int mbs = downloaded / 1048576;
|
||||||
|
if (mbs % 5 == 0 && mbs != 0) {
|
||||||
|
if (!flag)
|
||||||
|
System.out.println("Downloaded " + mbs + "MBs so far");
|
||||||
|
flag = true;
|
||||||
|
} else
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
libsFileList.add(new File(libsDirectory, fileName).getAbsolutePath());
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (is != null) {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (fos != null) {
|
||||||
|
fos.flush();
|
||||||
|
}
|
||||||
|
if (fos != null) {
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Download finished!");
|
||||||
|
passed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completedCheck++;
|
||||||
|
screen.getProgressBar().setValue(completedCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState("Bytecode Viewer Boot Screen - Checking & Deleting Foreign/Outdated Libraries...");
|
||||||
|
System.out.println("Checking & Deleting foreign/outdated libraries");
|
||||||
|
for (String s : libsFileList) {
|
||||||
|
File f = new File(s);
|
||||||
|
boolean delete = true;
|
||||||
|
for (String urlS : urlList) {
|
||||||
|
String fileName = urlS.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), urlS.length());
|
||||||
|
if (fileName.equals(f.getName()))
|
||||||
|
delete = false;
|
||||||
|
}
|
||||||
|
if (delete) {
|
||||||
|
f.delete();
|
||||||
|
System.out.println("Detected & Deleted Foriegn/Outdated Jar/File: " + f.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setState("Bytecode Viewer Boot Screen - Loading Libraries...");
|
||||||
|
System.out.println("Loading libraries...");
|
||||||
|
|
||||||
|
for (String s : libsFileList) {
|
||||||
|
if (s.endsWith(".jar")) {
|
||||||
|
File f = new File(s);
|
||||||
|
if (f.exists()) {
|
||||||
|
setState("Bytecode Viewer Boot Screen - Loading Library " + f.getName());
|
||||||
|
System.out.println("Loading library " + f.getName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
JarInfo jar = new JarInfo(f);
|
||||||
|
ExternalLibrary lib = new ExternalLibrary(jar);
|
||||||
|
loader.bind(lib);
|
||||||
|
System.out.println("Succesfully loaded " + f.getName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
f.delete();
|
||||||
|
JOptionPane.showMessageDialog(null, "Error, Library " + f.getName() + " is corrupt, please restart to redownload it.",
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completedCheck++;
|
||||||
|
screen.getProgressBar().setValue(completedCheck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setState("Bytecode Viewer Boot Screen - Booting!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File libsDir() {
|
||||||
|
File dir = new File(System.getProperty("user.home"), ".Bytecode-Viewer");
|
||||||
|
while (!dir.exists())
|
||||||
|
dir.mkdirs();
|
||||||
|
|
||||||
|
return new File(dir, "libs");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setState(String s) {
|
||||||
|
screen.setTitle(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ILoader findLoader() {
|
||||||
|
// TODO: Find from providers
|
||||||
|
return new LibraryClassLoader();
|
||||||
|
}
|
||||||
|
}
|
35
src/the/bytecode/club/bootloader/ClassHelper.java
Normal file
35
src/the/bytecode/club/bootloader/ClassHelper.java
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 25 May 2015 (actually before this)
|
||||||
|
*/
|
||||||
|
public class ClassHelper {
|
||||||
|
|
||||||
|
public static Map<String, ClassNode> convertToMap(Collection<ClassNode> classes) {
|
||||||
|
Map<String, ClassNode> map = new HashMap<String, ClassNode>();
|
||||||
|
for (ClassNode cn : classes) {
|
||||||
|
map.put(cn.name, cn);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> Map<T, K> copyOf(Map<T, K> src) {
|
||||||
|
Map<T, K> dst = new HashMap<T, K>();
|
||||||
|
copy(src, dst);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T, K> void copy(Map<T, K> src, Map<T, K> dst) {
|
||||||
|
for(Entry<T, K> e : src.entrySet()) {
|
||||||
|
dst.put(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
207
src/the/bytecode/club/bootloader/ClassTree.java
Normal file
207
src/the/bytecode/club/bootloader/ClassTree.java
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import static the.bytecode.club.bootloader.ClassHelper.convertToMap;
|
||||||
|
import static the.bytecode.club.bootloader.ClassHelper.copyOf;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 25 May 2015 (actually before this)
|
||||||
|
*/
|
||||||
|
public class ClassTree {
|
||||||
|
private static final SetCreator<ClassNode> SET_CREATOR = new SetCreator<ClassNode>();
|
||||||
|
|
||||||
|
private final Map<String, ClassNode> classes;
|
||||||
|
private final NullPermeableHashMap<ClassNode, Set<ClassNode>> supers;
|
||||||
|
private final NullPermeableHashMap<ClassNode, Set<ClassNode>> delgates;
|
||||||
|
|
||||||
|
public ClassTree() {
|
||||||
|
classes = new HashMap<String, ClassNode>();
|
||||||
|
supers = new NullPermeableHashMap<ClassNode, Set<ClassNode>>(SET_CREATOR);
|
||||||
|
delgates = new NullPermeableHashMap<ClassNode, Set<ClassNode>>(SET_CREATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassTree(Collection<ClassNode> classes) {
|
||||||
|
this(convertToMap(classes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassTree(Map<String, ClassNode> classes_) {
|
||||||
|
classes = copyOf(classes_);
|
||||||
|
supers = new NullPermeableHashMap<ClassNode, Set<ClassNode>>(SET_CREATOR);
|
||||||
|
delgates = new NullPermeableHashMap<ClassNode, Set<ClassNode>>(SET_CREATOR);
|
||||||
|
|
||||||
|
build(classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: optimise
|
||||||
|
public void build(Map<String, ClassNode> classes) {
|
||||||
|
for (ClassNode node : classes.values()) {
|
||||||
|
for (String iface : node.interfaces) {
|
||||||
|
ClassNode ifacecs = classes.get(iface);
|
||||||
|
if (ifacecs == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
getDelegates0(ifacecs).add(node);
|
||||||
|
|
||||||
|
Set<ClassNode> superinterfaces = new HashSet<ClassNode>();
|
||||||
|
buildSubTree(classes, superinterfaces, ifacecs);
|
||||||
|
|
||||||
|
getSupers0(node).addAll(superinterfaces);
|
||||||
|
}
|
||||||
|
ClassNode currentSuper = classes.get(node.superName);
|
||||||
|
while (currentSuper != null) {
|
||||||
|
getDelegates0(currentSuper).add(node);
|
||||||
|
getSupers0(node).add(currentSuper);
|
||||||
|
for (String iface : currentSuper.interfaces) {
|
||||||
|
ClassNode ifacecs = classes.get(iface);
|
||||||
|
if (ifacecs == null)
|
||||||
|
continue;
|
||||||
|
getDelegates0(ifacecs).add(currentSuper);
|
||||||
|
Set<ClassNode> superinterfaces = new HashSet<ClassNode>();
|
||||||
|
buildSubTree(classes, superinterfaces, ifacecs);
|
||||||
|
getSupers0(currentSuper).addAll(superinterfaces);
|
||||||
|
getSupers0(node).addAll(superinterfaces);
|
||||||
|
}
|
||||||
|
currentSuper = classes.get(currentSuper.superName);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSupers0(node);
|
||||||
|
getDelegates0(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(ClassNode node) {
|
||||||
|
for (String iface : node.interfaces) {
|
||||||
|
ClassNode ifacecs = classes.get(iface);
|
||||||
|
if (ifacecs == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
getDelegates0(ifacecs).add(node);
|
||||||
|
|
||||||
|
Set<ClassNode> superinterfaces = new HashSet<ClassNode>();
|
||||||
|
buildSubTree(classes, superinterfaces, ifacecs);
|
||||||
|
|
||||||
|
getSupers0(node).addAll(superinterfaces);
|
||||||
|
}
|
||||||
|
ClassNode currentSuper = classes.get(node.superName);
|
||||||
|
while (currentSuper != null) {
|
||||||
|
getDelegates0(currentSuper).add(node);
|
||||||
|
getSupers0(node).add(currentSuper);
|
||||||
|
for (String iface : currentSuper.interfaces) {
|
||||||
|
ClassNode ifacecs = classes.get(iface);
|
||||||
|
if (ifacecs == null)
|
||||||
|
continue;
|
||||||
|
getDelegates0(ifacecs).add(currentSuper);
|
||||||
|
Set<ClassNode> superinterfaces = new HashSet<ClassNode>();
|
||||||
|
buildSubTree(classes, superinterfaces, ifacecs);
|
||||||
|
getSupers0(currentSuper).addAll(superinterfaces);
|
||||||
|
getSupers0(node).addAll(superinterfaces);
|
||||||
|
}
|
||||||
|
currentSuper = classes.get(currentSuper.superName);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSupers0(node);
|
||||||
|
getDelegates0(node);
|
||||||
|
|
||||||
|
classes.put(node.name, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildSubTree(Map<String, ClassNode> classes, Collection<ClassNode> superinterfaces, ClassNode current) {
|
||||||
|
superinterfaces.add(current);
|
||||||
|
for (String iface : current.interfaces) {
|
||||||
|
ClassNode cs = classes.get(iface);
|
||||||
|
if(cs != null) {
|
||||||
|
getDelegates0(cs).add(current);
|
||||||
|
buildSubTree(classes, superinterfaces, cs);
|
||||||
|
} else {
|
||||||
|
// System.out.println("Null interface -> " + iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<MethodNode> getMethodsFromSuper(MethodNode m) {
|
||||||
|
return getMethodsFromSuper(m.owner, m.name, m.desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<MethodNode> getMethodsFromSuper(ClassNode node, String name, String desc) {
|
||||||
|
Set<MethodNode> methods = new HashSet<MethodNode>();
|
||||||
|
for (ClassNode super_ : getSupers(node)) {
|
||||||
|
for (MethodNode mn : super_.methods) {
|
||||||
|
if (mn.name.equals(name) && mn.desc.equals(desc)) {
|
||||||
|
methods.add(mn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<MethodNode> getMethodsFromDelegates(MethodNode m) {
|
||||||
|
return getMethodsFromDelegates(m.owner, m.name, m.desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<MethodNode> getMethodsFromDelegates(ClassNode node, String name, String desc) {
|
||||||
|
Set<MethodNode> methods = new HashSet<MethodNode>();
|
||||||
|
for (ClassNode delegate : getDelegates(node)) {
|
||||||
|
for (MethodNode mn : delegate.methods) {
|
||||||
|
if (mn.name.equals(name) && mn.desc.equals(desc)) {
|
||||||
|
methods.add(mn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodNode getFirstMethodFromSuper(ClassNode node, String name, String desc) {
|
||||||
|
for (ClassNode super_ : getSupers(node)) {
|
||||||
|
for (MethodNode mn : super_.methods) {
|
||||||
|
if (mn.name.equals(name) && mn.desc.equals(desc)) {
|
||||||
|
return mn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNode getClass(String name) {
|
||||||
|
return classes.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInherited(ClassNode cn, String name, String desc) {
|
||||||
|
return getFirstMethodFromSuper(cn, name, desc) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInherited(ClassNode first, MethodNode mn) {
|
||||||
|
return mn.owner.name.equals(first.name) && isInherited(mn.owner, mn.name, mn.desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<ClassNode> getSupers0(ClassNode cn) {
|
||||||
|
return supers.getNonNull(cn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<ClassNode> getDelegates0(ClassNode cn) {
|
||||||
|
return delgates.getNonNull(cn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ClassNode> getClasses() {
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ClassNode> getSupers(ClassNode cn) {
|
||||||
|
return Collections.unmodifiableSet(supers.get(cn));
|
||||||
|
// return supers.get(cn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<ClassNode> getDelegates(ClassNode cn) {
|
||||||
|
return Collections.unmodifiableSet(delgates.get(cn));
|
||||||
|
// return delgates.get(cn);
|
||||||
|
}
|
||||||
|
}
|
28
src/the/bytecode/club/bootloader/DataContainer.java
Normal file
28
src/the/bytecode/club/bootloader/DataContainer.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public abstract class DataContainer<T> extends ArrayList<T> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -9022506488647444546L;
|
||||||
|
|
||||||
|
public DataContainer() {
|
||||||
|
this(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataContainer(int cap) {
|
||||||
|
super(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataContainer(Collection<T> data) {
|
||||||
|
addAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Map<String, T> namedMap();
|
||||||
|
}
|
87
src/the/bytecode/club/bootloader/ExternalLibrary.java
Normal file
87
src/the/bytecode/club/bootloader/ExternalLibrary.java
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.JarURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 19 Jul 2015 02:33:23
|
||||||
|
*/
|
||||||
|
public class ExternalLibrary extends ExternalResource<JarContents<ClassNode>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param location
|
||||||
|
*/
|
||||||
|
public ExternalLibrary(URL location) {
|
||||||
|
super(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param jar
|
||||||
|
*/
|
||||||
|
public ExternalLibrary(JarInfo jar) {
|
||||||
|
super(createJarURL(jar));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static URL createJarURL(JarInfo jar) {
|
||||||
|
try {
|
||||||
|
return jar.formattedURL();
|
||||||
|
} catch(MalformedURLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] read(InputStream in) throws IOException {
|
||||||
|
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(buffer)) != -1)
|
||||||
|
byteArrayOut.write(buffer, 0, bytesRead);
|
||||||
|
byteArrayOut.close();
|
||||||
|
return byteArrayOut.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ClassNode create(byte[] b) {
|
||||||
|
ClassReader cr = new ClassReader(b);
|
||||||
|
ClassNode cn = new ClassNode();
|
||||||
|
cr.accept(cn, 0);
|
||||||
|
return cn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see the.bytecode.club.bytecodeviewer.loadermodel.ExternalResource#load()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JarContents<ClassNode> load() throws IOException {
|
||||||
|
JarContents<ClassNode> contents = new JarContents<ClassNode>();
|
||||||
|
|
||||||
|
JarURLConnection con = (JarURLConnection) getLocation().openConnection();
|
||||||
|
JarFile jar = con.getJarFile();
|
||||||
|
|
||||||
|
Enumeration<JarEntry> entries = jar.entries();
|
||||||
|
while(entries.hasMoreElements()) {
|
||||||
|
JarEntry entry = entries.nextElement();
|
||||||
|
byte[] bytes = read(jar.getInputStream(entry));
|
||||||
|
if (entry.getName().endsWith(".class")) {
|
||||||
|
ClassNode cn = create(bytes);
|
||||||
|
contents.getClassContents().add(cn);
|
||||||
|
} else {
|
||||||
|
JarResource resource = new JarResource(entry.getName(), bytes);
|
||||||
|
contents.getResourceContents().add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
}
|
55
src/the/bytecode/club/bootloader/ExternalResource.java
Normal file
55
src/the/bytecode/club/bootloader/ExternalResource.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 19 Jul 2015 02:30:30
|
||||||
|
*/
|
||||||
|
public abstract class ExternalResource<T> {
|
||||||
|
|
||||||
|
private final URL location;
|
||||||
|
|
||||||
|
public ExternalResource(URL location) {
|
||||||
|
if(location == null)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract T load() throws IOException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((location == null) ? 0 : location.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;
|
||||||
|
ExternalResource<?> other = (ExternalResource<?>) obj;
|
||||||
|
if (location == null) {
|
||||||
|
if (other.location != null)
|
||||||
|
return false;
|
||||||
|
} else if (!location.equals(other.location))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Library @" + location.toExternalForm();
|
||||||
|
}
|
||||||
|
}
|
16
src/the/bytecode/club/bootloader/ILoader.java
Normal file
16
src/the/bytecode/club/bootloader/ILoader.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 19 Jul 2015 02:29:43
|
||||||
|
*/
|
||||||
|
public abstract interface ILoader {
|
||||||
|
|
||||||
|
public abstract void bind(ExternalResource<JarContents<ClassNode>> resource);
|
||||||
|
|
||||||
|
abstract Class<?> findClass(String name) throws ClassNotFoundException, NoClassDefFoundError;
|
||||||
|
|
||||||
|
public abstract Class<?> loadClass(String name) throws ClassNotFoundException, NoClassDefFoundError;
|
||||||
|
}
|
85
src/the/bytecode/club/bootloader/InitialBootScreen.java
Normal file
85
src/the/bytecode/club/bootloader/InitialBootScreen.java
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.swing.JEditorPane;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JProgressBar;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.text.html.HTMLEditorKit;
|
||||||
|
|
||||||
|
import the.bytecode.club.bytecodeviewer.Resources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 19 Jul 2015 04:12:21
|
||||||
|
*/
|
||||||
|
public class InitialBootScreen extends JFrame {
|
||||||
|
private static final long serialVersionUID = -1098467609722393444L;
|
||||||
|
|
||||||
|
private JProgressBar progressBar = new JProgressBar();
|
||||||
|
|
||||||
|
public InitialBootScreen() throws IOException {
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
this.setIconImages(Resources.iconList);
|
||||||
|
|
||||||
|
int i = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
|
||||||
|
if(i >= 840)
|
||||||
|
setSize(new Dimension(600, 800));
|
||||||
|
else if(i >= 640)
|
||||||
|
setSize(new Dimension(500, 600));
|
||||||
|
else if(i >= 440)
|
||||||
|
setSize(new Dimension(400, 400));
|
||||||
|
else
|
||||||
|
setSize(Toolkit.getDefaultToolkit().getScreenSize());
|
||||||
|
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Starting Up");
|
||||||
|
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||||
|
gridBagLayout.columnWidths = new int[]{0, 0};
|
||||||
|
gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
|
||||||
|
gridBagLayout.rowWeights = new double[]{1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
|
||||||
|
getContentPane().setLayout(gridBagLayout);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane();
|
||||||
|
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
||||||
|
gbc_scrollPane.gridheight = 24;
|
||||||
|
gbc_scrollPane.insets = new Insets(0, 0, 5, 0);
|
||||||
|
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
||||||
|
gbc_scrollPane.gridx = 0;
|
||||||
|
gbc_scrollPane.gridy = 0;
|
||||||
|
getContentPane().add(scrollPane, gbc_scrollPane);
|
||||||
|
|
||||||
|
JEditorPane editorPane = new JEditorPane();
|
||||||
|
editorPane.setEditorKit(new HTMLEditorKit());
|
||||||
|
|
||||||
|
editorPane.setText(convertStreamToString(InitialBootScreen.class.getClassLoader().getResourceAsStream("resources/intro.html")));
|
||||||
|
|
||||||
|
scrollPane.setViewportView(editorPane);
|
||||||
|
|
||||||
|
GridBagConstraints gbc_progressBar = new GridBagConstraints();
|
||||||
|
gbc_progressBar.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
gbc_progressBar.gridx = 0;
|
||||||
|
gbc_progressBar.gridy = 24;
|
||||||
|
getContentPane().add(progressBar, gbc_progressBar);
|
||||||
|
this.setLocationRelativeTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String convertStreamToString(java.io.InputStream is) throws IOException {
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||||
|
String string = s.hasNext() ? s.next() : "";
|
||||||
|
is.close();
|
||||||
|
s.close();
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JProgressBar getProgressBar() {
|
||||||
|
return progressBar;
|
||||||
|
}
|
||||||
|
}
|
142
src/the/bytecode/club/bootloader/JarContents.java
Normal file
142
src/the/bytecode/club/bootloader/JarContents.java
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public class JarContents<C extends ClassNode> {
|
||||||
|
|
||||||
|
private final DataContainer<C> classContents;
|
||||||
|
private final DataContainer<JarResource> resourceContents;
|
||||||
|
|
||||||
|
public JarContents() {
|
||||||
|
classContents = new ClassNodeContainer<C>();
|
||||||
|
resourceContents = new ResourceContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarContents(DataContainer<C> classContents, DataContainer<JarResource> resourceContents) {
|
||||||
|
this.classContents = classContents == null ? new ClassNodeContainer<C>() : classContents;
|
||||||
|
this.resourceContents = resourceContents == null ? new ResourceContainer() : resourceContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final DataContainer<C> getClassContents() {
|
||||||
|
return classContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final DataContainer<JarResource> getResourceContents() {
|
||||||
|
return resourceContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void merge(JarContents<C> contents) {
|
||||||
|
classContents.addAll(contents.classContents);
|
||||||
|
resourceContents.addAll(contents.resourceContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarContents<C> add(JarContents<C> contents) {
|
||||||
|
List<C> c1 = classContents;
|
||||||
|
List<C> c2 = contents.classContents;
|
||||||
|
|
||||||
|
List<JarResource> r1 = resourceContents;
|
||||||
|
List<JarResource> r2 = contents.resourceContents;
|
||||||
|
|
||||||
|
List<C> c3 = new ArrayList<C>(c1.size() + c2.size());
|
||||||
|
c3.addAll(c1);
|
||||||
|
c3.addAll(c2);
|
||||||
|
|
||||||
|
List<JarResource> r3 = new ArrayList<JarResource>(r1.size() + r2.size());
|
||||||
|
r3.addAll(r1);
|
||||||
|
r3.addAll(r2);
|
||||||
|
|
||||||
|
return new JarContents<C>(new ClassNodeContainer<>(c3), new ResourceContainer(r3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ClassNodeContainer<C extends ClassNode> extends DataContainer<C> {
|
||||||
|
private static final long serialVersionUID = -6169578803641192235L;
|
||||||
|
|
||||||
|
private Map<String, C> lastMap = new HashMap<String, C>();
|
||||||
|
private boolean invalidated;
|
||||||
|
|
||||||
|
public ClassNodeContainer() {
|
||||||
|
this(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNodeContainer(int cap) {
|
||||||
|
super(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNodeContainer(Collection<C> data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(C c) {
|
||||||
|
invalidated = true;
|
||||||
|
return super.add(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(Collection<? extends C> c) {
|
||||||
|
invalidated = true;
|
||||||
|
return super.addAll(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object c) {
|
||||||
|
invalidated = true;
|
||||||
|
return super.remove(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, C> namedMap() {
|
||||||
|
if (invalidated) {
|
||||||
|
invalidated = false;
|
||||||
|
Map<String, C> nodeMap = new HashMap<String, C>();
|
||||||
|
Iterator<C> it = iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
C cn = it.next();
|
||||||
|
if (nodeMap.containsKey(cn.name)) {
|
||||||
|
it.remove();
|
||||||
|
} else {
|
||||||
|
nodeMap.put(cn.name, cn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastMap = nodeMap;
|
||||||
|
}
|
||||||
|
return lastMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResourceContainer extends DataContainer<JarResource> {
|
||||||
|
private static final long serialVersionUID = -6169578803641192235L;
|
||||||
|
|
||||||
|
public ResourceContainer() {
|
||||||
|
this(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContainer(int cap) {
|
||||||
|
super(cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceContainer(List<JarResource> data) {
|
||||||
|
addAll(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, JarResource> namedMap() {
|
||||||
|
Map<String, JarResource> map = new HashMap<String, JarResource>();
|
||||||
|
for (JarResource resource : this) {
|
||||||
|
map.put(resource.getName(), resource);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
src/the/bytecode/club/bootloader/JarInfo.java
Normal file
105
src/the/bytecode/club/bootloader/JarInfo.java
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.JarURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds information about a single local or external JarFile.
|
||||||
|
*
|
||||||
|
* @author Bibl
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public class JarInfo {
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
private final JarType type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new holder as the JarFile is on the local system.
|
||||||
|
*
|
||||||
|
* @param path Path to jar.
|
||||||
|
*/
|
||||||
|
public JarInfo(File path) {
|
||||||
|
this(path.getAbsolutePath(), JarType.FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new holder.
|
||||||
|
*
|
||||||
|
* @param path Path to jar.
|
||||||
|
* @param type Type of jar.
|
||||||
|
*/
|
||||||
|
public JarInfo(String path, JarType type) {
|
||||||
|
this.path = path;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new holder.
|
||||||
|
*
|
||||||
|
* @param url URL to jar.
|
||||||
|
*/
|
||||||
|
public JarInfo(URL url) {
|
||||||
|
this(url.toExternalForm(), JarType.WEB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Real path to JarFile.
|
||||||
|
*/
|
||||||
|
public final String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final JarType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a string ready for a {@link JarURLConnection} to connect to.
|
||||||
|
*
|
||||||
|
* @param url Location of the JarFile.
|
||||||
|
* @param type Type of JarFile.
|
||||||
|
* @return The formatted url.
|
||||||
|
* @throws MalformedURLException
|
||||||
|
*/
|
||||||
|
public URL formattedURL() throws MalformedURLException {
|
||||||
|
StringBuilder sb = new StringBuilder().append("jar:").append(type.prefix()).append(path);
|
||||||
|
if (type.equals(JarType.FILE) && !path.endsWith(".jar")) {
|
||||||
|
File file = new File(path);
|
||||||
|
if (!file.exists())
|
||||||
|
sb.append(".jar");
|
||||||
|
}
|
||||||
|
sb.append("!/");
|
||||||
|
return new URL(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = (prime * result) + ((path == null) ? 0 : path.hashCode());
|
||||||
|
result = (prime * result) + ((type == null) ? 0 : type.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;
|
||||||
|
JarInfo other = (JarInfo) obj;
|
||||||
|
if (path == null) {
|
||||||
|
if (other.path != null)
|
||||||
|
return false;
|
||||||
|
} else if (!path.equals(other.path))
|
||||||
|
return false;
|
||||||
|
if (type != other.type)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
54
src/the/bytecode/club/bootloader/JarResource.java
Normal file
54
src/the/bytecode/club/bootloader/JarResource.java
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public class JarResource {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final byte[] data;
|
||||||
|
|
||||||
|
public JarResource(String name, byte[] data) {
|
||||||
|
this.name = name;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = (prime * result) + Arrays.hashCode(data);
|
||||||
|
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;
|
||||||
|
JarResource other = (JarResource) obj;
|
||||||
|
if (!Arrays.equals(data, other.data))
|
||||||
|
return false;
|
||||||
|
if (name == null) {
|
||||||
|
if (other.name != null)
|
||||||
|
return false;
|
||||||
|
} else if (!name.equals(other.name))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
25
src/the/bytecode/club/bootloader/JarType.java
Normal file
25
src/the/bytecode/club/bootloader/JarType.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of Jar Stored.
|
||||||
|
* @author Bibl
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public enum JarType {
|
||||||
|
|
||||||
|
/** Local file **/
|
||||||
|
FILE("file:"),
|
||||||
|
/** External URL **/
|
||||||
|
WEB("");
|
||||||
|
|
||||||
|
private final String prefix;
|
||||||
|
|
||||||
|
private JarType(String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the prefix for the JarURLConnection. **/
|
||||||
|
public String prefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
}
|
150
src/the/bytecode/club/bootloader/LibraryClassLoader.java
Normal file
150
src/the/bytecode/club/bootloader/LibraryClassLoader.java
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 19 Jul 2015 02:48:41
|
||||||
|
*
|
||||||
|
* TODO: Resource loading
|
||||||
|
*/
|
||||||
|
public class LibraryClassLoader extends ClassLoader implements ILoader {
|
||||||
|
|
||||||
|
private final Set<JarContents<ClassNode>> binded;
|
||||||
|
private final Map<String, Class<?>> classCache;
|
||||||
|
private final ClassTree tree;
|
||||||
|
|
||||||
|
public LibraryClassLoader() {
|
||||||
|
binded = new HashSet<JarContents<ClassNode>>();
|
||||||
|
classCache = new HashMap<String, Class<?>>();
|
||||||
|
tree = new ClassTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see the.bytecode.club.bytecodeviewer.loadermodel.ILoader#bind(the.bytecode.club.bytecodeviewer.loadermodel.ExternalResource)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void bind(ExternalResource<JarContents<ClassNode>> resource) {
|
||||||
|
try {
|
||||||
|
JarContents<ClassNode> contents = resource.load();
|
||||||
|
if(contents != null) {
|
||||||
|
binded.add(contents);
|
||||||
|
tree.build(contents.getClassContents().namedMap());
|
||||||
|
} else {
|
||||||
|
System.err.println("Null contents?");
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see the.bytecode.club.bytecodeviewer.loadermodel.ILoader#loadClass(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Class<?> findClass(String name) throws ClassNotFoundException, NoClassDefFoundError {
|
||||||
|
String byte_name = name.replace(".", "/");
|
||||||
|
if(classCache.containsKey(byte_name))
|
||||||
|
return classCache.get(byte_name);
|
||||||
|
|
||||||
|
ClassNode cn = null;
|
||||||
|
for(JarContents<ClassNode> contents : binded) {
|
||||||
|
cn = contents.getClassContents().namedMap().get(byte_name);
|
||||||
|
if(cn != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cn != null) {
|
||||||
|
Class<?> klass = define(cn);
|
||||||
|
if(klass != null) {
|
||||||
|
classCache.put(byte_name, klass);
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.loadClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
protected Class<?> define(ClassNode cn) {
|
||||||
|
ClassWriter writer = new ResolvingClassWriter(tree);
|
||||||
|
cn.accept(cn);
|
||||||
|
byte[] bytes = writer.toByteArray();
|
||||||
|
return defineClass(bytes, 0, bytes.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ResolvingClassWriter extends ClassWriter {
|
||||||
|
|
||||||
|
private final ClassTree classTree;
|
||||||
|
|
||||||
|
public ResolvingClassWriter(ClassTree classTree) {
|
||||||
|
super(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
this.classTree = classTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
void update(Map<String, ClassNode> classes) {
|
||||||
|
classTree.build(classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCommonSuperClass(final String type1, final String type2) {
|
||||||
|
ClassNode ccn = classTree.getClass(type1);
|
||||||
|
ClassNode dcn = classTree.getClass(type2);
|
||||||
|
|
||||||
|
//System.out.println(type1 + " " + type2);
|
||||||
|
if(ccn == null) {
|
||||||
|
classTree.build(create_quick(type1));
|
||||||
|
return getCommonSuperClass(type1, type2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dcn == null) {
|
||||||
|
classTree.build(create_quick(type2));
|
||||||
|
return getCommonSuperClass(type1, type2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<ClassNode> c = classTree.getSupers(ccn);
|
||||||
|
Set<ClassNode> d = classTree.getSupers(dcn);
|
||||||
|
|
||||||
|
if(c.contains(dcn))
|
||||||
|
return type1;
|
||||||
|
|
||||||
|
if(d.contains(ccn))
|
||||||
|
return type2;
|
||||||
|
|
||||||
|
if(Modifier.isInterface(ccn.access) || Modifier.isInterface(dcn.access)) {
|
||||||
|
return "java/lang/Object";
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
ClassNode nccn = classTree.getClass(ccn.superName);
|
||||||
|
if(nccn == null)
|
||||||
|
break;
|
||||||
|
ccn = nccn;
|
||||||
|
c = classTree.getSupers(ccn);
|
||||||
|
} while(!c.contains(dcn));
|
||||||
|
return ccn.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassNode create_quick(String name) {
|
||||||
|
try {
|
||||||
|
ClassReader cr = new ClassReader(name);
|
||||||
|
ClassNode cn = new ClassNode();
|
||||||
|
cr.accept(cn, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
|
||||||
|
return cn;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/the/bytecode/club/bootloader/LocateableJarContents.java
Normal file
28
src/the/bytecode/club/bootloader/LocateableJarContents.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public class LocateableJarContents<C extends ClassNode> extends JarContents<C> {
|
||||||
|
|
||||||
|
private final URL[] jarUrls;
|
||||||
|
|
||||||
|
public LocateableJarContents(URL... jarUrls) {
|
||||||
|
super();
|
||||||
|
this.jarUrls = jarUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocateableJarContents(DataContainer<C> classContents, DataContainer<JarResource> resourceContents, URL... jarUrls) {
|
||||||
|
super(classContents, resourceContents);
|
||||||
|
this.jarUrls = jarUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL[] getJarUrls() {
|
||||||
|
return jarUrls;
|
||||||
|
}
|
||||||
|
}
|
13
src/the/bytecode/club/bootloader/NullCreator.java
Normal file
13
src/the/bytecode/club/bootloader/NullCreator.java
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public class NullCreator<V> implements ValueCreator<V> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V create() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
31
src/the/bytecode/club/bootloader/NullPermeableHashMap.java
Normal file
31
src/the/bytecode/club/bootloader/NullPermeableHashMap.java
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public class NullPermeableHashMap<K, V> extends HashMap<K, V> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final ValueCreator<V> creator;
|
||||||
|
|
||||||
|
public NullPermeableHashMap(ValueCreator<V> creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NullPermeableHashMap() {
|
||||||
|
this(new NullCreator<V>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public V getNonNull(K k) {
|
||||||
|
V val = get(k);
|
||||||
|
if (val == null) {
|
||||||
|
val = creator.create();
|
||||||
|
put(k, val);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
16
src/the/bytecode/club/bootloader/SetCreator.java
Normal file
16
src/the/bytecode/club/bootloader/SetCreator.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created 25 May 2015 (actually before this)
|
||||||
|
*/
|
||||||
|
public class SetCreator<T> implements ValueCreator<Set<T>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<T> create() {
|
||||||
|
return new HashSet<T>();
|
||||||
|
}
|
||||||
|
}
|
10
src/the/bytecode/club/bootloader/ValueCreator.java
Normal file
10
src/the/bytecode/club/bootloader/ValueCreator.java
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package the.bytecode.club.bootloader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Bibl (don't ban me pls)
|
||||||
|
* @created ages ago
|
||||||
|
*/
|
||||||
|
public abstract interface ValueCreator<V> {
|
||||||
|
|
||||||
|
public abstract V create();
|
||||||
|
}
|
212
src/the/bytecode/club/bytecodeviewer/BootScreen.java
Normal file
212
src/the/bytecode/club/bytecodeviewer/BootScreen.java
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
package the.bytecode.club.bytecodeviewer;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Insets;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import javax.swing.JEditorPane;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JProgressBar;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.text.html.HTMLEditorKit;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatic updater for BCV libraries
|
||||||
|
*
|
||||||
|
* @author Konloch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BootScreen extends JFrame {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1098467609722393444L;
|
||||||
|
|
||||||
|
private static boolean FIRST_BOOT = false;
|
||||||
|
|
||||||
|
private JProgressBar progressBar = new JProgressBar();
|
||||||
|
|
||||||
|
public BootScreen() throws IOException {
|
||||||
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
this.setIconImages(Resources.iconList);
|
||||||
|
|
||||||
|
int i = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
|
||||||
|
if(i >= 840)
|
||||||
|
setSize(new Dimension(600, 800));
|
||||||
|
else if(i >= 640)
|
||||||
|
setSize(new Dimension(500, 600));
|
||||||
|
else if(i >= 440)
|
||||||
|
setSize(new Dimension(400, 400));
|
||||||
|
else
|
||||||
|
setSize(Toolkit.getDefaultToolkit().getScreenSize());
|
||||||
|
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Starting Up");
|
||||||
|
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||||
|
gridBagLayout.columnWidths = new int[]{0, 0};
|
||||||
|
gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
|
||||||
|
gridBagLayout.rowWeights = new double[]{1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
|
||||||
|
getContentPane().setLayout(gridBagLayout);
|
||||||
|
|
||||||
|
JScrollPane scrollPane = new JScrollPane();
|
||||||
|
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
||||||
|
gbc_scrollPane.gridheight = 24;
|
||||||
|
gbc_scrollPane.insets = new Insets(0, 0, 5, 0);
|
||||||
|
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
||||||
|
gbc_scrollPane.gridx = 0;
|
||||||
|
gbc_scrollPane.gridy = 0;
|
||||||
|
getContentPane().add(scrollPane, gbc_scrollPane);
|
||||||
|
|
||||||
|
JEditorPane editorPane = new JEditorPane();
|
||||||
|
editorPane.setEditorKit(new HTMLEditorKit());
|
||||||
|
|
||||||
|
editorPane.setText(convertStreamToString(BytecodeViewer.class.getClassLoader().getResourceAsStream("resources/intro.html")));
|
||||||
|
|
||||||
|
scrollPane.setViewportView(editorPane);
|
||||||
|
|
||||||
|
GridBagConstraints gbc_progressBar = new GridBagConstraints();
|
||||||
|
gbc_progressBar.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
gbc_progressBar.gridx = 0;
|
||||||
|
gbc_progressBar.gridy = 24;
|
||||||
|
getContentPane().add(progressBar, gbc_progressBar);
|
||||||
|
this.setLocationRelativeTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String convertStreamToString(java.io.InputStream is) throws IOException {
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||||
|
String string = s.hasNext() ? s.next() : "";
|
||||||
|
is.close();
|
||||||
|
s.close();
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DO_FIRST_BOOT(String args[], int CLI) {
|
||||||
|
if(CLI == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(CLI == 1)
|
||||||
|
this.setVisible(true);
|
||||||
|
|
||||||
|
if(FIRST_BOOT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FIRST_BOOT = true;
|
||||||
|
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Checking Libraries...");
|
||||||
|
System.out.println("Checking Libraries...");
|
||||||
|
|
||||||
|
try {
|
||||||
|
int completedCheck = 0;
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Checking Krakatau...");
|
||||||
|
System.out.println("Checking krakatau");
|
||||||
|
|
||||||
|
File krakatauZip = null;
|
||||||
|
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
|
||||||
|
if(f.getName().toLowerCase().startsWith("krakatau-")) {
|
||||||
|
BytecodeViewer.krakatauVersion = f.getName().split("-")[1].split("\\.")[0];
|
||||||
|
krakatauZip = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
|
||||||
|
if(f.getName().toLowerCase().startsWith("krakatau_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.krakatauVersion)) {
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
|
||||||
|
System.out.println("Removing oudated " + f.getName());
|
||||||
|
try {
|
||||||
|
FileUtils.deleteDirectory(f);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BytecodeViewer.krakatauWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "krakatau_" + BytecodeViewer.krakatauVersion + BytecodeViewer.fs + "Krakatau-master";
|
||||||
|
File krakatauDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "krakatau_" + BytecodeViewer.krakatauVersion);
|
||||||
|
if(!krakatauDirectory.exists()) {
|
||||||
|
try {
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Updating to "+krakatauDirectory.getName()+"...");
|
||||||
|
ZipUtils.unzipFilesToPath(krakatauZip.getAbsolutePath(), krakatauDirectory.getAbsolutePath());
|
||||||
|
System.out.println("Updated to krakatau v" + BytecodeViewer.krakatauVersion);
|
||||||
|
} catch(Exception e) {
|
||||||
|
BytecodeViewer.showMessage("ERROR: There was an issue unzipping Krakatau decompiler (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
|
||||||
|
"If the error persists contact @Konloch.");
|
||||||
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
||||||
|
krakatauZip.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completedCheck++;
|
||||||
|
progressBar.setValue(completedCheck);
|
||||||
|
|
||||||
|
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Checking Enjarify...");
|
||||||
|
System.out.println("Checking enjarify");
|
||||||
|
|
||||||
|
File enjarifyZip = null;
|
||||||
|
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
|
||||||
|
if(f.getName().toLowerCase().startsWith("enjarify-")) {
|
||||||
|
BytecodeViewer.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
|
||||||
|
enjarifyZip = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
|
||||||
|
if(f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.enjarifyVersion)) {
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
|
||||||
|
System.out.println("Removing oudated " + f.getName());
|
||||||
|
try {
|
||||||
|
FileUtils.deleteDirectory(f);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BytecodeViewer.enjarifyWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion + BytecodeViewer.fs + "enjarify-master";
|
||||||
|
File enjarifyDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion);
|
||||||
|
if(!enjarifyDirectory.exists()) {
|
||||||
|
try {
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Updating to "+enjarifyDirectory.getName()+"...");
|
||||||
|
ZipUtils.unzipFilesToPath(enjarifyZip.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
|
||||||
|
System.out.println("Updated to enjarify v" + BytecodeViewer.enjarifyVersion);
|
||||||
|
} catch(Exception e) {
|
||||||
|
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
|
||||||
|
"If the error persists contact @Konloch.");
|
||||||
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
||||||
|
enjarifyZip.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
completedCheck++;
|
||||||
|
progressBar.setValue(completedCheck);
|
||||||
|
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Booting!");
|
||||||
|
|
||||||
|
} catch(Exception e) {
|
||||||
|
Settings.saveGUI();
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
e.printStackTrace(new PrintWriter(sw));
|
||||||
|
e.printStackTrace();
|
||||||
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI("Bytecode Viewer ran into an error while booting, trying to force it anyways."+ BytecodeViewer.nl+ BytecodeViewer.nl+
|
||||||
|
"Please ensure you have an active internet connection and restart BCV. If this presists please visit http://github.com/Konloch/Bytecode-Viewer or http://bytecodeviewer.com"+ BytecodeViewer.nl + BytecodeViewer.nl + sw.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle("Bytecode Viewer Boot Screen - Finished");
|
||||||
|
|
||||||
|
if(CLI == 1)
|
||||||
|
BytecodeViewer.BOOT(args, false);
|
||||||
|
else {
|
||||||
|
BytecodeViewer.BOOT(args, true);
|
||||||
|
CommandLineInput.executeCommandLine(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,6 @@ import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader;
|
import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
|
import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.FileNavigationPane;
|
import the.bytecode.club.bytecodeviewer.gui.FileNavigationPane;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.BootScreen;
|
|
||||||
import the.bytecode.club.bytecodeviewer.gui.MainViewerGUI;
|
import the.bytecode.club.bytecodeviewer.gui.MainViewerGUI;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.RunOptions;
|
import the.bytecode.club.bytecodeviewer.gui.RunOptions;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.SearchingPane;
|
import the.bytecode.club.bytecodeviewer.gui.SearchingPane;
|
||||||
|
@ -323,6 +322,7 @@ public class BytecodeViewer {
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Thread PingBack = new Thread() {
|
public static Thread PingBack = new Thread() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
new HTTPRequest(new URL("https://bytecodeviewer.com/add.php")).read();
|
new HTTPRequest(new URL("https://bytecodeviewer.com/add.php")).read();
|
||||||
|
|
|
@ -1,403 +0,0 @@
|
||||||
package the.bytecode.club.bytecodeviewer.gui;
|
|
||||||
|
|
||||||
import javax.swing.JEditorPane;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.GridBagLayout;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
|
|
||||||
import javax.swing.JProgressBar;
|
|
||||||
|
|
||||||
import java.awt.GridBagConstraints;
|
|
||||||
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
|
|
||||||
import java.awt.Insets;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
|
|
||||||
import javax.swing.text.html.HTMLEditorKit;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
|
||||||
import the.bytecode.club.bytecodeviewer.CommandLineInput;
|
|
||||||
import the.bytecode.club.bytecodeviewer.Resources;
|
|
||||||
import the.bytecode.club.bytecodeviewer.Settings;
|
|
||||||
import the.bytecode.club.bytecodeviewer.ZipUtils;
|
|
||||||
import me.konloch.kontainer.io.HTTPRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Automatic updater for BCV libraries
|
|
||||||
*
|
|
||||||
* @author Konloch
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class BootScreen extends JFrame {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -1098467609722393444L;
|
|
||||||
|
|
||||||
private static boolean FIRST_BOOT = false;
|
|
||||||
|
|
||||||
private JProgressBar progressBar = new JProgressBar();
|
|
||||||
|
|
||||||
public BootScreen() throws IOException {
|
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
||||||
this.setIconImages(Resources.iconList);
|
|
||||||
|
|
||||||
int i = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
|
|
||||||
if(i >= 840)
|
|
||||||
setSize(new Dimension(600, 800));
|
|
||||||
else if(i >= 640)
|
|
||||||
setSize(new Dimension(500, 600));
|
|
||||||
else if(i >= 440)
|
|
||||||
setSize(new Dimension(400, 400));
|
|
||||||
else
|
|
||||||
setSize(Toolkit.getDefaultToolkit().getScreenSize());
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Starting Up");
|
|
||||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
|
||||||
gridBagLayout.columnWidths = new int[]{0, 0};
|
|
||||||
gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
|
|
||||||
gridBagLayout.rowWeights = new double[]{1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
|
|
||||||
getContentPane().setLayout(gridBagLayout);
|
|
||||||
|
|
||||||
JScrollPane scrollPane = new JScrollPane();
|
|
||||||
GridBagConstraints gbc_scrollPane = new GridBagConstraints();
|
|
||||||
gbc_scrollPane.gridheight = 24;
|
|
||||||
gbc_scrollPane.insets = new Insets(0, 0, 5, 0);
|
|
||||||
gbc_scrollPane.fill = GridBagConstraints.BOTH;
|
|
||||||
gbc_scrollPane.gridx = 0;
|
|
||||||
gbc_scrollPane.gridy = 0;
|
|
||||||
getContentPane().add(scrollPane, gbc_scrollPane);
|
|
||||||
|
|
||||||
JEditorPane editorPane = new JEditorPane();
|
|
||||||
editorPane.setEditorKit(new HTMLEditorKit());
|
|
||||||
|
|
||||||
editorPane.setText(convertStreamToString(BytecodeViewer.class.getClassLoader().getResourceAsStream("resources/intro.html")));
|
|
||||||
|
|
||||||
scrollPane.setViewportView(editorPane);
|
|
||||||
|
|
||||||
GridBagConstraints gbc_progressBar = new GridBagConstraints();
|
|
||||||
gbc_progressBar.fill = GridBagConstraints.HORIZONTAL;
|
|
||||||
gbc_progressBar.gridx = 0;
|
|
||||||
gbc_progressBar.gridy = 24;
|
|
||||||
getContentPane().add(progressBar, gbc_progressBar);
|
|
||||||
this.setLocationRelativeTo(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
static String convertStreamToString(java.io.InputStream is) throws IOException {
|
|
||||||
@SuppressWarnings("resource")
|
|
||||||
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
|
||||||
String string = s.hasNext() ? s.next() : "";
|
|
||||||
is.close();
|
|
||||||
s.close();
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DO_FIRST_BOOT(String args[], int CLI) {
|
|
||||||
if(CLI == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(CLI == 1)
|
|
||||||
this.setVisible(true);
|
|
||||||
|
|
||||||
if(FIRST_BOOT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FIRST_BOOT = true;
|
|
||||||
boolean foundAtleastOne = false;
|
|
||||||
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Checking Libraries...");
|
|
||||||
System.out.println("Checking Libraries...");
|
|
||||||
|
|
||||||
File libsDirectory = new File(BytecodeViewer.libsDirectory);
|
|
||||||
|
|
||||||
try {
|
|
||||||
int completedCheck = 0;
|
|
||||||
List<String> urlList = new ArrayList<String>();
|
|
||||||
HTTPRequest req = new HTTPRequest(new URL("https://github.com/Konloch/bytecode-viewer/tree/master/libs"));
|
|
||||||
for(String s : req.read())
|
|
||||||
if(s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/")) {
|
|
||||||
urlList.add("https://github.com"+s.split("<a href=")[1].split("\"")[1]);
|
|
||||||
foundAtleastOne = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!foundAtleastOne) {
|
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI("Bytecode Viewer ran into an issue, for some reason github is not returning what we're expecting. Please try rebooting, if this issue persists please contact @Konloch.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(args.length >= 1)
|
|
||||||
if(args[0].equalsIgnoreCase("-clean"))
|
|
||||||
libsDirectory.delete();
|
|
||||||
|
|
||||||
if(!libsDirectory.exists())
|
|
||||||
libsDirectory.mkdir();
|
|
||||||
|
|
||||||
List<String> libsList = new ArrayList<String>();
|
|
||||||
List<String> libsFileList = new ArrayList<String>();
|
|
||||||
for(File f : libsDirectory.listFiles()) {
|
|
||||||
libsList.add(f.getName());
|
|
||||||
libsFileList.add(f.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
progressBar.setMaximum(urlList.size()*2);
|
|
||||||
|
|
||||||
for(String s : urlList) {
|
|
||||||
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length());
|
|
||||||
if(!libsList.contains(fileName)) {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Downloading " + fileName);
|
|
||||||
System.out.println("Downloading " + fileName);
|
|
||||||
boolean passed = false;
|
|
||||||
while(!passed) {
|
|
||||||
InputStream is = null;
|
|
||||||
FileOutputStream fos = null;
|
|
||||||
try {
|
|
||||||
is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream();
|
|
||||||
fos = new FileOutputStream(BytecodeViewer.libsDirectory + BytecodeViewer.fs + fileName);
|
|
||||||
System.out.println("Downloading from "+s);
|
|
||||||
byte[] buffer = new byte[8192];
|
|
||||||
int len;
|
|
||||||
int downloaded = 0;
|
|
||||||
boolean flag = false;
|
|
||||||
while ((len = is.read(buffer)) > 0) {
|
|
||||||
fos.write(buffer, 0, len);
|
|
||||||
fos.flush();
|
|
||||||
downloaded += 8192;
|
|
||||||
int mbs = downloaded / 1048576;
|
|
||||||
if(mbs % 5 == 0 && mbs != 0) {
|
|
||||||
if(!flag)
|
|
||||||
System.out.println("Downloaded " + mbs + "MBs so far");
|
|
||||||
flag = true;
|
|
||||||
} else
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
libsFileList.add(BytecodeViewer.libsDirectory + BytecodeViewer.fs + fileName);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (is != null) {
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (fos != null) {
|
|
||||||
fos.flush();
|
|
||||||
}
|
|
||||||
if (fos != null) {
|
|
||||||
fos.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("Download finished!");
|
|
||||||
passed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completedCheck++;
|
|
||||||
progressBar.setValue(completedCheck);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(BytecodeViewer.deleteForiegnLibraries) {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Checking & Deleting Foreign/Outdated Libraries...");
|
|
||||||
System.out.println("Checking & Deleting foreign/outdated libraries");
|
|
||||||
for(String s : libsFileList) {
|
|
||||||
File f = new File(s);
|
|
||||||
boolean delete = true;
|
|
||||||
for(String urlS : urlList) {
|
|
||||||
String fileName = urlS.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), urlS.length());
|
|
||||||
if(fileName.equals(f.getName()))
|
|
||||||
delete = false;
|
|
||||||
}
|
|
||||||
if(delete) {
|
|
||||||
f.delete();
|
|
||||||
System.out.println("Detected & Deleted Foriegn/Outdated Jar/File: " + f.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Loading Libraries...");
|
|
||||||
System.out.println("Loading libraries...");
|
|
||||||
|
|
||||||
for(String s : libsFileList ) {
|
|
||||||
if(s.endsWith(".jar")) {
|
|
||||||
File f = new File(s);
|
|
||||||
if(f.exists()) {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Loading Library " + f.getName());
|
|
||||||
System.out.println("Loading library " + f.getName());
|
|
||||||
|
|
||||||
try {
|
|
||||||
JarFile jarFile = new JarFile(s);
|
|
||||||
Enumeration<JarEntry> e = jarFile.entries();
|
|
||||||
ClassPathHack.addFile(f);
|
|
||||||
while (e.hasMoreElements()) {
|
|
||||||
JarEntry je = (JarEntry) e.nextElement();
|
|
||||||
if(je.isDirectory() || !je.getName().endsWith(".class")){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
String className = je.getName().substring(0,je.getName().length()-6);
|
|
||||||
className = className.replace('/', '.');
|
|
||||||
ClassLoader.getSystemClassLoader().loadClass(className);
|
|
||||||
} catch(java.lang.VerifyError | java.lang.ExceptionInInitializerError | java.lang.IncompatibleClassChangeError | java.lang.NoClassDefFoundError | Exception e2) {
|
|
||||||
//ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("Succesfully loaded " + f.getName());
|
|
||||||
jarFile.close();
|
|
||||||
} catch(java.util.zip.ZipException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
f.delete();
|
|
||||||
BytecodeViewer.showMessage("Error, Library " + f.getName() + " is corrupt, please restart to redownload it.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completedCheck++;
|
|
||||||
progressBar.setValue(completedCheck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Checking Krakatau...");
|
|
||||||
System.out.println("Checking krakatau");
|
|
||||||
|
|
||||||
File krakatauZip = null;
|
|
||||||
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
|
|
||||||
if(f.getName().toLowerCase().startsWith("krakatau-")) {
|
|
||||||
BytecodeViewer.krakatauVersion = f.getName().split("-")[1].split("\\.")[0];
|
|
||||||
krakatauZip = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
|
|
||||||
if(f.getName().toLowerCase().startsWith("krakatau_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.krakatauVersion)) {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
|
|
||||||
System.out.println("Removing oudated " + f.getName());
|
|
||||||
try {
|
|
||||||
FileUtils.deleteDirectory(f);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BytecodeViewer.krakatauWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "krakatau_" + BytecodeViewer.krakatauVersion + BytecodeViewer.fs + "Krakatau-master";
|
|
||||||
File krakatauDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "krakatau_" + BytecodeViewer.krakatauVersion);
|
|
||||||
if(!krakatauDirectory.exists()) {
|
|
||||||
try {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Updating to "+krakatauDirectory.getName()+"...");
|
|
||||||
ZipUtils.unzipFilesToPath(krakatauZip.getAbsolutePath(), krakatauDirectory.getAbsolutePath());
|
|
||||||
System.out.println("Updated to krakatau v" + BytecodeViewer.krakatauVersion);
|
|
||||||
} catch(Exception e) {
|
|
||||||
BytecodeViewer.showMessage("ERROR: There was an issue unzipping Krakatau decompiler (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
|
|
||||||
"If the error persists contact @Konloch.");
|
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
|
||||||
krakatauZip.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
completedCheck++;
|
|
||||||
progressBar.setValue(completedCheck);
|
|
||||||
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Checking Enjarify...");
|
|
||||||
System.out.println("Checking enjarify");
|
|
||||||
|
|
||||||
File enjarifyZip = null;
|
|
||||||
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
|
|
||||||
if(f.getName().toLowerCase().startsWith("enjarify-")) {
|
|
||||||
BytecodeViewer.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
|
|
||||||
enjarifyZip = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
|
|
||||||
if(f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.enjarifyVersion)) {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
|
|
||||||
System.out.println("Removing oudated " + f.getName());
|
|
||||||
try {
|
|
||||||
FileUtils.deleteDirectory(f);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BytecodeViewer.enjarifyWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion + BytecodeViewer.fs + "enjarify-master";
|
|
||||||
File enjarifyDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion);
|
|
||||||
if(!enjarifyDirectory.exists()) {
|
|
||||||
try {
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Updating to "+enjarifyDirectory.getName()+"...");
|
|
||||||
ZipUtils.unzipFilesToPath(enjarifyZip.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
|
|
||||||
System.out.println("Updated to enjarify v" + BytecodeViewer.enjarifyVersion);
|
|
||||||
} catch(Exception e) {
|
|
||||||
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
|
|
||||||
"If the error persists contact @Konloch.");
|
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
|
||||||
enjarifyZip.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
completedCheck++;
|
|
||||||
progressBar.setValue(completedCheck);
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Booting!");
|
|
||||||
|
|
||||||
} catch(Exception e) {
|
|
||||||
Settings.saveGUI();
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
e.printStackTrace(new PrintWriter(sw));
|
|
||||||
e.printStackTrace();
|
|
||||||
new the.bytecode.club.bytecodeviewer.api.ExceptionUI("Bytecode Viewer ran into an error while booting, trying to force it anyways."+ BytecodeViewer.nl+ BytecodeViewer.nl+
|
|
||||||
"Please ensure you have an active internet connection and restart BCV. If this presists please visit http://github.com/Konloch/Bytecode-Viewer or http://bytecodeviewer.com"+ BytecodeViewer.nl + BytecodeViewer.nl + sw.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
setTitle("Bytecode Viewer Boot Screen - Finished");
|
|
||||||
|
|
||||||
if(CLI == 1)
|
|
||||||
BytecodeViewer.BOOT(args, false);
|
|
||||||
else {
|
|
||||||
BytecodeViewer.BOOT(args, true);
|
|
||||||
CommandLineInput.executeCommandLine(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ClassPathHack {
|
|
||||||
private static final Class<?>[] parameters = new Class[] {URL.class};
|
|
||||||
|
|
||||||
public static void addFile(File f) throws IOException {
|
|
||||||
// f.toURL is deprecated
|
|
||||||
addURL(f.toURI().toURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void addURL(URL u) throws IOException {
|
|
||||||
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
|
||||||
Class<?> sysclass = URLClassLoader.class;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Method method = sysclass.getDeclaredMethod("addURL", parameters);
|
|
||||||
method.setAccessible(true);
|
|
||||||
method.invoke(sysloader, u);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue