diff --git a/build.gradle b/build.gradle index 4966a42..f85207d 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group 'cn.enaium' -version '0.4.0' +version '0.5.0' sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/src/main/java/cn/enaium/joe/JavaOctetEditor.java b/src/main/java/cn/enaium/joe/JavaOctetEditor.java index 2cea340..462111f 100644 --- a/src/main/java/cn/enaium/joe/JavaOctetEditor.java +++ b/src/main/java/cn/enaium/joe/JavaOctetEditor.java @@ -58,8 +58,8 @@ public void run() { window.setJMenuBar(new JMenuBar() {{ add(new FileMenu()); - add(new HelpMenu()); add(new SearchMenu()); + add(new HelpMenu()); }}); window.setContentPane(new JPanel(new BorderLayout()) { diff --git a/src/main/java/cn/enaium/joe/dialog/SearchDialog.java b/src/main/java/cn/enaium/joe/dialog/SearchDialog.java index 35dd778..6e769aa 100644 --- a/src/main/java/cn/enaium/joe/dialog/SearchDialog.java +++ b/src/main/java/cn/enaium/joe/dialog/SearchDialog.java @@ -16,7 +16,7 @@ package cn.enaium.joe.dialog; -import cn.enaium.joe.gui.panel.search.Result; +import cn.enaium.joe.gui.panel.search.ResultPanel; import java.awt.*; @@ -24,12 +24,12 @@ * @author Enaium */ public class SearchDialog extends Dialog { - public Result result = new Result(); + public ResultPanel resultPanel = new ResultPanel(); public SearchDialog() { super("Search"); setLayout(new BorderLayout()); - setSize(400, 300); - add(result, BorderLayout.CENTER); + setSize(700, 400); + add(resultPanel, BorderLayout.CENTER); } } diff --git a/src/main/java/cn/enaium/joe/dialog/search/SearchFieldDialog.java b/src/main/java/cn/enaium/joe/dialog/search/SearchFieldDialog.java new file mode 100644 index 0000000..aba4d90 --- /dev/null +++ b/src/main/java/cn/enaium/joe/dialog/search/SearchFieldDialog.java @@ -0,0 +1,85 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.dialog.search; + +import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.dialog.SearchDialog; +import cn.enaium.joe.gui.panel.search.ResultNode; +import cn.enaium.joe.jar.Jar; +import cn.enaium.joe.util.ASyncUtil; +import cn.enaium.joe.util.StringUtil; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +import javax.swing.*; +import java.awt.*; +import java.util.Map; + +/** + * @author Enaium + * @since 0.5.0 + */ +public class SearchFieldDialog extends SearchDialog { + public SearchFieldDialog() { + setTitle("Search Field"); + add(new JPanel(new FlowLayout()) {{ + add(new JLabel("Owner:")); + JTextField owner = new JTextField(); + add(owner); + add(new JLabel("Name:")); + JTextField name = new JTextField(); + add(name); + add(new JLabel("Description:")); + JTextField description = new JTextField(); + add(description); + add(new JButton("Search") {{ + addActionListener(e -> { + ASyncUtil.execute(() -> { + float loaded = 0; + float total = 0; + Jar jar = JavaOctetEditor.getInstance().jar; + for (Map.Entry stringClassNodeEntry : jar.classes.entrySet()) { + for (MethodNode method : stringClassNodeEntry.getValue().methods) { + total += method.instructions.size(); + } + } + + for (Map.Entry stringClassNodeEntry : jar.classes.entrySet()) { + for (MethodNode method : stringClassNodeEntry.getValue().methods) { + for (AbstractInsnNode instruction : method.instructions) { + if (instruction instanceof FieldInsnNode) { + FieldInsnNode fieldInsnNode = (FieldInsnNode) instruction; + if ((fieldInsnNode.owner.contains(owner.getText()) || StringUtil.isBlank(owner.getText())) && + (fieldInsnNode.name.contains(name.getText()) || StringUtil.isBlank(name.getText())) && + (fieldInsnNode.desc.contains(description.getText()) || StringUtil.isBlank(description.getText())) + ) { + ((DefaultListModel) resultPanel.getList().getModel()).addElement(new ResultNode(stringClassNodeEntry.getValue(), fieldInsnNode.name + ":" + fieldInsnNode.desc)); + } + } + JavaOctetEditor.getInstance().bottomPanel.setProcess((int) ((loaded++ / total) * 100f)); + } + } + } + JavaOctetEditor.getInstance().bottomPanel.setProcess(0); + }); + }); + }}); + }}, BorderLayout.SOUTH); + } +} diff --git a/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java b/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java index 61560b6..cb62961 100644 --- a/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java +++ b/src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java @@ -54,12 +54,11 @@ public SearchLdcDialog() { for (Map.Entry stringClassNodeEntry : jar.classes.entrySet()) { for (MethodNode method : stringClassNodeEntry.getValue().methods) { - for (AbstractInsnNode instruction : method.instructions) { if (instruction instanceof LdcInsnNode) { String ldc = ((LdcInsnNode) instruction).cst.toString(); if (ldc.contains(text.getText())) { - ((DefaultListModel) result.getList().getModel()).addElement(new ResultNode(stringClassNodeEntry.getValue(), ldc)); + ((DefaultListModel) resultPanel.getList().getModel()).addElement(new ResultNode(stringClassNodeEntry.getValue(), ldc)); } } JavaOctetEditor.getInstance().bottomPanel.setProcess((int) ((loaded++ / total) * 100f)); diff --git a/src/main/java/cn/enaium/joe/dialog/search/SearchMethodDialog.java b/src/main/java/cn/enaium/joe/dialog/search/SearchMethodDialog.java new file mode 100644 index 0000000..481f15b --- /dev/null +++ b/src/main/java/cn/enaium/joe/dialog/search/SearchMethodDialog.java @@ -0,0 +1,85 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.dialog.search; + +import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.dialog.SearchDialog; +import cn.enaium.joe.gui.panel.search.ResultNode; +import cn.enaium.joe.jar.Jar; +import cn.enaium.joe.util.ASyncUtil; +import cn.enaium.joe.util.StringUtil; +import org.objectweb.asm.tree.*; + +import javax.swing.*; +import java.awt.*; +import java.util.Map; + +/** + * @author Enaium + * @since 0.5.0 + */ +public class SearchMethodDialog extends SearchDialog { + public SearchMethodDialog() { + setTitle("Search Method"); + add(new JPanel(new FlowLayout()) {{ + add(new JLabel("Owner:")); + JTextField owner = new JTextField(); + add(owner); + add(new JLabel("Name:")); + JTextField name = new JTextField(); + add(name); + add(new JLabel("Description:")); + JTextField description = new JTextField(); + add(description); + JCheckBox anInterface = new JCheckBox("Interface"); + add(anInterface); + add(new JButton("Search") {{ + addActionListener(e -> { + ASyncUtil.execute(() -> { + float loaded = 0; + float total = 0; + Jar jar = JavaOctetEditor.getInstance().jar; + for (Map.Entry stringClassNodeEntry : jar.classes.entrySet()) { + for (MethodNode method : stringClassNodeEntry.getValue().methods) { + total += method.instructions.size(); + } + } + + for (Map.Entry stringClassNodeEntry : jar.classes.entrySet()) { + for (MethodNode method : stringClassNodeEntry.getValue().methods) { + for (AbstractInsnNode instruction : method.instructions) { + if (instruction instanceof MethodInsnNode) { + MethodInsnNode methodInsnNode = (MethodInsnNode) instruction; + if ((methodInsnNode.owner.contains(owner.getText()) || StringUtil.isBlank(owner.getText())) && + (methodInsnNode.name.contains(name.getText()) || StringUtil.isBlank(name.getText())) && + (methodInsnNode.desc.contains(description.getText()) || StringUtil.isBlank(description.getText())) && + (methodInsnNode.itf && anInterface.isSelected() || !anInterface.isSelected()) + ) { + ((DefaultListModel) resultPanel.getList().getModel()).addElement(new ResultNode(stringClassNodeEntry.getValue(), methodInsnNode.name + "#" + methodInsnNode.desc)); + } + } + JavaOctetEditor.getInstance().bottomPanel.setProcess((int) ((loaded++ / total) * 100f)); + } + } + } + JavaOctetEditor.getInstance().bottomPanel.setProcess(0); + }); + }); + }}); + }}, BorderLayout.SOUTH); + } +} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java b/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java index ebba3a2..7415770 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java +++ b/src/main/java/cn/enaium/joe/gui/panel/menu/SearchMenu.java @@ -16,7 +16,9 @@ package cn.enaium.joe.gui.panel.menu; +import cn.enaium.joe.gui.panel.menu.search.FieldMenuItem; import cn.enaium.joe.gui.panel.menu.search.LdcMenuItem; +import cn.enaium.joe.gui.panel.menu.search.MethodMenuItem; import javax.swing.*; @@ -27,5 +29,7 @@ public class SearchMenu extends JMenu { public SearchMenu() { super("Search"); add(new LdcMenuItem()); + add(new FieldMenuItem()); + add(new MethodMenuItem()); } } diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/search/FieldMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/search/FieldMenuItem.java new file mode 100644 index 0000000..46643ea --- /dev/null +++ b/src/main/java/cn/enaium/joe/gui/panel/menu/search/FieldMenuItem.java @@ -0,0 +1,40 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.gui.panel.menu.search; + +import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.dialog.search.SearchFieldDialog; +import cn.enaium.joe.jar.Jar; + +import javax.swing.*; + +/** + * @author Enaium + * @since 0.5.0 + */ +public class FieldMenuItem extends JMenuItem { + public FieldMenuItem() { + super("Field"); + addActionListener(e -> { + Jar jar = JavaOctetEditor.getInstance().jar; + if (jar == null) { + return; + } + new SearchFieldDialog().setVisible(true); + }); + } +} diff --git a/src/main/java/cn/enaium/joe/gui/panel/menu/search/MethodMenuItem.java b/src/main/java/cn/enaium/joe/gui/panel/menu/search/MethodMenuItem.java new file mode 100644 index 0000000..057431d --- /dev/null +++ b/src/main/java/cn/enaium/joe/gui/panel/menu/search/MethodMenuItem.java @@ -0,0 +1,41 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.gui.panel.menu.search; + +import cn.enaium.joe.JavaOctetEditor; +import cn.enaium.joe.dialog.search.SearchFieldDialog; +import cn.enaium.joe.dialog.search.SearchMethodDialog; +import cn.enaium.joe.jar.Jar; + +import javax.swing.*; + +/** + * @author Enaium + * @since 0.5.0 + */ +public class MethodMenuItem extends JMenuItem { + public MethodMenuItem() { + super("Method"); + addActionListener(e -> { + Jar jar = JavaOctetEditor.getInstance().jar; + if (jar == null) { + return; + } + new SearchMethodDialog().setVisible(true); + }); + } +} diff --git a/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java b/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java index 9d183e6..c561f2f 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java +++ b/src/main/java/cn/enaium/joe/gui/panel/search/ResultNode.java @@ -16,8 +16,11 @@ package cn.enaium.joe.gui.panel.search; +import cn.enaium.joe.util.HtmlUtil; import org.objectweb.asm.tree.ClassNode; +import java.awt.*; + /** * @author Enaium */ @@ -40,6 +43,6 @@ public String getResult() { @Override public String toString() { - return result; + return HtmlUtil.toHtml(HtmlUtil.setColor(classNode.name, new Color(255, 255, 255)) + "#" + HtmlUtil.setColor(result, new Color(151, 194, 120))); } } diff --git a/src/main/java/cn/enaium/joe/gui/panel/search/Result.java b/src/main/java/cn/enaium/joe/gui/panel/search/ResultPanel.java similarity index 92% rename from src/main/java/cn/enaium/joe/gui/panel/search/Result.java rename to src/main/java/cn/enaium/joe/gui/panel/search/ResultPanel.java index d83d74c..8ecdd19 100644 --- a/src/main/java/cn/enaium/joe/gui/panel/search/Result.java +++ b/src/main/java/cn/enaium/joe/gui/panel/search/ResultPanel.java @@ -21,26 +21,22 @@ import cn.enaium.joe.gui.panel.file.tree.node.*; import cn.enaium.joe.util.ASyncUtil; import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodNode; import javax.swing.*; -import javax.swing.table.DefaultTableModel; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.nio.charset.StandardCharsets; /** * @author Enaium */ -public class Result extends JPanel { +public class ResultPanel extends JPanel { private final JList list; - public Result() { + public ResultPanel() { super(new BorderLayout()); list = new JList<>(new DefaultListModel<>()); add(new JScrollPane(list), BorderLayout.CENTER); @@ -53,7 +49,7 @@ public Result() { SwingUtilities.invokeLater(() -> { FileTreePanel fileTreePanel = JavaOctetEditor.getInstance().fileTreePanel; DefaultTreeModel model = (DefaultTreeModel) fileTreePanel.getModel(); - if (selectEntry(fileTreePanel, list.getSelectedValue().getClassNode(), model, (DefaultTreeNode) model.getRoot())) { + if (selectEntry(fileTreePanel, list.getSelectedValue().getClassNode(), model, FileTreePanel.classesRoot)) { fileTreePanel.repaint(); } }); diff --git a/src/main/java/cn/enaium/joe/util/HtmlUtil.java b/src/main/java/cn/enaium/joe/util/HtmlUtil.java new file mode 100644 index 0000000..de9c01a --- /dev/null +++ b/src/main/java/cn/enaium/joe/util/HtmlUtil.java @@ -0,0 +1,33 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.util; + +import java.awt.*; + +/** + * @author Enaium + * @since 0.5.0 + */ +public class HtmlUtil { + public static String toHtml(String text) { + return String.format("%s", text); + } + + public static String setColor(String text, Color color) { + return String.format("%s", color.getRed(), color.getGreen(), color.getBlue(), text); + } +} diff --git a/src/main/java/cn/enaium/joe/util/StringUtil.java b/src/main/java/cn/enaium/joe/util/StringUtil.java new file mode 100644 index 0000000..88db8fc --- /dev/null +++ b/src/main/java/cn/enaium/joe/util/StringUtil.java @@ -0,0 +1,27 @@ +/* + * Copyright 2022 Enaium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.enaium.joe.util; + +/** + * @author Enaium + * @since 0.5.0 + */ +public class StringUtil { + public static boolean isBlank(String string) { + return string.replace(" ", "").isEmpty(); + } +}