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