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