Skip to content
This repository was archived by the owner on Jan 2, 2023. It is now read-only.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# JavaOctetEditor

![](https://s1.ax1x.com/2022/07/30/vi7Lp8.png)
![](https://s1.ax1x.com/2022/08/11/v8T7M8.png)
![](https://s1.ax1x.com/2022/08/11/v8Toxf.png)
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
}

group 'cn.enaium'
version '0.7.0'
version '0.8.0'

sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8

Expand All @@ -30,8 +30,8 @@ repositories {
}

dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'

implementation 'com.formdev:flatlaf:2.4'
implementation 'com.formdev:flatlaf-extras:2.4'
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
45 changes: 45 additions & 0 deletions src/main/java/cn/enaium/joe/gui/component/LabelNodeComboBox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.component;

import cn.enaium.joe.util.OpcodeUtil;
import cn.enaium.joe.wrapper.LabelNodeWrapper;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.LabelNode;

import javax.swing.*;

/**
* @author Enaium
* @since 0.8.0
*/
public class LabelNodeComboBox extends JComboBox<LabelNodeWrapper> {
public LabelNodeComboBox(AbstractInsnNode instruction, LabelNode select) {
super(new DefaultComboBoxModel<>());
LabelNodeWrapper selected = null;
for (AbstractInsnNode abstractInsnNode : OpcodeUtil.getInstructionList(instruction)) {
if (abstractInsnNode instanceof LabelNode) {
LabelNodeWrapper anObject = new LabelNodeWrapper(((LabelNode) abstractInsnNode));
if (abstractInsnNode.equals(select)) {
selected = anObject;
}
((DefaultComboBoxModel<LabelNodeWrapper>) getModel()).addElement(anObject);
}
}
getModel().setSelectedItem(selected);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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.confirm;

import cn.enaium.joe.util.MessageUtil;
import cn.enaium.joe.wrapper.Wrapper;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Type;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
* @author Enaium
* @since 0.8.0
*/
public class BootstrapMethodArgumentEditPanel extends ConfirmPanel {
public BootstrapMethodArgumentEditPanel(Wrapper<Object[]> wrapper) {
setLayout(new BorderLayout());
DefaultListModel<Object> objectDefaultListModel = new DefaultListModel<>();
JList<Object> objectJList = new JList<>(objectDefaultListModel);
for (Object bsmArg : wrapper.getWrapper()) {
objectDefaultListModel.addElement(bsmArg);
}
add(new JScrollPane(objectJList), BorderLayout.CENTER);
add(new JPanel() {{
add(new JButton("Add") {{
addActionListener(e -> {
MessageUtil.confirm(new ConfirmPanel() {{
setLayout(new BorderLayout());
JPanel left = new JPanel(new GridLayout(0, 1));
JPanel right = new JPanel(new GridLayout(0, 1));
add(left, BorderLayout.WEST);
add(right, BorderLayout.CENTER);
JComboBox<String> jComboBox = new JComboBox<>(new String[]{"String", "float", "double", "int", "long", "Class"});
left.add(new JLabel("Type:"));
right.add(jComboBox);
left.add(new JLabel("Var:"));
JTextField ldc = new JTextField();
right.add(ldc);
setConfirm(() -> {
Object value;
if (jComboBox.getSelectedItem() != null) {
switch (jComboBox.getSelectedItem().toString()) {
case "float":
value = Float.parseFloat(ldc.getText());
break;
case "double":
value = Double.parseDouble(ldc.getText());
break;
case "int":
value = Integer.parseInt(ldc.getText());
break;
case "long":
value = Long.parseLong(ldc.getText());
break;
case "Class":
value = Type.getType(ldc.getText());
break;
default:
value = ldc.getText();
}
objectDefaultListModel.addElement(value);
}
});
}}, "Add");
});
}});
add(new JButton("Add Handle") {{
addActionListener(e -> {
Wrapper<Handle> handleWrapper = new Wrapper<>(new Handle(1, "", "", "", false));
HandleEditPanel confirmPanel = new HandleEditPanel(handleWrapper);
MessageUtil.confirm(confirmPanel, "Add Handle", () -> {
confirmPanel.getConfirm().run();
objectDefaultListModel.addElement(handleWrapper.getWrapper());
}, () -> {
});
});
}});
add(new JButton("Remove") {{
addActionListener(e -> {
if (objectJList.getSelectedIndex() != -1) {
objectDefaultListModel.remove(objectJList.getSelectedIndex());
}
});
}});
}}, BorderLayout.SOUTH);
setConfirm(() -> {
List<Object> objects = new ArrayList<>();
for (int i = 0; i < objectDefaultListModel.size(); i++) {
objects.add(objectDefaultListModel.get(i));
}
wrapper.setWrapper(objects.toArray(new Object[0]));
});
}
}
48 changes: 48 additions & 0 deletions src/main/java/cn/enaium/joe/gui/panel/confirm/ConfirmPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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.confirm;

import javax.swing.*;
import java.awt.*;

/**
* @author Enaium
* @since 0.8.0
*/
public class ConfirmPanel extends JPanel {

private Runnable confirm = () -> {
};
private Runnable cancel = () -> {
};

public Runnable getConfirm() {
return confirm;
}

public void setConfirm(Runnable confirm) {
this.confirm = confirm;
}

public Runnable getCancel() {
return cancel;
}

public void setCancel(Runnable cancel) {
this.cancel = cancel;
}
}
123 changes: 123 additions & 0 deletions src/main/java/cn/enaium/joe/gui/panel/confirm/FrameListEditPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* 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.confirm;

import cn.enaium.joe.util.MessageUtil;
import cn.enaium.joe.util.OpcodeUtil;
import cn.enaium.joe.util.StringUtil;
import org.objectweb.asm.tree.FrameNode;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author Enaium
* @since 0.8.0
*/
public class FrameListEditPanel extends ConfirmPanel {

public FrameListEditPanel(FrameNode frameNode) {
setLayout(new BorderLayout(10, 10));
JPanel left = new JPanel(new BorderLayout());
JPanel right = new JPanel(new BorderLayout());
left.add(new JLabel("Local", JLabel.CENTER), BorderLayout.NORTH);
ObjectList localObjectList = new ObjectList(frameNode.local);
left.add(localObjectList, BorderLayout.CENTER);
right.add(new JLabel("Stack", JLabel.CENTER), BorderLayout.NORTH);
ObjectList stackObjectList = new ObjectList(frameNode.stack);
right.add(stackObjectList, BorderLayout.CENTER);
add(left, BorderLayout.WEST);
add(new JSeparator(JSeparator.VERTICAL), BorderLayout.CENTER);
add(right, BorderLayout.EAST);
setConfirm(() -> {
frameNode.local = localObjectList.getList().stream().map(it -> {
Map<String, Integer> reverse = OpcodeUtil.reverse(OpcodeUtil.FRAME_ELEMENT);
if (reverse.containsKey(it.toString())) {
return reverse.get(it.toString());
} else {
return it;
}
}).collect(Collectors.toList());

frameNode.stack = stackObjectList.getList().stream().map(it -> {
Map<String, Integer> reverse = OpcodeUtil.reverse(OpcodeUtil.FRAME_ELEMENT);
if (reverse.containsKey(it.toString())) {
return reverse.get(it.toString());
} else {
return it;
}
}).collect(Collectors.toList());
});
}

private static class ObjectList extends JPanel {
DefaultListModel<String> stringDefaultListModel = new DefaultListModel<>();

public ObjectList(List<Object> list) {
setLayout(new BorderLayout());
setBorder(new EmptyBorder(5, 5, 5, 5));
JList<String> jList = new JList<>(stringDefaultListModel);
for (Object o : list) {
if (o instanceof String) {
stringDefaultListModel.addElement(o.toString());
} else if (o instanceof Integer) {
stringDefaultListModel.addElement(OpcodeUtil.FRAME_ELEMENT.get(Integer.parseInt(o.toString())));
}
}
add(new JScrollPane(jList), BorderLayout.CENTER);
add(new JPanel(new GridLayout(1, 3)) {{
add(new JButton("Add String") {{
addActionListener(e -> {
String s = JOptionPane.showInputDialog(ObjectList.this, "Input:");
if (s != null && !StringUtil.isBlank(s)) {
stringDefaultListModel.addElement(s);
}
});
}});
add(new JButton("Add Type") {{
addActionListener(e -> {
JComboBox<String> message = new JComboBox<>(OpcodeUtil.FRAME_ELEMENT.values().toArray(new String[0]));
MessageUtil.confirm(message, "Type", () -> {
Object selectedItem = message.getSelectedItem();
if (selectedItem != null) {
stringDefaultListModel.addElement(selectedItem.toString());
}
}, () -> {

});
});
}});
add(new JButton("Remove") {{
addActionListener(e -> {
if (jList.getSelectedIndex() != -1) {
stringDefaultListModel.remove(jList.getSelectedIndex());
}
});
}});
}}, BorderLayout.SOUTH);
}

public List<Object> getList() {
return Arrays.asList(stringDefaultListModel.toArray());
}
}
}
Loading