1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.verifier;
18
19 import java.awt.AWTEvent;
20 import java.awt.CardLayout;
21 import java.awt.Color;
22 import java.awt.Dimension;
23 import java.awt.GridLayout;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.InputEvent;
26 import java.awt.event.WindowEvent;
27 import java.util.Arrays;
28
29 import javax.swing.BorderFactory;
30 import javax.swing.JFrame;
31 import javax.swing.JList;
32 import javax.swing.JMenu;
33 import javax.swing.JMenuBar;
34 import javax.swing.JMenuItem;
35 import javax.swing.JOptionPane;
36 import javax.swing.JPanel;
37 import javax.swing.JScrollPane;
38 import javax.swing.JSplitPane;
39 import javax.swing.JTextPane;
40 import javax.swing.ListSelectionModel;
41 import javax.swing.event.ListSelectionEvent;
42
43 import org.apache.bcel.Repository;
44 import org.apache.bcel.classfile.JavaClass;
45 import org.apache.commons.lang3.ArrayUtils;
46
47
48
49
50
51
52 public class VerifierAppFrame extends JFrame {
53
54 private static final long serialVersionUID = -542458133073307640L;
55 private JPanel contentPane;
56 private final JSplitPane jSplitPane1 = new JSplitPane();
57 private final JPanel jPanel1 = new JPanel();
58 private final JPanel jPanel2 = new JPanel();
59 private final JSplitPane jSplitPane2 = new JSplitPane();
60 private final JPanel jPanel3 = new JPanel();
61 private final JList<String> classNamesJList = new JList<>();
62 private final GridLayout gridLayout1 = new GridLayout();
63 private final JPanel messagesPanel = new JPanel();
64 private final GridLayout gridLayout2 = new GridLayout();
65 private final JMenuBar jMenuBar1 = new JMenuBar();
66 private final JMenu jMenu1 = new JMenu();
67 private final JScrollPane jScrollPane1 = new JScrollPane();
68 private final JScrollPane messagesScrollPane = new JScrollPane();
69 private final JScrollPane jScrollPane3 = new JScrollPane();
70 private final GridLayout gridLayout4 = new GridLayout();
71 private final JScrollPane jScrollPane4 = new JScrollPane();
72 private final CardLayout cardLayout1 = new CardLayout();
73 private String currentClass;
74 private final GridLayout gridLayout3 = new GridLayout();
75 private final JTextPane pass1TextPane = new JTextPane();
76 private final JTextPane pass2TextPane = new JTextPane();
77 private final JTextPane messagesTextPane = new JTextPane();
78 private final JMenuItem newFileMenuItem = new JMenuItem();
79 private final JSplitPane jSplitPane3 = new JSplitPane();
80 private final JSplitPane jSplitPane4 = new JSplitPane();
81 private final JScrollPane jScrollPane2 = new JScrollPane();
82 private final JScrollPane jScrollPane5 = new JScrollPane();
83 private final JScrollPane jScrollPane6 = new JScrollPane();
84 private final JScrollPane jScrollPane7 = new JScrollPane();
85 private final JList<String> pass3aJList = new JList<>();
86 private final JList<String> pass3bJList = new JList<>();
87 private final JTextPane pass3aTextPane = new JTextPane();
88 private final JTextPane pass3bTextPane = new JTextPane();
89 private final JMenu jMenu2 = new JMenu();
90 private final JMenuItem whatisMenuItem = new JMenuItem();
91 private final JMenuItem aboutMenuItem = new JMenuItem();
92
93
94 public VerifierAppFrame() {
95 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
96 try {
97 jbInit();
98 } catch (final Exception e) {
99 e.printStackTrace();
100 }
101 }
102
103 void aboutMenuItemActionPerformed(final ActionEvent e) {
104 JOptionPane.showMessageDialog(this, Verifier.BANNER, Verifier.NAME, JOptionPane.INFORMATION_MESSAGE);
105 }
106
107 synchronized void classNamesJListValueChanged(final ListSelectionEvent e) {
108 if (e.getValueIsAdjusting()) {
109 return;
110 }
111 currentClass = classNamesJList.getSelectedValue();
112 try {
113 verify();
114 } catch (final ClassNotFoundException ex) {
115
116 ex.printStackTrace();
117 }
118 classNamesJList.setSelectedValue(currentClass, true);
119 }
120
121
122
123
124 JList<String> getClassNamesJList() {
125 return classNamesJList;
126 }
127
128
129 private void jbInit() {
130
131 contentPane = (JPanel) getContentPane();
132 contentPane.setLayout(cardLayout1);
133 setJMenuBar(jMenuBar1);
134 this.setSize(new Dimension(708, 451));
135 setTitle("JustIce");
136 jPanel1.setMinimumSize(new Dimension(100, 100));
137 jPanel1.setPreferredSize(new Dimension(100, 100));
138 jPanel1.setLayout(gridLayout1);
139 jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT);
140 jPanel2.setLayout(gridLayout2);
141 jPanel3.setMinimumSize(new Dimension(200, 100));
142 jPanel3.setPreferredSize(new Dimension(400, 400));
143 jPanel3.setLayout(gridLayout4);
144 messagesPanel.setMinimumSize(new Dimension(100, 100));
145 messagesPanel.setLayout(gridLayout3);
146 jPanel2.setMinimumSize(new Dimension(200, 100));
147 jMenu1.setText("File");
148 jScrollPane1.getViewport().setBackground(Color.red);
149 messagesScrollPane.getViewport().setBackground(Color.red);
150 messagesScrollPane.setPreferredSize(new Dimension(10, 10));
151 classNamesJList.addListSelectionListener(this::classNamesJListValueChanged);
152 classNamesJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
153 jScrollPane3.setBorder(BorderFactory.createLineBorder(Color.black));
154 jScrollPane3.setPreferredSize(new Dimension(100, 100));
155 gridLayout4.setRows(4);
156 gridLayout4.setColumns(1);
157 gridLayout4.setHgap(1);
158 jScrollPane4.setBorder(BorderFactory.createLineBorder(Color.black));
159 jScrollPane4.setPreferredSize(new Dimension(100, 100));
160 pass1TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
161 pass1TextPane.setToolTipText("");
162 pass1TextPane.setEditable(false);
163 pass2TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
164 pass2TextPane.setEditable(false);
165 messagesTextPane.setBorder(BorderFactory.createRaisedBevelBorder());
166 messagesTextPane.setEditable(false);
167 newFileMenuItem.setText("New...");
168 newFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(78, InputEvent.CTRL_MASK, true));
169 newFileMenuItem.addActionListener(this::newFileMenuItemActionPerformed);
170 pass3aTextPane.setEditable(false);
171 pass3bTextPane.setEditable(false);
172 pass3aJList.addListSelectionListener(this::pass3aJList_valueChanged);
173 pass3bJList.addListSelectionListener(this::pass3bJList_valueChanged);
174 jMenu2.setText("Help");
175 whatisMenuItem.setText("What is...");
176 whatisMenuItem.addActionListener(this::whatisMenuItemActionPerformed);
177 aboutMenuItem.setText("About");
178 aboutMenuItem.addActionListener(this::aboutMenuItemActionPerformed);
179 jSplitPane2.add(messagesPanel, JSplitPane.BOTTOM);
180 messagesPanel.add(messagesScrollPane, null);
181 messagesScrollPane.getViewport().add(messagesTextPane, null);
182 jSplitPane2.add(jPanel3, JSplitPane.TOP);
183 jPanel3.add(jScrollPane3, null);
184 jScrollPane3.getViewport().add(pass1TextPane, null);
185 jPanel3.add(jScrollPane4, null);
186 jPanel3.add(jSplitPane3, null);
187 jSplitPane3.add(jScrollPane2, JSplitPane.LEFT);
188 jScrollPane2.getViewport().add(pass3aJList, null);
189 jSplitPane3.add(jScrollPane5, JSplitPane.RIGHT);
190 jScrollPane5.getViewport().add(pass3aTextPane, null);
191 jPanel3.add(jSplitPane4, null);
192 jSplitPane4.add(jScrollPane6, JSplitPane.LEFT);
193 jScrollPane6.getViewport().add(pass3bJList, null);
194 jSplitPane4.add(jScrollPane7, JSplitPane.RIGHT);
195 jScrollPane7.getViewport().add(pass3bTextPane, null);
196 jScrollPane4.getViewport().add(pass2TextPane, null);
197 jSplitPane1.add(jPanel2, JSplitPane.TOP);
198 jPanel2.add(jScrollPane1, null);
199 jSplitPane1.add(jPanel1, JSplitPane.BOTTOM);
200 jPanel1.add(jSplitPane2, null);
201 jScrollPane1.getViewport().add(classNamesJList, null);
202 jMenuBar1.add(jMenu1);
203 jMenuBar1.add(jMenu2);
204 contentPane.add(jSplitPane1, "jSplitPane1");
205 jMenu1.add(newFileMenuItem);
206 jMenu2.add(whatisMenuItem);
207 jMenu2.add(aboutMenuItem);
208 jSplitPane2.setDividerLocation(300);
209 jSplitPane3.setDividerLocation(150);
210 jSplitPane4.setDividerLocation(150);
211 }
212
213 void newFileMenuItemActionPerformed(final ActionEvent e) {
214 final String className = JOptionPane.showInputDialog("Please enter the fully qualified name of a class or interface to verify:");
215 if (className == null || className.isEmpty()) {
216 return;
217 }
218 VerifierFactory.getVerifier(className);
219 classNamesJList.setSelectedValue(className, true);
220 }
221
222 synchronized void pass3aJList_valueChanged(final ListSelectionEvent e) {
223 if (e.getValueIsAdjusting()) {
224 return;
225 }
226 final Verifier v = VerifierFactory.getVerifier(currentClass);
227 final StringBuilder all3amsg = new StringBuilder();
228 boolean all3aok = true;
229 boolean rejected = false;
230 for (int i = 0; i < pass3aJList.getModel().getSize(); i++) {
231 if (pass3aJList.isSelectedIndex(i)) {
232 final VerificationResult vr = v.doPass3a(i);
233 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
234 all3aok = false;
235 rejected = true;
236 }
237 JavaClass jc = null;
238 try {
239 jc = Repository.lookupClass(v.getClassName());
240 all3amsg.append("Method '").append(jc.getMethods()[i]).append("': ").append(vr.getMessage().replace('\n', ' ')).append("\n\n");
241 } catch (final ClassNotFoundException ex) {
242
243 ex.printStackTrace();
244 }
245 }
246 }
247 pass3aTextPane.setText(all3amsg.toString());
248 pass3aTextPane.setBackground(all3aok ? Color.green : rejected ? Color.red : Color.yellow);
249 }
250
251 synchronized void pass3bJList_valueChanged(final ListSelectionEvent e) {
252 if (e.getValueIsAdjusting()) {
253 return;
254 }
255 final Verifier v = VerifierFactory.getVerifier(currentClass);
256 final StringBuilder all3bmsg = new StringBuilder();
257 boolean all3bok = true;
258 boolean rejected = false;
259 for (int i = 0; i < pass3bJList.getModel().getSize(); i++) {
260 if (pass3bJList.isSelectedIndex(i)) {
261 final VerificationResult vr = v.doPass3b(i);
262 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
263 all3bok = false;
264 rejected = true;
265 }
266 JavaClass jc = null;
267 try {
268 jc = Repository.lookupClass(v.getClassName());
269 all3bmsg.append("Method '").append(jc.getMethods()[i]).append("': ").append(vr.getMessage().replace('\n', ' ')).append("\n\n");
270 } catch (final ClassNotFoundException ex) {
271
272 ex.printStackTrace();
273 }
274 }
275 }
276 pass3bTextPane.setText(all3bmsg.toString());
277 pass3bTextPane.setBackground(all3bok ? Color.green : rejected ? Color.red : Color.yellow);
278 }
279
280
281 @Override
282 protected void processWindowEvent(final WindowEvent e) {
283 super.processWindowEvent(e);
284 if (e.getID() == WindowEvent.WINDOW_CLOSING) {
285 System.exit(0);
286 }
287 }
288
289 private void verify() throws ClassNotFoundException {
290 setTitle("PLEASE WAIT");
291 final Verifier v = VerifierFactory.getVerifier(currentClass);
292 v.flush();
293 VerificationResult vr;
294 vr = v.doPass1();
295 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
296 pass1TextPane.setText(vr.getMessage());
297 pass1TextPane.setBackground(Color.red);
298 pass2TextPane.setText("");
299 pass2TextPane.setBackground(Color.yellow);
300 pass3aTextPane.setText("");
301 pass3aJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
302 pass3aTextPane.setBackground(Color.yellow);
303 pass3bTextPane.setText("");
304 pass3bJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
305 pass3bTextPane.setBackground(Color.yellow);
306 } else {
307 pass1TextPane.setBackground(Color.green);
308 pass1TextPane.setText(vr.getMessage());
309 vr = v.doPass2();
310 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
311 pass2TextPane.setText(vr.getMessage());
312 pass2TextPane.setBackground(Color.red);
313 pass3aTextPane.setText("");
314 pass3aTextPane.setBackground(Color.yellow);
315 pass3aJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
316 pass3bTextPane.setText("");
317 pass3bTextPane.setBackground(Color.yellow);
318 pass3bJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
319 } else {
320 pass2TextPane.setText(vr.getMessage());
321 pass2TextPane.setBackground(Color.green);
322 final JavaClass jc = Repository.lookupClass(currentClass);
323
324
325
326 final String[] methodNames = new String[jc.getMethods().length];
327 Arrays.setAll(methodNames, i -> jc.getMethods()[i].toString().replace('\n', ' ').replace('\t', ' '));
328 pass3aJList.setListData(methodNames);
329 pass3aJList.setSelectionInterval(0, jc.getMethods().length - 1);
330 pass3bJList.setListData(methodNames);
331 pass3bJList.setSelectionInterval(0, jc.getMethods().length - 1);
332 }
333 }
334 final String[] msgs = v.getMessages();
335 messagesTextPane.setBackground(msgs.length == 0 ? Color.green : Color.yellow);
336 final StringBuilder allmsgs = new StringBuilder();
337 for (int i = 0; i < msgs.length; i++) {
338 msgs[i] = msgs[i].replace('\n', ' ');
339 allmsgs.append(msgs[i]).append("\n\n");
340 }
341 messagesTextPane.setText(allmsgs.toString());
342 setTitle(currentClass + " - " + Verifier.NAME);
343 }
344
345 void whatisMenuItemActionPerformed(final ActionEvent e) {
346 JOptionPane.showMessageDialog(this,
347 "The upper four boxes to the right reflect verification passes according to"
348 + " The Java Virtual Machine Specification.\nThese are (in that order):"
349 + " Pass one, Pass two, Pass three (before data flow analysis), Pass three (data flow analysis).\n"
350 + "The bottom box to the right shows (warning) messages; warnings do not cause a class to be rejected.",
351 Verifier.NAME, JOptionPane.INFORMATION_MESSAGE);
352 }
353
354 }