private int verifyVersionEx() {
    String min = getMinVersion();
    String max = getMaxVersion();
    int retval = OK;
    // No min and max, version always ok.
    if (min == null && max == null) return (OK);

    if (!pathIsValid()) return (BAD_REAL_PATH);
    // No get the version ...
    // We cannot look to the version of this vm because we should
    // test the given JDK VM.
    String[] params = {
      pathSelectionPanel.getPath() + File.separator + "bin" + File.separator + "java", "-version"
    };
    String[] output = new String[2];
    FileExecutor fe = new FileExecutor();
    fe.executeCommand(params, output);
    // "My" VM writes the version on stderr :-(
    String vs = (output[0].length() > 0) ? output[0] : output[1];
    if (min != null) {
      if (!compareVersions(vs, min, true, 4, 4, "__NO_NOT_IDENTIFIER_")) retval = BAD_VERSION;
    }
    if (max != null)
      if (!compareVersions(vs, max, false, 4, 4, "__NO_NOT_IDENTIFIER_")) retval = BAD_VERSION;
    if (retval == OK
        && badRegEntries != null
        && badRegEntries.size() > 0) { // Test for bad registry entry.
      if (badRegEntries.contains(getDetectedVersion())) retval = BAD_REG_PATH;
    }
    return (retval);
  }
  // check if sudo password is correct (so sudo can be used in all other scripts, even without
  // password, lasts for 5 minutes)
  private void doSudoCmd() {
    String pass = passwordField.getText();

    File file = null;
    try {
      // write file in /tmp
      file = new File("/tmp/cmd_sudo.sh"); // ""c:/temp/run.bat""
      FileOutputStream fos = new FileOutputStream(file);
      fos.write("echo $password | sudo -S ls\nexit $?".getBytes()); // "echo $password > pipo.txt"
      fos.close();

      // execute
      HashMap vars = new HashMap();
      vars.put("password", pass);

      List oses = new ArrayList();
      oses.add(
          new OsConstraint(
              "unix", null, null,
              null)); // "windows",System.getProperty("os.name"),System.getProperty("os.version"),System.getProperty("os.arch")));

      ArrayList plist = new ArrayList();
      ParsableFile pf = new ParsableFile(file.getAbsolutePath(), null, null, oses);
      plist.add(pf);
      ScriptParser sp = new ScriptParser(plist, new VariableSubstitutor(vars));
      sp.parseFiles();

      ArrayList elist = new ArrayList();
      ExecutableFile ef =
          new ExecutableFile(
              file.getAbsolutePath(),
              ExecutableFile.POSTINSTALL,
              ExecutableFile.ABORT,
              oses,
              false);
      elist.add(ef);
      FileExecutor fe = new FileExecutor(elist);
      int retval = fe.executeFiles(ExecutableFile.POSTINSTALL, this);
      if (retval == 0) {
        idata.setVariable("password", pass);
        isValid = true;
      }
      //			else is already showing dialog
      //			{
      //				JOptionPane.showMessageDialog(this, "Cannot execute 'sudo' cmd, check your password",
      // "Error", JOptionPane.ERROR_MESSAGE);
      //			}
    } catch (Exception e) {
      //				JOptionPane.showMessageDialog(this, "Cannot execute 'sudo' cmd, check your password",
      // "Error", JOptionPane.ERROR_MESSAGE);
      e.printStackTrace();
      isValid = false;
    }
    try {
      if (file != null && file.exists())
        file.delete(); // you don't want the file with password tobe arround, in case of error
    } catch (Exception e) {
      // ignore
    }
  }
