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