ExternalLauncher.java :  » Mail-Clients » pooka » net » suberic » pooka » Java Open Source

Java Open Source » Mail Clients » pooka 
pooka » net » suberic » pooka » ExternalLauncher.java
package net.suberic.pooka;

import javax.activation.*;
import java.io.*;
import java.util.StringTokenizer;

/**
 * This class is a generic class which will allow an external program
 * to start up and access a file.
 */
public class ExternalLauncher implements CommandObject, Runnable {

  private String verb;
  private DataHandler dh;

  // for, err, showing progress in downloading the temporary file.
  private net.suberic.util.swing.ProgressDialog mDialog;
  
  private File mTmpFile = null;

  public ExternalLauncher() {
  };
  
  /**
   * This sets the CommandContext to the given command and DataHandler.
   * Note that for this implementation, the verb is expected to bet the
   * external command which is run, with %s representing the name of
   * the temporary file.
   *
   * As specified in javax.activation.CommandObject.
   */
  public void setCommandContext(java.lang.String newVerb,
        DataHandler newDh)
    throws java.io.IOException {
    verb = newVerb;
    dh = newDh;
  }

  /**
   * Sets a ProgressDialog for watching the downloading of the temporary
   * file.
   */
  public void setProgressDialog(net.suberic.util.swing.ProgressDialog pDialog) {
    mDialog = pDialog;
  }

  /**
   * Gets the ProgressDialog for watching the downloading of the temporary
   * file.
   */
  public net.suberic.util.swing.ProgressDialog getProgressDialog() {
    return mDialog;
  }

  /**
   * This starts the run() method in a separate Thread.  It is implemented
   * this way so as to present the same interface as a CommandObject which
   * extends Window.
   */
  public void show() {
    Thread t = new Thread(this, "External Viewer");
    t.start();
  }
  