Exemple #3
0
  /**
   * Executes this ShellScript with the given Params.<br>
   * NOTE: the params cannot be contain whitespaces.<br>
   * This (su -c &lt;br&gt;"cp from to"&lt;/br&gt;) would not work:<br>
   * because the underlaying java.runtime.exec("command") does not handle balanced or unbalanced (")
   * correctly.<br>
   * else just whitespace separate tokens.<br>
   * This means for the sample. runtime.exec() would ever execute such as: su "-c" "\"cp" "fromFile"
   * "toFile\""<br>
   * But this his hidden in Sun's native code ;-(<br>
   * This was the reason to write this class to have a Workaround :-)
   *
   * @param itsParams
   * @return the output from stdout of the execution.
   */
  public String exec(String itsParams) {
    FileExecutor.getExecOutput(
        new String[] {UnixHelper.getCustomCommand("chmod"), "+x", itsLocation});

    if (itsParams != null) {
      return FileExecutor.getExecOutput(new String[] {itsLocation, itsParams});
    } else {
      return FileExecutor.getExecOutput(new String[] {itsLocation});
    }
  }
    /**
     * Internal helper method.
     *
     * @param executor The executor, only used when using external compiler.
     * @param output The output from the compiler ([0] = stdout, [1] = stderr)
     * @return The result of the compilation.
     */
    private int runCompiler(FileExecutor executor, String[] output, List<String> cmdline) {
      if (cmdline.get(0).equals(ECLIPSE_COMPILER_NAME)) {
        return runEclipseCompiler(output, cmdline);
      }

      return executor.executeCommand(cmdline.toArray(new String[cmdline.size()]), output);
    }
  /** The run method. */
  public void run() {
    try {
      // We get the list of uninstaller listeners
      List[] listeners = getListenerLists();
      // We get the list of the files to delete
      ArrayList executables = getExecutablesList();

      FileExecutor executor = new FileExecutor(executables);
      executor.executeFiles(ExecutableFile.UNINSTALL, this.handler);

      ArrayList files = getFilesList();
      int size = files.size();

      // Custem action listener stuff --- beforeDeletion ----
      informListeners(listeners[0], UninstallerListener.BEFORE_DELETION, files, handler);

      handler.startAction("destroy", size);

      // We destroy the files
      for (int i = 0; i < size; i++) {
        File file = (File) files.get(i);
        // Custem action listener stuff --- beforeDelete ----
        informListeners(listeners[1], UninstallerListener.BEFORE_DELETE, file, handler);

        file.delete();

        // Custem action listener stuff --- afterDelete ----
        informListeners(listeners[1], UninstallerListener.AFTER_DELETE, file, handler);

        handler.progress(i, file.getAbsolutePath());
      }

      // Custem action listener stuff --- afterDeletion ----
      informListeners(listeners[0], UninstallerListener.AFTER_DELETION, files, handler);

      // We make a complementary cleanup
      handler.progress(size, "[ cleanups ]");
      cleanup(new File(installPath));

      handler.stopAction();
    } catch (Exception err) {
      handler.stopAction();
      err.printStackTrace();
      handler.emitError("exception caught", err.toString());
    }
  }
  /** The run method. */
  public void run() {
    instances.add(this);
    try {
      listener.startUnpack();
      String currentOs = System.getProperty("os.name").toLowerCase();
      //
      // Initialisations
      FileOutputStream out = null;
      ArrayList parsables = new ArrayList();
      ArrayList executables = new ArrayList();
      List packs = idata.selectedPacks;
      int npacks = packs.size();
      udata = UninstallData.getInstance();

      // Specific to the web installers
      if (idata.kind.equalsIgnoreCase("web") || idata.kind.equalsIgnoreCase("web-kunststoff")) {
        InputStream kin = getClass().getResourceAsStream("/res/WebInstallers.url");
        BufferedReader kreader = new BufferedReader(new InputStreamReader(kin));
        jarLocation = kreader.readLine();
      }

      // We unpack the selected packs
      for (int i = 0; i < npacks; i++) {
        // We get the pack stream
        int n = idata.allPacks.indexOf(packs.get(i));
        ObjectInputStream objIn = new ObjectInputStream(getPackAsStream(n));

        // We unpack the files
        int nfiles = objIn.readInt();
        listener.changeUnpack(0, nfiles, ((Pack) packs.get(i)).name);
        for (int j = 0; j < nfiles; j++) {
          // We read the header
          PackFile pf = (PackFile) objIn.readObject();
          if (null == pf.os || matchOS(currentOs, pf.os.toLowerCase())) {
            // We translate & build the path
            String path = translatePath(pf.targetPath);
            File pathFile = new File(path);
            String fname = pathFile.getName();
            int z = fname.length();
            File dest = pathFile.getParentFile();
            if (!dest.exists()) dest.mkdirs();

            // We add the path to the log,
            udata.addFile(path);

            listener.progressUnpack(j, path);

            // if this file exists and shouldnot override skip this file
            if (((pf.override == false) && (pathFile.exists()))) {
              objIn.skip(pf.length);
              continue;
            }

            // We copy the file
            out = new FileOutputStream(path);
            byte[] buffer = new byte[5120];
            long bytesCopied = 0;
            while (bytesCopied < pf.length) {
              int maxBytes =
                  (pf.length - bytesCopied < buffer.length
                      ? (int) (pf.length - bytesCopied)
                      : buffer.length);
              int bytesInBuffer = objIn.read(buffer, 0, maxBytes);
              if (bytesInBuffer == -1) throw new IOException("Unexpected end of stream");

              out.write(buffer, 0, bytesInBuffer);

              bytesCopied += bytesInBuffer;
            }
            // Cleanings
            out.close();

            // Empty dirs restoring
            String _n = pathFile.getName();
            if (_n.startsWith("izpack-keepme") && _n.endsWith(".tmp")) pathFile.delete();

          } else objIn.skip(pf.length);
        }

        // Load information about parsable files
        int numParsables = objIn.readInt();
        int k;
        for (k = 0; k < numParsables; k++) {
          ParsableFile pf = (ParsableFile) objIn.readObject();
          pf.path = translatePath(pf.path);
          parsables.add(pf);
        }

        // Load information about executable files
        int numExecutables = objIn.readInt();
        for (k = 0; k < numExecutables; k++) {
          ExecutableFile ef = (ExecutableFile) objIn.readObject();
          ef.path = translatePath(ef.path);
          if (null != ef.argList && !ef.argList.isEmpty()) {
            String arg = null;
            for (int j = 0; j < ef.argList.size(); j++) {
              arg = (String) ef.argList.get(j);
              arg = translatePath(arg);
              ef.argList.set(j, arg);
            }
          }
          executables.add(ef);
          if (ef.executionStage == ExecutableFile.UNINSTALL) {
            udata.addExecutable(ef);
          }
        }
        objIn.close();
      }

      // We use the scripts parser
      ScriptParser parser = new ScriptParser(parsables, vs);
      parser.parseFiles();

      // We use the file executor
      FileExecutor executor = new FileExecutor(executables);
      if (executor.executeFiles(ExecutableFile.POSTINSTALL) != 0)
        javax.swing.JOptionPane.showMessageDialog(
            null,
            "The installation was not completed.",
            "Installation warning",
            javax.swing.JOptionPane.WARNING_MESSAGE);

      // We put the uninstaller
      putUninstaller();

      // The end :-)
      listener.stopUnpack();
    } catch (Exception err) {
      listener.stopUnpack();
      listener.errorUnpack(err.toString());
    }
    instances.remove(instances.indexOf(this));
  }
    /**
     * Check whether the given compiler works.
     *
     * <p>This performs two steps:
     *
     * <ol>
     *   <li>check whether we can successfully call "compiler -help"
     *   <li>check whether we can successfully call "compiler -help arguments" (not all compilers
     *       return an error here)
     * </ol>
     *
     * On failure, the method CompileHandler#errorCompile is called with a descriptive error
     * message.
     *
     * @param compiler the compiler to use
     * @param arguments additional arguments to pass to the compiler
     * @return false on error
     */
    public CompileResult checkCompiler(String compiler, ArrayList arguments) {
      int retval = 0;
      FileExecutor executor = new FileExecutor();
      String[] output = new String[2];

      Debug.trace("checking whether \"" + compiler + " -help\" works");

      {
        String[] args = {compiler, "-help"};

        retval = executor.executeCommand(args, output);

        if (retval != 0) {
          CompileResult result =
              new CompileResult(
                  this.langpack.getString("CompilePanel.error.compilernotfound"),
                  args,
                  output[0],
                  output[1]);
          this.listener.handleCompileError(result);
          if (!result.isContinue()) return result;
        }
      }

      Debug.trace("checking whether \"" + compiler + " -help +arguments\" works");

      // used to collect the arguments for executing the compiler
      LinkedList args = new LinkedList(arguments);

      // add -help argument to prevent the compiler from doing anything
      args.add(0, "-help");

      // add compiler in front of arguments
      args.add(0, compiler);

      // construct classpath argument for compiler
      // - collect all classpaths
      StringBuffer classpath_sb = new StringBuffer();
      Iterator cp_it = this.classpath.iterator();
      while (cp_it.hasNext()) {
        String cp = (String) cp_it.next();
        if (classpath_sb.length() > 0) classpath_sb.append(File.pathSeparatorChar);
        classpath_sb.append(new File(cp).getAbsolutePath());
      }

      String classpath_str = classpath_sb.toString();

      // - add classpath argument to command line
      if (classpath_str.length() > 0) {
        args.add("-classpath");
        args.add(classpath_str);
      }

      String[] args_arr = (String[]) args.toArray(output);

      retval = executor.executeCommand(args_arr, output);

      if (retval != 0) {
        CompileResult result =
            new CompileResult(
                this.langpack.getString("CompilePanel.error.invalidarguments"),
                args_arr,
                output[0],
                output[1]);
        this.listener.handleCompileError(result);
        if (!result.isContinue()) return result;
      }

      return new CompileResult();
    }
    public CompileResult perform(String compiler, ArrayList arguments) {
      Debug.trace("starting job " + this.name);
      // we have some maximum command line length - need to count
      int cmdline_len = 0;

      // used to collect the arguments for executing the compiler
      LinkedList args = new LinkedList(arguments);

      {
        Iterator arg_it = args.iterator();
        while (arg_it.hasNext()) cmdline_len += ((String) arg_it.next()).length() + 1;
      }

      // add compiler in front of arguments
      args.add(0, compiler);
      cmdline_len += compiler.length() + 1;

      // construct classpath argument for compiler
      // - collect all classpaths
      StringBuffer classpath_sb = new StringBuffer();
      Iterator cp_it = this.classpath.iterator();
      while (cp_it.hasNext()) {
        String cp = (String) cp_it.next();
        if (classpath_sb.length() > 0) classpath_sb.append(File.pathSeparatorChar);
        classpath_sb.append(new File(cp).getAbsolutePath());
      }

      String classpath_str = classpath_sb.toString();

      // - add classpath argument to command line
      if (classpath_str.length() > 0) {
        args.add("-classpath");
        cmdline_len = cmdline_len + 11;
        args.add(classpath_str);
        cmdline_len += classpath_str.length() + 1;
      }

      // remember how many arguments we have which don't change for the
      // job
      int common_args_no = args.size();
      // remember how long the common command line is
      int common_args_len = cmdline_len;

      // used for execution
      FileExecutor executor = new FileExecutor();
      String output[] = new String[2];

      // used for displaying the progress bar
      String jobfiles = "";
      int fileno = 0;
      int last_fileno = 0;

      // now iterate over all files of this job
      Iterator file_it = this.files.iterator();

      while (file_it.hasNext()) {
        File f = (File) file_it.next();

        String fpath = f.getAbsolutePath();

        Debug.trace("processing " + fpath);

        // we add the file _first_ to the arguments to have a better
        // chance to get something done if the command line is almost
        // MAX_CMDLINE_SIZE or even above
        fileno++;
        jobfiles += f.getName() + " ";
        args.add(fpath);
        cmdline_len += fpath.length();

        // start compilation if maximum command line length reached
        if (cmdline_len >= MAX_CMDLINE_SIZE) {
          Debug.trace("compiling " + jobfiles);

          // display useful progress bar (avoid showing 100% while
          // still
          // compiling a lot)
          this.listener.progress(last_fileno, jobfiles);
          last_fileno = fileno;

          String[] full_cmdline = (String[]) args.toArray(output);

          int retval = executor.executeCommand(full_cmdline, output);

          // update progress bar: compilation of fileno files done
          this.listener.progress(fileno, jobfiles);

          if (retval != 0) {
            CompileResult result =
                new CompileResult(
                    this.langpack.getString("CompilePanel.error"),
                    full_cmdline,
                    output[0],
                    output[1]);
            this.listener.handleCompileError(result);
            if (!result.isContinue()) return result;
          } else {
            // verify that all files have been compiled successfully
            // I found that sometimes, no error code is returned
            // although
            // compilation failed.
            Iterator arg_it = args.listIterator(common_args_no);
            while (arg_it.hasNext()) {
              File java_file = new File((String) arg_it.next());

              String basename = java_file.getName();
              int dotpos = basename.lastIndexOf('.');
              basename = basename.substring(0, dotpos) + ".class";
              File class_file = new File(java_file.getParentFile(), basename);

              if (!class_file.exists()) {
                CompileResult result =
                    new CompileResult(
                        this.langpack.getString("CompilePanel.error.noclassfile")
                            + java_file.getAbsolutePath(),
                        full_cmdline,
                        output[0],
                        output[1]);
                this.listener.handleCompileError(result);
                if (!result.isContinue()) return result;
                // don't continue any further
                break;
              }
            }
          }

          // clean command line: remove files we just compiled
          for (int i = args.size() - 1; i >= common_args_no; i--) {
            args.removeLast();
          }

          cmdline_len = common_args_len;
          jobfiles = "";
        }
      }

      if (cmdline_len > common_args_len) {
        this.listener.progress(last_fileno, jobfiles);

        String[] full_cmdline = (String[]) args.toArray(output);

        int retval = executor.executeCommand(full_cmdline, output);

        this.listener.progress(fileno, jobfiles);

        if (retval != 0) {
          CompileResult result =
              new CompileResult(
                  this.langpack.getString("CompilePanel.error"),
                  full_cmdline,
                  output[0],
                  output[1]);
          this.listener.handleCompileError(result);
          if (!result.isContinue()) return result;
        }
      }

      Debug.trace("job " + this.name + " done (" + fileno + " files compiled)");

      return new CompileResult();
    }
