@Override
  public void doWork() throws OperatorException {
    String command = getParameterAsString(PARAMETER_COMMAND);
    final boolean logOut = !stdout.isConnected() && getParameterAsBoolean(PARAMETER_LOG_STDOUT);
    final boolean logErr = !stderr.isConnected() && getParameterAsBoolean(PARAMETER_LOG_STDERR);
    final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>(3));
    try {
      final Process process = Runtime.getRuntime().exec(command);
      final ByteArrayOutputStream stdOutBuf = new ByteArrayOutputStream();
      final ByteArrayOutputStream stdErrBuf = new ByteArrayOutputStream();

      if (stdin.isConnected()) {
        final FileObject input = stdin.getData(FileObject.class);
        new Thread(getName() + "-stdin") {
          public void run() {
            try {
              Tools.copyStreamSynchronously(input.openStream(), process.getOutputStream(), true);
            } catch (Exception e) {
              exceptions.add(e);
            }
          };
        }.start();
      }

      new Thread(getName() + "-stdout") {
        public void run() {
          try {
            if (logOut) {
              logOutput("stdout:", process.getInputStream());
            } else {
              Tools.copyStreamSynchronously(process.getInputStream(), stdOutBuf, true);
            }
          } catch (Exception e) {
            exceptions.add(e);
          }
        }
      }.start();
      new Thread(getName() + "-stderr") {
        public void run() {
          try {
            if (logErr) {
              logOutput("stderr:", process.getErrorStream());
            } else {
              Tools.copyStreamSynchronously(process.getErrorStream(), stdErrBuf, true);
            }
          } catch (Exception e) {
            exceptions.add(e);
          }
        }
      }.start();

      Tools.waitForProcess(this, process, command);
      getLogger().info("Program exited succesfully.");

      if (stdout.isConnected()) {
        stdout.deliver(new BufferedFileObject(stdOutBuf.toByteArray()));
      }
      if (stderr.isConnected()) {
        stderr.deliver(new BufferedFileObject(stdErrBuf.toByteArray()));
      }
    } catch (IOException e) {
      throw new UserError(this, e, 310, new Object[] {command, e.getMessage()});
    } finally {
      getLogger()
          .log(
              Level.WARNING,
              "com.rapidminer.operator.CommandLineOperator.errors_occurred",
              new Object[] {exceptions.size(), command});
      for (Throwable t : exceptions) {
        getLogger().log(Level.WARNING, t.toString(), t);
      }
      if (!exceptions.isEmpty()) {
        Throwable t = exceptions.get(0);
        if (t instanceof OperatorException) {
          throw (OperatorException) t;
        } else {
          throw new UserError(this, t, 310, new Object[] {command, t.getMessage()});
        }
      }
    }

    dummyPorts.passDataThrough();
  }