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