From 8a6e6c0542d1d2ce8308670f63d099c9d1bfacaf Mon Sep 17 00:00:00 2001 From: TheBiblMan Date: Sun, 19 Jul 2015 04:21:23 +0100 Subject: [PATCH] faster loading. (please fix this fucking code, it's too bad) -Bibl --- src/the/bytecode/club/bootloader/Boot.java | 198 +++++++++ .../bytecode/club/bootloader/ClassHelper.java | 35 ++ .../bytecode/club/bootloader/ClassTree.java | 207 +++++++++ .../club/bootloader/DataContainer.java | 28 ++ .../club/bootloader/ExternalLibrary.java | 87 ++++ .../club/bootloader/ExternalResource.java | 55 +++ src/the/bytecode/club/bootloader/ILoader.java | 16 + .../club/bootloader/InitialBootScreen.java | 85 ++++ .../bytecode/club/bootloader/JarContents.java | 142 ++++++ src/the/bytecode/club/bootloader/JarInfo.java | 105 +++++ .../bytecode/club/bootloader/JarResource.java | 54 +++ src/the/bytecode/club/bootloader/JarType.java | 25 ++ .../club/bootloader/LibraryClassLoader.java | 150 +++++++ .../bootloader/LocateableJarContents.java | 28 ++ .../bytecode/club/bootloader/NullCreator.java | 13 + .../club/bootloader/NullPermeableHashMap.java | 31 ++ .../bytecode/club/bootloader/SetCreator.java | 16 + .../club/bootloader/ValueCreator.java | 10 + .../club/bytecodeviewer/BootScreen.java | 212 +++++++++ .../club/bytecodeviewer/BytecodeViewer.java | 2 +- .../club/bytecodeviewer/gui/BootScreen.java | 403 ------------------ 21 files changed, 1498 insertions(+), 404 deletions(-) create mode 100644 src/the/bytecode/club/bootloader/Boot.java create mode 100644 src/the/bytecode/club/bootloader/ClassHelper.java create mode 100644 src/the/bytecode/club/bootloader/ClassTree.java create mode 100644 src/the/bytecode/club/bootloader/DataContainer.java create mode 100644 src/the/bytecode/club/bootloader/ExternalLibrary.java create mode 100644 src/the/bytecode/club/bootloader/ExternalResource.java create mode 100644 src/the/bytecode/club/bootloader/ILoader.java create mode 100644 src/the/bytecode/club/bootloader/InitialBootScreen.java create mode 100644 src/the/bytecode/club/bootloader/JarContents.java create mode 100644 src/the/bytecode/club/bootloader/JarInfo.java create mode 100644 src/the/bytecode/club/bootloader/JarResource.java create mode 100644 src/the/bytecode/club/bootloader/JarType.java create mode 100644 src/the/bytecode/club/bootloader/LibraryClassLoader.java create mode 100644 src/the/bytecode/club/bootloader/LocateableJarContents.java create mode 100644 src/the/bytecode/club/bootloader/NullCreator.java create mode 100644 src/the/bytecode/club/bootloader/NullPermeableHashMap.java create mode 100644 src/the/bytecode/club/bootloader/SetCreator.java create mode 100644 src/the/bytecode/club/bootloader/ValueCreator.java create mode 100644 src/the/bytecode/club/bytecodeviewer/BootScreen.java delete mode 100644 src/the/bytecode/club/bytecodeviewer/gui/BootScreen.java diff --git a/src/the/bytecode/club/bootloader/Boot.java b/src/the/bytecode/club/bootloader/Boot.java new file mode 100644 index 00000000..7b5812b0 --- /dev/null +++ b/src/the/bytecode/club/bootloader/Boot.java @@ -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 urlList = new ArrayList(); + 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(" libsList = new ArrayList(); + List libsFileList = new ArrayList(); + 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(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/ClassHelper.java b/src/the/bytecode/club/bootloader/ClassHelper.java new file mode 100644 index 00000000..9a7cdd04 --- /dev/null +++ b/src/the/bytecode/club/bootloader/ClassHelper.java @@ -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 convertToMap(Collection classes) { + Map map = new HashMap(); + for (ClassNode cn : classes) { + map.put(cn.name, cn); + } + return map; + } + + public static Map copyOf(Map src) { + Map dst = new HashMap(); + copy(src, dst); + return dst; + } + + public static void copy(Map src, Map dst) { + for(Entry e : src.entrySet()) { + dst.put(e.getKey(), e.getValue()); + } + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/ClassTree.java b/src/the/bytecode/club/bootloader/ClassTree.java new file mode 100644 index 00000000..75521fbc --- /dev/null +++ b/src/the/bytecode/club/bootloader/ClassTree.java @@ -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 SET_CREATOR = new SetCreator(); + + private final Map classes; + private final NullPermeableHashMap> supers; + private final NullPermeableHashMap> delgates; + + public ClassTree() { + classes = new HashMap(); + supers = new NullPermeableHashMap>(SET_CREATOR); + delgates = new NullPermeableHashMap>(SET_CREATOR); + } + + public ClassTree(Collection classes) { + this(convertToMap(classes)); + } + + public ClassTree(Map classes_) { + classes = copyOf(classes_); + supers = new NullPermeableHashMap>(SET_CREATOR); + delgates = new NullPermeableHashMap>(SET_CREATOR); + + build(classes); + } + + // TODO: optimise + public void build(Map 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 superinterfaces = new HashSet(); + 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 superinterfaces = new HashSet(); + 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 superinterfaces = new HashSet(); + 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 superinterfaces = new HashSet(); + 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 classes, Collection 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 getMethodsFromSuper(MethodNode m) { + return getMethodsFromSuper(m.owner, m.name, m.desc); + } + + public Set getMethodsFromSuper(ClassNode node, String name, String desc) { + Set methods = new HashSet(); + 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 getMethodsFromDelegates(MethodNode m) { + return getMethodsFromDelegates(m.owner, m.name, m.desc); + } + + public Set getMethodsFromDelegates(ClassNode node, String name, String desc) { + Set methods = new HashSet(); + 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 getSupers0(ClassNode cn) { + return supers.getNonNull(cn); + } + + private Set getDelegates0(ClassNode cn) { + return delgates.getNonNull(cn); + } + + public Map getClasses() { + return classes; + } + + public Set getSupers(ClassNode cn) { + return Collections.unmodifiableSet(supers.get(cn)); + // return supers.get(cn); + } + + public Set getDelegates(ClassNode cn) { + return Collections.unmodifiableSet(delgates.get(cn)); + // return delgates.get(cn); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/DataContainer.java b/src/the/bytecode/club/bootloader/DataContainer.java new file mode 100644 index 00000000..7ed158c1 --- /dev/null +++ b/src/the/bytecode/club/bootloader/DataContainer.java @@ -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 extends ArrayList { + + private static final long serialVersionUID = -9022506488647444546L; + + public DataContainer() { + this(16); + } + + public DataContainer(int cap) { + super(cap); + } + + public DataContainer(Collection data) { + addAll(data); + } + + public abstract Map namedMap(); +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/ExternalLibrary.java b/src/the/bytecode/club/bootloader/ExternalLibrary.java new file mode 100644 index 00000000..b8b7194a --- /dev/null +++ b/src/the/bytecode/club/bootloader/ExternalLibrary.java @@ -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> { + + /** + * @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 load() throws IOException { + JarContents contents = new JarContents(); + + JarURLConnection con = (JarURLConnection) getLocation().openConnection(); + JarFile jar = con.getJarFile(); + + Enumeration 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; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/ExternalResource.java b/src/the/bytecode/club/bootloader/ExternalResource.java new file mode 100644 index 00000000..0832c268 --- /dev/null +++ b/src/the/bytecode/club/bootloader/ExternalResource.java @@ -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 { + + 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(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/ILoader.java b/src/the/bytecode/club/bootloader/ILoader.java new file mode 100644 index 00000000..4a32679e --- /dev/null +++ b/src/the/bytecode/club/bootloader/ILoader.java @@ -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> resource); + + abstract Class findClass(String name) throws ClassNotFoundException, NoClassDefFoundError; + + public abstract Class loadClass(String name) throws ClassNotFoundException, NoClassDefFoundError; +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/InitialBootScreen.java b/src/the/bytecode/club/bootloader/InitialBootScreen.java new file mode 100644 index 00000000..de8b5ccd --- /dev/null +++ b/src/the/bytecode/club/bootloader/InitialBootScreen.java @@ -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; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/JarContents.java b/src/the/bytecode/club/bootloader/JarContents.java new file mode 100644 index 00000000..47748317 --- /dev/null +++ b/src/the/bytecode/club/bootloader/JarContents.java @@ -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 { + + private final DataContainer classContents; + private final DataContainer resourceContents; + + public JarContents() { + classContents = new ClassNodeContainer(); + resourceContents = new ResourceContainer(); + } + + public JarContents(DataContainer classContents, DataContainer resourceContents) { + this.classContents = classContents == null ? new ClassNodeContainer() : classContents; + this.resourceContents = resourceContents == null ? new ResourceContainer() : resourceContents; + } + + public final DataContainer getClassContents() { + return classContents; + } + + public final DataContainer getResourceContents() { + return resourceContents; + } + + public void merge(JarContents contents) { + classContents.addAll(contents.classContents); + resourceContents.addAll(contents.resourceContents); + } + + public JarContents add(JarContents contents) { + List c1 = classContents; + List c2 = contents.classContents; + + List r1 = resourceContents; + List r2 = contents.resourceContents; + + List c3 = new ArrayList(c1.size() + c2.size()); + c3.addAll(c1); + c3.addAll(c2); + + List r3 = new ArrayList(r1.size() + r2.size()); + r3.addAll(r1); + r3.addAll(r2); + + return new JarContents(new ClassNodeContainer<>(c3), new ResourceContainer(r3)); + } + + public static class ClassNodeContainer extends DataContainer { + private static final long serialVersionUID = -6169578803641192235L; + + private Map lastMap = new HashMap(); + private boolean invalidated; + + public ClassNodeContainer() { + this(16); + } + + public ClassNodeContainer(int cap) { + super(cap); + } + + public ClassNodeContainer(Collection data) { + super(data); + } + + @Override + public boolean add(C c) { + invalidated = true; + return super.add(c); + } + + @Override + public boolean addAll(Collection c) { + invalidated = true; + return super.addAll(c); + } + + @Override + public boolean remove(Object c) { + invalidated = true; + return super.remove(c); + } + + @Override + public Map namedMap() { + if (invalidated) { + invalidated = false; + Map nodeMap = new HashMap(); + Iterator 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 { + private static final long serialVersionUID = -6169578803641192235L; + + public ResourceContainer() { + this(16); + } + + public ResourceContainer(int cap) { + super(cap); + } + + public ResourceContainer(List data) { + addAll(data); + } + + @Override + public Map namedMap() { + Map map = new HashMap(); + for (JarResource resource : this) { + map.put(resource.getName(), resource); + } + return map; + } + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/JarInfo.java b/src/the/bytecode/club/bootloader/JarInfo.java new file mode 100644 index 00000000..765be06d --- /dev/null +++ b/src/the/bytecode/club/bootloader/JarInfo.java @@ -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; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/JarResource.java b/src/the/bytecode/club/bootloader/JarResource.java new file mode 100644 index 00000000..a79a3fbf --- /dev/null +++ b/src/the/bytecode/club/bootloader/JarResource.java @@ -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; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/JarType.java b/src/the/bytecode/club/bootloader/JarType.java new file mode 100644 index 00000000..2a27a59f --- /dev/null +++ b/src/the/bytecode/club/bootloader/JarType.java @@ -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; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/LibraryClassLoader.java b/src/the/bytecode/club/bootloader/LibraryClassLoader.java new file mode 100644 index 00000000..98675ba0 --- /dev/null +++ b/src/the/bytecode/club/bootloader/LibraryClassLoader.java @@ -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> binded; + private final Map> classCache; + private final ClassTree tree; + + public LibraryClassLoader() { + binded = new HashSet>(); + classCache = new HashMap>(); + tree = new ClassTree(); + } + + /* (non-Javadoc) + * @see the.bytecode.club.bytecodeviewer.loadermodel.ILoader#bind(the.bytecode.club.bytecodeviewer.loadermodel.ExternalResource) + */ + @Override + public void bind(ExternalResource> resource) { + try { + JarContents 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 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 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 c = classTree.getSupers(ccn); + Set 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; + } + } + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/LocateableJarContents.java b/src/the/bytecode/club/bootloader/LocateableJarContents.java new file mode 100644 index 00000000..c598dbfd --- /dev/null +++ b/src/the/bytecode/club/bootloader/LocateableJarContents.java @@ -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 extends JarContents { + + private final URL[] jarUrls; + + public LocateableJarContents(URL... jarUrls) { + super(); + this.jarUrls = jarUrls; + } + + public LocateableJarContents(DataContainer classContents, DataContainer resourceContents, URL... jarUrls) { + super(classContents, resourceContents); + this.jarUrls = jarUrls; + } + + public URL[] getJarUrls() { + return jarUrls; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/NullCreator.java b/src/the/bytecode/club/bootloader/NullCreator.java new file mode 100644 index 00000000..91fc45cf --- /dev/null +++ b/src/the/bytecode/club/bootloader/NullCreator.java @@ -0,0 +1,13 @@ +package the.bytecode.club.bootloader; + +/** + * @author Bibl (don't ban me pls) + * @created ages ago + */ +public class NullCreator implements ValueCreator { + + @Override + public V create() { + return null; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/NullPermeableHashMap.java b/src/the/bytecode/club/bootloader/NullPermeableHashMap.java new file mode 100644 index 00000000..9a93edf4 --- /dev/null +++ b/src/the/bytecode/club/bootloader/NullPermeableHashMap.java @@ -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 extends HashMap { + + private static final long serialVersionUID = 1L; + + private final ValueCreator creator; + + public NullPermeableHashMap(ValueCreator creator) { + this.creator = creator; + } + + public NullPermeableHashMap() { + this(new NullCreator()); + } + + public V getNonNull(K k) { + V val = get(k); + if (val == null) { + val = creator.create(); + put(k, val); + } + return val; + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/SetCreator.java b/src/the/bytecode/club/bootloader/SetCreator.java new file mode 100644 index 00000000..fd161495 --- /dev/null +++ b/src/the/bytecode/club/bootloader/SetCreator.java @@ -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 implements ValueCreator> { + + @Override + public Set create() { + return new HashSet(); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bootloader/ValueCreator.java b/src/the/bytecode/club/bootloader/ValueCreator.java new file mode 100644 index 00000000..3e6970a9 --- /dev/null +++ b/src/the/bytecode/club/bootloader/ValueCreator.java @@ -0,0 +1,10 @@ +package the.bytecode.club.bootloader; + +/** + * @author Bibl (don't ban me pls) + * @created ages ago + */ +public abstract interface ValueCreator { + + public abstract V create(); +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/BootScreen.java b/src/the/bytecode/club/bytecodeviewer/BootScreen.java new file mode 100644 index 00000000..21074fb2 --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/BootScreen.java @@ -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); + } +} \ No newline at end of file diff --git a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index 62c50984..1c820636 100644 --- a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -34,7 +34,6 @@ import org.objectweb.asm.tree.ClassNode; import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader; import the.bytecode.club.bytecodeviewer.gui.ClassViewer; 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.RunOptions; import the.bytecode.club.bytecodeviewer.gui.SearchingPane; @@ -323,6 +322,7 @@ public class BytecodeViewer { }; public static Thread PingBack = new Thread() { + @Override public void run() { try { new HTTPRequest(new URL("https://bytecodeviewer.com/add.php")).read(); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/BootScreen.java b/src/the/bytecode/club/bytecodeviewer/gui/BootScreen.java deleted file mode 100644 index 0b276be7..00000000 --- a/src/the/bytecode/club/bytecodeviewer/gui/BootScreen.java +++ /dev/null @@ -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 urlList = new ArrayList(); - 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("= 1) - if(args[0].equalsIgnoreCase("-clean")) - libsDirectory.delete(); - - if(!libsDirectory.exists()) - libsDirectory.mkdir(); - - List libsList = new ArrayList(); - List libsFileList = new ArrayList(); - 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 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(); - } - - } - } - -}