Package org.rascalmpl.library.util

Source Code of org.rascalmpl.library.util.ShellExec

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   * Mark Hills - Mark.Hills@cwi.nl (CWI)
*******************************************************************************/
package org.rascalmpl.library.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.imp.pdb.facts.IInteger;
import org.eclipse.imp.pdb.facts.IList;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.ISourceLocation;
import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory;

public class ShellExec {
 
  private static HashMap<IInteger, Process> runningProcesses = new HashMap<IInteger, Process>();
  private static HashMap<IInteger, InputStreamReader> processInputStreams = new HashMap<IInteger, InputStreamReader>();
  private static HashMap<IInteger, InputStreamReader> processErrorStreams = new HashMap<IInteger, InputStreamReader>();
  private static HashMap<IInteger, OutputStreamWriter> processOutputStreams = new HashMap<IInteger, OutputStreamWriter>();
  private static IInteger processCounter = null;
 
  private final IValueFactory vf;

  public ShellExec(IValueFactory vf) {
    this.vf = vf;
  }

  public IInteger createProcess(IString processCommand) {
    return createProcessInternal(processCommand,null,null,null);
  }

  public IInteger createProcess(IString processCommand, ISourceLocation workingDir) {
    return createProcessInternal(processCommand,null,null,workingDir);
  }

  public IInteger createProcess(IString processCommand, IList arguments) {
    return createProcessInternal(processCommand,arguments,null,null);
  }

  public IInteger createProcess(IString processCommand, IList arguments, ISourceLocation workingDir) {
    return createProcessInternal(processCommand,arguments,null,workingDir);
  }

  public IInteger createProcess(IString processCommand, IMap envVars) {
    return createProcessInternal(processCommand,null,envVars,null);
  }

  public IInteger createProcess(IString processCommand, IMap envVars, ISourceLocation workingDir) {
    return createProcessInternal(processCommand,null,envVars,workingDir);
  }

  public IInteger createProcess(IString processCommand, IList arguments, IMap envVars) {
    return createProcessInternal(processCommand,arguments,envVars,null);
  }

  public IInteger createProcess(IString processCommand, IList arguments, IMap envVars, ISourceLocation workingDir) {
    return createProcessInternal(processCommand,arguments,envVars,workingDir);
  }

  private synchronized IInteger createProcessInternal(IString processCommand, IList arguments, IMap envVars, ISourceLocation workingDir) {
    try {
      // Build the arg array using the command and the command arguments passed in the arguments list
      List<String> args = new ArrayList<String>();
      args.add(processCommand.getValue());
      for (int n = 0; n < arguments.length(); ++n) {
        if (arguments.get(n) instanceof IString)
          args.add(((IString)arguments.get(n)).getValue());
        else
          throw RuntimeExceptionFactory.illegalArgument(arguments.get(n),null, null);
      }
      ProcessBuilder pb = new ProcessBuilder(args);
     
      // Built the environment var map using the envVars map
      Map<String,String> vars = new HashMap<String,String>();
      if (envVars != null && envVars.size() > 0) {
        for (IValue varKey : envVars) {
          if (varKey instanceof IString) {
            IString strKey = (IString) varKey;
            IValue varVal = envVars.get(varKey);
            if (varVal instanceof IString) {
              IString strVal = (IString) varVal;
              vars.put(strKey.getValue(),  strVal.getValue());
            } else {
              throw RuntimeExceptionFactory.illegalArgument(varVal,null, null);
            }
          } else {
            throw RuntimeExceptionFactory.illegalArgument(varKey,null, null);
          }
        }
      }
      Map<String,String> currentEnv = pb.environment();
      try {
        for (String strKey : vars.keySet()) {
          currentEnv.put(strKey, vars.get(strKey));
        }
      } catch (UnsupportedOperationException uoe) {
        throw RuntimeExceptionFactory.permissionDenied(vf.string("Modifying environment variables is not allowed on this machine."), null, null);
      } catch (IllegalArgumentException iae) {
        throw RuntimeExceptionFactory.permissionDenied(vf.string("Modifying environment variables is not allowed on this machine."), null, null);
      }
     
      File cwd = null;
      if (workingDir != null) {
        cwd = new File(workingDir.getURI().getPath());
        pb.directory(cwd);
      }
     
      Process newProcess = pb.start();
      if (processCounter == null) processCounter = vf.integer(0);
      processCounter = processCounter.add(vf.integer(1));
      runningProcesses.put(processCounter, newProcess);
      return processCounter;
    } catch (IOException e) {
      throw RuntimeExceptionFactory.javaException(e, null, null);
    }
  }