Exemple #9
0
  /* (non-Javadoc)
   * @see com.izforge.izpack.installer.IUnpacker#run()
   */
  public void run() {
    addToInstances();
    try {
      //
      // Initialisations
      FileOutputStream out = null;
      ArrayList<ParsableFile> parsables = new ArrayList<ParsableFile>();
      ArrayList<ExecutableFile> executables = new ArrayList<ExecutableFile>();
      ArrayList<UpdateCheck> updatechecks = new ArrayList<UpdateCheck>();
      List packs = idata.selectedPacks;
      int npacks = packs.size();
      handler.startAction("Unpacking", npacks);
      udata = UninstallData.getInstance();
      // Custom action listener stuff --- load listeners ----
      List[] customActions = getCustomActions();
      // Custom action listener stuff --- beforePacks ----
      informListeners(customActions, InstallerListener.BEFORE_PACKS, idata, npacks, handler);
      packs = idata.selectedPacks;
      npacks = packs.size();

      // We unpack the selected packs
      for (int i = 0; i < npacks; i++) {
        // We get the pack stream
        // int n = idata.allPacks.indexOf(packs.get(i));
        Pack p = (Pack) packs.get(i);

        // evaluate condition
        if (p.hasCondition()) {
          if (rules != null) {
            if (!rules.isConditionTrue(p.getCondition())) {
              // skip pack, condition is not fullfilled.
              continue;
            }
          } else {
            // TODO: skip pack, because condition can not be checked
          }
        }

        // Custom action listener stuff --- beforePack ----
        informListeners(
            customActions, InstallerListener.BEFORE_PACK, packs.get(i), npacks, handler);
        ObjectInputStream objIn = new ObjectInputStream(getPackAsStream(p.id, p.uninstall));

        // We unpack the files
        int nfiles = objIn.readInt();

        // We get the internationalized name of the pack
        final Pack pack = ((Pack) packs.get(i));
        String stepname = pack.name; // the message to be passed to the
        // installpanel
        if (langpack != null && !(pack.id == null || "".equals(pack.id))) {

          final String name = langpack.getString(pack.id);
          if (name != null && !"".equals(name)) {
            stepname = name;
          }
        }
        handler.nextStep(stepname, i + 1, nfiles);
        for (int j = 0; j < nfiles; j++) {
          // We read the header
          PackFile pf = (PackFile) objIn.readObject();
          // TODO: reaction if condition can not be checked
          if (pf.hasCondition() && (rules != null)) {
            if (!rules.isConditionTrue(pf.getCondition())) {
              if (!pf.isBackReference()) {
                // skip, condition is not fulfilled
                objIn.skip(pf.length());
              }
              continue;
            }
          }
          if (OsConstraint.oneMatchesCurrentSystem(pf.osConstraints())) {
            // We translate & build the path
            String path = IoHelper.translatePath(pf.getTargetPath(), vs);
            File pathFile = new File(path);
            File dest = pathFile;
            if (!pf.isDirectory()) {
              dest = pathFile.getParentFile();
            }

            if (!dest.exists()) {
              // If there are custom actions which would be called
              // at
              // creating a directory, create it recursively.
              List fileListeners = customActions[customActions.length - 1];
              if (fileListeners != null && fileListeners.size() > 0) {
                mkDirsWithEnhancement(dest, pf, customActions);
              } else
              // Create it in on step.
              {
                if (!dest.mkdirs()) {
                  handler.emitError(
                      "Error creating directories",
                      "Could not create directory\n" + dest.getPath());
                  handler.stopAction();
                  this.result = false;
                  return;
                }
              }
            }

            if (pf.isDirectory()) {
              continue;
            }

            // Custom action listener stuff --- beforeFile ----
            informListeners(customActions, InstallerListener.BEFORE_FILE, pathFile, pf, null);
            // We add the path to the log,
            udata.addFile(path, pack.uninstall);

            handler.progress(j, path);

            // if this file exists and should not be overwritten,
            // check
            // what to do
            if ((pathFile.exists()) && (pf.override() != PackFile.OVERRIDE_TRUE)) {
              boolean overwritefile = false;

              // don't overwrite file if the user said so
              if (pf.override() != PackFile.OVERRIDE_FALSE) {
                if (pf.override() == PackFile.OVERRIDE_TRUE) {
                  overwritefile = true;
                } else if (pf.override() == PackFile.OVERRIDE_UPDATE) {
                  // check mtime of involved files
                  // (this is not 100% perfect, because the
                  // already existing file might
                  // still be modified but the new installed
                  // is just a bit newer; we would
                  // need the creation time of the existing
                  // file or record with which mtime
                  // it was installed...)
                  overwritefile = (pathFile.lastModified() < pf.lastModified());
                } else {
                  int def_choice = -1;

                  if (pf.override() == PackFile.OVERRIDE_ASK_FALSE) {
                    def_choice = AbstractUIHandler.ANSWER_NO;
                  }
                  if (pf.override() == PackFile.OVERRIDE_ASK_TRUE) {
                    def_choice = AbstractUIHandler.ANSWER_YES;
                  }

                  int answer =
                      handler.askQuestion(
                          idata.langpack.getString("InstallPanel.overwrite.title")
                              + " - "
                              + pathFile.getName(),
                          idata.langpack.getString("InstallPanel.overwrite.question")
                              + pathFile.getAbsolutePath(),
                          AbstractUIHandler.CHOICES_YES_NO,
                          def_choice);

                  overwritefile = (answer == AbstractUIHandler.ANSWER_YES);
                }
              }

              if (!overwritefile) {
                if (!pf.isBackReference() && !((Pack) packs.get(i)).loose) {
                  objIn.skip(pf.length());
                }
                continue;
              }
            }

            // We copy the file
            InputStream pis = objIn;
            if (pf.isBackReference()) {
              InputStream is = getPackAsStream(pf.previousPackId, pack.uninstall);
              pis = new ObjectInputStream(is);
              // must wrap for blockdata use by objectstream
              // (otherwise strange result)
              // skip on underlaying stream (for some reason not
              // possible on ObjectStream)
              is.skip(pf.offsetInPreviousPack - 4);
              // but the stream header is now already read (== 4
              // bytes)
            } else if (((Pack) packs.get(i)).loose) {
              /* Old way of doing the job by using the (absolute) sourcepath.
               * Since this is very likely to fail and does not confirm to the documentation,
               * prefer using relative path's
              pis = new FileInputStream(pf.sourcePath);
               */

              File resolvedFile = new File(getAbsolutInstallSource(), pf.getRelativeSourcePath());
              if (!resolvedFile.exists()) {
                // try alternative destination - the current working directory
                // user.dir is likely (depends on launcher type) the current directory of the
                // executable or jar-file...
                final File userDir = new File(System.getProperty("user.dir"));
                resolvedFile = new File(userDir, pf.getRelativeSourcePath());
              }
              if (resolvedFile.exists()) {
                pis = new FileInputStream(resolvedFile);
                // may have a different length & last modified than we had at compiletime, therefore
                // we have to build a new PackFile for the copy process...
                pf =
                    new PackFile(
                        resolvedFile.getParentFile(),
                        resolvedFile,
                        pf.getTargetPath(),
                        pf.osConstraints(),
                        pf.override(),
                        pf.getAdditionals());
              } else {
                // file not found
                // issue a warning (logging api pending)
                // since this file was loosely bundled, we continue with the installation.
                System.out.println(
                    "Could not find loosely bundled file: " + pf.getRelativeSourcePath());
                out.close();
                continue;
              }
            }

            if (pf.isPack200Jar()) {
              int key = objIn.readInt();
              InputStream pack200Input =
                  Unpacker.class.getResourceAsStream("/packs/pack200-" + key);
              Pack200.Unpacker unpacker = getPack200Unpacker();
              java.util.jar.JarOutputStream jarOut =
                  new java.util.jar.JarOutputStream(new FileOutputStream(pathFile));
              unpacker.unpack(pack200Input, jarOut);
              jarOut.close();
            } else {
              out = new FileOutputStream(pathFile);
              byte[] buffer = new byte[5120];
              long bytesCopied = 0;
              while (bytesCopied < pf.length()) {
                if (performInterrupted()) { // Interrupt was initiated; perform it.
                  out.close();
                  if (pis != objIn) {
                    pis.close();
                  }
                  return;
                }
                int maxBytes = (int) Math.min(pf.length() - bytesCopied, buffer.length);
                int bytesInBuffer = pis.read(buffer, 0, maxBytes);
                if (bytesInBuffer == -1) {
                  throw new IOException("Unexpected end of stream (installer corrupted?)");
                }

                out.write(buffer, 0, bytesInBuffer);

                bytesCopied += bytesInBuffer;
              }
              out.close();
            }

            if (pis != objIn) {
              pis.close();
            }

            // Set file modification time if specified
            if (pf.lastModified() >= 0) {
              pathFile.setLastModified(pf.lastModified());
            }
            // Custom action listener stuff --- afterFile ----
            informListeners(customActions, InstallerListener.AFTER_FILE, pathFile, pf, null);

          } else {
            if (!pf.isBackReference()) {
              objIn.skip(pf.length());
            }
          }
        }

        // Load information about parsable files
        int numParsables = objIn.readInt();
        for (int k = 0; k < numParsables; k++) {
          ParsableFile pf = (ParsableFile) objIn.readObject();
          if (pf.hasCondition() && (rules != null)) {
            if (!rules.isConditionTrue(pf.getCondition())) {
              // skip, condition is not fulfilled
              continue;
            }
          }
          pf.path = IoHelper.translatePath(pf.path, vs);
          parsables.add(pf);
        }

        // Load information about executable files
        int numExecutables = objIn.readInt();
        for (int k = 0; k < numExecutables; k++) {
          ExecutableFile ef = (ExecutableFile) objIn.readObject();
          if (ef.hasCondition() && (rules != null)) {
            if (!rules.isConditionTrue(ef.getCondition())) {
              // skip, condition is false
              continue;
            }
          }
          ef.path = IoHelper.translatePath(ef.path, vs);
          if (null != ef.argList && !ef.argList.isEmpty()) {
            String arg = null;
            for (int j = 0; j < ef.argList.size(); j++) {
              arg = ef.argList.get(j);
              arg = IoHelper.translatePath(arg, vs);
              ef.argList.set(j, arg);
            }
          }
          executables.add(ef);
          if (ef.executionStage == ExecutableFile.UNINSTALL) {
            udata.addExecutable(ef);
          }
        }
        // Custom action listener stuff --- uninstall data ----
        handleAdditionalUninstallData(udata, customActions);

        // Load information about updatechecks
        int numUpdateChecks = objIn.readInt();

        for (int k = 0; k < numUpdateChecks; k++) {
          UpdateCheck uc = (UpdateCheck) objIn.readObject();

          updatechecks.add(uc);
        }

        objIn.close();

        if (performInterrupted()) { // Interrupt was initiated; perform it.
          return;
        }

        // Custom action listener stuff --- afterPack ----
        informListeners(customActions, InstallerListener.AFTER_PACK, packs.get(i), i, handler);
      }

      // We use the scripts parser
      ScriptParser parser = new ScriptParser(parsables, vs);
      parser.parseFiles();
      if (performInterrupted()) { // Interrupt was initiated; perform it.
        return;
      }

      // We use the file executor
      FileExecutor executor = new FileExecutor(executables);
      if (executor.executeFiles(ExecutableFile.POSTINSTALL, handler) != 0) {
        handler.emitError("File execution failed", "The installation was not completed");
        this.result = false;
      }

      if (performInterrupted()) { // Interrupt was initiated; perform it.
        return;
      }

      // We put the uninstaller (it's not yet complete...)
      putUninstaller();

      // update checks _after_ uninstaller was put, so we don't delete it
      performUpdateChecks(updatechecks);

      if (performInterrupted()) { // Interrupt was initiated; perform it.
        return;
      }

      // Custom action listener stuff --- afterPacks ----
      informListeners(customActions, InstallerListener.AFTER_PACKS, idata, handler, null);
      if (performInterrupted()) { // Interrupt was initiated; perform it.
        return;
      }

      // write installation information
      writeInstallationInformation();

      // The end :-)
      handler.stopAction();
    } catch (Exception err) {
      // TODO: finer grained error handling with useful error messages
      handler.stopAction();
      if ("Installation cancelled".equals(err.getMessage())) {
        handler.emitNotification("Installation cancelled");
      } else {
        handler.emitError("An error occured", err.getMessage());
        err.printStackTrace();
      }
      this.result = false;
      Housekeeper.getInstance().shutDown(4);
    } finally {
      removeFromInstances();
    }
  }