View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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   * This class implements a machine-generated frame for use with the GraphicalVerfifier.
51   *
52   * @see GraphicalVerifier
53   */
54  public class VerifierAppFrame extends JFrame {
55  
56      private static final long serialVersionUID = -542458133073307640L;
57  
58      /** Machine-generated GUI component. */
59      private JPanel contentPane;
60      /** Machine-generated GUI component. */
61      private final JSplitPane jSplitPane1 = new JSplitPane();
62      /** Machine-generated GUI component. */
63      private final JPanel jPanel1 = new JPanel();
64      /** Machine-generated GUI component. */
65      private final JPanel jPanel2 = new JPanel();
66      /** Machine-generated GUI component. */
67      private final JSplitPane jSplitPane2 = new JSplitPane();
68      /** Machine-generated GUI component. */
69      private final JPanel jPanel3 = new JPanel();
70      /** Machine-generated GUI component. */
71      private final JList<String> classNamesJList = new JList<>();
72      /** Machine-generated GUI component. */
73      private final GridLayout gridLayout1 = new GridLayout();
74      /** Machine-generated GUI component. */
75      private final JPanel messagesPanel = new JPanel();
76      /** Machine-generated GUI component. */
77      private final GridLayout gridLayout2 = new GridLayout();
78      /** Machine-generated GUI component. */
79      private final JMenuBar jMenuBar1 = new JMenuBar();
80      /** Machine-generated GUI component. */
81      private final JMenu jMenu1 = new JMenu();
82      /** Machine-generated GUI component. */
83      private final JScrollPane jScrollPane1 = new JScrollPane();
84      /** Machine-generated GUI component. */
85      private final JScrollPane messagesScrollPane = new JScrollPane();
86      /** Machine-generated GUI component. */
87      private final JScrollPane jScrollPane3 = new JScrollPane();
88      /** Machine-generated GUI component. */
89      private final GridLayout gridLayout4 = new GridLayout();
90      /** Machine-generated GUI component. */
91      private final JScrollPane jScrollPane4 = new JScrollPane();
92      /** Machine-generated GUI component. */
93      private final CardLayout cardLayout1 = new CardLayout();
94      /** The current class being verified. */
95      private String currentClass;
96      /** Machine-generated GUI component. */
97      private final GridLayout gridLayout3 = new GridLayout();
98      /** Machine-generated GUI component. */
99      private final JTextPane pass1TextPane = new JTextPane();
100     /** Machine-generated GUI component. */
101     private final JTextPane pass2TextPane = new JTextPane();
102     /** Machine-generated GUI component. */
103     private final JTextPane messagesTextPane = new JTextPane();
104     /** Machine-generated GUI component. */
105     private final JMenuItem newFileMenuItem = new JMenuItem();
106     /** Machine-generated GUI component. */
107     private final JSplitPane jSplitPane3 = new JSplitPane();
108     /** Machine-generated GUI component. */
109     private final JSplitPane jSplitPane4 = new JSplitPane();
110     /** Machine-generated GUI component. */
111     private final JScrollPane jScrollPane2 = new JScrollPane();
112     /** Machine-generated GUI component. */
113     private final JScrollPane jScrollPane5 = new JScrollPane();
114     /** Machine-generated GUI component. */
115     private final JScrollPane jScrollPane6 = new JScrollPane();
116     /** Machine-generated GUI component. */
117     private final JScrollPane jScrollPane7 = new JScrollPane();
118     /** Machine-generated GUI component. */
119     private final JList<String> pass3aJList = new JList<>();
120     /** Machine-generated GUI component. */
121     private final JList<String> pass3bJList = new JList<>();
122     /** Machine-generated GUI component. */
123     private final JTextPane pass3aTextPane = new JTextPane();
124     /** Machine-generated GUI component. */
125     private final JTextPane pass3bTextPane = new JTextPane();
126     /** Machine-generated GUI component. */
127     private final JMenu jMenu2 = new JMenu();
128     /** Machine-generated GUI component. */
129     private final JMenuItem whatisMenuItem = new JMenuItem();
130     /** Machine-generated GUI component. */
131     private final JMenuItem aboutMenuItem = new JMenuItem();
132 
133     /** Constructs a new instance. */
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             // FIXME: report the error using the GUI
156             ex.printStackTrace();
157         }
158         classNamesJList.setSelectedValue(currentClass, true);
159     }
160 
161     /**
162      * @return The classNamesJList.
163      */
164     JList<String> getClassNamesJList() {
165         return classNamesJList;
166     }
167 
168     /** Initizalization of the components. */
169     private void jbInit() {
170         // setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Ihr Symbol]")));
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); // let observers do the rest.
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                     // FIXME: handle the error
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                     // FIXME: handle the error
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     /** Overridden to stop the application on a closing window. */
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(); // Don't cache the verification result for this class.
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 { // Must be VERIFIED_OK, Pass 1 does not know VERIFIED_NOTYET
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 { // must be Verified_OK, because Pass1 was OK (cannot be Verified_NOTYET).
360                 pass2TextPane.setText(vr.getMessage());
361                 pass2TextPane.setBackground(Color.green);
362                 final JavaClass jc = Repository.lookupClass(currentClass);
363                 /*
364                  * boolean all3aok = true; boolean all3bok = true; String all3amsg = ""; String all3bmsg = "";
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 }