Example #1
0
  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;
  }
Example #2
0
  /**
   * Read and validate a Module file. - Check it has a Zip Entry named buildfile - If it has a
   * metadata file, read and parse it.
   *
   * @param file Module File
   */
  public void read(ZipFile zip) {
    version = "";

    try {
      // Try to parse the metadata. Failure is not catastrophic, we can
      // treat it like an old-style module with no metadata and parse
      // the first lines of the buildFile
      DefaultHandler handler = null;

      ZipEntry data = zip.getEntry(ZIP_ENTRY_NAME);
      if (data == null) {
        data = zip.getEntry(GameModule.BUILDFILE);
        if (data == null) return;

        handler = new ModuleBuildFileXMLHandler();
      } else {
        handler = new MetadataXMLHandler();
      }

      BufferedInputStream in = null;
      try {
        in = new BufferedInputStream(zip.getInputStream(data));

        synchronized (parser) {
          parser.setContentHandler(handler);
          parser.setDTDHandler(handler);
          parser.setEntityResolver(handler);
          parser.setErrorHandler(handler);
          parser.parse(new InputSource(in));
        }

        in.close();
      } finally {
        IOUtils.closeQuietly(in);
      }

      zip.close();
    } catch (IOException e) {
      Logger.log(e);
    } catch (SAXEndException e) {
      // Indicates End of module/extension parsing. not an error.
    } catch (SAXException e) {
      Logger.log(e);
    } finally {
      IOUtils.closeQuietly(zip);
    }
  }
Example #3
0
    protected Process launch(String[] args) throws IOException {
      Logger.log(StringUtils.join(args, " "));

      // set up and start the child process
      final ProcessBuilder pb = new ProcessBuilder(args);
      pb.directory(Info.getBinDir());
      final Process p = pb.start();

      // write the port for this socket to child's stdin and close
      ObjectOutputStream oout = null;
      try {
        oout = new ObjectOutputStream(p.getOutputStream());
        oout.writeInt(serverSocket.getLocalPort());
        oout.writeObject(lr);
        // Note: We don't try to close() the socket here because the
        // pipe might already have been closed from the other end,
        // and that would cause close() to throw spuriously.
      } finally {
        IOUtils.closeQuietly(oout);
      }

      // FIXME: this is probably too long
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
      }

      // check whether the child is still alive
      try {
        // If this doesn't throw, our baby is dead.
        p.exitValue();
        Logger.log(IOUtils.toString(p.getErrorStream()));
        return null;
      } catch (IllegalThreadStateException e) {
        // It's alive! It's ALIIIIIIVE!!!
        return p;
      }
    }
Example #4
0
  /**
   * Factory method to build and return an appropriate MetaData class based on the contents of the
   * file. Return null if the file is not a Zip archive, or it is not a VASSAL Module, Extension or
   * Save Game.
   *
   * @param file metadata file
   * @return MetaData object
   */
  public static AbstractMetaData buildMetaData(File file) {

    // Check the file exists and is a file
    if (file == null || !file.exists() || !file.isFile()) return null;

    ZipFile zip = null;
    try {
      // Check it is a Zip file
      zip = new ZipFile(file);

      // Check if it is a Save Game file
      ZipEntry entry = zip.getEntry(GameState.SAVEFILE_ZIP_ENTRY);
      if (entry != null) {
        return new SaveMetaData(zip);
      }

      // Check if it has a buildFile
      ZipEntry buildFileEntry = zip.getEntry(GameModule.BUILDFILE);
      if (buildFileEntry == null) {
        return null;
      }

      // It's either a module or an Extension, check for existence of metadata
      entry = zip.getEntry(ExtensionMetaData.ZIP_ENTRY_NAME);
      if (entry != null) {
        return new ExtensionMetaData(zip);
      }

      entry = zip.getEntry(ModuleMetaData.ZIP_ENTRY_NAME);
      if (entry != null) {
        return new ModuleMetaData(zip);
      }

      // read the first few lines of the buildFile
      BufferedReader br = null;
      try {
        br = new BufferedReader(new InputStreamReader(zip.getInputStream(buildFileEntry)));
        for (int i = 0; i < 10; i++) {
          final String s = br.readLine();
          if (s.indexOf(BUILDFILE_MODULE_ELEMENT1) > 0
              || s.indexOf(BUILDFILE_MODULE_ELEMENT2) > 0) {
            br.close();
            return new ModuleMetaData(zip);
          } else if (s.indexOf(BUILDFILE_EXTENSION_ELEMENT) > 0) {
            br.close();
            return new ExtensionMetaData(zip);
          }
        }
        br.close();
      } finally {
        IOUtils.closeQuietly(br);
      }

      zip.close();
    } catch (ZipException e) {
      // It is not a Zip file, check for an Importable file
      return ImportAction.buildMetaData(file);
    } catch (IOException e) {
      Logger.log(e);
    } finally {
      IOUtils.closeQuietly(zip);
    }

    return null;
  }
Example #5
0
 public Object execute() {
   final Future<?> future = Logger.enqueue(entry);
   if (entry.wait) FutureUtils.wait(future);
   return "OK";
 }
Example #6
0
    @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;
    }