1 33 34 package edu.rice.cs.drjava; 35 36 import static edu.rice.cs.drjava.config.OptionConstants.*; 37 38 import java.io.File ; 39 import java.io.IOException ; 40 import java.io.ByteArrayOutputStream ; 41 import java.net.MalformedURLException ; 42 import java.net.URL ; 43 import java.net.URLClassLoader ; 44 import java.util.ArrayList ; 45 import java.util.LinkedList ; 46 import java.util.List ; 47 import java.util.jar.JarFile ; 48 import java.util.jar.Manifest ; 49 50 import javax.swing.JFileChooser ; 51 import javax.swing.JOptionPane ; 52 import javax.swing.SwingUtilities ; 53 54 import edu.rice.cs.drjava.config.FileConfiguration; 55 import edu.rice.cs.drjava.config.FileOption; 56 import edu.rice.cs.drjava.platform.PlatformFactory; 57 import edu.rice.cs.drjava.ui.DrJavaErrorHandler; 58 import edu.rice.cs.drjava.ui.ClassPathFilter; 59 import edu.rice.cs.drjava.ui.SplashScreen; 60 import edu.rice.cs.util.ArgumentTokenizer; 61 import edu.rice.cs.util.FileOps; 62 import edu.rice.cs.util.Log; 63 import edu.rice.cs.util.classloader.ToolsJarClassLoader; 64 import edu.rice.cs.util.newjvm.ExecJVM; 65 66 73 public class DrJava { 74 75 private static Log _log = new Log("DrJava.txt", false); 76 77 78 public static final String TEST_DEBUGGER_CLASS = "com.sun.jdi.Bootstrap"; 79 80 public static final String TEST_14_COMPILER_CLASS = "com.sun.tools.javac.v8.JavaCompiler"; 81 82 public static final String TEST_15_16_COMPILER_CLASS = "com.sun.tools.javac.main.JavaCompiler"; 83 84 85 public static final String TEST_COMPILER_CLASS; 86 static { 87 if (System.getProperty("java.version").startsWith("1.4")) { 88 TEST_COMPILER_CLASS = TEST_14_COMPILER_CLASS; 89 } 90 else { 91 TEST_COMPILER_CLASS = TEST_15_16_COMPILER_CLASS; 92 } 93 } 94 95 private static final String DEFAULT_MAX_HEAP_SIZE_ARG = "-Xmx128M"; 96 97 private static final ArrayList <String > _filesToOpen = new ArrayList <String >(); 98 private static final ArrayList <String > _jvmArgs = new ArrayList <String >(); 99 100 static volatile boolean _showDebugConsole = false; 101 102 105 106 107 public static final File DEFAULT_PROPERTIES_FILE = new File (System.getProperty("user.home"), ".drjava"); 108 109 110 private static volatile File _propertiesFile = DEFAULT_PROPERTIES_FILE; 111 112 113 private static volatile FileConfiguration _config = _initConfig(); 114 115 private static ToolsJarClassLoader _toolsLoader = new ToolsJarClassLoader(getConfig().getSetting(JAVAC_LOCATION)); 116 private static final ClassLoader _thisLoader = DrJava.class.getClassLoader(); 117 118 119 public static File getPropertiesFile() { return _propertiesFile; } 120 121 122 public static FileConfiguration getConfig() { return _config; } 123 124 125 public static String [] getFilesToOpen() { return _filesToOpen.toArray(new String [0]); } 126 127 128 public static boolean getShowDebugConsole() { return _showDebugConsole; } 129 130 133 public static void main(final String [] args) { 134 PlatformFactory.ONLY.beforeUISetup(); 136 137 new SplashScreen().flash(); 138 configureAndLoadDrJavaRoot(args); 140 } 141 142 public static void configureAndLoadDrJavaRoot(String [] args) { 143 try { 144 if (handleCommandLineArgs(args)) { 146 147 boolean restart = !checkForCompilersAndDebugger(args); 149 150 restart |= getConfig().getSetting(MASTER_JVM_ARGS).length() > 0; 152 153 LinkedList <String > classArgsList = new LinkedList <String >(); 154 classArgsList.addAll(_filesToOpen); 155 156 if (_showDebugConsole) { classArgsList.addFirst("-debugConsole"); } 158 159 if (!_propertiesFile.equals(DEFAULT_PROPERTIES_FILE)) { 160 classArgsList.addFirst(_propertiesFile.getAbsolutePath()); 162 classArgsList.addFirst("-config"); 163 } 164 165 String [] classArgs = classArgsList.toArray(new String [0]); 166 167 if (restart) { 168 String pathSep = System.getProperty("path.separator"); 170 String classPath = System.getProperty("java.class.path"); 171 172 File toolsFromConfig = getConfig().getSetting(JAVAC_LOCATION); 174 classPath += pathSep + ToolsJarClassLoader.getToolsJarClassPath(toolsFromConfig); 175 176 try { 178 ExecJVM.runJVM("edu.rice.cs.drjava.DrJavaRoot", classArgs, classPath, _jvmArgs.toArray(new String [0]), null); 181 } 182 catch (IOException ioe) { 183 final String [] text = { 185 "DrJava was unable to load its compiler and debugger. Would you ", 186 "like to start DrJava without a compiler and debugger?", "\nReason: " + ioe.toString() 187 }; 188 int result = JOptionPane.showConfirmDialog(null, text, "Could Not Load Compiler and Debugger", 189 JOptionPane.YES_NO_OPTION); 190 if (result != JOptionPane.YES_OPTION) { System.exit(0); } 191 } 192 } 193 194 else { 195 DrJavaRoot.main(classArgs); 197 } 198 } 199 } 200 catch (Throwable t) { 201 System.out.println(t.getClass().getName() + ": " + t.getMessage()); 203 t.printStackTrace(System.err);System.out.println("error thrown"); 204 new DrJavaErrorHandler().handle(t); 205 } 206 } 207 208 211 static boolean handleCommandLineArgs(String [] args) { 212 boolean heapSizeGiven = false; 214 int argIndex = 0; 216 int len = args.length; 217 _filesToOpen.clear(); 218 219 while(argIndex < len) { 220 String arg = args[argIndex++]; 221 222 if (arg.equals("-config")) { 223 if (len == argIndex) { 224 return true; 226 } 227 setPropertiesFile(args[argIndex++]); 229 _config = _initConfig(); _toolsLoader = new ToolsJarClassLoader(getConfig().getSetting(JAVAC_LOCATION)); 231 } 232 233 else if (arg.startsWith("-X") || arg.startsWith("-D")) { 234 if (arg.startsWith("-Xmx")) { heapSizeGiven = true; } 235 _jvmArgs.add(arg); 236 } 237 238 else if (arg.equals("-debugConsole")) _showDebugConsole = true; 239 240 else if (arg.equals("-help") || arg.equals("-?")) { 241 displayUsage(); 242 return false; 243 } 244 else { 245 --argIndex; 247 break; 248 } 249 } 250 251 List <String > configArgs = ArgumentTokenizer.tokenize(getConfig().getSetting(MASTER_JVM_ARGS)); 252 for (String arg : configArgs) { 253 if (arg.startsWith("-Xmx")) { heapSizeGiven = true; } 254 _jvmArgs.add(arg); 255 } 256 257 if (PlatformFactory.ONLY.isMacPlatform()) { 258 String iconLoc = System.getProperty("edu.rice.cs.drjava.icon"); 259 if (iconLoc != null) { _jvmArgs.add("-Xdock:name=DrJava"); 261 _jvmArgs.add("-Xdock:icon=" + iconLoc); 262 } 263 } 264 265 if (!heapSizeGiven) { _jvmArgs.add(DEFAULT_MAX_HEAP_SIZE_ARG); } 266 267 _log.log("_jvmArgs = " + _jvmArgs); 268 269 271 for (int i = argIndex; i < len; i++) { _filesToOpen.add(args[i]); } 272 return true; 273 } 274 275 276 static void displayUsage() { 277 final StringBuilder buf = new StringBuilder (); 278 buf.append("Usage: java -jar drjava.jar [OPTIONS] [FILES]\n\n"); 279 buf.append("where options include:\n"); 280 buf.append(" -config [FILE] use a custom config file\n"); 281 buf.append(" -help | -? print this help message\n"); 282 buf.append(" -X<jvmOption> specify a JVM configuration option for the master DrJava JVM\n"); 283 buf.append(" -D<name>[=<value>] set a Java property for the master DrJava JVM\n"); 284 System.out.print(buf.toString()); 285 } 286 287 292 static boolean checkForCompilersAndDebugger(String [] args) { 293 if (canLoad(_thisLoader, TEST_COMPILER_CLASS) && canLoad(_thisLoader, TEST_DEBUGGER_CLASS)) { 294 return true; 295 } 296 else { 297 boolean haveCompiler = canLoad(_thisLoader, TEST_COMPILER_CLASS) || 298 canLoad(_toolsLoader, TEST_COMPILER_CLASS); 299 boolean haveDebugger = canLoad(_thisLoader, TEST_DEBUGGER_CLASS) || 300 canLoad(_toolsLoader, TEST_DEBUGGER_CLASS); 301 if (!haveCompiler || !haveDebugger) { promptForToolsJar(!haveCompiler, !haveDebugger); } 302 return false; 303 } 304 } 305 306 309 public static boolean hasAvailableDebugger() { 310 return canLoad(_thisLoader, TEST_DEBUGGER_CLASS) || canLoad(_toolsLoader, TEST_DEBUGGER_CLASS); 311 } 312 313 public static boolean hasAvailableCompiler() { 314 return canLoad(_thisLoader, TEST_COMPILER_CLASS) || canLoad(_toolsLoader, TEST_COMPILER_CLASS); 315 } 316 317 318 public static boolean canLoad(ClassLoader cl, String className) { 319 try { 320 cl.loadClass(className); 321 return true; 322 } 323 catch(ClassNotFoundException e) { return false; } 324 catch(UnsupportedClassVersionError e) { return false; } 325 catch(RuntimeException e) { return false; } 326 } 327 328 333 public static void promptForToolsJar(boolean needCompiler, boolean needDebugger) { 334 File selectedFile = getConfig().getSetting(JAVAC_LOCATION); 335 String selectedVersion = _getToolsJarVersion(selectedFile); 336 337 final String [] text; 338 if (selectedVersion==null) { 339 text = new String [] { 340 "DrJava cannot find a 'tools.jar' file for the version of Java ", 341 "that is being used to run DrJava (Java version "+System.getProperty("java.version")+").", 342 "Would you like to specify the location of the requisite 'tools.jar' file?", 343 "If you say 'No', DrJava might be unable to compile or debug Java programs." 344 }; 345 } 346 else { 347 text = new String [] { 348 "DrJava cannot find a 'tools.jar' file for the version of Java ", 349 "that is being used to run DrJava (Java version "+System.getProperty("java.version")+").", 350 "The file you have selected appears to be for version "+selectedVersion+".", 351 "Would you like to specify the ocation of the requisite 'tools.jar' file?", 352 "If you say 'No', DrJava might be unable to compile or debug Java programs.)" 353 }; 354 } 355 356 int result = JOptionPane.showConfirmDialog(null, text, "Locate 'tools.jar'?", JOptionPane.YES_NO_OPTION); 357 358 if (result == JOptionPane.YES_OPTION) { 359 JFileChooser chooser = new JFileChooser (); 360 chooser.setFileFilter(new ClassPathFilter() { 361 public boolean accept(File f) { 362 if (f.isDirectory()) return true; 363 String ext = getExtension(f); 364 return ext != null && ext.equals("jar"); 365 } 366 public String getDescription() { return "Jar Files"; } 367 }); 368 369 do { 371 if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { 372 File jar = chooser.getSelectedFile(); 373 374 if (jar != null) { 375 getConfig().setSetting(JAVAC_LOCATION, jar); 377 378 if (needCompiler && classLoadersCanFind(TEST_COMPILER_CLASS)) needCompiler = false; 380 381 if (needDebugger && classLoadersCanFind(TEST_DEBUGGER_CLASS)) needDebugger = false; 383 } 384 } 385 } 387 while ((needCompiler || needDebugger) && _userWantsToPickAgain()); 388 389 if ((! needCompiler) && (! needDebugger)) _saveConfig(); 391 } 392 } 393 394 395 398 public static boolean classLoadersCanFind(String className) { 399 File jar = getConfig().getSetting(JAVAC_LOCATION); 401 if (jar != FileOption.NULL_FILE) { 402 try { 403 URL [] urls = new URL [] { FileOps.toURL(jar) }; 404 URLClassLoader loader = new URLClassLoader (urls); 405 if (canLoad(loader, className)) return true; 406 } 407 catch(MalformedURLException e) { } 408 } 409 return canLoad(_toolsLoader, className); 410 } 411 412 415 static void setPropertiesFile(String fileName) { 416 if (!fileName.endsWith(".java")) _propertiesFile = new File (fileName); 417 } 418 419 422 static FileConfiguration _initConfig() throws IllegalStateException { 423 426 FileConfiguration config; 427 428 try { _propertiesFile.createNewFile(); } catch (IOException e) { } 430 431 config = new FileConfiguration(_propertiesFile); 432 try { config.loadConfiguration(); } 433 catch (Exception e) { 434 config.resetToDefaults(); 436 config.storeStartupException(e); 437 } 438 _config = config; return config; 440 } 441 442 443 protected static void _saveConfig() { 444 try { getConfig().saveConfiguration(); } 445 catch(IOException e) { 446 JOptionPane.showMessageDialog(null, 447 "Could not save the location of tools.jar in \n" + 448 "the '.drjava' file in your home directory. \n" + 449 "Another process may be using the file.\n\n" + e, 450 "Could Not Save Changes", 451 JOptionPane.ERROR_MESSAGE); 452 } 454 } 455 456 459 private static boolean _userWantsToPickAgain() { 460 File selectedFile = getConfig().getSetting(JAVAC_LOCATION); 461 String selectedVersion = _getToolsJarVersion(selectedFile); 462 463 final String [] text; 464 if (selectedVersion==null) { 465 text = new String [] { 466 "The file you chose did not appear to be the correct 'tools.jar'", 467 "that is compatible with the version of Java that is used to", 468 "run DrJava (Java version "+System.getProperty("java.version")+").", 469 "Your choice might be an incompatible version of the file.", 470 "Would you like to pick again? The 'tools.jar' file is ", 471 "generally located in the 'lib' subdirectory under your ", 472 "JDK installation directory.", 473 "(If you say 'No', DrJava might be unable to compile or ", 474 "debug programs.)" 475 }; 476 } 477 else { 478 text = new String [] { 479 "The file you chose did not appear to be the correct 'tools.jar'", 480 "that is compatible with the version of Java that is used to", 481 "run DrJava (Java version "+System.getProperty("java.version")+").", 482 "The file you have selected appears to be for", 483 "Java version "+selectedVersion+".", 484 "Your choice might be an incompatible version of the file.", 485 "Would you like to pick again? The 'tools.jar' file is ", 486 "generally located in the 'lib' subdirectory under your ", 487 "JDK installation directory.", 488 "If you say 'No', DrJava might be unable to compile or ", 489 "debug programs." 490 }; 491 } 492 493 int result = JOptionPane.showConfirmDialog(null, text, "Locate 'tools.jar'?", JOptionPane.YES_NO_OPTION); 494 return result == JOptionPane.YES_OPTION; 495 } 496 497 498 private static String _getToolsJarVersion(File toolsJarFile) { 499 try { 500 JarFile jf = new JarFile (toolsJarFile); 501 Manifest mf = jf.getManifest(); 502 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 503 mf.write(baos); 504 String str = baos.toString(); 505 final String CB = "Created-By: "; 510 int beginPos = str.indexOf(CB); 511 if (beginPos >= 0) { 512 beginPos += CB.length(); 513 int endPos = str.indexOf(System.getProperty("line.separator"), beginPos); 514 if (endPos >= 0) return str.substring(beginPos, endPos); 515 else { 516 endPos = str.indexOf(' ', beginPos); 517 if (endPos >= 0) return str.substring(beginPos, endPos); 518 else { 519 endPos = str.indexOf('\t', beginPos); 520 if (endPos >= 0) return str.substring(beginPos, endPos); 521 } 522 } 523 } 524 } 525 catch(Exception rte) { } 526 return null; 527 } 528 } 529 530 | Popular Tags |