  /**
   * This is the main method for the ExternalLaucher.  It creates a 
   * temporary file from the DataHandler and then uses the verb command,
   * along with the wrappers specified by ExternalLauncher.fileHandler
   * and ExternalLauncher.cmdWrapper, to access the file itself.
   */
  public void run() {
    try {
      String extension = ".tmp";
      String filename = dh.getName();
      if (filename == null)
  filename = "unavailable";
      int dotLoc = filename.lastIndexOf('.');
      if (dotLoc > 0) {
  extension = filename.substring(dotLoc);
      }
      mTmpFile = File.createTempFile("pooka_", extension);

      boolean cancelled = false;

      if (mDialog == null) {
  FileOutputStream fos = new FileOutputStream(mTmpFile);
  dh.writeTo(fos);
  fos.close();
      } else {
  mDialog.show();
  InputStream decodedIS = dh.getInputStream();
  BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(mTmpFile));
  int b=0;
  byte[] buf = new byte[32768];
  
  b = decodedIS.read(buf);
  while (b != -1 && ! cancelled) {
    outStream.write(buf, 0, b);
    mDialog.setValue(mDialog.getValue() + b);
    if (mDialog.isCancelled())
      cancelled = true;

    b = decodedIS.read(buf);
  }
  
  outStream.close();
      }
      
      if (! cancelled) {
  if (mDialog != null)
    mDialog.dispose();
  
  String fileHandler = Pooka.getProperty("ExternalLauncher.fileHandler." + java.io.File.separator, null);
  String wrapper = Pooka.getProperty("ExternalLauncher.cmdWrapper." + java.io.File.separator, null);
  String fileName = mTmpFile.getAbsolutePath();
  
  String parsedVerb;
  String[] cmdArray;
  
  String origParsedCommand = substituteString(verb, "%s", fileName);
  
  if (fileHandler != null && wrapper != null) { 
    
    parsedVerb = substituteString(fileHandler, "%v", verb);
    parsedVerb = substituteString(parsedVerb, "%s", fileName);
    
    StringTokenizer tok = new StringTokenizer(wrapper);
    cmdArray = new String[tok.countTokens()];
    for (int i = 0; tok.hasMoreTokens(); i++) {
      String currentString = tok.nextToken();
      if (currentString.equals("%v"))
        cmdArray[i] = parsedVerb;
      else
        cmdArray[i]=currentString;
    } 
  } else {
    parsedVerb = substituteString(verb, "%s", fileName);
    
    cmdArray = parseCommandString(parsedVerb);
    
    mTmpFile.deleteOnExit();
  }
  
  try {
    if (Pooka.isDebug()) {
      System.out.println("running external command " + parsedVerb);
    }
    
    Process p = Runtime.getRuntime().exec(cmdArray);
    
    long startTime = System.currentTimeMillis();
    
    try {
      p.waitFor();
    } catch (InterruptedException ie) {
    }
    
    int exitValue = p.exitValue();
    
    if (Pooka.isDebug()) {
      System.out.println("finished external command " + parsedVerb);
    }
    
    if (exitValue != 0) {
      long externalTimeoutMillis = 5000;
      try {
        externalTimeoutMillis = Long.parseLong(Pooka.getProperty("ExternalLauncher.externalTimeoutMillis", "5000"));
      } catch (NumberFormatException nfe) {
        // just use the default.
      }
      if (System.currentTimeMillis() - startTime < externalTimeoutMillis) {
        if (Pooka.isDebug())
    System.out.println("external command " + parsedVerb + ":  exitValue is " + exitValue + " and timeout < externalTimeoutMillis; showing error.");
        
        showError(origParsedCommand, p);
      }
    }
  } catch (java.io.IOException processIoe) {
    Pooka.getUIFactory().showError("Error running process " + processIoe.getMessage());
    processIoe.printStackTrace();
  }
      } // if ! cancelled
    } catch (java.io.IOException ioe) {
      Pooka.getUIFactory().showError("Error opening temp file " + ioe.getMessage());
      ioe.printStackTrace();
    }
  }
  
  /**
   * Shows an error.
   */
  public void showError(String command, Process p) {

    // build up the error message.
    try {
      StringWriter errorWriter = new StringWriter();
      BufferedWriter bw = new BufferedWriter(errorWriter);
      bw.write(Pooka.getProperty("ExternalLauncher.error.failedToRun", "Failed executing command:"));
      bw.newLine();
      bw.write(command);
      bw.newLine();
      bw.newLine();
      bw.write(Pooka.getProperty("ExternalLauncher.error.output", "Output:"));
      bw.newLine();
    
      try {
  InputStream errorStream = p.getErrorStream();
  BufferedReader br = new BufferedReader(new InputStreamReader(errorStream));
  for (String nextLine = br.readLine(); nextLine != null; nextLine = br.readLine()) {
    bw.write(nextLine);
    bw.newLine();
  }
      } catch (IOException ioe) {
  bw.write("Error not available");
  bw.newLine();
      }
      bw.flush();
      bw.close();
    
      String errorMessage = errorWriter.toString();
      Pooka.getUIFactory().showError(errorMessage);
    } catch (IOException ioe) {
      // shouldn't happen, but...
      Pooka.getUIFactory().showError(Pooka.getProperty("ExternalLauncher.error.failedToRun", "Failed executing command:"));
    }
  }
  
  /**
   * This method subsitutes all occurances of key with value in String
   * original.
   */
  public static String substituteString(String original, String key, String value) {
    // you know, i'm already doing this for the replyIntro; maybe i
    // should generalize these both a bit...
    
    StringBuffer modifiedString = new StringBuffer(original);
    int current = original.lastIndexOf(key, original.length());
    while (current != -1) {
      modifiedString.replace(current, current + key.length(), value);
      current = original.substring(0, current).lastIndexOf(key, current);
    }
    
    return modifiedString.toString();
  }
  
  /**
   * This parses a command string into a command array. 
   */
  public String[] parseCommandString(String cmdString) {
    StringTokenizer tok = new StringTokenizer(cmdString);
    String[] cmdArray = new String[tok.countTokens()];
    for (int i = 0; tok.hasMoreTokens(); i++) {
      String currentString = tok.nextToken();
      cmdArray[i]=currentString;
    }

    return cmdArray;
  }

  public void cancelSave() {
    try {
      mTmpFile.delete();
    } catch (Exception e) {}
    if (mDialog != null)
      mDialog.dispose();
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.