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  */
18 package org.apache.bcel.verifier;
19 
20 import java.awt.AWTEvent;
21 import java.awt.CardLayout;
22 import java.awt.Color;
23 import java.awt.Dimension;
24 import java.awt.GridLayout;
25 import java.awt.event.ActionEvent;
26 import java.awt.event.InputEvent;
27 import java.awt.event.WindowEvent;
28 import javax.swing.BorderFactory;
29 import javax.swing.JFrame;
30 import javax.swing.JList;
31 import javax.swing.JMenu;
32 import javax.swing.JMenuBar;
33 import javax.swing.JMenuItem;
34 import javax.swing.JOptionPane;
35 import javax.swing.JPanel;
36 import javax.swing.JScrollPane;
37 import javax.swing.JSplitPane;
38 import javax.swing.JTextPane;
39 import javax.swing.ListSelectionModel;
40 import javax.swing.event.ListSelectionEvent;
41 
42 import org.apache.bcel.Repository;
43 import org.apache.bcel.classfile.JavaClass;
44 
45 /**
46  * This class implements a machine-generated frame for use with
47  * the GraphicalVerfifier.
48  *
49  * @version $Id$
50  * @see GraphicalVerifier
51  */
52 public class VerifierAppFrame extends JFrame {
53 
54     private static final long serialVersionUID = -542458133073307640L;
55     private static final String JUSTICE_VERSION = "JustIce by Enver Haase";
56 
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 current_class;
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     /** Constructor. */
VerifierAppFrame()97     public VerifierAppFrame() {
98         enableEvents(AWTEvent.WINDOW_EVENT_MASK);
99         try {
100             jbInit();
101         } catch (final Exception e) {
102             e.printStackTrace();
103         }
104     }
105 
106 
107     /** Initizalization of the components. */
jbInit()108     private void jbInit() throws Exception {
109         //setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Ihr Symbol]")));
110         contentPane = (JPanel) this.getContentPane();
111         contentPane.setLayout(cardLayout1);
112         this.setJMenuBar(jMenuBar1);
113         this.setSize(new Dimension(708, 451));
114         this.setTitle("JustIce");
115         jPanel1.setMinimumSize(new Dimension(100, 100));
116         jPanel1.setPreferredSize(new Dimension(100, 100));
117         jPanel1.setLayout(gridLayout1);
118         jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT);
119         jPanel2.setLayout(gridLayout2);
120         jPanel3.setMinimumSize(new Dimension(200, 100));
121         jPanel3.setPreferredSize(new Dimension(400, 400));
122         jPanel3.setLayout(gridLayout4);
123         messagesPanel.setMinimumSize(new Dimension(100, 100));
124         messagesPanel.setLayout(gridLayout3);
125         jPanel2.setMinimumSize(new Dimension(200, 100));
126         jMenu1.setText("File");
127         jScrollPane1.getViewport().setBackground(Color.red);
128         messagesScrollPane.getViewport().setBackground(Color.red);
129         messagesScrollPane.setPreferredSize(new Dimension(10, 10));
130         classNamesJList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
131 
132             @Override
133             public void valueChanged( final ListSelectionEvent e ) {
134                 classNamesJList_valueChanged(e);
135             }
136         });
137         classNamesJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
138         jScrollPane3.setBorder(BorderFactory.createLineBorder(Color.black));
139         jScrollPane3.setPreferredSize(new Dimension(100, 100));
140         gridLayout4.setRows(4);
141         gridLayout4.setColumns(1);
142         gridLayout4.setHgap(1);
143         jScrollPane4.setBorder(BorderFactory.createLineBorder(Color.black));
144         jScrollPane4.setPreferredSize(new Dimension(100, 100));
145         pass1TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
146         pass1TextPane.setToolTipText("");
147         pass1TextPane.setEditable(false);
148         pass2TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
149         pass2TextPane.setEditable(false);
150         messagesTextPane.setBorder(BorderFactory.createRaisedBevelBorder());
151         messagesTextPane.setEditable(false);
152         newFileMenuItem.setText("New...");
153         newFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(78,
154                 InputEvent.CTRL_MASK, true));
155         newFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
156 
157             @Override
158             public void actionPerformed( final ActionEvent e ) {
159                 newFileMenuItem_actionPerformed(e);
160             }
161         });
162         pass3aTextPane.setEditable(false);
163         pass3bTextPane.setEditable(false);
164         pass3aJList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
165 
166             @Override
167             public void valueChanged( final ListSelectionEvent e ) {
168                 pass3aJList_valueChanged(e);
169             }
170         });
171         pass3bJList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
172 
173             @Override
174             public void valueChanged( final ListSelectionEvent e ) {
175                 pass3bJList_valueChanged(e);
176             }
177         });
178         jMenu2.setText("Help");
179         whatisMenuItem.setText("What is...");
180         whatisMenuItem.addActionListener(new java.awt.event.ActionListener() {
181 
182             @Override
183             public void actionPerformed( final ActionEvent e ) {
184                 whatisMenuItem_actionPerformed(e);
185             }
186         });
187         aboutMenuItem.setText("About");
188         aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
189 
190             @Override
191             public void actionPerformed( final ActionEvent e ) {
192                 aboutMenuItem_actionPerformed(e);
193             }
194         });
195         jSplitPane2.add(messagesPanel, JSplitPane.BOTTOM);
196         messagesPanel.add(messagesScrollPane, null);
197         messagesScrollPane.getViewport().add(messagesTextPane, null);
198         jSplitPane2.add(jPanel3, JSplitPane.TOP);
199         jPanel3.add(jScrollPane3, null);
200         jScrollPane3.getViewport().add(pass1TextPane, null);
201         jPanel3.add(jScrollPane4, null);
202         jPanel3.add(jSplitPane3, null);
203         jSplitPane3.add(jScrollPane2, JSplitPane.LEFT);
204         jScrollPane2.getViewport().add(pass3aJList, null);
205         jSplitPane3.add(jScrollPane5, JSplitPane.RIGHT);
206         jScrollPane5.getViewport().add(pass3aTextPane, null);
207         jPanel3.add(jSplitPane4, null);
208         jSplitPane4.add(jScrollPane6, JSplitPane.LEFT);
209         jScrollPane6.getViewport().add(pass3bJList, null);
210         jSplitPane4.add(jScrollPane7, JSplitPane.RIGHT);
211         jScrollPane7.getViewport().add(pass3bTextPane, null);
212         jScrollPane4.getViewport().add(pass2TextPane, null);
213         jSplitPane1.add(jPanel2, JSplitPane.TOP);
214         jPanel2.add(jScrollPane1, null);
215         jSplitPane1.add(jPanel1, JSplitPane.BOTTOM);
216         jPanel1.add(jSplitPane2, null);
217         jScrollPane1.getViewport().add(classNamesJList, null);
218         jMenuBar1.add(jMenu1);
219         jMenuBar1.add(jMenu2);
220         contentPane.add(jSplitPane1, "jSplitPane1");
221         jMenu1.add(newFileMenuItem);
222         jMenu2.add(whatisMenuItem);
223         jMenu2.add(aboutMenuItem);
224         jSplitPane2.setDividerLocation(300);
225         jSplitPane3.setDividerLocation(150);
226         jSplitPane4.setDividerLocation(150);
227     }
228 
229 
230     /** Overridden to stop the application on a closing window. */
231     @Override
processWindowEvent( final WindowEvent e )232     protected void processWindowEvent( final WindowEvent e ) {
233         super.processWindowEvent(e);
234         if (e.getID() == WindowEvent.WINDOW_CLOSING) {
235             System.exit(0);
236         }
237     }
238 
239 
classNamesJList_valueChanged( final ListSelectionEvent e )240     synchronized void classNamesJList_valueChanged( final ListSelectionEvent e ) {
241         if (e.getValueIsAdjusting()) {
242             return;
243         }
244         current_class = classNamesJList.getSelectedValue();
245         try {
246             verify();
247         } catch (final ClassNotFoundException ex) {
248             // FIXME: report the error using the GUI
249             ex.printStackTrace();
250         }
251         classNamesJList.setSelectedValue(current_class, true);
252     }
253 
254 
verify()255     private void verify() throws ClassNotFoundException {
256         setTitle("PLEASE WAIT");
257         final Verifier v = VerifierFactory.getVerifier(current_class);
258         v.flush(); // Don't cache the verification result for this class.
259         VerificationResult vr;
260         vr = v.doPass1();
261         if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
262             pass1TextPane.setText(vr.getMessage());
263             pass1TextPane.setBackground(Color.red);
264             pass2TextPane.setText("");
265             pass2TextPane.setBackground(Color.yellow);
266             pass3aTextPane.setText("");
267             pass3aJList.setListData(new String[0]);
268             pass3aTextPane.setBackground(Color.yellow);
269             pass3bTextPane.setText("");
270             pass3bJList.setListData(new String[0]);
271             pass3bTextPane.setBackground(Color.yellow);
272         } else { // Must be VERIFIED_OK, Pass 1 does not know VERIFIED_NOTYET
273             pass1TextPane.setBackground(Color.green);
274             pass1TextPane.setText(vr.getMessage());
275             vr = v.doPass2();
276             if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
277                 pass2TextPane.setText(vr.getMessage());
278                 pass2TextPane.setBackground(Color.red);
279                 pass3aTextPane.setText("");
280                 pass3aTextPane.setBackground(Color.yellow);
281                 pass3aJList.setListData(new String[0]);
282                 pass3bTextPane.setText("");
283                 pass3bTextPane.setBackground(Color.yellow);
284                 pass3bJList.setListData(new String[0]);
285             } else { // must be Verified_OK, because Pass1 was OK (cannot be Verified_NOTYET).
286                 pass2TextPane.setText(vr.getMessage());
287                 pass2TextPane.setBackground(Color.green);
288                 final JavaClass jc = Repository.lookupClass(current_class);
289                 /*
290                  boolean all3aok = true;
291                  boolean all3bok = true;
292                  String all3amsg = "";
293                  String all3bmsg = "";
294                  */
295                 final String[] methodnames = new String[jc.getMethods().length];
296                 for (int i = 0; i < jc.getMethods().length; i++) {
297                     methodnames[i] = jc.getMethods()[i].toString().replace('\n', ' ').replace('\t',
298                             ' ');
299                 }
300                 pass3aJList.setListData(methodnames);
301                 pass3aJList.setSelectionInterval(0, jc.getMethods().length - 1);
302                 pass3bJList.setListData(methodnames);
303                 pass3bJList.setSelectionInterval(0, jc.getMethods().length - 1);
304             }
305         }
306         final String[] msgs = v.getMessages();
307         messagesTextPane.setBackground(msgs.length == 0 ? Color.green : Color.yellow);
308         final StringBuilder allmsgs = new StringBuilder();
309         for (int i = 0; i < msgs.length; i++) {
310             msgs[i] = msgs[i].replace('\n', ' ');
311             allmsgs.append(msgs[i]).append("\n\n");
312         }
313         messagesTextPane.setText(allmsgs.toString());
314         setTitle(current_class + " - " + JUSTICE_VERSION);
315     }
316 
317 
newFileMenuItem_actionPerformed( final ActionEvent e )318     void newFileMenuItem_actionPerformed( final ActionEvent e ) {
319         final String classname = JOptionPane
320                 .showInputDialog("Please enter the fully qualified name of a class or interface to verify:");
321         if ((classname == null) || (classname.isEmpty())) {
322             return;
323         }
324         VerifierFactory.getVerifier(classname); // let observers do the rest.
325         classNamesJList.setSelectedValue(classname, true);
326     }
327 
328 
pass3aJList_valueChanged( final ListSelectionEvent e )329     synchronized void pass3aJList_valueChanged( final ListSelectionEvent e ) {
330         if (e.getValueIsAdjusting()) {
331             return;
332         }
333         final Verifier v = VerifierFactory.getVerifier(current_class);
334         final StringBuilder all3amsg = new StringBuilder();
335         boolean all3aok = true;
336         boolean rejected = false;
337         for (int i = 0; i < pass3aJList.getModel().getSize(); i++) {
338             if (pass3aJList.isSelectedIndex(i)) {
339                 final VerificationResult vr = v.doPass3a(i);
340                 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
341                     all3aok = false;
342                     rejected = true;
343                 }
344                 JavaClass jc = null;
345                 try {
346                     jc = Repository.lookupClass(v.getClassName());
347                     all3amsg.append("Method '").append(jc.getMethods()[i]).append("': ")
348                             .append(vr.getMessage().replace('\n', ' ') ).append("\n\n");
349                 } catch (final ClassNotFoundException ex) {
350                     // FIXME: handle the error
351                     ex.printStackTrace();
352                 }
353             }
354         }
355         pass3aTextPane.setText(all3amsg.toString());
356         pass3aTextPane.setBackground(all3aok ? Color.green : (rejected ? Color.red : Color.yellow));
357     }
358 
359 
pass3bJList_valueChanged( final ListSelectionEvent e )360     synchronized void pass3bJList_valueChanged( final ListSelectionEvent e ) {
361         if (e.getValueIsAdjusting()) {
362             return;
363         }
364         final Verifier v = VerifierFactory.getVerifier(current_class);
365         final StringBuilder all3bmsg = new StringBuilder();
366         boolean all3bok = true;
367         boolean rejected = false;
368         for (int i = 0; i < pass3bJList.getModel().getSize(); i++) {
369             if (pass3bJList.isSelectedIndex(i)) {
370                 final VerificationResult vr = v.doPass3b(i);
371                 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
372                     all3bok = false;
373                     rejected = true;
374                 }
375                 JavaClass jc = null;
376                 try {
377                     jc = Repository.lookupClass(v.getClassName());
378                     all3bmsg.append("Method '").append(jc.getMethods()[i]).append("': ")
379                             .append(vr.getMessage().replace('\n', ' ')).append("\n\n");
380                 } catch (final ClassNotFoundException ex) {
381                     // FIXME: handle the error
382                     ex.printStackTrace();
383                 }
384             }
385         }
386         pass3bTextPane.setText(all3bmsg.toString());
387         pass3bTextPane.setBackground(all3bok ? Color.green : (rejected ? Color.red : Color.yellow));
388     }
389 
390 
aboutMenuItem_actionPerformed( final ActionEvent e )391     void aboutMenuItem_actionPerformed( final ActionEvent e ) {
392         JOptionPane
393                 .showMessageDialog(
394                         this,
395                         "JustIce is a Java class file verifier.\n"+
396                         "It was implemented by Enver Haase in 2001, 2002.\n<http://commons.apache.org/bcel/>",
397                         JUSTICE_VERSION, JOptionPane.INFORMATION_MESSAGE);
398     }
399 
400 
whatisMenuItem_actionPerformed( final ActionEvent e )401     void whatisMenuItem_actionPerformed( final ActionEvent e ) {
402         JOptionPane
403                 .showMessageDialog(
404                         this,
405                         "The upper four boxes to the right reflect verification passes according to"+
406                         " The Java Virtual Machine Specification.\nThese are (in that order):"+
407                         " Pass one, Pass two, Pass three (before data flow analysis), Pass three (data flow analysis).\n"+
408                         "The bottom box to the right shows (warning) messages; warnings do not cause a class to be rejected.",
409                         JUSTICE_VERSION, JOptionPane.INFORMATION_MESSAGE);
410     }
411 
412 
413     /**
414      * @return the classNamesJList
415      */
getClassNamesJList()416     JList<String> getClassNamesJList() {
417         return classNamesJList;
418     }
419 
420 
421 }
422