Clover coverage report - DrJava Test Coverage (drjava-20120304-r5456)
Coverage timestamp: Sun Mar 4 2012 03:13:23 CST
file stats: LOC: 668   Methods: 16
NCLOC: 382   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DrJava.java 3.4% 8.8% 37.5% 8.7%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.drjava;
 38   
 39    import static edu.rice.cs.drjava.config.OptionConstants.*;
 40   
 41    import java.io.*;
 42    import java.util.ArrayList;
 43    import java.util.LinkedList;
 44    import java.util.List;
 45   
 46    import javax.swing.JOptionPane;
 47   
 48    import edu.rice.cs.drjava.config.ResourceBundleConfiguration;
 49    import edu.rice.cs.drjava.config.FileConfiguration;
 50    import edu.rice.cs.drjava.config.OptionConstants;
 51    import edu.rice.cs.drjava.platform.PlatformFactory;
 52    import edu.rice.cs.drjava.ui.DrJavaErrorHandler;
 53    import edu.rice.cs.plt.concurrent.DelayedInterrupter;
 54    import edu.rice.cs.plt.concurrent.JVMBuilder;
 55    import edu.rice.cs.plt.reflect.JavaVersion;
 56    import edu.rice.cs.util.ArgumentTokenizer;
 57    import edu.rice.cs.util.Log;
 58    import edu.rice.cs.util.UnexpectedException;
 59    import edu.rice.cs.util.FileOps;
 60    import edu.rice.cs.drjava.model.DrJavaFileUtils;
 61   
 62    import static edu.rice.cs.plt.debug.DebugUtil.debug;
 63   
 64    /** Startup class for DrJava consisting entirely of static members. The main method reads the .drjava file (creating
 65    * one if none exists) to get the critical information required to start the main JVM for DrJava:
 66    * (i) the location of tools.jar in the Java JDK installed on this machine (so DrJava can invoke the javac compiler
 67    * stored in tools.jar)
 68    * (ii) the argument string for invoking the main JVM (notably -X options used to determine maximum heap size, etc.)
 69    *
 70    * Here is a summary of the launch mechanism of DrJava:
 71    *
 72    * 1. DrJava.main will be started.
 73    *
 74    * 2. DrJava.handleCommandLineArgs scans the command line arguments.
 75    * 2.1. This involves determining if the -new parameter forces a new instance.
 76    *
 77    * 3. DrJava.configureAndLoadDrJavaRoot determines if remote control should be used:
 78    * 3.1. If -new doesn't force a new instance
 79    * 3.2. and REMOTE_CONTROL_ENABLED
 80    * 3.3. and files have been specified on the command line
 81    * 3.4. and the remote control server can be contacted
 82    * 3.5. then DrJava will open the files in an existing instance and quit
 83    *
 84    * 4. DrJava.configureAndLoadDrJavaRoot determines if a restart is necessary:
 85    * 4.1. If MASTER_JVM_XMX is set
 86    * 4.2. or MASTER_JVM_ARGS is set
 87    * 4.3. then DrJava will attempt to restart itself with the specified JVM arguments
 88    * 4.4. Files that have arrived via Mac OS X's handleOpenFile event up to this point
 89    * are included in the main arguments for the restarted DrJava.
 90    * 4.5. If that fails, DrJava will ask if the user wants to delete the settings in the .drjava file
 91    * 4.5.1. If the user says "yes", DrJava will attempt another restart. If that fails, DrJava gives up.
 92    * 4.5.2. If the user says "no", DrJava gives up.
 93    * 4.6. If additional files arrive via the handleOpenFile event, DrJava will
 94    * attempt to use the remote control to open the files in the restarted DrJava.
 95    * 4.6.1. DrJava will perform NUM_REMOTE_CONTROL_RETRIES attempts to contact the
 96    * remote control server, with WAIT_BEFORE_REMOTE_CONTROL_RETRY ms of sleep time in between.
 97    *
 98    * 5. If neither the remote control was used nor a restart was necessary, DrJava will
 99    * call DrJavaRoot.main.
 100    * 5.1. Files that have arrived via Mac OS X's handleOpenFile event up to this point
 101    * are included in the arguments for DrJavaRoot.main.
 102    * 5.2. If additional files arrive via the handleOpenFile event, DrJava will
 103    * MainFrame.handleRemoteOpenFile.
 104    *
 105    * @version $Id: DrJava.java 5443 2011-08-17 04:58:50Z rcartwright $
 106    */
 107    public class DrJava {
 108    public static volatile Log _log = new Log("DrJava.txt", false);
 109   
 110    private static final String DEFAULT_MAX_HEAP_SIZE_ARG = "-Xmx128M";
 111   
 112    private static final ArrayList<String> _filesToOpen = new ArrayList<String>();
 113    private static final ArrayList<String> _jvmArgs = new ArrayList<String>();
 114   
 115    static volatile boolean _showDebugConsole = false;
 116   
 117    /** true if a new instance of DrJava should be started instead of
 118    * connecting to an already running instance. */
 119    static volatile boolean _forceNewInstance = false;
 120   
 121    /** true if a new DrJava needs to be restarted to adjust parameters. */
 122    static volatile boolean _doRestart = false;
 123   
 124    /** true if DrJava has already launched the new instance. */
 125    static volatile boolean _alreadyRestarted = false;
 126   
 127    /** true if the restarted DrJava will use remote control, and we can try to
 128    * pass along files to open that arrived too late. */
 129    static volatile boolean _restartedDrJavaUsesRemoteControl = true;
 130   
 131    /** Time in millisecond before restarting DrJava to change the heap size, etc. is deemed a success. */
 132    private static final int WAIT_BEFORE_DECLARING_SUCCESS = 5000;
 133   
 134    /** Number of times we retry opening with the remote control. */
 135    private static final int NUM_REMOTE_CONTROL_RETRIES = 15;
 136   
 137    /** Time in millisecond that we wait before making another remote control attempt. */
 138    private static final int WAIT_BEFORE_REMOTE_CONTROL_RETRY = 500;
 139   
 140    /* Config objects can't be public static final, since we have to delay construction until we know the
 141    * config file's location. (Might be specified on command line.) Instead, use accessor methods to
 142    * prevent others from assigning new values. */
 143   
 144    /** Default properties file used by the configuration object, i.e. ".drjava" in the user's home directory. */
 145    public static final File DEFAULT_PROPERTIES_FILE = new File(System.getProperty("user.home"), ".drjava");
 146   
 147    /** Properties file used by the configuration object. Defaults to DEFAULT_PROPERTIES_FILE. */
 148    private static volatile File _propertiesFile = DEFAULT_PROPERTIES_FILE;
 149   
 150    /** Configuration object with all customized and default values.
 151    * Lazily initialized from _propertiesFile in getConfig() or handleCommandLineArgs(). */
 152    private static volatile FileConfiguration _config;
 153   
 154    /** Name of the resource bundle that controls whether options are editable or not. */
 155    public static final String RESOURCE_BUNDLE_NAME = "edu.rice.cs.drjava.config.options";
 156   
 157    /** Returns the properties file used by the configuration object. */
 158  38 public static File getPropertiesFile() { return _propertiesFile; }
 159   
 160    /** Returns the configuration object with all customized and default values. */
 161  274645 public static synchronized FileConfiguration getConfig() {
 162  274645 if (_config == null) {
 163  4 _config = _initConfig(); // read specified .djrava file into _config
 164    }
 165  274645 return _config;
 166    }
 167   
 168    /** @return an array of the files that were passed on the command line. */
 169  0 public static synchronized String[] getFilesToOpen() { return _filesToOpen.toArray(new String[0]); }
 170   
 171    /** Add a file to the list of files to open. */
 172  0 public static synchronized void addFileToOpen(String s) {
 173  0 _filesToOpen.add(s);
 174  0 boolean isProjectFile =
 175    s.endsWith(OptionConstants.PROJECT_FILE_EXTENSION) ||
 176    s.endsWith(OptionConstants.PROJECT_FILE_EXTENSION2) ||
 177    s.endsWith(OptionConstants.OLD_PROJECT_FILE_EXTENSION);
 178  0 _forceNewInstance |= isProjectFile;
 179  0 if (_doRestart && _alreadyRestarted) {
 180  0 _log.log("addFileToOpen: already done the restart, trying to use remote control");
 181    // we already did the restart, try to use the remote control to open the file
 182  0 if (DrJava.getConfig().getSetting(OptionConstants.REMOTE_CONTROL_ENABLED)) {
 183  0 _log.log("\tremote control...");
 184  0 openWithRemoteControl(_filesToOpen,NUM_REMOTE_CONTROL_RETRIES );
 185  0 _log.log("\tclearing _filesToOpen");
 186  0 clearFilesToOpen();
 187    }
 188    }
 189    }
 190   
 191    /** Clear the list of files to open. */
 192  833 public static synchronized void clearFilesToOpen() {
 193  833 _filesToOpen.clear();
 194    }
 195   
 196    /** Open the specified files using the remote control. If the remote control server is not
 197    * running, numAttempts attempts will be made, with WAIT_BEFORE_REMOTE_CONTROL_RETRY
 198    * ms of sleep time in between.
 199    * @param files files to open with remote control
 200    * @param numAttempts of attempts to be made
 201    * @return true if successful
 202    */
 203  0 public static synchronized boolean openWithRemoteControl(ArrayList<String> files, int numAttempts) {
 204  0 if (! DrJava.getConfig().getSetting(OptionConstants.REMOTE_CONTROL_ENABLED) ||
 205    ! _restartedDrJavaUsesRemoteControl ||
 206  0 files.size() == 0) return false;
 207   
 208  0 ArrayList<String> fs = new ArrayList<String>(files);
 209  0 int failCount = 0;
 210  0 while(failCount<numAttempts) {
 211  0 try {
 212  0 RemoteControlClient.openFile(null);
 213  0 if (RemoteControlClient.isServerRunning()) {
 214    // existing instance is running and responding
 215  0 for (int i = 0; i < fs.size(); ++i) {
 216  0 _log.log("opening with remote control "+fs.get(i));
 217  0 RemoteControlClient.openFile(new File(fs.get(i)));
 218  0 files.remove(fs.get(i));
 219    }
 220  0 return true; // success
 221    }
 222    else {
 223  0 ++failCount;
 224  0 _log.log("Failed to open with remote control, attempt "+failCount+" of "+NUM_REMOTE_CONTROL_RETRIES);
 225  0 if (failCount>=numAttempts) return false; // failure
 226  0 try { Thread.sleep(WAIT_BEFORE_REMOTE_CONTROL_RETRY); }
 227    catch(InterruptedException ie) { /* just try again now */ }
 228    }
 229    }
 230  0 catch(IOException ioe) { ioe.printStackTrace(); }
 231    }
 232  0 return false; // failure
 233    }
 234   
 235    /** @return true if the debug console should be enabled */
 236  0 public static boolean getShowDebugConsole() { return _showDebugConsole; }
 237   
 238    /** Starts running DrJava.
 239    * @param args Command line argument array
 240    */
 241  0 public static void main(final String[] args) {
 242    // handleCommandLineArgs will return true if DrJava should be loaded
 243  0 if (handleCommandLineArgs(args)) {
 244    // Platform-specific UI setup.
 245  0 PlatformFactory.ONLY.beforeUISetup();
 246   
 247    // Utilities.showDebug("Calling configureAndLoadDrJavaRoot with args = " + args);
 248  0 configureAndLoadDrJavaRoot(args);
 249    }
 250    }
 251   
 252  0 public static void configureAndLoadDrJavaRoot(String[] args) {
 253  0 try {
 254    // if there were files passed on the command line,
 255    // try to open them in an existing instance
 256  0 if (!_forceNewInstance &&
 257    DrJava.getConfig().getSetting(OptionConstants.REMOTE_CONTROL_ENABLED) &&
 258    (_filesToOpen.size() > 0)) {
 259  0 if (openWithRemoteControl(_filesToOpen,1)) System.exit(0); // files opened in existing instance, quit
 260    }
 261   
 262    // The code below is in a loop so that DrJava can retry launching itself
 263    // if it fails the first time after resetting the configuration file.
 264    // This helps for example when the main JVM heap size is too large, and
 265    // the JVM cannot be created.
 266  0 int failCount = 0;
 267  0 while(failCount < 2) {
 268    // Restart if there are custom JVM args
 269  0 String masterMemory = getConfig().getSetting(MASTER_JVM_XMX).trim();
 270  0 boolean _doRestart = (getConfig().getSetting(MASTER_JVM_ARGS).length() > 0)
 271    || (!"".equals(masterMemory) && !OptionConstants.heapSizeChoices.get(0).equals(masterMemory));
 272  0 _log.log("_doRestart: "+_doRestart);
 273   
 274  0 LinkedList<String> classArgs = new LinkedList<String>();
 275   
 276    // Add the parameters "-debugConsole" to classArgsList if _showDebugConsole is true
 277  0 if (_showDebugConsole) { classArgs.addFirst("-debugConsole"); }
 278   
 279  0 if (! _propertiesFile.equals(DEFAULT_PROPERTIES_FILE)) {
 280    // Placed in reversed order to get "-config filename"
 281  0 classArgs.addFirst(_propertiesFile.getAbsolutePath());
 282  0 classArgs.addFirst("-config");
 283    }
 284   
 285  0 synchronized(DrJava.class) {
 286  0 classArgs.addAll(_filesToOpen);
 287  0 clearFilesToOpen();
 288  0 _log.log("_filesToOpen copied into class arguments, clearing _filesToOpen");
 289    }
 290   
 291  0 if (_doRestart) {
 292  0 if (DrJava.getConfig().getSetting(OptionConstants.REMOTE_CONTROL_ENABLED)) {
 293    // at this time, OUR remote control server hasn't been started yet
 294    // if one is running, then we won't be able to contact the restarted DrJava
 295  0 _restartedDrJavaUsesRemoteControl = !RemoteControlClient.isServerRunning();
 296    } else {
 297    // no remote control
 298  0 _restartedDrJavaUsesRemoteControl = false;
 299    }
 300   
 301    // Run a new copy of DrJava and exit
 302  0 try {
 303  0 boolean failed = false;
 304  0 JVMBuilder jvmb = JVMBuilder.DEFAULT.jvmArguments(_jvmArgs);
 305   
 306    // extend classpath if JUnit/ConcJUnit location specified
 307  0 _log.log("JVMBuilder: classPath = "+jvmb.classPath());
 308  0 ArrayList<File> extendedClassPath = new ArrayList<File>();
 309  0 for(File f: jvmb.classPath()) { extendedClassPath.add(f); }
 310  0 _log.log("JVMBuilder: extendedClassPath = "+extendedClassPath);
 311  0 jvmb = jvmb.classPath(edu.rice.cs.plt.iter.IterUtil.asSizedIterable(extendedClassPath));
 312  0 _log.log("JVMBuilder: jvmArguments = "+jvmb.jvmArguments());
 313  0 _log.log("JVMBuilder: classPath = "+jvmb.classPath());
 314  0 _log.log("JVMBuilder: mainParams = "+classArgs);
 315   
 316    // start new DrJava
 317  0 Process p = jvmb.start(DrJavaRoot.class.getName(), classArgs);
 318  0 _alreadyRestarted = true;
 319  0 _log.log("_alreadyRestarted = true");
 320  0 DelayedInterrupter timeout = new DelayedInterrupter(WAIT_BEFORE_DECLARING_SUCCESS);
 321  0 try {
 322  0 int exitValue = p.waitFor();
 323  0 timeout.abort();
 324  0 failed = (exitValue != 0);
 325    }
 326    catch(InterruptedException e) { /* timeout was reached */ }
 327  0 _log.log("failed = "+failed);
 328  0 if (failed) {
 329  0 if (failCount > 0) {
 330    // 2nd time that spawning has failed, give up
 331  0 JOptionPane.showMessageDialog(null,
 332    "DrJava was unable to start, and resetting your configuration\n" +
 333    "did not help. Please file a support request at\n" +
 334    "https://sourceforge.net/projects/drjava/",
 335    "Could Not Start DrJava",
 336    JOptionPane.ERROR_MESSAGE);
 337  0 System.exit(1);
 338    }
 339    else {
 340    // 1st time that spawning has failed, offer to reset configuration
 341  0 int result = JOptionPane.showConfirmDialog(null,
 342    "DrJava was unable to start. Your configuration file (.drjava)\n" +
 343    "might be corrupt. Do you want to reset your configuration?",
 344    "Could Not Start DrJava",
 345    JOptionPane.YES_NO_OPTION);
 346  0 if (result != JOptionPane.YES_OPTION) { System.exit(0); }
 347    // reset configuration, save, and reload it
 348  0 getConfig().resetToDefaults();
 349  0 getConfig().saveConfiguration();
 350  0 if (!handleCommandLineArgs(args)) { System.exit(0); }
 351  0 ++failCount;
 352  0 continue;
 353    }
 354    }
 355    else {
 356    // check if there are any files left in _filesToOpen
 357  0 _log.log("not failed, send remaining files via remote control: "+_filesToOpen);
 358  0 openWithRemoteControl(_filesToOpen, NUM_REMOTE_CONTROL_RETRIES);
 359    }
 360    }
 361    catch (IOException ioe) {
 362    // Display error
 363  0 final String[] text = {
 364    "DrJava was unable to load its compiler and debugger. Would you ",
 365    "like to start DrJava without a compiler and debugger?", "\nReason: " + ioe.toString()
 366    };
 367  0 int result = JOptionPane.showConfirmDialog(null, text, "Could Not Load Compiler and Debugger",
 368    JOptionPane.YES_NO_OPTION);
 369  0 if (result != JOptionPane.YES_OPTION) { System.exit(0); }
 370    }
 371    }
 372   
 373    else {
 374    // No restart -- just invoke DrJavaRoot.main.
 375  0 DrJavaRoot.main(classArgs.toArray(new String[0]));
 376    // when we return from here, DrJavaRoot._mainFrame has been initialized
 377    // but we may still have files in _filesToOpen that were not processed
 378    // do that now
 379  0 ArrayList<String> fs = new ArrayList<String>(_filesToOpen);
 380  0 for(String f: fs) {
 381  0 DrJavaRoot.handleRemoteOpenFile(new File(f), -1);
 382    }
 383    }
 384  0 break;
 385    }
 386    }
 387    catch(Throwable t) {
 388    // Show any errors to the System.err and in an DrJavaErrorHandler
 389  0 System.out.println(t.getClass().getName() + ": " + t.getMessage());
 390  0 t.printStackTrace(System.err);System.out.println("error thrown");
 391  0 DrJavaErrorHandler.record(t);
 392    }
 393    }
 394   
 395    /** Handles any command line arguments that have been specified.
 396    * @return true if DrJava should load, false if not
 397    */
 398  0 static boolean handleCommandLineArgs(String[] args) {
 399  0 boolean heapSizeGiven = false; // indicates whether args includes an argument of the form -Xmx<number>
 400   
 401    // Loop through arguments looking for known options
 402  0 int argIndex = 0;
 403  0 int len = args.length;
 404  0 _log.log("handleCommandLineArgs. _filesToOpen: " + _filesToOpen);
 405   
 406  0 while(argIndex < len) {
 407  0 String arg = args[argIndex++];
 408   
 409  0 if (arg.equals("-config")) {
 410  0 if (len == argIndex) {
 411    // config option is missing file name; should we generate an error?
 412  0 return true;
 413    }
 414    // arg.length > i+1 implying args list incudes config file name and perhaps files to open
 415  0 setPropertiesFile(args[argIndex++]);
 416    }
 417   
 418  0 else if (arg.startsWith("-X") || arg.startsWith("-D")) {
 419  0 if (arg.startsWith("-Xmx")) { heapSizeGiven = true; }
 420  0 _jvmArgs.add(arg);
 421    }
 422   
 423  0 else if (arg.equals("-debugConsole")) _showDebugConsole = true;
 424   
 425  0 else if (arg.equals("-new")) _forceNewInstance = true;
 426   
 427  0 else if (arg.equals("-delete-after-restart")) {
 428  0 File deleteAfterRestart = new File(args[argIndex++]);
 429  0 deleteAfterRestart.delete();
 430    }
 431   
 432  0 else if (arg.equals("-jll")) {
 433  0 String[] argsForJLL = new String[args.length-argIndex];
 434  0 System.arraycopy(args, argIndex, argsForJLL, 0, argsForJLL.length);
 435  0 edu.rice.cs.javalanglevels.LanguageLevelConverter.main(argsForJLL);
 436  0 System.exit(0);
 437    }
 438   
 439  0 else if (arg.equals("-help") || arg.equals("-?")) {
 440  0 displayUsage();
 441  0 return false;
 442    }
 443    else {
 444    // this is the first file to open, do not consume
 445  0 --argIndex;
 446  0 break;
 447    }
 448    }
 449   
 450  0 synchronized(DrJava.class) {
 451  0 _config = _initConfig(); // read specified .djrava file into _config
 452    }
 453   
 454  0 if ((!("".equals(getConfig().getSetting(MASTER_JVM_XMX)))) &&
 455    (!(OptionConstants.heapSizeChoices.get(0).equals(getConfig().getSetting(MASTER_JVM_XMX))))) {
 456  0 _jvmArgs.add("-Xmx" + getConfig().getSetting(MASTER_JVM_XMX).trim() + "M");
 457  0 heapSizeGiven = true;
 458    }
 459  0 List<String> configArgs = ArgumentTokenizer.tokenize(getConfig().getSetting(MASTER_JVM_ARGS));
 460  0 for (String arg : configArgs) {
 461  0 if (arg.startsWith("-Xmx")) { heapSizeGiven = true; }
 462  0 _jvmArgs.add(arg);
 463    }
 464   
 465  0 if (PlatformFactory.ONLY.isMacPlatform()) {
 466  0 String iconLoc = System.getProperty("edu.rice.cs.drjava.icon");
 467  0 if (iconLoc != null) { // we are running inside the Mac app wrapper
 468  0 _jvmArgs.add("-Xdock:name=DrJava");
 469  0 _jvmArgs.add("-Xdock:icon=" + iconLoc);
 470    }
 471    }
 472   
 473  0 if (!heapSizeGiven) { _jvmArgs.add(DEFAULT_MAX_HEAP_SIZE_ARG); }
 474   
 475  0 _log.log("_jvmArgs = " + _jvmArgs);
 476   
 477    // Open the remaining args as filenames
 478   
 479  0 for (int i = argIndex; i < len; i++) { addFileToOpen(args[i]); }
 480  0 _log.log("\t _filesToOpen now contains: " + _filesToOpen);
 481   
 482  0 return true;
 483    }
 484   
 485    /** Displays a usage message about the available options. */
 486  0 static void displayUsage() {
 487  0 System.out.println("Usage: java -jar drjava.jar [OPTIONS] [FILES]\n");
 488  0 System.out.println("where options include:");
 489  0 System.out.println(" -config [FILE] use a custom config file");
 490  0 System.out.println(" -new force the creation of a new DrJava instance;");
 491  0 System.out.println(" do not connect to existing instance");
 492  0 System.out.println(" -help | -? print this help message");
 493  0 System.out.println(" -X<jvmOption> specify a JVM configuration option for the master DrJava JVM");
 494  0 System.out.println(" -D<name>[=<value>] set a Java property for the master DrJava JVM");
 495  0 System.out.println(" -jll [ARGS] invoke the Java Language Level converter, specify files in ARGS");
 496    }
 497   
 498    /** Switches the config object to use a custom config file. Ensures that Java source files aren't
 499    * accidentally used.
 500    */
 501  820 static void setPropertiesFile(String fileName) {
 502  820 if (!DrJavaFileUtils.isSourceFile(fileName)) _propertiesFile = new File(fileName);
 503    }
 504   
 505    /** Initializes the configuration object with the current notion of the properties file.
 506    * @throws IllegalStateException if config has already been assigned
 507    */
 508  824 static FileConfiguration _initConfig() throws IllegalStateException {
 509    // // Make sure someone doesn't try to change the config object.
 510    // if (_config != null) throw new IllegalStateException("Can only call initConfig once!");
 511   
 512  824 FileConfiguration config;
 513   
 514  824 final File propFile = _propertiesFile; // a static variable shared across configurations in tests
 515   
 516  824 try { propFile.createNewFile(); } // be nice and ensure a config file if there isn't one
 517    catch (IOException e) { /* IOException occurred, continue without a real file */ }
 518   
 519  824 config = new FileConfiguration(propFile);
 520  824 try { config.loadConfiguration(); }
 521    catch (Exception e) {
 522    // Problem parsing the config file. Use defaults and remember what happened (for the UI).
 523  0 config.storeStartupException(e);
 524    }
 525  824 _config = new ResourceBundleConfiguration(RESOURCE_BUNDLE_NAME,config);
 526  824 return _config;
 527    }
 528   
 529    /** Saves the contents of the config file. TO DO: log any IOExceptions that occur. */
 530  0 protected static void _saveConfig() {
 531  0 try { getConfig().saveConfiguration(); }
 532    catch(IOException e) {
 533  0 JOptionPane.showMessageDialog(null,
 534    "Could not save the location of tools.jar in \n" +
 535    "the '.drjava' file in your home directory. \n" +
 536    "Another process may be using the file.\n\n" + e,
 537    "Could Not Save Changes",
 538    JOptionPane.ERROR_MESSAGE);
 539    // log this error
 540  0 DrJavaErrorHandler.record(new UnexpectedException(e, "Could not save the location of tools.jar in \n" +
 541    "the '.drjava' file in your home directory. \n" +
 542    "Another process may be using the file.\n\n"));
 543    }
 544    }
 545   
 546    // /** Displays a prompt to the user indicating that tools.jar could not be found in the specified location, and asks
 547    // * if he would like to specify a new location.
 548    // */
 549    // private static boolean _userWantsToPickAgain() {
 550    // File selectedFile = getConfig().getSetting(JAVAC_LOCATION);
 551    // String selectedVersion = _getToolsJarVersion(selectedFile);
 552    //
 553    // final String[] text;
 554    // if (selectedVersion==null) {
 555    // text = new String[] {
 556    // "The file you chose did not appear to be the correct 'tools.jar'",
 557    // "that is compatible with the version of Java that is used to",
 558    // "run DrJava (Java version " + System.getProperty("java.version") + ").",
 559    // "Your choice might be an incompatible version of the file.",
 560    // "Would you like to pick again? The 'tools.jar' file is ",
 561    // "generally located in the 'lib' subdirectory under your ",
 562    // "JDK installation directory.",
 563    // "(If you say 'No', DrJava might be unable to compile or ",
 564    // "debug programs.)"
 565    // };
 566    // }
 567    // else {
 568    // text = new String[] {
 569    // "The file you chose did not appear to be the correct 'tools.jar'",
 570    // "that is compatible with the version of Java that is used to",
 571    // "run DrJava (Java version " + System.getProperty("java.version") + ").",
 572    // "The file you have selected appears to be for",
 573    // "Java version " + selectedVersion + ".",
 574    // "Your choice might be an incompatible version of the file.",
 575    // "Would you like to pick again? The 'tools.jar' file is ",
 576    // "generally located in the 'lib' subdirectory under your ",
 577    // "JDK installation directory.",
 578    // "If you say 'No', DrJava might be unable to compile or ",
 579    // "debug programs."
 580    // };
 581    // }
 582    //
 583    // int result = JOptionPane.showConfirmDialog(null, text, "Locate 'tools.jar'?", JOptionPane.YES_NO_OPTION);
 584    // return result == JOptionPane.YES_OPTION;
 585    // }
 586   
 587    /* Erase all non-final bindings created in this class. Only used in testing. */
 588  833 public static void cleanUp() {
 589  833 _log.log("cleanUp. _filesToOpen: " + _filesToOpen);
 590  833 clearFilesToOpen();
 591  833 _log.log("\t_filesToOpen cleared");
 592  833 _jvmArgs.clear();
 593    // Do not set _config or _propertiesFile to null because THEY ARE static
 594    }
 595   
 596    /** Warn if this system is Linux with Compiz. */
 597  0 public static boolean warnIfLinuxWithCompiz() {
 598  0 try {
 599  0 if (!System.getProperty("os.name").equals("Linux")) return false; // not Linux
 600  0 if (!DrJava.getConfig().getSetting(OptionConstants.WARN_IF_COMPIZ)) return false; // set to ignore
 601   
 602    // get /bin/ps
 603  0 File ps = new File("/bin/ps");
 604   
 605    // execute ps
 606  0 ProcessBuilder pb = new ProcessBuilder(ps.getAbsolutePath(), "-A");
 607  0 Process psProc = pb.start();
 608  0 psProc.waitFor();
 609   
 610    // read the output of ps
 611  0 BufferedReader br = new BufferedReader(new InputStreamReader(psProc.getInputStream()));
 612  0 boolean compiz = false;
 613  0 String line = null;
 614  0 while((line=br.readLine()) != null) {
 615    // find the PID of JUnitTestRunner, i.e. the PID of the current process
 616  0 if ((line.endsWith("compiz")) ||
 617    (line.endsWith("compiz.real"))) {
 618  0 compiz = true;
 619  0 break;
 620    }
 621    }
 622  0 if (!compiz) return false; // no Compiz
 623   
 624  0 final JavaVersion.FullVersion ver160_20 = JavaVersion.parseFullVersion("1.6.0_20");
 625  0 if (JavaVersion.CURRENT_FULL.compareTo(ver160_20)>=0) return false; // Java >= 1.6.0_20
 626   
 627  0 String[] options = new String[] { "Yes", "Yes, and ignore from now on", "No" };
 628  0 int res = javax.swing.JOptionPane.
 629    showOptionDialog(null,
 630    "<html>DrJava has detected that you are using Compiz with a version<br>" +
 631    "of Java that is older than " + ver160_20 + ".<br>" +
 632    "<br>" +
 633    "Compiz and older versions of Java are incompatible and can cause<br>" +
 634    "DrJava or your computer to crash.<br>" +
 635    "<br>" +
 636    "We recommend that you <b>update to " + ver160_20 + " or newer</b>,<br>" +
 637    "or that you disable Compiz if you still experience problems.<br>" +
 638    "On Ubuntu, go to System->Preferences->Appearence, display the<br>" +
 639    "Visual Effects tab, and select 'None'.<br>" +
 640    "<br>" +
 641    "For more information, please go to http://drjava.org/compiz<br>" +
 642    "<br>" +
 643    "Do you want to start DrJava anyway?</html>",
 644    "Compiz detected",
 645    JOptionPane.DEFAULT_OPTION,
 646    javax.swing.JOptionPane.WARNING_MESSAGE,
 647    null,
 648    options,
 649    options[0]);
 650  0 switch(res) {
 651  0 case 1:
 652    // set "ignore" option
 653  0 DrJava.getConfig().setSetting(OptionConstants.WARN_IF_COMPIZ, false);
 654  0 break;
 655  0 case 2:
 656  0 System.exit(0);
 657  0 break;
 658    }
 659  0 return compiz;
 660    }
 661    catch(IOException ioe) {
 662  0 return false; // do not warn
 663    }
 664    catch(InterruptedException ie) {
 665  0 return false; // do not warn
 666    }
 667    }
 668    }