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