View Javadoc
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 }