protected File promptForFile() { // prompt the user to pick a file final FileChooser fc = FileChooser.createFileChooser( window, (DirectoryConfigurer) Prefs.getGlobalPrefs().getOption(Prefs.MODULES_DIR_KEY)); addFileFilters(fc); // loop until cancellation or we get an existing file if (fc.showOpenDialog() == FileChooser.APPROVE_OPTION) { lr.module = fc.getSelectedFile(); if (lr.module != null) { if (lr.module.exists()) { final AbstractMetaData metadata = MetaDataFactory.buildMetaData(lr.module); if (metadata == null || !(metadata instanceof ModuleMetaData)) { ErrorDialog.show("Error.invalid_vassal_module", lr.module.getAbsolutePath()); Logger.log( "-- Load of " + lr.module.getAbsolutePath() + " failed: Not a Vassal module"); lr.module = null; } } else { lr.module = null; } // FIXME: do something to warn about nonexistant file // FileNotFoundDialog.warning(window, lr.module); } } return lr.module; }
@Override public Void doInBackground() throws InterruptedException, IOException { // FIXME: this should be in an abstract method and farmed out to subclasses // send some basic information to the log if (lr.module != null) { Logger.log("-- Loading module file " + lr.module.getAbsolutePath()); } if (lr.game != null) { Logger.log("-- Loading game file " + lr.game.getAbsolutePath()); } if (lr.importFile != null) { Logger.log("-- Importing module file " + lr.importFile.getAbsolutePath()); } // end FIXME // set default heap sizes int initialHeap = DEFAULT_INITIAL_HEAP; int maximumHeap = DEFAULT_MAXIMUM_HEAP; String moduleName = null; // FIXME: this should be in an abstract method and farmed out to subclasses, // rather than a case structure for each kind of thing which may be loaded. // find module-specific heap settings, if any if (lr.module != null) { final AbstractMetaData data = MetaDataFactory.buildMetaData(lr.module); if (data == null) { ErrorDialog.show("Error.invalid_vassal_file", lr.module.getAbsolutePath()); setWaitCursor(false); return null; } if (data instanceof ModuleMetaData) { moduleName = ((ModuleMetaData) data).getName(); // log the module name Logger.log("-- Loading module " + moduleName); // read module prefs final ReadOnlyPrefs p = new ReadOnlyPrefs(moduleName); // read initial heap size initialHeap = getHeapSize(p, GlobalOptions.INITIAL_HEAP, DEFAULT_INITIAL_HEAP); // read maximum heap size maximumHeap = getHeapSize(p, GlobalOptions.MAXIMUM_HEAP, DEFAULT_MAXIMUM_HEAP); } } else if (lr.importFile != null) { final Prefs p = Prefs.getGlobalPrefs(); // read initial heap size initialHeap = getHeapSize(p, GlobalOptions.INITIAL_HEAP, DEFAULT_INITIAL_HEAP); // read maximum heap size maximumHeap = getHeapSize(p, GlobalOptions.MAXIMUM_HEAP, DEFAULT_MAXIMUM_HEAP); } // end FIXME // // Heap size sanity checks: fall back to failsafe heap sizes in // case the given initial or maximum heap is not usable. // // FIXME: The heap size messages are too nonspecific. They should // differientiate between loading a module and importing a module, // since the heap sizes are set in different places for those two // actions. // maximum heap must fit in physical RAM if (maximumHeap > PHYS_MEMORY && PHYS_MEMORY > 0) { initialHeap = FAILSAFE_INITIAL_HEAP; maximumHeap = FAILSAFE_MAXIMUM_HEAP; FutureUtils.wait( WarningDialog.show("Warning.maximum_heap_too_large", FAILSAFE_MAXIMUM_HEAP)); } // maximum heap must be at least the failsafe size else if (maximumHeap < FAILSAFE_MAXIMUM_HEAP) { initialHeap = FAILSAFE_INITIAL_HEAP; maximumHeap = FAILSAFE_MAXIMUM_HEAP; FutureUtils.wait( WarningDialog.show("Warning.maximum_heap_too_small", FAILSAFE_MAXIMUM_HEAP)); } // initial heap must be at least the failsafe size else if (initialHeap < FAILSAFE_INITIAL_HEAP) { initialHeap = FAILSAFE_INITIAL_HEAP; maximumHeap = FAILSAFE_MAXIMUM_HEAP; FutureUtils.wait( WarningDialog.show("Warning.initial_heap_too_small", FAILSAFE_INITIAL_HEAP)); } // initial heap must be less than or equal to maximum heap else if (initialHeap > maximumHeap) { initialHeap = FAILSAFE_INITIAL_HEAP; maximumHeap = FAILSAFE_MAXIMUM_HEAP; FutureUtils.wait( WarningDialog.show("Warning.initial_heap_too_large", FAILSAFE_INITIAL_HEAP)); } // create a socket for communicating which the child process serverSocket = new ServerSocket(0, 0, InetAddress.getByName(null)); cmdS = new LaunchCommandServer(serverSocket); new Thread(cmdS, "command server " + id).start(); // build the argument list final ArrayList<String> al = new ArrayList<String>(); al.add(Info.javaBinPath); al.add(""); // reserved for initial heap al.add(""); // reserved for maximum heap al.add("-DVASSAL.id=" + id); // instance id // pass on the user's home, if it's set final String userHome = System.getProperty("user.home"); if (userHome != null) al.add("-Duser.home=" + userHome); // set the classpath al.add("-cp"); al.add(System.getProperty("java.class.path")); if (Info.isMacOSX()) { // set the MacOS X dock parameters // use the module name for the dock if we found a module name // FIXME: should "Unnamed module" be localized? final String d_name = moduleName != null && moduleName.length() > 0 ? moduleName : "Unnamed module"; // get the path to the app icon final String d_icon = new File(Info.getBaseDir(), "Contents/Resources/VASSAL.icns").getAbsolutePath(); al.add("-Xdock:name=" + d_name); al.add("-Xdock:icon=" + d_icon); // Quartz can cause font rendering problems; turn it off? final Boolean disableQuartz = (Boolean) Prefs.getGlobalPrefs().getValue(Prefs.DISABLE_QUARTZ); al.add( "-Dapple.awt.graphics.UseQuartz=" + (Boolean.TRUE.equals(disableQuartz) ? "false" : "true")); } else if (Info.isWindows()) { // Disable the 2D to Direct3D pipeline? final Boolean disableD3d = (Boolean) Prefs.getGlobalPrefs().getValue(Prefs.DISABLE_D3D); if (Boolean.TRUE.equals(disableD3d)) { al.add("-Dsun.java2d.d3d=false"); } } al.add(entryPoint); final String[] args = al.toArray(new String[al.size()]); // try to start a child process with the given heap sizes args[1] = "-Xms" + initialHeap + "M"; args[2] = "-Xmx" + maximumHeap + "M"; Process p = launch(args); // launch failed, use conservative heap sizes if (p == null) { args[1] = "-Xms" + FAILSAFE_INITIAL_HEAP + "M"; args[2] = "-Xmx" + FAILSAFE_MAXIMUM_HEAP + "M"; p = launch(args); if (p == null) { throw new IOException("failed to start child process"); } else { FutureUtils.wait( WarningDialog.show("Warning.maximum_heap_too_large", FAILSAFE_MAXIMUM_HEAP)); } } // read the port for the child's socket from its stdout final DataInputStream din = new DataInputStream(p.getInputStream()); final int childPort = din.readInt(); // pump child's stderr to our own stderr new Thread(new StreamPump(p.getErrorStream(), System.err), "err pump " + id).start(); // pump child's stdout to our own stdout new Thread(new StreamPump(p.getInputStream(), System.out), "out pump " + id).start(); // Check that the child's port is sane. Reading stdout from a // failed launch tends to give impossible port numbers. if (childPort < 0 || childPort > 65535) { throw new IOException("port out of range: " + childPort); } // create the client for the child's socket clientSocket = new Socket((String) null, childPort); cmdC = new CommandClient(clientSocket); children.add(cmdC); // block until the process ends p.waitFor(); return null; }