001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 *
017 */
018package org.apache.bcel.verifier;
019
020import java.awt.AWTEvent;
021import java.awt.CardLayout;
022import java.awt.Color;
023import java.awt.Dimension;
024import java.awt.GridLayout;
025import java.awt.event.ActionEvent;
026import java.awt.event.InputEvent;
027import java.awt.event.WindowEvent;
028import javax.swing.BorderFactory;
029import javax.swing.JFrame;
030import javax.swing.JList;
031import javax.swing.JMenu;
032import javax.swing.JMenuBar;
033import javax.swing.JMenuItem;
034import javax.swing.JOptionPane;
035import javax.swing.JPanel;
036import javax.swing.JScrollPane;
037import javax.swing.JSplitPane;
038import javax.swing.JTextPane;
039import javax.swing.ListSelectionModel;
040import javax.swing.event.ListSelectionEvent;
041
042import org.apache.bcel.Repository;
043import org.apache.bcel.classfile.JavaClass;
044
045/**
046 * This class implements a machine-generated frame for use with
047 * the GraphicalVerfifier.
048 *
049 * @version $Id: VerifierAppFrame.java 1749603 2016-06-21 20:50:19Z ggregory $
050 * @see GraphicalVerifier
051 */
052public class VerifierAppFrame extends JFrame {
053
054    private static final long serialVersionUID = -542458133073307640L;
055    private static final String JUSTICE_VERSION = "JustIce by Enver Haase";
056
057    private JPanel contentPane;
058    private final JSplitPane jSplitPane1 = new JSplitPane();
059    private final JPanel jPanel1 = new JPanel();
060    private final JPanel jPanel2 = new JPanel();
061    private final JSplitPane jSplitPane2 = new JSplitPane();
062    private final JPanel jPanel3 = new JPanel();
063    private final JList<String> classNamesJList = new JList<>();
064    private final GridLayout gridLayout1 = new GridLayout();
065    private final JPanel messagesPanel = new JPanel();
066    private final GridLayout gridLayout2 = new GridLayout();
067    private final JMenuBar jMenuBar1 = new JMenuBar();
068    private final JMenu jMenu1 = new JMenu();
069    private final JScrollPane jScrollPane1 = new JScrollPane();
070    private final JScrollPane messagesScrollPane = new JScrollPane();
071    private final JScrollPane jScrollPane3 = new JScrollPane();
072    private final GridLayout gridLayout4 = new GridLayout();
073    private final JScrollPane jScrollPane4 = new JScrollPane();
074    private final CardLayout cardLayout1 = new CardLayout();
075    private String current_class;
076    private final GridLayout gridLayout3 = new GridLayout();
077    private final JTextPane pass1TextPane = new JTextPane();
078    private final JTextPane pass2TextPane = new JTextPane();
079    private final JTextPane messagesTextPane = new JTextPane();
080    private final JMenuItem newFileMenuItem = new JMenuItem();
081    private final JSplitPane jSplitPane3 = new JSplitPane();
082    private final JSplitPane jSplitPane4 = new JSplitPane();
083    private final JScrollPane jScrollPane2 = new JScrollPane();
084    private final JScrollPane jScrollPane5 = new JScrollPane();
085    private final JScrollPane jScrollPane6 = new JScrollPane();
086    private final JScrollPane jScrollPane7 = new JScrollPane();
087    private final JList<String> pass3aJList = new JList<>();
088    private final JList<String> pass3bJList = new JList<>();
089    private final JTextPane pass3aTextPane = new JTextPane();
090    private final JTextPane pass3bTextPane = new JTextPane();
091    private final JMenu jMenu2 = new JMenu();
092    private final JMenuItem whatisMenuItem = new JMenuItem();
093    private final JMenuItem aboutMenuItem = new JMenuItem();
094
095
096    /** Constructor. */
097    public VerifierAppFrame() {
098        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
099        try {
100            jbInit();
101        } catch (final Exception e) {
102            e.printStackTrace();
103        }
104    }
105
106
107    /** Initizalization of the components. */
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
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
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
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
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
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
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
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
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     */
416    JList<String> getClassNamesJList() {
417        return classNamesJList;
418    }
419
420
421}