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