    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$
    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}