1 package edu.jiangxin.apktoolbox.convert.protobuf.supervised;
2
3 import edu.jiangxin.apktoolbox.convert.protobuf.unsupervised.ByteUtil;
4 import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
5 import edu.jiangxin.apktoolbox.swing.extend.filepanel.FilePanel;
6 import edu.jiangxin.apktoolbox.utils.Constants;
7 import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
8 import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
9 import org.fife.ui.rtextarea.RTextScrollPane;
10
11 import javax.swing.*;
12 import java.awt.*;
13 import java.io.File;
14 import java.io.PrintWriter;
15 import java.io.Serial;
16 import java.io.StringWriter;
17 import java.nio.file.Path;
18
19 public class SupervisedProtobufConvertPanel extends EasyPanel {
20 @Serial
21 private static final long serialVersionUID = 1L;
22
23 private FilePanel descriptorCachePanel;
24
25 private JPanel contentPanel;
26
27 private JPanel operationPanel;
28
29 private JTextArea inputTextArea;
30 private RSyntaxTextArea outputTextArea;
31
32 @Override
33 public void initUI() {
34 BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
35 setLayout(boxLayout);
36
37 createDescriptorCachePanel();
38 add(descriptorCachePanel);
39 add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
40
41 createContentPanel();
42 add(contentPanel);
43 add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
44
45 createOperationPanel();
46 add(operationPanel);
47 }
48
49 private void createDescriptorCachePanel() {
50 descriptorCachePanel = new FilePanel("Descriptor Cache Directory");
51 descriptorCachePanel.initialize();
52 descriptorCachePanel.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
53 }
54
55 private void createContentPanel() {
56 contentPanel = new JPanel();
57
58 BoxLayout boxLayout = new BoxLayout(contentPanel, BoxLayout.X_AXIS);
59 contentPanel.setLayout(boxLayout);
60
61 inputTextArea = new JTextArea();
62 inputTextArea.setLineWrap(true);
63 inputTextArea.setWrapStyleWord(true);
64 inputTextArea.setText("0a2f0a084a6f686e20446f6510011a106a6f686e406578616d706c652e636f6d220f0a0b3131312d3232322d33333310010a1e0a084a616e6520446f6510021a106a616e65406578616d706c652e636f6d");
65
66 JScrollPane inputScrollPanel = new JScrollPane(inputTextArea);
67 inputScrollPanel.setPreferredSize(new Dimension(200, 500));
68
69 outputTextArea = new RSyntaxTextArea();
70 outputTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON);
71 outputTextArea.setCodeFoldingEnabled(true);
72 outputTextArea.setEditable(false);
73
74 RTextScrollPane outputScrollPane = new RTextScrollPane(outputTextArea);
75 outputScrollPane.setPreferredSize(new Dimension(200, 500));
76
77 contentPanel.add(inputScrollPanel);
78 contentPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
79 contentPanel.add(outputScrollPane);
80 }
81
82 private void createOperationPanel() {
83 operationPanel = new JPanel();
84
85 BoxLayout boxLayout = new BoxLayout(operationPanel, BoxLayout.X_AXIS);
86 operationPanel.setLayout(boxLayout);
87
88 JButton convertButton = new JButton("Convert");
89
90 convertButton.addActionListener(e -> convertProtoToJson());
91
92 operationPanel.add(convertButton);
93 }
94
95 private void convertProtoToJson() {
96 try {
97 String hexString = inputTextArea.getText();
98 byte[] byteArray = ByteUtil.hex2bytes(hexString);
99 File descriptorCacheDirectory = descriptorCachePanel.getFile();
100 Path path = descriptorCacheDirectory.toPath();
101 final DescriptorCache cache = DescriptorCache.fromDirectory(path);
102 if (cache.isEmpty()) {
103 displayErrorMessage(
104 "The descriptor cache is empty, could not load any descriptor, check the cache directory:\n"
105 + path.toAbsolutePath(), "Empty descriptor cache"
106 );
107 return;
108 }
109
110 final ProtoToJson protoToJson = ProtoToJson.fromCache(cache);
111 final String jsonString;
112 try {
113 jsonString = protoToJson.toJson(byteArray);
114 } catch (final RuntimeException e) {
115 displayErrorMessage(
116 "Unable to find a descriptor matching the given JSON message, check the cache directory:\n"
117 + path.toAbsolutePath(), "No matching descriptor found"
118 );
119 return;
120 }
121
122 outputTextArea.setText(jsonString);
123 } catch (final Throwable t) {
124 final StringWriter sw = new StringWriter();
125 final PrintWriter pw = new PrintWriter(sw);
126 t.printStackTrace(pw);
127 displayErrorMessage(sw.toString(), "Error");
128 }
129 }
130
131 private static void displayErrorMessage(final String message, final String title) {
132 JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
133 }
134 }