package gui; import com.jgoodies.forms.factories.FormFactory; import com.jgoodies.forms.layout.ColumnSpec; import com.jgoodies.forms.layout.FormLayout; import com.jgoodies.forms.layout.RowSpec; import parser.apk.APK; import parser.dex.DEX; import parser.utils.FileTypesDetector; import tree.TreeNode; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.HashMap; import java.util.HashSet; public class StringSearcher extends JPanel { final JTextField searchMethod; JTree treePkg; public StringSearcher() { // ----------------------------------------------- Layout ------------------------------------------------------ setLayout(new FormLayout(new ColumnSpec[]{ColumnSpec.decode("11dlu"), ColumnSpec.decode("min:grow"), FormFactory.LABEL_COMPONENT_GAP_COLSPEC, ColumnSpec.decode("100px"), ColumnSpec.decode("10dlu"),}, new RowSpec[]{RowSpec.decode("15dlu"), RowSpec.decode("23px"), RowSpec.decode("21px"), RowSpec.decode("23px"), FormFactory.RELATED_GAP_ROWSPEC, RowSpec.decode("default:grow"), FormFactory.DEFAULT_ROWSPEC,})); searchMethod = new JTextField(); add(searchMethod, "2, 2, fill, fill"); final JButton jButtonSearch = new JButton("Search"); add(jButtonSearch, "4, 2, fill, fill"); // -------------------------------- JTree ----------------------------------- final JScrollPane jScrollPane = new JScrollPane(); add(jScrollPane, "2, 6, 3, 1, fill, fill"); treePkg = new JTree(); jScrollPane.setViewportView(treePkg); // ------ Node ------- jButtonSearch.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final StringSearcherTask task = new StringSearcherTask(Main.filePath, searchMethod.getText(), treePkg, jButtonSearch); task.execute(); jButtonSearch.setEnabled(false); } }); } } class StringSearcherTask extends SwingWorker<Void, Void> { static int count = 0; private final JButton jButtonSearch; String filePath; String method; JTree methodTree; TreeNode treeNode; static int id = 0; public StringSearcherTask(String filePath, String method, JTree jTree, JButton jButtonSearch) { this.filePath = filePath; this.method = method; this.methodTree = jTree; this.jButtonSearch = jButtonSearch; treeNode = new TreeNode(); treeNode.setSelfId(id); treeNode.setNodeName(method); } @Override public Void doInBackground() { HashMap<String, String> methods; File file = new File(filePath); try { if (FileTypesDetector.isAPK(file)) { APK apk = new APK(file); methods = apk.getMethods(); } else if (FileTypesDetector.isDEX(file)) { DEX dex = new DEX(file); methods = dex.getMethods(); } else { return null; } HashSet<String> methodSet = new HashSet<>(); this.methodTree.setModel(new DefaultTreeModel(createNodes(method, methods, methodSet))); count = 0; id =0; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 以递归的方式创建节点。 * * @param method 方法名 * @param methods 方法Map * @param methodSet 已搜索過的方法集合 * @return rootNode DefaultMutableTreeNode */ private DefaultMutableTreeNode createNodes(String method, HashMap<String, String> methods, HashSet<String> methodSet) { DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(method); if (methodSet.contains(method)) { return rootNode; } for (String key : methods.keySet()) { String methodBody = methods.get(key); if (methodBody.contains(method)) { methodSet.add(method); if (key.contains(";.handleMessage")) { key = "Handler;.send"; rootNode.add(createNodes(key, methods, methodSet)); continue; } if (key.contains("$")) { key = key.split(";.")[0] + ";.<init>"; rootNode.add(createNodes(key, methods, methodSet)); continue; } if (key.contains("$") && key.contains(";.run()V")) { key = key.split(";.")[0] + ";.start"; rootNode.add(createNodes(key, methods, methodSet)); continue; } rootNode.add(createNodes(key, methods, methodSet)); } } return rootNode; } @Override protected void done() { System.out.println("搜索完毕。"); jButtonSearch.setEnabled(true); } }