    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.Color;
    021import java.awt.Dialog;
    022import java.awt.Frame;
    023import java.awt.SystemColor;
    024import java.awt.event.ActionEvent;
    025import java.awt.event.ActionListener;
    026import java.awt.event.WindowAdapter;
    027import java.awt.event.WindowEvent;
    028
    029import javax.swing.JButton;
    030import javax.swing.JDialog;
    031import javax.swing.JPanel;
    032import javax.swing.WindowConstants;
    033
    034import org.apache.bcel.Repository;
    035import org.apache.bcel.classfile.JavaClass;
    036import org.apache.bcel.classfile.Utility;
    037
    038/**
    039 * A class for simple graphical class file verification. Use the main(String []) method with fully qualified class names
    040 * as arguments to use it as a stand-alone application. Use the VerifyDialog(String) constructor to use this class in
    041 * your application. [This class was created using VisualAge for Java, but it does not work under VAJ itself (Version
    042 * 3.02 JDK 1.2)]
    043 *
    044 * @see #main(String[])
    045 * @see #VerifyDialog(String)
    046 */
    047public class VerifyDialog extends JDialog {
    048
    049    /** Machine-generated, made final. */
    050    final class IvjEventHandler implements ActionListener {
    051
    052        @Override
    053        public void actionPerformed(final ActionEvent e) {
    054            if (e.getSource() == VerifyDialog.this.getPass1Button()) {
    055                connEtoC1(e);
    056            }
    057            if (e.getSource() == VerifyDialog.this.getPass2Button()) {
    058                connEtoC2(e);
    059            }
    060            if (e.getSource() == VerifyDialog.this.getPass3Button()) {
    061                connEtoC3(e);
    062            }
    063            if (e.getSource() == VerifyDialog.this.getFlushButton()) {
    064                connEtoC4(e);
    065            }
    066        }
    067    }
    068
    069    private static final long serialVersionUID = -6374807677043142313L;
    070
    071    /**
    072     * This field is here to count the number of open VerifyDialog instances so the JVM can be exited afer every Dialog had
    073     * been closed.
    074     */
    075    private static int classesToVerify;
    076
    077    /**
    078     * Verifies one or more class files. Verification results are presented graphically: Red means 'rejected', green means
    079     * 'passed' while yellow means 'could not be verified yet'.
    080     *
    081     * @param args String[] fully qualified names of classes to verify.
    082     */
    083    public static void main(final String[] args) {
    084        classesToVerify = args.length;
    085        for (final String arg : args) {
    086            try {
    087                final VerifyDialog aVerifyDialog;
    088                aVerifyDialog = new VerifyDialog(arg);
    089                aVerifyDialog.setModal(true);
    090                aVerifyDialog.addWindowListener(new WindowAdapter() {
    091
    092                    @Override
    093                    public void windowClosing(final WindowEvent e) {
    094                        classesToVerify--;
    095                        if (classesToVerify == 0) {
    096                            System.exit(0);
    097                        }
    098                    }
    099                });
    100                aVerifyDialog.setVisible(true);
    101            } catch (final Throwable exception) {
    102                System.err.println("Exception occurred in main() of JDialog");
    103                exception.printStackTrace(System.out);
    104            }
    105        }
    106    }
    107
    108    /** Machine-generated. */
    109    private JPanel ivjJDialogContentPane;
    110    /** Machine-generated. */
    111    private JPanel ivjPass1Panel;
    112    /** Machine-generated. */
    113    private JPanel ivjPass2Panel;
    114    /** Machine-generated. */
    115    private JPanel ivjPass3Panel;
    116    /** Machine-generated. */
    117    private JButton ivjPass1Button;
    118    /** Machine-generated. */
    119    private JButton ivjPass2Button;
    120    /** Machine-generated. */
    121    private JButton ivjPass3Button;
    122
    123    /** Machine-generated. */
    124    private final IvjEventHandler ivjEventHandler = new IvjEventHandler();
    125
    126    /**
    127     * The class to verify. Default set to 'java.lang.Object' in case this class is instantiated via one of the many
    128     * machine-generated constructors.
    129     */
    130    private String className = "java.lang.Object";
    131
    132    /** Machine-generated. */
    133    private JButton ivjFlushButton;
    134
    135    /** Machine-generated. */
    136    public VerifyDialog() {
    137        initialize();
    138    }
    139
    140    /** Machine-generated. */
    141    public VerifyDialog(final Dialog owner) {
    142        super(owner);
    143    }
    144
    145    /** Machine-generated. */
    146    public VerifyDialog(final Dialog owner, final boolean modal) {
    147        super(owner, modal);
    148    }
    149
    150    /** Machine-generated. */
    151    public VerifyDialog(final Dialog owner, final String title) {
    152        super(owner, title);
    153    }
    154
    155    /** Machine-generated. */
    156    public VerifyDialog(final Dialog owner, final String title, final boolean modal) {
    157        super(owner, title, modal);
    158    }
    159
    160    /** Machine-generated. */
    161    public VerifyDialog(final Frame owner) {
    162        super(owner);
    163    }
    164
    165    /** Machine-generated. */
    166    public VerifyDialog(final Frame owner, final boolean modal) {
    167        super(owner, modal);
    168    }
    169
    170    /** Machine-generated. */
    171    public VerifyDialog(final Frame owner, final String title) {
    172        super(owner, title);
    173    }
    174
    175    /** Machine-generated. */
    176    public VerifyDialog(final Frame owner, final String title, final boolean modal) {
    177        super(owner, title, modal);
    178    }
    179
    180    /**
    181     * Use this constructor if you want a possibility to verify other class files than {@link Object}.
    182     *
    183     * @param fullyQualifiedClassName "java.lang.String"
    184     */
    185    public VerifyDialog(String fullyQualifiedClassName) {
    186        final int dotclasspos = fullyQualifiedClassName.lastIndexOf(JavaClass.EXTENSION);
    187        if (dotclasspos != -1) {
    188            fullyQualifiedClassName = fullyQualifiedClassName.substring(0, dotclasspos);
    189        }
    190        fullyQualifiedClassName = Utility.pathToPackage(fullyQualifiedClassName);
    191        this.className = fullyQualifiedClassName;
    192        initialize();
    193    }
    194
    195    /** Machine-generated. */
    196    private void connEtoC1(final ActionEvent arg1) {
    197        try {
    198            // user code begin {1}
    199            // user code end
    200            this.pass1Button_ActionPerformed(arg1);
    201            // user code begin {2}
    202            // user code end
    203        } catch (final Throwable ivjExc) {
    204            // user code begin {3}
    205            // user code end
    206            handleException(ivjExc);
    207        }
    208    }
    209
    210    /** Machine-generated. */
    211    private void connEtoC2(final ActionEvent arg1) {
    212        try {
    213            // user code begin {1}
    214            // user code end
    215            this.pass2Button_ActionPerformed(arg1);
    216            // user code begin {2}
    217            // user code end
    218        } catch (final Throwable ivjExc) {
    219            // user code begin {3}
    220            // user code end
    221            handleException(ivjExc);
    222        }
    223    }
    224
    225    /** Machine-generated. */
    226    private void connEtoC3(final ActionEvent arg1) {
    227        try {
    228            // user code begin {1}
    229            // user code end
    230            this.pass4Button_ActionPerformed(arg1);
    231            // user code begin {2}
    232            // user code end
    233        } catch (final Throwable ivjExc) {
    234            // user code begin {3}
    235            // user code end
    236            handleException(ivjExc);
    237        }
    238    }
    239
    240    /** Machine-generated. */
    241    private void connEtoC4(final ActionEvent arg1) {
    242        try {
    243            // user code begin {1}
    244            // user code end
    245            this.flushButton_ActionPerformed(arg1);
    246            // user code begin {2}
    247            // user code end
    248        } catch (final Throwable ivjExc) {
    249            // user code begin {3}
    250            // user code end
    251            handleException(ivjExc);
    252        }
    253    }
    254
    255    /** Machine-generated. */
    256    public void flushButton_ActionPerformed(final ActionEvent actionEvent) {
    257        VerifierFactory.getVerifier(className).flush();
    258        Repository.removeClass(className); // Make sure it will be reloaded.
    259        getPass1Panel().setBackground(Color.gray);
    260        getPass1Panel().repaint();
    261        getPass2Panel().setBackground(Color.gray);
    262        getPass2Panel().repaint();
    263        getPass3Panel().setBackground(Color.gray);
    264        getPass3Panel().repaint();
    265    }
    266
    267    /** Machine-generated. */
    268    private JButton getFlushButton() {
    269        if (ivjFlushButton == null) {
    270            try {
    271                ivjFlushButton = new JButton();
    272                ivjFlushButton.setName("FlushButton");
    273                ivjFlushButton.setText("Flush: Forget old verification results");
    274                ivjFlushButton.setBackground(SystemColor.controlHighlight);
    275                ivjFlushButton.setBounds(60, 215, 300, 30);
    276                ivjFlushButton.setForeground(Color.red);
    277                ivjFlushButton.setActionCommand("FlushButton");
    278                // user code begin {1}
    279                // user code end
    280            } catch (final Throwable ivjExc) {
    281                // user code begin {2}
    282                // user code end
    283                handleException(ivjExc);
    284            }
    285        }
    286        return ivjFlushButton;
    287    }
    288
    289    /** Machine-generated. */
    290    private JPanel getJDialogContentPane() {
    291        if (ivjJDialogContentPane == null) {
    292            try {
    293                ivjJDialogContentPane = new JPanel();
    294                ivjJDialogContentPane.setName("JDialogContentPane");
    295                ivjJDialogContentPane.setLayout(null);
    296                getJDialogContentPane().add(getPass1Panel(), getPass1Panel().getName());
    297                getJDialogContentPane().add(getPass3Panel(), getPass3Panel().getName());
    298                getJDialogContentPane().add(getPass2Panel(), getPass2Panel().getName());
    299                getJDialogContentPane().add(getPass1Button(), getPass1Button().getName());
    300                getJDialogContentPane().add(getPass2Button(), getPass2Button().getName());
    301                getJDialogContentPane().add(getPass3Button(), getPass3Button().getName());
    302                getJDialogContentPane().add(getFlushButton(), getFlushButton().getName());
    303                // user code begin {1}
    304                // user code end
    305            } catch (final Throwable ivjExc) {
    306                // user code begin {2}
    307                // user code end
    308                handleException(ivjExc);
    309            }
    310        }
    311        return ivjJDialogContentPane;
    312    }
    313
    314    /** Machine-generated. */
    315    private JButton getPass1Button() {
    316        if (ivjPass1Button == null) {
    317            try {
    318                ivjPass1Button = new JButton();
    319                ivjPass1Button.setName("Pass1Button");
    320                ivjPass1Button.setText("Pass1: Verify binary layout of .class file");
    321                ivjPass1Button.setBackground(SystemColor.controlHighlight);
    322                ivjPass1Button.setBounds(100, 40, 300, 30);
    323                ivjPass1Button.setActionCommand("Button1");
    324                // user code begin {1}
    325                // user code end
    326            } catch (final Throwable ivjExc) {
    327                // user code begin {2}
    328                // user code end
    329                handleException(ivjExc);
    330            }
    331        }
    332        return ivjPass1Button;
    333    }
    334
    335    /** Machine-generated. */
    336    private JPanel getPass1Panel() {
    337        if (ivjPass1Panel == null) {
    338            try {
    339                ivjPass1Panel = new JPanel();
    340                ivjPass1Panel.setName("Pass1Panel");
    341                ivjPass1Panel.setLayout(null);
    342                ivjPass1Panel.setBackground(SystemColor.controlShadow);
    343                ivjPass1Panel.setBounds(30, 30, 50, 50);
    344                // user code begin {1}
    345                // user code end
    346            } catch (final Throwable ivjExc) {
    347                // user code begin {2}
    348                // user code end
    349                handleException(ivjExc);
    350            }
    351        }
    352        return ivjPass1Panel;
    353    }
    354
    355    /** Machine-generated. */
    356    private JButton getPass2Button() {
    357        if (ivjPass2Button == null) {
    358            try {
    359                ivjPass2Button = new JButton();
    360                ivjPass2Button.setName("Pass2Button");
    361                ivjPass2Button.setText("Pass 2: Verify static .class file constraints");
    362                ivjPass2Button.setBackground(SystemColor.controlHighlight);
    363                ivjPass2Button.setBounds(100, 100, 300, 30);
    364                ivjPass2Button.setActionCommand("Button2");
    365                // user code begin {1}
    366                // user code end
    367            } catch (final Throwable ivjExc) {
    368                // user code begin {2}
    369                // user code end
    370                handleException(ivjExc);
    371            }
    372        }
    373        return ivjPass2Button;
    374    }
    375
    376    /** Machine-generated. */
    377    private JPanel getPass2Panel() {
    378        if (ivjPass2Panel == null) {
    379            try {
    380                ivjPass2Panel = new JPanel();
    381                ivjPass2Panel.setName("Pass2Panel");
    382                ivjPass2Panel.setLayout(null);
    383                ivjPass2Panel.setBackground(SystemColor.controlShadow);
    384                ivjPass2Panel.setBounds(30, 90, 50, 50);
    385                // user code begin {1}
    386                // user code end
    387            } catch (final Throwable ivjExc) {
    388                // user code begin {2}
    389                // user code end
    390                handleException(ivjExc);
    391            }
    392        }
    393        return ivjPass2Panel;
    394    }
    395
    396    /** Machine-generated. */
    397    private JButton getPass3Button() {
    398        if (ivjPass3Button == null) {
    399            try {
    400                ivjPass3Button = new JButton();
    401                ivjPass3Button.setName("Pass3Button");
    402                ivjPass3Button.setText("Passes 3a+3b: Verify code arrays");
    403                ivjPass3Button.setBackground(SystemColor.controlHighlight);
    404                ivjPass3Button.setBounds(100, 160, 300, 30);
    405                ivjPass3Button.setActionCommand("Button2");
    406                // user code begin {1}
    407                // user code end
    408            } catch (final Throwable ivjExc) {
    409                // user code begin {2}
    410                // user code end
    411                handleException(ivjExc);
    412            }
    413        }
    414        return ivjPass3Button;
    415    }
    416
    417    /** Machine-generated. */
    418    private JPanel getPass3Panel() {
    419        if (ivjPass3Panel == null) {
    420            try {
    421                ivjPass3Panel = new JPanel();
    422                ivjPass3Panel.setName("Pass3Panel");
    423                ivjPass3Panel.setLayout(null);
    424                ivjPass3Panel.setBackground(SystemColor.controlShadow);
    425                ivjPass3Panel.setBounds(30, 150, 50, 50);
    426                // user code begin {1}
    427                // user code end
    428            } catch (final Throwable ivjExc) {
    429                // user code begin {2}
    430                // user code end
    431                handleException(ivjExc);
    432            }
    433        }
    434        return ivjPass3Panel;
    435    }
    436
    437    /** Machine-generated. */
    438    private void handleException(final Throwable exception) {
    439        /* Uncomment the following lines to print uncaught exceptions to stdout */
    440        System.out.println("--------- UNCAUGHT EXCEPTION ---------");
    441        exception.printStackTrace(System.out);
    442        // manually added code
    443        if (exception instanceof ThreadDeath) {
    444            throw (ThreadDeath) exception;
    445        }
    446        if (exception instanceof VirtualMachineError) {
    447            throw (VirtualMachineError) exception;
    448        }
    449    }
    450
    451    /** Machine-generated. */
    452    private void initConnections() {
    453        // user code begin {1}
    454        // user code end
    455        getPass1Button().addActionListener(ivjEventHandler);
    456        getPass2Button().addActionListener(ivjEventHandler);
    457        getPass3Button().addActionListener(ivjEventHandler);
    458        getFlushButton().addActionListener(ivjEventHandler);
    459    }
    460
    461    /** Machine-generated. */
    462    private void initialize() {
    463        try {
    464            // user code begin {1}
    465            // user code end
    466            setName("VerifyDialog");
    467            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    468            setSize(430, 280);
    469            setVisible(true);
    470            setModal(true);
    471            setResizable(false);
    472            setContentPane(getJDialogContentPane());
    473            initConnections();
    474        } catch (final Throwable ivjExc) {
    475            handleException(ivjExc);
    476        }
    477        // user code begin {2}
    478        setTitle("'" + className + "' verification - JustIce / BCEL");
    479        // user code end
    480    }
    481
    482    /** Machine-generated. */
    483    public void pass1Button_ActionPerformed(final ActionEvent actionEvent) {
    484        final Verifier v = VerifierFactory.getVerifier(className);
    485        final VerificationResult vr = v.doPass1();
    486        if (vr.getStatus() == VerificationResult.VERIFIED_OK) {
    487            getPass1Panel().setBackground(Color.green);
    488            getPass1Panel().repaint();
    489        }
    490        if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
    491            getPass1Panel().setBackground(Color.red);
    492            getPass1Panel().repaint();
    493        }
    494    }
    495
    496    /** Machine-generated. */
    497    public void pass2Button_ActionPerformed(final ActionEvent actionEvent) {
    498        pass1Button_ActionPerformed(actionEvent);
    499        final Verifier v = VerifierFactory.getVerifier(className);
    500        final VerificationResult vr = v.doPass2();
    501        if (vr.getStatus() == VerificationResult.VERIFIED_OK) {
    502            getPass2Panel().setBackground(Color.green);
    503            getPass2Panel().repaint();
    504        }
    505        if (vr.getStatus() == VerificationResult.VERIFIED_NOTYET) {
    506            getPass2Panel().setBackground(Color.yellow);
    507            getPass2Panel().repaint();
    508        }
    509        if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
    510            getPass2Panel().setBackground(Color.red);
    511            getPass2Panel().repaint();
    512        }
    513    }
    514
    515    /** Machine-generated. */
    516    public void pass4Button_ActionPerformed(final ActionEvent actionEvent) {
    517        pass2Button_ActionPerformed(actionEvent);
    518        Color color = Color.green;
    519        final Verifier v = VerifierFactory.getVerifier(className);
    520        VerificationResult vr = v.doPass2();
    521        if (vr.getStatus() == VerificationResult.VERIFIED_OK) {
    522            JavaClass jc = null;
    523            try {
    524                jc = Repository.lookupClass(className);
    525                final int nr = jc.getMethods().length;
    526                for (int i = 0; i < nr; i++) {
    527                    vr = v.doPass3b(i);
    528                    if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
    529                        color = Color.red;
    530                        break;
    531                    }
    532                }
    533            } catch (final ClassNotFoundException ex) {
    534                // FIXME: report the error
    535                ex.printStackTrace();
    536            }
    537        } else {
    538            color = Color.yellow;
    539        }
    540        getPass3Panel().setBackground(color);
    541        getPass3Panel().repaint();
    542    }
    543}