1 19 20 package jode.swingui; 21 import jode.GlobalOptions; 22 import jode.decompiler.Decompiler; 23 import jode.decompiler.ProgressListener; 24 25 import javax.swing.*; 26 import javax.swing.event.*; 27 import javax.swing.tree.*; 28 29 import java.awt.*; 30 import java.awt.event.*; 31 import java.io.*; 32 33 public class Main 34 implements ActionListener, Runnable , TreeSelectionListener { 35 Decompiler decompiler; 36 JFrame frame; 37 JTree classTree; 38 JPanel statusLine; 39 PackagesTreeModel packModel; 40 HierarchyTreeModel hierModel; 41 JTextArea sourcecodeArea, errorArea; 42 Thread decompileThread; 43 String currentClassPath, lastClassName; 44 45 JProgressBar progressBar; 46 47 boolean hierarchyTree; 48 49 public Main(String classpath) { 50 decompiler = new Decompiler(); 51 setClassPath(classpath); 52 frame = new JFrame(GlobalOptions.copyright); 53 fillContentPane(frame.getContentPane()); 54 addMenu(frame); 55 frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 56 frame.addWindowListener(new WindowAdapter() { 57 public void windowClosing(WindowEvent e) { 58 System.exit(0); 59 } 60 }); 61 } 62 63 public void show() { 64 frame.pack(); 65 frame.show(); 66 } 67 68 public void fillContentPane(Container contentPane) { 69 statusLine = new JPanel(); 70 hierarchyTree = false; 71 packModel = new PackagesTreeModel(this); 72 hierModel = null; 73 Font monospaced = new Font("monospaced", Font.PLAIN, 12); 74 classTree = new JTree(packModel); 75 classTree.setRootVisible(false); 76 DefaultTreeSelectionModel selModel = new DefaultTreeSelectionModel(); 77 selModel.setSelectionMode(selModel.SINGLE_TREE_SELECTION); 78 classTree.setSelectionModel(selModel); 79 classTree.addTreeSelectionListener(this); 80 JScrollPane spClassTree = new JScrollPane(classTree); 81 sourcecodeArea = new JTextArea(20, 80); 82 sourcecodeArea.setEditable(false); 83 sourcecodeArea.setFont(monospaced); 84 JScrollPane spText = new JScrollPane(sourcecodeArea); 85 errorArea = new JTextArea(3, 80); 86 errorArea.setEditable(false); 87 errorArea.setFont(monospaced); 88 JScrollPane spError = new JScrollPane(errorArea); 89 90 JSplitPane rightPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 91 spText, spError); 92 JSplitPane allPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, 93 spClassTree, rightPane); 94 contentPane.setLayout(new BorderLayout()); 95 contentPane.add(allPane, BorderLayout.CENTER); 96 contentPane.add(statusLine, BorderLayout.SOUTH); 97 progressBar = new JProgressBar(); 98 statusLine.add(progressBar); 99 rightPane.setDividerLocation(300); 100 rightPane.setDividerSize(4); 101 allPane.setDividerLocation(200); 102 allPane.setDividerSize(4); 103 decompiler.setErr(new PrintWriter 104 (new BufferedWriter(new AreaWriter(errorArea)), true)); 105 } 106 107 public synchronized void valueChanged(TreeSelectionEvent e) { 108 if (decompileThread != null) 109 return; 110 TreePath path = e.getNewLeadSelectionPath(); 111 if (path == null) 112 return; 113 Object node = path.getLastPathComponent(); 114 if (node != null) { 115 if (hierarchyTree && hierModel.isValidClass(node)) 116 lastClassName = hierModel.getFullName(node); 117 else if (!hierarchyTree && packModel.isValidClass(node)) 118 lastClassName = packModel.getFullName(node); 119 else 120 return; 121 122 startDecompiler(); 123 } 124 } 125 126 public void actionPerformed(ActionEvent e) { 127 if (e.getSource() == classTree) 128 startDecompiler(); 129 } 130 131 public synchronized void startDecompiler() { 132 if (decompileThread == null) { 133 decompileThread = new Thread (this); 134 decompileThread.setPriority(Thread.MIN_PRIORITY); 135 136 progressBar.setMinimum(0); 137 progressBar.setMaximum(1000); 138 progressBar.setString("decompiling"); 139 progressBar.setStringPainted(true); 140 decompileThread.start(); 141 } 142 } 143 144 public class AreaWriter extends Writer { 145 boolean initialized = false; 146 boolean lastCR = false; 147 private JTextArea area; 148 149 public AreaWriter(JTextArea a) { 150 area = a; 151 } 152 153 public void write(char[] b, int off, int len) throws IOException { 154 155 if (!initialized) { 156 area.setText(""); 157 initialized = true; 158 } 159 String str = new String (b, off, len); 160 StringBuffer sb = new StringBuffer (len); 161 while (str != null && str.length() > 0) { 162 if (lastCR && str.charAt(0) == '\n') 163 str = str.substring(1); 164 int crIndex = str.indexOf('\r'); 165 if (crIndex >= 0) { 166 sb.append(str.substring(0, crIndex)); 167 sb.append("\n"); 168 str = str.substring(crIndex+1); 169 lastCR = true; 170 } else { 171 sb.append(str); 172 str = null; 173 } 174 } 175 area.append(sb.toString()); 176 } 177 178 public void flush() { 179 } 180 181 public void close() { 182 } 183 } 184 185 public void run() { 186 errorArea.setText(""); 187 Writer writer = new BufferedWriter 188 (new AreaWriter(sourcecodeArea), 1024); 189 190 ProgressListener progListener = new ProgressListener() 191 { 192 public void updateProgress(final double progress, 193 final String detail) { 194 SwingUtilities.invokeLater(new Runnable () 195 { 196 public void run() { 197 progressBar.setValue((int)(1000 * progress)); 198 progressBar.setString(detail); 199 } 200 }); 201 } 202 }; 203 try { 204 decompiler.decompile(lastClassName, writer, progListener); 205 } catch (Throwable t) { 206 try { 207 writer.write("\nException while decompiling:"); 208 PrintWriter pw = new PrintWriter(writer); 209 t.printStackTrace(pw); 210 pw.flush(); 211 } catch (IOException ex) { 212 213 ex.printStackTrace(); 214 } 215 } finally { 216 try { 217 writer.close(); 218 } catch (IOException ex) { 219 220 } 221 synchronized(this) { 222 decompileThread = null; 223 } 224 } 225 SwingUtilities.invokeLater(new Runnable () 226 { 227 public void run() { 228 progressBar.setValue(0); 229 progressBar.setString(""); 230 } 231 }); 232 } 233 234 public void addMenu(JFrame frame) { 235 JMenuBar bar = new JMenuBar(); 236 JMenu menu; 237 JMenuItem item; 238 menu = new JMenu("File"); 239 item = new JMenuItem("Garbage collect"); 240 item.addActionListener(new ActionListener() { 241 public void actionPerformed(ActionEvent ev) { 242 System.gc(); 243 System.runFinalization(); 244 } 245 }); 246 menu.add(item); 247 item = new JMenuItem("Exit"); 248 item.addActionListener(new ActionListener() { 249 public void actionPerformed(ActionEvent ev) { 250 System.exit(0); 251 } 252 }); 253 menu.add(item); 254 bar.add(menu); 255 menu = new JMenu("Options"); 256 final JCheckBoxMenuItem hierItem 257 = new JCheckBoxMenuItem("Class hierarchy", hierarchyTree); 258 hierItem.addActionListener(new ActionListener() { 259 public void actionPerformed(ActionEvent ev) { 260 hierarchyTree = hierItem.isSelected(); 261 if (hierarchyTree && hierModel == null) { 262 hierModel = new HierarchyTreeModel(Main.this, progressBar); 263 reselect(); 264 } 265 classTree.setModel(hierarchyTree 266 ? (TreeModel) hierModel : packModel); 267 if (lastClassName != null) { 268 TreePath lastPath = (hierarchyTree 269 ? hierModel.getPath(lastClassName) 270 : packModel.getPath(lastClassName)); 271 classTree.setSelectionPath(lastPath); 272 classTree.scrollPathToVisible(lastPath); 273 } 274 } 275 }); 276 menu.add(hierItem); 277 menu.add(new JSeparator()); 278 item = new JMenuItem("Set classpath..."); 279 item.addActionListener(new ActionListener() { 280 public void actionPerformed(ActionEvent ev) { 281 282 String newClassPath = (String ) JOptionPane.showInputDialog 283 (null, "New classpath:", null, 284 JOptionPane.QUESTION_MESSAGE, null, 285 null, currentClassPath); 286 if (newClassPath != null 287 && !newClassPath.equals(currentClassPath)) 288 setClassPath(newClassPath); 289 } 290 }); 291 menu.add(item); 292 item = new JMenuItem("Reload classpath"); 293 item.addActionListener(new ActionListener() { 294 public void actionPerformed(ActionEvent ev) { 295 setClassPath(currentClassPath); 296 } 297 }); 298 menu.add(item); 299 bar.add(menu); 300 frame.setJMenuBar(bar); 301 } 302 303 public void setClassPath(String classpath) { 304 if (classpath == null || classpath.length() == 0) 305 classpath = "."; 306 currentClassPath = classpath; 307 jode.bytecode.ClassInfo.setClassPath(classpath); 308 decompiler.setClassPath(classpath); 309 if (classTree != null) 310 classTree.clearSelection(); 311 if (packModel != null) 312 packModel.rebuild(); 313 if (hierModel != null && hierarchyTree) { 314 hierModel.rebuild(); 315 } else { 316 hierModel = null; 317 } 318 } 319 320 public void treeNodesChanged(TreeModelEvent e) { 321 reselect(); 322 } 323 324 public void treeNodesInserted(TreeModelEvent e) { 325 reselect(); 326 } 327 328 public void treeNodesRemoved(TreeModelEvent e) { 329 reselect(); 330 } 331 332 public void treeStructureChanged(TreeModelEvent e) { 333 reselect(); 334 } 335 336 public void reselect() { 337 if (lastClassName != null) { 338 TreePath lastPath = (hierarchyTree 339 ? hierModel.getPath(lastClassName) 340 : packModel.getPath(lastClassName)); 341 if (lastPath != null) { 342 classTree.setSelectionPath(lastPath); 343 classTree.scrollPathToVisible(lastPath); 344 } 345 } 346 } 347 348 public static void usage() { 349 System.err.println("Usage: java jode.swingui.Main [CLASSPATH]"); 350 System.err.println("The directories in CLASSPATH should be separated by ','."); 351 System.err.println("If no CLASSPATH is given the virtual machine classpath is used."); 352 } 353 354 public static void main(String [] params) { 355 String cp = System.getProperty("java.class.path", ""); 356 cp = cp.replace(File.pathSeparatorChar, 357 Decompiler.altPathSeparatorChar); 358 String bootClassPath = System.getProperty("sun.boot.class.path"); 359 if (bootClassPath != null) 360 cp += Decompiler.altPathSeparatorChar 361 + bootClassPath.replace(File.pathSeparatorChar, 362 Decompiler.altPathSeparatorChar); 363 int i = 0; 364 if (i < params.length) { 365 if (params[i].equals("--classpath") 366 || params[i].equals("--cp") 367 || params[i].equals("-c")) 368 cp = params[++i]; 369 else if (params[i].startsWith("-")) { 370 if (!params[i].equals("--help") 371 && !params[i].equals("-h")) 372 System.err.println("Unknown option: "+params[i]); 373 usage(); 374 return; 375 } else 376 cp = params[i]; 377 i++; 378 } 379 if (i < params.length) { 380 System.err.println("Too many arguments."); 381 usage(); 382 return; 383 } 384 Main win = new Main(cp); 385 win.show(); 386 } 387 } 388 | Popular Tags |