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