  public synchronized void killProcess(IInteger processId) {
    if (!runningProcesses.containsKey(processId))
      throw RuntimeExceptionFactory.illegalArgument(processId, null, null);

    if (processInputStreams.containsKey(processId)) {
      try {
        processInputStreams.get(processId).close();
      } catch (IOException e) {
        // eat it, we are just throwing it away anyway
      } finally {
        processInputStreams.remove(processId);
      }
    }
   
    if (processErrorStreams.containsKey(processId)) {
      try {
        processErrorStreams.get(processId).close();
      } catch (IOException e) {
        // eat it, we are just throwing it away anyway
      } finally {
        processErrorStreams.remove(processId);
      }
    }

    if (processOutputStreams.containsKey(processId)) {
      try {
        processOutputStreams.get(processId).close();
      } catch (IOException e) {
        // eat it, we are just throwing it away anyway
      } finally {
        processOutputStreams.remove(processId);
      }
    }

    Process runningProcess = runningProcesses.get(processId);
    runningProcess.destroy();
    runningProcesses.remove(processId);
    return;
  }
 
  public synchronized IString readFrom(IInteger processId) {
    if (!runningProcesses.containsKey(processId))
      throw RuntimeExceptionFactory.illegalArgument(processId, null, null);
    try {
      Process runningProcess = runningProcesses.get(processId);
      InputStreamReader isr = null;
      if (processInputStreams.containsKey(processId)) {
        isr = processInputStreams.get(processId);
      } else {
        isr = new InputStreamReader(runningProcess.getInputStream());
        processInputStreams.put(processId, isr);
      }
      StringBuffer line = new StringBuffer();
      while (isr.ready()) {
        line.append((char)isr.read());
      }
      return vf.string(line.toString());
    } catch (IOException e) {
      throw RuntimeExceptionFactory.javaException(e, null, null);
    }
  }
 
  public synchronized IString readFromErr(IInteger processId) {
    if (!runningProcesses.containsKey(processId))
      throw RuntimeExceptionFactory.illegalArgument(processId, null, null);
    try {
      Process runningProcess = runningProcesses.get(processId);
      InputStreamReader isr = null;
      if (processErrorStreams.containsKey(processId)) {
        isr = processErrorStreams.get(processId);
      } else {
        isr = new InputStreamReader(runningProcess.getErrorStream());
        processErrorStreams.put(processId, isr);
      }
      StringBuffer line = new StringBuffer();
      while (isr.ready()) {
        line.append((char)isr.read());
      }
      return vf.string(line.toString());
    } catch (IOException e) {
      throw RuntimeExceptionFactory.javaException(e, null, null);
    }
  }

  public synchronized IString readEntireStream(IInteger processId) {
    if (!runningProcesses.containsKey(processId))
      throw RuntimeExceptionFactory.illegalArgument(processId, null, null);
    try {
      Process runningProcess = runningProcesses.get(processId);
      BufferedReader br = new BufferedReader(new InputStreamReader(runningProcess.getInputStream()));
      StringBuffer lines = new StringBuffer();
      String line = "";
      while (null != (line = br.readLine())) {
        lines.append(line);
      }
      if (br != null) br.close();
      return vf.string(lines.toString());
    } catch (IOException e) {
      throw RuntimeExceptionFactory.javaException(e, null, null);
    }
  }

  public synchronized IString readEntireErrStream(IInteger processId) {
    if (!runningProcesses.containsKey(processId))
      throw RuntimeExceptionFactory.illegalArgument(processId, null, null);
    try {
      Process runningProcess = runningProcesses.get(processId);
      BufferedReader br = new BufferedReader(new InputStreamReader(runningProcess.getErrorStream()));
      StringBuffer lines = new StringBuffer();
      String line = "";
      while (null != (line = br.readLine())) {
        lines.append(line);
      }
      if (br != null) br.close();
      return vf.string(lines.toString());
    } catch (IOException e) {
      throw RuntimeExceptionFactory.javaException(e, null, null);
    }
  }

  public void writeTo(IInteger processId, IString msg) {
    if (!runningProcesses.containsKey(processId))
      throw RuntimeExceptionFactory.illegalArgument(processId, null, null);
    try {
      Process runningProcess = runningProcesses.get(processId);
      OutputStreamWriter osw = null;
      if (processOutputStreams.containsKey(processId)) {
        osw = processOutputStreams.get(processId);
      } else {
        osw = new OutputStreamWriter(runningProcess.getOutputStream());
        processOutputStreams.put(processId, osw);
      }
      osw.append(msg.getValue());
      osw.flush();
    } catch (IOException e) {
      throw RuntimeExceptionFactory.javaException(e, null, null);
    }
  }

}
TOP

Related Classes of org.rascalmpl.library.util.ShellExec

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.