SupervisedProtobufConvertPanel.java
package edu.jiangxin.apktoolbox.convert.protobuf.supervised;
import edu.jiangxin.apktoolbox.convert.protobuf.unsupervised.ByteUtil;
import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
import edu.jiangxin.apktoolbox.swing.extend.filepanel.FilePanel;
import edu.jiangxin.apktoolbox.utils.Constants;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.PrintWriter;
import java.io.Serial;
import java.io.StringWriter;
import java.nio.file.Path;
public class SupervisedProtobufConvertPanel extends EasyPanel {
@Serial
private static final long serialVersionUID = 1L;
private FilePanel descriptorCachePanel;
private JPanel contentPanel;
private JPanel operationPanel;
private JTextArea inputTextArea;
private RSyntaxTextArea outputTextArea;
@Override
public void initUI() {
BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
setLayout(boxLayout);
createDescriptorCachePanel();
add(descriptorCachePanel);
add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
createContentPanel();
add(contentPanel);
add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
createOperationPanel();
add(operationPanel);
}
private void createDescriptorCachePanel() {
descriptorCachePanel = new FilePanel("Descriptor Cache Directory");
descriptorCachePanel.initialize();
descriptorCachePanel.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
private void createContentPanel() {
contentPanel = new JPanel();
BoxLayout boxLayout = new BoxLayout(contentPanel, BoxLayout.X_AXIS);
contentPanel.setLayout(boxLayout);
inputTextArea = new JTextArea();
inputTextArea.setLineWrap(true);
inputTextArea.setWrapStyleWord(true);
inputTextArea.setText("0a2f0a084a6f686e20446f6510011a106a6f686e406578616d706c652e636f6d220f0a0b3131312d3232322d33333310010a1e0a084a616e6520446f6510021a106a616e65406578616d706c652e636f6d");
JScrollPane inputScrollPanel = new JScrollPane(inputTextArea);
inputScrollPanel.setPreferredSize(new Dimension(200, 500));
outputTextArea = new RSyntaxTextArea();
outputTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON);
outputTextArea.setCodeFoldingEnabled(true);
outputTextArea.setEditable(false);
RTextScrollPane outputScrollPane = new RTextScrollPane(outputTextArea);
outputScrollPane.setPreferredSize(new Dimension(200, 500));
contentPanel.add(inputScrollPanel);
contentPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
contentPanel.add(outputScrollPane);
}
private void createOperationPanel() {
operationPanel = new JPanel();
BoxLayout boxLayout = new BoxLayout(operationPanel, BoxLayout.X_AXIS);
operationPanel.setLayout(boxLayout);
JButton convertButton = new JButton("Convert");
convertButton.addActionListener(e -> convertProtoToJson());
operationPanel.add(convertButton);
}
private void convertProtoToJson() {
try {
String hexString = inputTextArea.getText();
byte[] byteArray = ByteUtil.hex2bytes(hexString);
File descriptorCacheDirectory = descriptorCachePanel.getFile();
Path path = descriptorCacheDirectory.toPath();
final DescriptorCache cache = DescriptorCache.fromDirectory(path);
if (cache.isEmpty()) {
displayErrorMessage(
"The descriptor cache is empty, could not load any descriptor, check the cache directory:\n"
+ path.toAbsolutePath(), "Empty descriptor cache"
);
return;
}
final ProtoToJson protoToJson = ProtoToJson.fromCache(cache);
final String jsonString;
try {
jsonString = protoToJson.toJson(byteArray);
} catch (final RuntimeException e) {
displayErrorMessage(
"Unable to find a descriptor matching the given JSON message, check the cache directory:\n"
+ path.toAbsolutePath(), "No matching descriptor found"
);
return;
}
outputTextArea.setText(jsonString);
} catch (final Throwable t) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
displayErrorMessage(sw.toString(), "Error");
}
}
private static void displayErrorMessage(final String message, final String title) {
JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
}
}