VerifierAppFrame.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *  Unless required by applicable law or agreed to in writing, software
  12.  *  distributed under the License is distributed on an "AS IS" BASIS,
  13.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *  See the License for the specific language governing permissions and
  15.  *  limitations under the License.
  16.  */
  17. package org.apache.bcel.verifier;

  18. import java.awt.AWTEvent;
  19. import java.awt.CardLayout;
  20. import java.awt.Color;
  21. import java.awt.Dimension;
  22. import java.awt.GridLayout;
  23. import java.awt.event.ActionEvent;
  24. import java.awt.event.InputEvent;
  25. import java.awt.event.WindowEvent;
  26. import java.util.Arrays;

  27. import javax.swing.BorderFactory;
  28. import javax.swing.JFrame;
  29. import javax.swing.JList;
  30. import javax.swing.JMenu;
  31. import javax.swing.JMenuBar;
  32. import javax.swing.JMenuItem;
  33. import javax.swing.JOptionPane;
  34. import javax.swing.JPanel;
  35. import javax.swing.JScrollPane;
  36. import javax.swing.JSplitPane;
  37. import javax.swing.JTextPane;
  38. import javax.swing.ListSelectionModel;
  39. import javax.swing.event.ListSelectionEvent;

  40. import org.apache.bcel.Repository;
  41. import org.apache.bcel.classfile.JavaClass;
  42. import org.apache.commons.lang3.ArrayUtils;

  43. /**
  44.  * This class implements a machine-generated frame for use with the GraphicalVerfifier.
  45.  *
  46.  * @see GraphicalVerifier
  47.  */
  48. public class VerifierAppFrame extends JFrame {

  49.     private static final long serialVersionUID = -542458133073307640L;
  50.     private JPanel contentPane;
  51.     private final JSplitPane jSplitPane1 = new JSplitPane();
  52.     private final JPanel jPanel1 = new JPanel();
  53.     private final JPanel jPanel2 = new JPanel();
  54.     private final JSplitPane jSplitPane2 = new JSplitPane();
  55.     private final JPanel jPanel3 = new JPanel();
  56.     private final JList<String> classNamesJList = new JList<>();
  57.     private final GridLayout gridLayout1 = new GridLayout();
  58.     private final JPanel messagesPanel = new JPanel();
  59.     private final GridLayout gridLayout2 = new GridLayout();
  60.     private final JMenuBar jMenuBar1 = new JMenuBar();
  61.     private final JMenu jMenu1 = new JMenu();
  62.     private final JScrollPane jScrollPane1 = new JScrollPane();
  63.     private final JScrollPane messagesScrollPane = new JScrollPane();
  64.     private final JScrollPane jScrollPane3 = new JScrollPane();
  65.     private final GridLayout gridLayout4 = new GridLayout();
  66.     private final JScrollPane jScrollPane4 = new JScrollPane();
  67.     private final CardLayout cardLayout1 = new CardLayout();
  68.     private String currentClass;
  69.     private final GridLayout gridLayout3 = new GridLayout();
  70.     private final JTextPane pass1TextPane = new JTextPane();
  71.     private final JTextPane pass2TextPane = new JTextPane();
  72.     private final JTextPane messagesTextPane = new JTextPane();
  73.     private final JMenuItem newFileMenuItem = new JMenuItem();
  74.     private final JSplitPane jSplitPane3 = new JSplitPane();
  75.     private final JSplitPane jSplitPane4 = new JSplitPane();
  76.     private final JScrollPane jScrollPane2 = new JScrollPane();
  77.     private final JScrollPane jScrollPane5 = new JScrollPane();
  78.     private final JScrollPane jScrollPane6 = new JScrollPane();
  79.     private final JScrollPane jScrollPane7 = new JScrollPane();
  80.     private final JList<String> pass3aJList = new JList<>();
  81.     private final JList<String> pass3bJList = new JList<>();
  82.     private final JTextPane pass3aTextPane = new JTextPane();
  83.     private final JTextPane pass3bTextPane = new JTextPane();
  84.     private final JMenu jMenu2 = new JMenu();
  85.     private final JMenuItem whatisMenuItem = new JMenuItem();
  86.     private final JMenuItem aboutMenuItem = new JMenuItem();

  87.     /** Constructs a new instance. */
  88.     public VerifierAppFrame() {
  89.         enableEvents(AWTEvent.WINDOW_EVENT_MASK);
  90.         try {
  91.             jbInit();
  92.         } catch (final Exception e) {
  93.             e.printStackTrace();
  94.         }
  95.     }

  96.     void aboutMenuItemActionPerformed(final ActionEvent e) {
  97.         JOptionPane.showMessageDialog(this, Verifier.BANNER, Verifier.NAME, JOptionPane.INFORMATION_MESSAGE);
  98.     }

  99.     synchronized void classNamesJListValueChanged(final ListSelectionEvent e) {
  100.         if (e.getValueIsAdjusting()) {
  101.             return;
  102.         }
  103.         currentClass = classNamesJList.getSelectedValue();
  104.         try {
  105.             verify();
  106.         } catch (final ClassNotFoundException ex) {
  107.             // FIXME: report the error using the GUI
  108.             ex.printStackTrace();
  109.         }
  110.         classNamesJList.setSelectedValue(currentClass, true);
  111.     }

  112.     /**
  113.      * @return the classNamesJList
  114.      */
  115.     JList<String> getClassNamesJList() {
  116.         return classNamesJList;
  117.     }

  118.     /** Initizalization of the components. */
  119.     private void jbInit() {
  120.         // setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Ihr Symbol]")));
  121.         contentPane = (JPanel) getContentPane();
  122.         contentPane.setLayout(cardLayout1);
  123.         setJMenuBar(jMenuBar1);
  124.         this.setSize(new Dimension(708, 451));
  125.         setTitle("JustIce");
  126.         jPanel1.setMinimumSize(new Dimension(100, 100));
  127.         jPanel1.setPreferredSize(new Dimension(100, 100));
  128.         jPanel1.setLayout(gridLayout1);
  129.         jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT);
  130.         jPanel2.setLayout(gridLayout2);
  131.         jPanel3.setMinimumSize(new Dimension(200, 100));
  132.         jPanel3.setPreferredSize(new Dimension(400, 400));
  133.         jPanel3.setLayout(gridLayout4);
  134.         messagesPanel.setMinimumSize(new Dimension(100, 100));
  135.         messagesPanel.setLayout(gridLayout3);
  136.         jPanel2.setMinimumSize(new Dimension(200, 100));
  137.         jMenu1.setText("File");
  138.         jScrollPane1.getViewport().setBackground(Color.red);
  139.         messagesScrollPane.getViewport().setBackground(Color.red);
  140.         messagesScrollPane.setPreferredSize(new Dimension(10, 10));
  141.         classNamesJList.addListSelectionListener(this::classNamesJListValueChanged);
  142.         classNamesJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  143.         jScrollPane3.setBorder(BorderFactory.createLineBorder(Color.black));
  144.         jScrollPane3.setPreferredSize(new Dimension(100, 100));
  145.         gridLayout4.setRows(4);
  146.         gridLayout4.setColumns(1);
  147.         gridLayout4.setHgap(1);
  148.         jScrollPane4.setBorder(BorderFactory.createLineBorder(Color.black));
  149.         jScrollPane4.setPreferredSize(new Dimension(100, 100));
  150.         pass1TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
  151.         pass1TextPane.setToolTipText("");
  152.         pass1TextPane.setEditable(false);
  153.         pass2TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
  154.         pass2TextPane.setEditable(false);
  155.         messagesTextPane.setBorder(BorderFactory.createRaisedBevelBorder());
  156.         messagesTextPane.setEditable(false);
  157.         newFileMenuItem.setText("New...");
  158.         newFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(78, InputEvent.CTRL_MASK, true));
  159.         newFileMenuItem.addActionListener(this::newFileMenuItemActionPerformed);
  160.         pass3aTextPane.setEditable(false);
  161.         pass3bTextPane.setEditable(false);
  162.         pass3aJList.addListSelectionListener(this::pass3aJList_valueChanged);
  163.         pass3bJList.addListSelectionListener(this::pass3bJList_valueChanged);
  164.         jMenu2.setText("Help");
  165.         whatisMenuItem.setText("What is...");
  166.         whatisMenuItem.addActionListener(this::whatisMenuItemActionPerformed);
  167.         aboutMenuItem.setText("About");
  168.         aboutMenuItem.addActionListener(this::aboutMenuItemActionPerformed);
  169.         jSplitPane2.add(messagesPanel, JSplitPane.BOTTOM);
  170.         messagesPanel.add(messagesScrollPane, null);
  171.         messagesScrollPane.getViewport().add(messagesTextPane, null);
  172.         jSplitPane2.add(jPanel3, JSplitPane.TOP);
  173.         jPanel3.add(jScrollPane3, null);
  174.         jScrollPane3.getViewport().add(pass1TextPane, null);
  175.         jPanel3.add(jScrollPane4, null);
  176.         jPanel3.add(jSplitPane3, null);
  177.         jSplitPane3.add(jScrollPane2, JSplitPane.LEFT);
  178.         jScrollPane2.getViewport().add(pass3aJList, null);
  179.         jSplitPane3.add(jScrollPane5, JSplitPane.RIGHT);
  180.         jScrollPane5.getViewport().add(pass3aTextPane, null);
  181.         jPanel3.add(jSplitPane4, null);
  182.         jSplitPane4.add(jScrollPane6, JSplitPane.LEFT);
  183.         jScrollPane6.getViewport().add(pass3bJList, null);
  184.         jSplitPane4.add(jScrollPane7, JSplitPane.RIGHT);
  185.         jScrollPane7.getViewport().add(pass3bTextPane, null);
  186.         jScrollPane4.getViewport().add(pass2TextPane, null);
  187.         jSplitPane1.add(jPanel2, JSplitPane.TOP);
  188.         jPanel2.add(jScrollPane1, null);
  189.         jSplitPane1.add(jPanel1, JSplitPane.BOTTOM);
  190.         jPanel1.add(jSplitPane2, null);
  191.         jScrollPane1.getViewport().add(classNamesJList, null);
  192.         jMenuBar1.add(jMenu1);
  193.         jMenuBar1.add(jMenu2);
  194.         contentPane.add(jSplitPane1, "jSplitPane1");
  195.         jMenu1.add(newFileMenuItem);
  196.         jMenu2.add(whatisMenuItem);
  197.         jMenu2.add(aboutMenuItem);
  198.         jSplitPane2.setDividerLocation(300);
  199.         jSplitPane3.setDividerLocation(150);
  200.         jSplitPane4.setDividerLocation(150);
  201.     }

  202.     void newFileMenuItemActionPerformed(final ActionEvent e) {
  203.         final String className = JOptionPane.showInputDialog("Please enter the fully qualified name of a class or interface to verify:");
  204.         if (className == null || className.isEmpty()) {
  205.             return;
  206.         }
  207.         VerifierFactory.getVerifier(className); // let observers do the rest.
  208.         classNamesJList.setSelectedValue(className, true);
  209.     }

  210.     synchronized void pass3aJList_valueChanged(final ListSelectionEvent e) {
  211.         if (e.getValueIsAdjusting()) {
  212.             return;
  213.         }
  214.         final Verifier v = VerifierFactory.getVerifier(currentClass);
  215.         final StringBuilder all3amsg = new StringBuilder();
  216.         boolean all3aok = true;
  217.         boolean rejected = false;
  218.         for (int i = 0; i < pass3aJList.getModel().getSize(); i++) {
  219.             if (pass3aJList.isSelectedIndex(i)) {
  220.                 final VerificationResult vr = v.doPass3a(i);
  221.                 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
  222.                     all3aok = false;
  223.                     rejected = true;
  224.                 }
  225.                 JavaClass jc = null;
  226.                 try {
  227.                     jc = Repository.lookupClass(v.getClassName());
  228.                     all3amsg.append("Method '").append(jc.getMethods()[i]).append("': ").append(vr.getMessage().replace('\n', ' ')).append("\n\n");
  229.                 } catch (final ClassNotFoundException ex) {
  230.                     // FIXME: handle the error
  231.                     ex.printStackTrace();
  232.                 }
  233.             }
  234.         }
  235.         pass3aTextPane.setText(all3amsg.toString());
  236.         pass3aTextPane.setBackground(all3aok ? Color.green : rejected ? Color.red : Color.yellow);
  237.     }

  238.     synchronized void pass3bJList_valueChanged(final ListSelectionEvent e) {
  239.         if (e.getValueIsAdjusting()) {
  240.             return;
  241.         }
  242.         final Verifier v = VerifierFactory.getVerifier(currentClass);
  243.         final StringBuilder all3bmsg = new StringBuilder();
  244.         boolean all3bok = true;
  245.         boolean rejected = false;
  246.         for (int i = 0; i < pass3bJList.getModel().getSize(); i++) {
  247.             if (pass3bJList.isSelectedIndex(i)) {
  248.                 final VerificationResult vr = v.doPass3b(i);
  249.                 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
  250.                     all3bok = false;
  251.                     rejected = true;
  252.                 }
  253.                 JavaClass jc = null;
  254.                 try {
  255.                     jc = Repository.lookupClass(v.getClassName());
  256.                     all3bmsg.append("Method '").append(jc.getMethods()[i]).append("': ").append(vr.getMessage().replace('\n', ' ')).append("\n\n");
  257.                 } catch (final ClassNotFoundException ex) {
  258.                     // FIXME: handle the error
  259.                     ex.printStackTrace();
  260.                 }
  261.             }
  262.         }
  263.         pass3bTextPane.setText(all3bmsg.toString());
  264.         pass3bTextPane.setBackground(all3bok ? Color.green : rejected ? Color.red : Color.yellow);
  265.     }

  266.     /** Overridden to stop the application on a closing window. */
  267.     @Override
  268.     protected void processWindowEvent(final WindowEvent e) {
  269.         super.processWindowEvent(e);
  270.         if (e.getID() == WindowEvent.WINDOW_CLOSING) {
  271.             System.exit(0);
  272.         }
  273.     }

  274.     private void verify() throws ClassNotFoundException {
  275.         setTitle("PLEASE WAIT");
  276.         final Verifier v = VerifierFactory.getVerifier(currentClass);
  277.         v.flush(); // Don't cache the verification result for this class.
  278.         VerificationResult vr;
  279.         vr = v.doPass1();
  280.         if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
  281.             pass1TextPane.setText(vr.getMessage());
  282.             pass1TextPane.setBackground(Color.red);
  283.             pass2TextPane.setText("");
  284.             pass2TextPane.setBackground(Color.yellow);
  285.             pass3aTextPane.setText("");
  286.             pass3aJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
  287.             pass3aTextPane.setBackground(Color.yellow);
  288.             pass3bTextPane.setText("");
  289.             pass3bJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
  290.             pass3bTextPane.setBackground(Color.yellow);
  291.         } else { // Must be VERIFIED_OK, Pass 1 does not know VERIFIED_NOTYET
  292.             pass1TextPane.setBackground(Color.green);
  293.             pass1TextPane.setText(vr.getMessage());
  294.             vr = v.doPass2();
  295.             if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
  296.                 pass2TextPane.setText(vr.getMessage());
  297.                 pass2TextPane.setBackground(Color.red);
  298.                 pass3aTextPane.setText("");
  299.                 pass3aTextPane.setBackground(Color.yellow);
  300.                 pass3aJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
  301.                 pass3bTextPane.setText("");
  302.                 pass3bTextPane.setBackground(Color.yellow);
  303.                 pass3bJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY);
  304.             } else { // must be Verified_OK, because Pass1 was OK (cannot be Verified_NOTYET).
  305.                 pass2TextPane.setText(vr.getMessage());
  306.                 pass2TextPane.setBackground(Color.green);
  307.                 final JavaClass jc = Repository.lookupClass(currentClass);
  308.                 /*
  309.                  * boolean all3aok = true; boolean all3bok = true; String all3amsg = ""; String all3bmsg = "";
  310.                  */
  311.                 final String[] methodNames = new String[jc.getMethods().length];
  312.                 Arrays.setAll(methodNames, i -> jc.getMethods()[i].toString().replace('\n', ' ').replace('\t', ' '));
  313.                 pass3aJList.setListData(methodNames);
  314.                 pass3aJList.setSelectionInterval(0, jc.getMethods().length - 1);
  315.                 pass3bJList.setListData(methodNames);
  316.                 pass3bJList.setSelectionInterval(0, jc.getMethods().length - 1);
  317.             }
  318.         }
  319.         final String[] msgs = v.getMessages();
  320.         messagesTextPane.setBackground(msgs.length == 0 ? Color.green : Color.yellow);
  321.         final StringBuilder allmsgs = new StringBuilder();
  322.         for (int i = 0; i < msgs.length; i++) {
  323.             msgs[i] = msgs[i].replace('\n', ' ');
  324.             allmsgs.append(msgs[i]).append("\n\n");
  325.         }
  326.         messagesTextPane.setText(allmsgs.toString());
  327.         setTitle(currentClass + " - " + Verifier.NAME);
  328.     }

  329.     void whatisMenuItemActionPerformed(final ActionEvent e) {
  330.         JOptionPane.showMessageDialog(this,
  331.             "The upper four boxes to the right reflect verification passes according to"
  332.                 + " The Java Virtual Machine Specification.\nThese are (in that order):"
  333.                 + " Pass one, Pass two, Pass three (before data flow analysis), Pass three (data flow analysis).\n"
  334.                 + "The bottom box to the right shows (warning) messages; warnings do not cause a class to be rejected.",
  335.             Verifier.NAME, JOptionPane.INFORMATION_MESSAGE);
  336.     }

  337. }