View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
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   * This class implements a machine-generated frame for use with the GraphicalVerfifier.
49   *
50   * @see GraphicalVerifier
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      /** Constructs a new instance. */
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             // FIXME: report the error using the GUI
116             ex.printStackTrace();
117         }
118         classNamesJList.setSelectedValue(currentClass, true);
119     }
120 
121     /**
122      * @return the classNamesJList
123      */
124     JList<String> getClassNamesJList() {
125         return classNamesJList;
126     }
127 
128     /** Initizalization of the components. */
129     private void jbInit() {
130         // setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Ihr Symbol]")));
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); // let observers do the rest.
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                     // FIXME: handle the error
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                     // FIXME: handle the error
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     /** Overridden to stop the application on a closing window. */
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(); // Don't cache the verification result for this class.
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 { // Must be VERIFIED_OK, Pass 1 does not know VERIFIED_NOTYET
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 { // must be Verified_OK, because Pass1 was OK (cannot be Verified_NOTYET).
320                 pass2TextPane.setText(vr.getMessage());
321                 pass2TextPane.setBackground(Color.green);
322                 final JavaClass jc = Repository.lookupClass(currentClass);
323                 /*
324                  * boolean all3aok = true; boolean all3bok = true; String all3amsg = ""; String all3bmsg = "";
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 }