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}