code: 
  package com.dtmilano.android.viewclient;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.URLDecoder;
  import java.util.ArrayList;
  import java.util.StringTokenizer;
  import java.util.jar.JarEntry;
  import java.util.jar.JarFile;
  import java.util.zip.ZipException;
  
  public class ViewClient {
  
      private static final boolean DEBUG = false;
  
      private static final String PROGNAME = "java -jar androidviewclient.jar";
  
      private static final String MONKEYRUNNER = "monkeyrunner";
  
      private static final int DELAY = 500;
  
      /**
       * The <em>tools</em> directory in the jar.
       */
      private static final String TOOLS = "tools";
  
      private enum Command {
          DUMP, CULEBRA
      };
  
      private volatile boolean mProcessFinished = false;
  
      /**
       * The destination file as command is extracted from jar.
       */
      private File mDest = null;
  
      private boolean mIsDestCreated = false;
  
      private boolean mKeep = false;
  
      /**
       * Command arguments.
       */
      private String[] mArgs = null;
  
      private JarFile mJar;
  
      /**
       * @author diego
       */
      private abstract class StreamReaderThread extends Thread {
          private InputStream mIs;
          private OutputStream mOs;
  
          /**
           * @param is
           * @param os
           */
          public StreamReaderThread(InputStream is, OutputStream os) {
              this.mIs = is;
              this.mOs = os;
          }
  
          /*
           * (non-Javadoc)
           * @see java.lang.Thread#run()
           */
          @Override
          public void run() {
              do {
                  try {
                      while (mIs.available() > 0) {
                          mOs.write(mIs.read());
                      }
                  } catch (IOException e) {
                      e.printStackTrace();
                  } finally {
                      try {
                          Thread.sleep(DELAY);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              } while (!mProcessFinished);
          }
      }
  
      /**
       * @author diego
       */
      private class OutputStreamReaderThread extends StreamReaderThread {
  
          /**
           * @param is
           * @param os
           */
          public OutputStreamReaderThread(InputStream is) {
              super(is, System.out);
          }
  
      }
  
      /**
       * @author diego
       */
      private class ErrorStreamReaderThread extends StreamReaderThread {
  
          /**
           * @param is
           * @param os
           */
          public ErrorStreamReaderThread(InputStream is) {
              super(is, System.err);
          }
  
      }
  
      /**
       * <em>ViewClient</em>
       * 
       * @throws IOException
       */
      public ViewClient(Command cmd, String[] args) throws IOException {
          if (args != null && args.length > 0) {
              mArgs = args;
          }
          final File file = new File(URLDecoder.decode(ViewClient.class.getProtectionDomain()
                  .getCodeSource()
                  .getLocation().getPath(), "UTF-8"));
          if (DEBUG) {
              System.err.println("jar=" + file.getCanonicalPath() + "    exists? " + file.exists());
          }
  
          try {
              mJar = new JarFile(file);
          } catch (ZipException e) {
              error("Tools should be started using the jar file.", e);
              usage();
          }
  
          final String entry = TOOLS + "/" + cmd.name().toLowerCase();
          final JarEntry jarEntry = mJar.getJarEntry(entry);
          if (jarEntry != null) {
              final InputStream is = mJar.getInputStream(jarEntry);
              // We cannot use /tmp or similar because sometimes it's mounted
              // noexec
              mDest = new File(System.getProperty("user.home") + File.separator
                      + cmd.name().toLowerCase());
              final FileOutputStream fos = new java.io.FileOutputStream(mDest);
              while (is.available() > 0) {
                  fos.write(is.read());
              }
              fos.close();
              is.close();
              mDest.setExecutable(true);
              mIsDestCreated = true;
              if (!mKeep) {
                  mDest.deleteOnExit();
              }
          }
          else {
              fatal("Cannot extract " + entry + " from jar");
          }
  
      }
  
      /**
       * Executes the command in a separate process.
       * 
       * @return the exit value of the process
       * @throws IOException
       * @throws InterruptedException
       */
      public int execute() throws IOException, InterruptedException {
          if (!mIsDestCreated) {
              throw new IllegalStateException("Destination was not extracted successfully");
          }
          final Runtime runtime = Runtime.getRuntime();
          final ArrayList<String> cmdList = new ArrayList<String>();
          final String monkeyrunner = locateMonkeyRunner();
          if (monkeyrunner != null) {
              cmdList.add(monkeyrunner);
              cmdList.add("-plugin");
              cmdList.add(mJar.getName());
          }
          else {
              if (isWindows()) {
                  fatal(String.format(
                          "%s was not found and %s does not support shebang in scripts. Aborting.",
                          MONKEYRUNNER, System.getProperty("os.name")));
              }
          }
          cmdList.add(mDest.getAbsolutePath());
          if (mArgs != null) {
              for (String arg : mArgs) {
                  cmdList.add(arg);
              }
          }
          if (DEBUG) {
              System.err.println("executing: " + cmdList);
          }
          final Process process = runtime.exec(cmdList.toArray(new String[] {}));
          if (process != null) {
              mProcessFinished = false;
              new OutputStreamReaderThread(process.getInputStream()).start();
              new ErrorStreamReaderThread(process.getErrorStream()).start();
              process.waitFor();
              try {
                  Thread.sleep(DELAY + 500);
              } catch (InterruptedException e) {
                  // do nothing
              }
              mProcessFinished = true;
              if (DEBUG) {
                  System.err.println("process=" + process + "    " + process.exitValue());
              }
              return process.exitValue();
          }
  
          throw new RuntimeException("Couldn't create process");
      }
  
      /**
       * @return
       */
      private static boolean isWindows() {
          final String os = System.getProperty("os.name");
          return os.toUpperCase().contains("WINDOWS");
      }
  
      /**
       * Locates <code>monkeyrunner</code> executable in path.
       * 
       * @return the absolute path of <code>monkeyrunner</code> or
       *         <code>null</code> if not found
       */
      private static String locateMonkeyRunner() {
          final StringTokenizer tokenizer = new StringTokenizer(System.getenv("PATH"),
                  File.pathSeparator);
          while (tokenizer.hasMoreTokens()) {
              final String dir = tokenizer.nextToken();
              File monkeyrunner = new File(dir + File.separator + MONKEYRUNNER + (isWindows() ? ".bat" : ""));
              if (DEBUG) {
                  System.err.println("searching for " + monkeyrunner + "    exist? " + monkeyrunner.exists());
              }
              if (monkeyrunner.exists()) {
                  return monkeyrunner.getAbsolutePath();
              }
          }
  
          return null;
      }
  
      /**
       * Prints usage and exits.
       */
      private static void usage() {
          System.err.println(String.format("usage: %s COMMAND [OPTION]... [ARGS]...", PROGNAME));
          System.err.println("");
          System.err.println("Commands:");
          for (Command cmd : Command.values()) {
              System.err.println("  " + cmd.name().toLowerCase());
          }
          System.exit(1);
      }
  
      /**
       * Obtains the extra arguments in the command line (following command, which
       * is assumed to be in args[0]).
       * 
       * @param args the arguments
       * @return The string array obtained from the arguments
       */
      private static String[] obtainExtraArgs(String[] args) {
          if (args.length > 1) {
              final String[] extras = new String[args.length - 1];
              for (int i = 1; i < args.length; i++) {
                  extras[i - 1] = args[i];
              }
              return extras;
          }
          return null;
      }
  
      private static void error(String msg) {
          System.err.print("ERROR: ");
          System.err.println(msg);
      }
  
      private void error(String msg, Exception e) {
          error(msg);
          e.printStackTrace(System.err);
      }
  
      private static void fatal(String msg) {
          error(msg);
          System.exit(1);
      }
  
      public static void main(String[] args) throws IOException, InterruptedException {
          if (args.length < 1) {
              usage();
          }
  
          final String cmdStr = args[0];
          final String[] extras = obtainExtraArgs(args);
  
          if (DEBUG) {
              System.err.println("main: cmd=" + cmdStr + "    extras=" + extras);
          }
  
          try {
              System.exit(new ViewClient(Command.valueOf(cmdStr.toUpperCase()), extras).execute());
          } catch (IllegalArgumentException e) {
              error("Unknown command: '" + cmdStr + "'");
              usage();
          }
  
      }
  }
  