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 */ 017package org.apache.bcel.verifier; 018 019import java.awt.AWTEvent; 020import java.awt.CardLayout; 021import java.awt.Color; 022import java.awt.Dimension; 023import java.awt.GridLayout; 024import java.awt.event.ActionEvent; 025import java.awt.event.InputEvent; 026import java.awt.event.WindowEvent; 027import java.util.Arrays; 028 029import javax.swing.BorderFactory; 030import javax.swing.JFrame; 031import javax.swing.JList; 032import javax.swing.JMenu; 033import javax.swing.JMenuBar; 034import javax.swing.JMenuItem; 035import javax.swing.JOptionPane; 036import javax.swing.JPanel; 037import javax.swing.JScrollPane; 038import javax.swing.JSplitPane; 039import javax.swing.JTextPane; 040import javax.swing.ListSelectionModel; 041import javax.swing.event.ListSelectionEvent; 042 043import org.apache.bcel.Repository; 044import org.apache.bcel.classfile.JavaClass; 045import org.apache.commons.lang3.ArrayUtils; 046 047/** 048 * This class implements a machine-generated frame for use with the GraphicalVerfifier. 049 * 050 * @see GraphicalVerifier 051 */ 052public class VerifierAppFrame extends JFrame { 053 054 private static final long serialVersionUID = -542458133073307640L; 055 private JPanel contentPane; 056 private final JSplitPane jSplitPane1 = new JSplitPane(); 057 private final JPanel jPanel1 = new JPanel(); 058 private final JPanel jPanel2 = new JPanel(); 059 private final JSplitPane jSplitPane2 = new JSplitPane(); 060 private final JPanel jPanel3 = new JPanel(); 061 private final JList<String> classNamesJList = new JList<>(); 062 private final GridLayout gridLayout1 = new GridLayout(); 063 private final JPanel messagesPanel = new JPanel(); 064 private final GridLayout gridLayout2 = new GridLayout(); 065 private final JMenuBar jMenuBar1 = new JMenuBar(); 066 private final JMenu jMenu1 = new JMenu(); 067 private final JScrollPane jScrollPane1 = new JScrollPane(); 068 private final JScrollPane messagesScrollPane = new JScrollPane(); 069 private final JScrollPane jScrollPane3 = new JScrollPane(); 070 private final GridLayout gridLayout4 = new GridLayout(); 071 private final JScrollPane jScrollPane4 = new JScrollPane(); 072 private final CardLayout cardLayout1 = new CardLayout(); 073 private String currentClass; 074 private final GridLayout gridLayout3 = new GridLayout(); 075 private final JTextPane pass1TextPane = new JTextPane(); 076 private final JTextPane pass2TextPane = new JTextPane(); 077 private final JTextPane messagesTextPane = new JTextPane(); 078 private final JMenuItem newFileMenuItem = new JMenuItem(); 079 private final JSplitPane jSplitPane3 = new JSplitPane(); 080 private final JSplitPane jSplitPane4 = new JSplitPane(); 081 private final JScrollPane jScrollPane2 = new JScrollPane(); 082 private final JScrollPane jScrollPane5 = new JScrollPane(); 083 private final JScrollPane jScrollPane6 = new JScrollPane(); 084 private final JScrollPane jScrollPane7 = new JScrollPane(); 085 private final JList<String> pass3aJList = new JList<>(); 086 private final JList<String> pass3bJList = new JList<>(); 087 private final JTextPane pass3aTextPane = new JTextPane(); 088 private final JTextPane pass3bTextPane = new JTextPane(); 089 private final JMenu jMenu2 = new JMenu(); 090 private final JMenuItem whatisMenuItem = new JMenuItem(); 091 private final JMenuItem aboutMenuItem = new JMenuItem(); 092 093 /** Constructs a new instance. */ 094 public VerifierAppFrame() { 095 enableEvents(AWTEvent.WINDOW_EVENT_MASK); 096 try { 097 jbInit(); 098 } catch (final Exception e) { 099 e.printStackTrace(); 100 } 101 } 102 103 void aboutMenuItemActionPerformed(final ActionEvent e) { 104 JOptionPane.showMessageDialog(this, Verifier.BANNER, Verifier.NAME, JOptionPane.INFORMATION_MESSAGE); 105 } 106 107 synchronized void classNamesJListValueChanged(final ListSelectionEvent e) { 108 if (e.getValueIsAdjusting()) { 109 return; 110 } 111 currentClass = classNamesJList.getSelectedValue(); 112 try { 113 verify(); 114 } catch (final ClassNotFoundException ex) { 115 // FIXME: report the error using the GUI 116 ex.printStackTrace(); 117 } 118 classNamesJList.setSelectedValue(currentClass, true); 119 } 120 121 /** 122 * @return the classNamesJList 123 */ 124 JList<String> getClassNamesJList() { 125 return classNamesJList; 126 } 127 128 /** Initizalization of the components. */ 129 private void jbInit() { 130 // setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Ihr Symbol]"))); 131 contentPane = (JPanel) getContentPane(); 132 contentPane.setLayout(cardLayout1); 133 setJMenuBar(jMenuBar1); 134 this.setSize(new Dimension(708, 451)); 135 setTitle("JustIce"); 136 jPanel1.setMinimumSize(new Dimension(100, 100)); 137 jPanel1.setPreferredSize(new Dimension(100, 100)); 138 jPanel1.setLayout(gridLayout1); 139 jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT); 140 jPanel2.setLayout(gridLayout2); 141 jPanel3.setMinimumSize(new Dimension(200, 100)); 142 jPanel3.setPreferredSize(new Dimension(400, 400)); 143 jPanel3.setLayout(gridLayout4); 144 messagesPanel.setMinimumSize(new Dimension(100, 100)); 145 messagesPanel.setLayout(gridLayout3); 146 jPanel2.setMinimumSize(new Dimension(200, 100)); 147 jMenu1.setText("File"); 148 jScrollPane1.getViewport().setBackground(Color.red); 149 messagesScrollPane.getViewport().setBackground(Color.red); 150 messagesScrollPane.setPreferredSize(new Dimension(10, 10)); 151 classNamesJList.addListSelectionListener(this::classNamesJListValueChanged); 152 classNamesJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 153 jScrollPane3.setBorder(BorderFactory.createLineBorder(Color.black)); 154 jScrollPane3.setPreferredSize(new Dimension(100, 100)); 155 gridLayout4.setRows(4); 156 gridLayout4.setColumns(1); 157 gridLayout4.setHgap(1); 158 jScrollPane4.setBorder(BorderFactory.createLineBorder(Color.black)); 159 jScrollPane4.setPreferredSize(new Dimension(100, 100)); 160 pass1TextPane.setBorder(BorderFactory.createRaisedBevelBorder()); 161 pass1TextPane.setToolTipText(""); 162 pass1TextPane.setEditable(false); 163 pass2TextPane.setBorder(BorderFactory.createRaisedBevelBorder()); 164 pass2TextPane.setEditable(false); 165 messagesTextPane.setBorder(BorderFactory.createRaisedBevelBorder()); 166 messagesTextPane.setEditable(false); 167 newFileMenuItem.setText("New..."); 168 newFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(78, InputEvent.CTRL_MASK, true)); 169 newFileMenuItem.addActionListener(this::newFileMenuItemActionPerformed); 170 pass3aTextPane.setEditable(false); 171 pass3bTextPane.setEditable(false); 172 pass3aJList.addListSelectionListener(this::pass3aJList_valueChanged); 173 pass3bJList.addListSelectionListener(this::pass3bJList_valueChanged); 174 jMenu2.setText("Help"); 175 whatisMenuItem.setText("What is..."); 176 whatisMenuItem.addActionListener(this::whatisMenuItemActionPerformed); 177 aboutMenuItem.setText("About"); 178 aboutMenuItem.addActionListener(this::aboutMenuItemActionPerformed); 179 jSplitPane2.add(messagesPanel, JSplitPane.BOTTOM); 180 messagesPanel.add(messagesScrollPane, null); 181 messagesScrollPane.getViewport().add(messagesTextPane, null); 182 jSplitPane2.add(jPanel3, JSplitPane.TOP); 183 jPanel3.add(jScrollPane3, null); 184 jScrollPane3.getViewport().add(pass1TextPane, null); 185 jPanel3.add(jScrollPane4, null); 186 jPanel3.add(jSplitPane3, null); 187 jSplitPane3.add(jScrollPane2, JSplitPane.LEFT); 188 jScrollPane2.getViewport().add(pass3aJList, null); 189 jSplitPane3.add(jScrollPane5, JSplitPane.RIGHT); 190 jScrollPane5.getViewport().add(pass3aTextPane, null); 191 jPanel3.add(jSplitPane4, null); 192 jSplitPane4.add(jScrollPane6, JSplitPane.LEFT); 193 jScrollPane6.getViewport().add(pass3bJList, null); 194 jSplitPane4.add(jScrollPane7, JSplitPane.RIGHT); 195 jScrollPane7.getViewport().add(pass3bTextPane, null); 196 jScrollPane4.getViewport().add(pass2TextPane, null); 197 jSplitPane1.add(jPanel2, JSplitPane.TOP); 198 jPanel2.add(jScrollPane1, null); 199 jSplitPane1.add(jPanel1, JSplitPane.BOTTOM); 200 jPanel1.add(jSplitPane2, null); 201 jScrollPane1.getViewport().add(classNamesJList, null); 202 jMenuBar1.add(jMenu1); 203 jMenuBar1.add(jMenu2); 204 contentPane.add(jSplitPane1, "jSplitPane1"); 205 jMenu1.add(newFileMenuItem); 206 jMenu2.add(whatisMenuItem); 207 jMenu2.add(aboutMenuItem); 208 jSplitPane2.setDividerLocation(300); 209 jSplitPane3.setDividerLocation(150); 210 jSplitPane4.setDividerLocation(150); 211 } 212 213 void newFileMenuItemActionPerformed(final ActionEvent e) { 214 final String className = JOptionPane.showInputDialog("Please enter the fully qualified name of a class or interface to verify:"); 215 if (className == null || className.isEmpty()) { 216 return; 217 } 218 VerifierFactory.getVerifier(className); // let observers do the rest. 219 classNamesJList.setSelectedValue(className, true); 220 } 221 222 synchronized void pass3aJList_valueChanged(final ListSelectionEvent e) { 223 if (e.getValueIsAdjusting()) { 224 return; 225 } 226 final Verifier v = VerifierFactory.getVerifier(currentClass); 227 final StringBuilder all3amsg = new StringBuilder(); 228 boolean all3aok = true; 229 boolean rejected = false; 230 for (int i = 0; i < pass3aJList.getModel().getSize(); i++) { 231 if (pass3aJList.isSelectedIndex(i)) { 232 final VerificationResult vr = v.doPass3a(i); 233 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) { 234 all3aok = false; 235 rejected = true; 236 } 237 JavaClass jc = null; 238 try { 239 jc = Repository.lookupClass(v.getClassName()); 240 all3amsg.append("Method '").append(jc.getMethods()[i]).append("': ").append(vr.getMessage().replace('\n', ' ')).append("\n\n"); 241 } catch (final ClassNotFoundException ex) { 242 // FIXME: handle the error 243 ex.printStackTrace(); 244 } 245 } 246 } 247 pass3aTextPane.setText(all3amsg.toString()); 248 pass3aTextPane.setBackground(all3aok ? Color.green : rejected ? Color.red : Color.yellow); 249 } 250 251 synchronized void pass3bJList_valueChanged(final ListSelectionEvent e) { 252 if (e.getValueIsAdjusting()) { 253 return; 254 } 255 final Verifier v = VerifierFactory.getVerifier(currentClass); 256 final StringBuilder all3bmsg = new StringBuilder(); 257 boolean all3bok = true; 258 boolean rejected = false; 259 for (int i = 0; i < pass3bJList.getModel().getSize(); i++) { 260 if (pass3bJList.isSelectedIndex(i)) { 261 final VerificationResult vr = v.doPass3b(i); 262 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) { 263 all3bok = false; 264 rejected = true; 265 } 266 JavaClass jc = null; 267 try { 268 jc = Repository.lookupClass(v.getClassName()); 269 all3bmsg.append("Method '").append(jc.getMethods()[i]).append("': ").append(vr.getMessage().replace('\n', ' ')).append("\n\n"); 270 } catch (final ClassNotFoundException ex) { 271 // FIXME: handle the error 272 ex.printStackTrace(); 273 } 274 } 275 } 276 pass3bTextPane.setText(all3bmsg.toString()); 277 pass3bTextPane.setBackground(all3bok ? Color.green : rejected ? Color.red : Color.yellow); 278 } 279 280 /** Overridden to stop the application on a closing window. */ 281 @Override 282 protected void processWindowEvent(final WindowEvent e) { 283 super.processWindowEvent(e); 284 if (e.getID() == WindowEvent.WINDOW_CLOSING) { 285 System.exit(0); 286 } 287 } 288 289 private void verify() throws ClassNotFoundException { 290 setTitle("PLEASE WAIT"); 291 final Verifier v = VerifierFactory.getVerifier(currentClass); 292 v.flush(); // Don't cache the verification result for this class. 293 VerificationResult vr; 294 vr = v.doPass1(); 295 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) { 296 pass1TextPane.setText(vr.getMessage()); 297 pass1TextPane.setBackground(Color.red); 298 pass2TextPane.setText(""); 299 pass2TextPane.setBackground(Color.yellow); 300 pass3aTextPane.setText(""); 301 pass3aJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY); 302 pass3aTextPane.setBackground(Color.yellow); 303 pass3bTextPane.setText(""); 304 pass3bJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY); 305 pass3bTextPane.setBackground(Color.yellow); 306 } else { // Must be VERIFIED_OK, Pass 1 does not know VERIFIED_NOTYET 307 pass1TextPane.setBackground(Color.green); 308 pass1TextPane.setText(vr.getMessage()); 309 vr = v.doPass2(); 310 if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) { 311 pass2TextPane.setText(vr.getMessage()); 312 pass2TextPane.setBackground(Color.red); 313 pass3aTextPane.setText(""); 314 pass3aTextPane.setBackground(Color.yellow); 315 pass3aJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY); 316 pass3bTextPane.setText(""); 317 pass3bTextPane.setBackground(Color.yellow); 318 pass3bJList.setListData(ArrayUtils.EMPTY_STRING_ARRAY); 319 } else { // must be Verified_OK, because Pass1 was OK (cannot be Verified_NOTYET). 320 pass2TextPane.setText(vr.getMessage()); 321 pass2TextPane.setBackground(Color.green); 322 final JavaClass jc = Repository.lookupClass(currentClass); 323 /* 324 * boolean all3aok = true; boolean all3bok = true; String all3amsg = ""; String all3bmsg = ""; 325 */ 326 final String[] methodNames = new String[jc.getMethods().length]; 327 Arrays.setAll(methodNames, i -> jc.getMethods()[i].toString().replace('\n', ' ').replace('\t', ' ')); 328 pass3aJList.setListData(methodNames); 329 pass3aJList.setSelectionInterval(0, jc.getMethods().length - 1); 330 pass3bJList.setListData(methodNames); 331 pass3bJList.setSelectionInterval(0, jc.getMethods().length - 1); 332 } 333 } 334 final String[] msgs = v.getMessages(); 335 messagesTextPane.setBackground(msgs.length == 0 ? Color.green : Color.yellow); 336 final StringBuilder allmsgs = new StringBuilder(); 337 for (int i = 0; i < msgs.length; i++) { 338 msgs[i] = msgs[i].replace('\n', ' '); 339 allmsgs.append(msgs[i]).append("\n\n"); 340 } 341 messagesTextPane.setText(allmsgs.toString()); 342 setTitle(currentClass + " - " + Verifier.NAME); 343 } 344 345 void whatisMenuItemActionPerformed(final ActionEvent e) { 346 JOptionPane.showMessageDialog(this, 347 "The upper four boxes to the right reflect verification passes according to" 348 + " The Java Virtual Machine Specification.\nThese are (in that order):" 349 + " Pass one, Pass two, Pass three (before data flow analysis), Pass three (data flow analysis).\n" 350 + "The bottom box to the right shows (warning) messages; warnings do not cause a class to be rejected.", 351 Verifier.NAME, JOptionPane.INFORMATION_MESSAGE); 352 } 353 354}