/* * Copyright � 2015 | Alexander01998 | All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package tk.wurst_client.hooks.reader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Opcodes; import tk.wurst_client.hooks.reader.data.JarData; public class JarDataReader { private JTree tree; public JarDataReader(JTree tree) { this.tree = tree; } public JarData read(File file) throws IOException { DefaultMutableTreeNode root = new DefaultMutableTreeNode(file.getName()); JarData jarData = new JarData(); JarInputStream input = new JarInputStream(new FileInputStream(file)); for(JarEntry entry; (entry = input.getNextJarEntry()) != null;) if(entry.isDirectory()) root.add(new DefaultMutableTreeNode(entry.getName() .substring(0, entry.getName().length() - 1) .replace("/", "."), true)); else if(entry.getName().endsWith(".class")) { ClassReader reader = new ClassReader(input); ClassDataReader wReader = new ClassDataReader(Opcodes.ASM4, jarData); reader.accept(wReader, 0); if(entry.getName().contains("/")) getNode( root, entry.getName() .substring(0, entry.getName().lastIndexOf("/")) .replace("/", ".")).add( new DefaultMutableTreeNode(entry.getName().substring( entry.getName().lastIndexOf("/") + 1), false)); else root.add(new DefaultMutableTreeNode(entry.getName(), false)); }else if(entry.getName().contains("/")) getNode( root, entry.getName() .substring(0, entry.getName().lastIndexOf("/")) .replace("/", ".")).add( new DefaultMutableTreeNode(entry.getName().substring( entry.getName().lastIndexOf("/") + 1), false)); else root.add(new DefaultMutableTreeNode(entry, false)); input.close(); getNode(root, "META-INF").add( new DefaultMutableTreeNode("MANIFEST.MF", false)); sortNode(root); tree.setModel(new DefaultTreeModel(root)); return jarData; } private DefaultMutableTreeNode getNode(DefaultMutableTreeNode root, String s) { @SuppressWarnings("unchecked") Enumeration<DefaultMutableTreeNode> nodes = root.depthFirstEnumeration(); while(nodes.hasMoreElements()) { DefaultMutableTreeNode node = nodes.nextElement(); if(node.toString().equalsIgnoreCase(s)) return node; } DefaultMutableTreeNode node = new DefaultMutableTreeNode(s, true); root.add(node); return node; } private void sortNode(DefaultMutableTreeNode node) { List<DefaultMutableTreeNode> packages = new ArrayList<DefaultMutableTreeNode>(); List<DefaultMutableTreeNode> classes = new ArrayList<DefaultMutableTreeNode>(); List<DefaultMutableTreeNode> files = new ArrayList<DefaultMutableTreeNode>(); for(Enumeration subnodes = node.children(); subnodes.hasMoreElements();) { DefaultMutableTreeNode subnode = (DefaultMutableTreeNode)subnodes.nextElement(); if(subnode.getAllowsChildren()) { if(subnode.getChildCount() > 0) { sortNode(subnode); packages.add(subnode); } }else if(subnode.toString().endsWith(".class")) classes.add(new DefaultMutableTreeNode(subnode.toString() .substring(0, subnode.toString().length() - 6), false)); else files.add(subnode); } node.removeAllChildren(); packages .sort((DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) -> o1 .toString().compareToIgnoreCase(o2.toString())); for(DefaultMutableTreeNode packageNode : packages) node.add(packageNode); classes .sort((DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) -> o1 .toString().compareToIgnoreCase(o2.toString())); for(DefaultMutableTreeNode classNode : classes) node.add(classNode); files.sort((DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) -> o1 .toString().compareToIgnoreCase(o2.toString())); for(DefaultMutableTreeNode fileNode : files) node.add(fileNode); } }