Some improvements to the admin module:

- Re-org exec a bit
- Add checks for env vars in admin
- Check upper case host name on Windoze
- Fix problem with user admin binary converter in Rabbit 2.1
- Add pauses to prevent RPC errors (timing issue in JInterface?)
This commit is contained in:
Dave Syer
2010-09-27 12:42:14 +02:00
parent 74e6c05d77
commit 80a03be673
19 changed files with 787 additions and 612 deletions

View File

@@ -28,4 +28,8 @@ public class OtpAuthException extends OtpException {
super(cause);
}
public OtpAuthException(String msg, com.ericsson.otp.erlang.OtpAuthException cause) {
super(msg, cause);
}
}

View File

@@ -46,9 +46,8 @@ public class SimpleConnectionFactory implements ConnectionFactory, InitializingB
public SimpleConnectionFactory(String selfNodeName, String cookie, String peerNodeName) {
this.selfNodeName = selfNodeName;
this(selfNodeName, peerNodeName);
this.cookie = cookie;
this.peerNodeName = peerNodeName;
}
public SimpleConnectionFactory(String selfNodeName, String peerNodeName) {

View File

@@ -23,6 +23,7 @@ import org.springframework.erlang.OtpIOException;
import org.springframework.erlang.UncategorizedOtpException;
import org.springframework.util.Assert;
import com.ericsson.otp.erlang.OtpAuthException;
import com.ericsson.otp.erlang.OtpConnection;
/**
@@ -47,6 +48,9 @@ public class ErlangUtils {
if (ex instanceof IOException) {
return new OtpIOException((IOException) ex);
}
if (ex instanceof OtpAuthException) {
return new org.springframework.erlang.OtpAuthException((OtpAuthException) ex);
}
//fallback
return new UncategorizedOtpException(ex);
}

View File

@@ -16,389 +16,404 @@
package org.springframework.util.exec;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.StringReader;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.StringTokenizer;
import java.util.Vector;
/* Derived from ant exec task. All the 'backward compat with jdk1.1, 1.2'
removed. Since jdk1.3 supports working dir, no need for scripts.
removed. Since jdk1.3 supports working dir, no need for scripts.
All ant-specific code has been removed as well, this is a completely
independent component.
Costin
*/
All ant-specific code has been removed as well, this is a completely
independent component.
Costin
*/
/**
* Runs an external program.
*
*
* @author thomas.haas@softwired-inc.com
*/
public class Execute {
/** Invalid exit code. **/
public final static int INVALID = Integer.MAX_VALUE;
/** Invalid exit code. **/
public final static int INVALID = Integer.MAX_VALUE;
private String[] cmdl = null;
private String[] env = null;
private int exitValue = INVALID;
private ExecuteStreamHandler streamHandler;
private ExecuteWatchdog watchdog;
private File workingDirectory = null;
private boolean newEnvironment = false;
private String[] cmdl = null;
private String[] env = null;
private int exitValue = INVALID;
private ExecuteStreamHandler streamHandler;
private ExecuteWatchdog watchdog;
private File workingDirectory = null;
private boolean newEnvironment = false;
private Process process;
private static Vector<String> procEnvironment = null;
private static Vector<String> procEnvironment = null;
/**
* Find the list of environment variables for this process.
*/
public static synchronized Vector<String> getProcEnvironment() {
if (procEnvironment != null) return procEnvironment;
/**
* Find the list of environment variables for this process.
*/
public static synchronized Vector<String> getProcEnvironment() {
if (procEnvironment != null)
return procEnvironment;
procEnvironment = new Vector<String>();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Execute exe = new Execute(new PumpStreamHandler(out));
exe.setCommandline(getProcEnvCommand());
// Make sure we do not recurse forever
exe.setNewenvironment(true);
int retval = exe.execute();
if ( retval != 0 ) {
// Just try to use what we got
}
procEnvironment = new Vector<String>();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Execute exe = new Execute(new PumpStreamHandler(out));
exe.setCommandline(getProcEnvCommand());
// Make sure we do not recurse forever
exe.setNewenvironment(true);
int retval = exe.execute();
if (retval != 0) {
// Just try to use what we got
}
BufferedReader in =
new BufferedReader(new StringReader(out.toString()));
String var = null;
String line, lineSep = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
if (line.indexOf('=') == -1) {
// Chunk part of previous env var (UNIX env vars can
// contain embedded new lines).
if (var == null) {
var = lineSep + line;
}
else {
var += lineSep + line;
}
}
else {
// New env var...append the previous one if we have it.
if (var != null) {
procEnvironment.addElement(var);
}
var = line;
}
}
// Since we "look ahead" before adding, there's one last env var.
procEnvironment.addElement(var);
}
catch (Exception exc) {
exc.printStackTrace();
// Just try to see how much we got
}
return procEnvironment;
}
BufferedReader in = new BufferedReader(new StringReader(
out.toString()));
String var = null;
String line, lineSep = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
if (line.indexOf('=') == -1) {
// Chunk part of previous env var (UNIX env vars can
// contain embedded new lines).
if (var == null) {
var = lineSep + line;
} else {
var += lineSep + line;
}
} else {
// New env var...append the previous one if we have it.
if (var != null) {
procEnvironment.addElement(var);
}
var = line;
}
}
// Since we "look ahead" before adding, there's one last env var.
procEnvironment.addElement(var);
} catch (Exception exc) {
exc.printStackTrace();
// Just try to see how much we got
}
return procEnvironment;
}
private static String[] getProcEnvCommand() {
if ( Os.isFamily("os/2") ) {
// OS/2 - use same mechanism as Windows 2000
// Not sure
String[] cmd = {"cmd", "/c", "set" };
return cmd;
}
else if ( Os.isFamily("windows") ) {
String[] cmd = {"cmd", "/c", "set" };
return cmd;
}
else if ( Os.isFamily("unix") ) {
// Generic UNIX
// Alternatively one could use: /bin/sh -c env
String[] cmd = {"/usr/bin/env"};
return cmd;
}
else if ( Os.isFamily("netware") ) {
String[] cmd = {"env"};
return cmd;
}
else {
// MAC OS 9 and previous
// TODO: I have no idea how to get it, someone must fix it
String[] cmd = null;
return cmd;
}
}
private static String[] getProcEnvCommand() {
if (Os.isFamily("os/2")) {
// OS/2 - use same mechanism as Windows 2000
// Not sure
String[] cmd = { "cmd", "/c", "set" };
return cmd;
} else if (Os.isFamily("windows")) {
String[] cmd = { "cmd", "/c", "set" };
return cmd;
} else if (Os.isFamily("unix")) {
// Generic UNIX
// Alternatively one could use: /bin/sh -c env
String[] cmd = { "/usr/bin/env" };
return cmd;
} else if (Os.isFamily("netware")) {
String[] cmd = { "env" };
return cmd;
} else {
// MAC OS 9 and previous
// TODO: I have no idea how to get it, someone must fix it
String[] cmd = null;
return cmd;
}
}
/**
* Creates a new execute object using <code>PumpStreamHandler</code> for
* stream handling.
*/
public Execute() {
this(new PumpStreamHandler(), null);
}
/**
* Creates a new execute object using <code>PumpStreamHandler</code> for
* stream handling.
*/
public Execute() {
this(new PumpStreamHandler(), null);
}
/**
* Creates a new execute object.
*
* @param streamHandler
* the stream handler used to handle the input and output streams
* of the subprocess.
*/
public Execute(ExecuteStreamHandler streamHandler) {
this(streamHandler, null);
}
/**
* Creates a new execute object.
*
* @param streamHandler the stream handler used to handle the input and
* output streams of the subprocess.
*/
public Execute(ExecuteStreamHandler streamHandler) {
this(streamHandler, null);
}
/**
* Creates a new execute object.
*
* @param streamHandler
* the stream handler used to handle the input and output streams
* of the subprocess.
* @param watchdog
* a watchdog for the subprocess or <code>null</code> to to
* disable a timeout for the subprocess.
*/
public Execute(ExecuteStreamHandler streamHandler, ExecuteWatchdog watchdog) {
this.streamHandler = streamHandler;
this.watchdog = watchdog;
}
/**
* Creates a new execute object.
*
* @param streamHandler the stream handler used to handle the input and
* output streams of the subprocess.
* @param watchdog a watchdog for the subprocess or <code>null</code> to
* to disable a timeout for the subprocess.
*/
public Execute(ExecuteStreamHandler streamHandler, ExecuteWatchdog watchdog) {
this.streamHandler = streamHandler;
this.watchdog = watchdog;
}
/**
* Returns the commandline used to create a subprocess.
*
* @return the commandline used to create a subprocess
*/
public String[] getCommandline() {
return cmdl;
}
public String getCommandLineString() {
return array2string(getCommandline());
}
/**
* Returns the commandline used to create a subprocess.
*
* @return the commandline used to create a subprocess
*/
public String[] getCommandline() {
return cmdl;
}
/**
* Sets the commandline of the subprocess to launch.
*
* @param commandline
* the commandline of the subprocess to launch
*/
public void setCommandline(String[] commandline) {
cmdl = commandline;
}
public String getCommandLineString() {
return array2string(getCommandline());
}
/**
* Set whether to propagate the default environment or not.
*
* @param newenv
* whether to propagate the process environment.
*/
public void setNewenvironment(boolean newenv) {
newEnvironment = newenv;
}
/**
* Sets the commandline of the subprocess to launch.
*
* @param commandline the commandline of the subprocess to launch
*/
public void setCommandline(String[] commandline) {
cmdl = commandline;
}
/**
* Returns the environment used to create a subprocess.
*
* @return the environment used to create a subprocess
*/
public String[] getEnvironment() {
if (env == null || newEnvironment)
return env;
return patchEnvironment();
}
/**
* Set whether to propagate the default environment or not.
*
* @param newenv whether to propagate the process environment.
*/
public void setNewenvironment(boolean newenv) {
newEnvironment = newenv;
}
/**
* Sets the environment variables for the subprocess to launch.
*
* @param env
* array of Strings, each element of which has an environment
* variable settings in format <em>key=value</em>
*/
public void setEnvironment(String[] env) {
this.env = env;
}
/**
* Returns the environment used to create a subprocess.
*
* @return the environment used to create a subprocess
*/
public String[] getEnvironment() {
if (env == null || newEnvironment) return env;
return patchEnvironment();
}
/**
* Sets the working directory of the process to execute.
*
* <p>
* This is emulated using the antRun scripts unless the OS is Windows NT in
* which case a cmd.exe is spawned, or MRJ and setting user.dir works, or
* JDK 1.3 and there is official support in java.lang.Runtime.
*
* @param wd
* the working directory of the process.
*/
public void setWorkingDirectory(File wd) {
workingDirectory = wd;
}
/**
* Runs a process defined by the command line and returns its exit status.
*
* @return the exit status of the subprocess or <code>INVALID</code>
* @throws Exception
* if launching of the subprocess failed
*/
public int execute() throws Exception {
process = Runtime.getRuntime().exec(getCommandline(), getEnvironment(),
workingDirectory);
try {
streamHandler.setProcessInputStream(process.getOutputStream());
streamHandler.setProcessOutputStream(process.getInputStream());
streamHandler.setProcessErrorStream(process.getErrorStream());
} catch (IOException e) {
process.destroy();
throw e;
}
streamHandler.start();
/**
* Sets the environment variables for the subprocess to launch.
*
* @param env array of Strings, each element of which has
* an environment variable settings in format <em>key=value</em>
*/
public void setEnvironment(String[] env) {
this.env = env;
}
if (watchdog != null)
watchdog.start(process, Thread.currentThread());
/**
* Sets the working directory of the process to execute.
*
* <p>This is emulated using the antRun scripts unless the OS is
* Windows NT in which case a cmd.exe is spawned,
* or MRJ and setting user.dir works, or JDK 1.3 and there is
* official support in java.lang.Runtime.
*
* @param wd the working directory of the process.
*/
public void setWorkingDirectory(File wd) {
workingDirectory = wd;
}
if (log.isTraceEnabled())
log.trace("Waiting process ");
waitFor(process);
process = null;
// costin
boolean wait=true;
public void setWait( boolean b ) {
wait=b;
}
if (log.isTraceEnabled())
log.trace("End waiting, stop threads ");
if (watchdog != null)
watchdog.stop();
if (log.isTraceEnabled())
log.trace("Watchdog stopped ");
streamHandler.stop();
if (log.isTraceEnabled())
log.trace("Stream handler stopped ");
if (watchdog != null) {
Exception ex = watchdog.getException();
if (ex != null)
throw ex;
}
int exit = getExitValue();
Process process;
/**
* Runs a process defined by the command line and returns its exit status.
*
* @return the exit status of the subprocess or <code>INVALID</code>
* @throws Exception if launching of the subprocess failed
*/
public int execute() throws Exception {
process =
Runtime.getRuntime().exec( getCommandline(), getEnvironment(),
workingDirectory );
try {
streamHandler.setProcessInputStream(process.getOutputStream());
streamHandler.setProcessOutputStream(process.getInputStream());
streamHandler.setProcessErrorStream(process.getErrorStream());
} catch (IOException e) {
process.destroy();
throw e;
}
streamHandler.start();
if (log.isDebugEnabled()) {
log.debug("Done exit=" + exit + " " + getCommandLineString());
}
return exit;
}
if (watchdog != null) watchdog.start(process,
Thread.currentThread());
public void kill() {
if (process != null) {
process.destroy();
}
}
if( log.isTraceEnabled() ) log.trace("Waiting process ");
waitFor(process);
private String array2string(String sa[]) {
if (sa == null)
return "null";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < sa.length; i++)
sb.append(sa[i]).append(" ");
return sb.toString();
}
if( log.isTraceEnabled() ) log.trace("End waiting, stop threads ");
if (watchdog != null) watchdog.stop();
if( log.isTraceEnabled() ) log.trace("Watchdog stopped ");
streamHandler.stop();
if( log.isTraceEnabled() ) log.trace("Stream handler stopped ");
if (watchdog != null) {
Exception ex=watchdog.getException();
if( ex!=null )
throw ex;
}
int exit= getExitValue();
protected void waitFor(Process process) {
try {
process.waitFor();
setExitValue(process.exitValue());
} catch (InterruptedException e) {
log.info("waitFor() interrupted ");
}
}
if( log.isDebugEnabled() ) {
log.debug("Done exit=" + exit + " " + getCommandLineString());
}
return exit;
}
protected void setExitValue(int value) {
exitValue = value;
}
private String array2string( String sa[]) {
if( sa==null ) return "null";
StringBuffer sb=new StringBuffer();
for( int i=0; i<sa.length; i++ ) sb.append(sa[i]).append(" ");
return sb.toString();
}
/**
* query the exit value of the process.
*
* @return the exit value, 1 if the process was killed, or Project.INVALID
* if no exit value has been received
*/
public int getExitValue() {
return exitValue;
}
protected void waitFor(Process process) {
try {
process.waitFor();
setExitValue(process.exitValue());
} catch (InterruptedException e) {
log.info("waitFor() interrupted ");
}
}
protected void setExitValue(int value) {
exitValue = value;
}
/**
* query the exit value of the process.
* @return the exit value, 1 if the process was killed,
* or Project.INVALID if no exit value has been received
*/
public int getExitValue() {
return exitValue;
}
/**
* Patch the current environment with the new values from the user.
* @return the patched environment
*/
private String[] patchEnvironment() {
@SuppressWarnings("unchecked")
/**
* Patch the current environment with the new values from the user.
*
* @return the patched environment
*/
private String[] patchEnvironment() {
@SuppressWarnings("unchecked")
Vector<String> osEnv = (Vector<String>) getProcEnvironment().clone();
for (int i = 0; i < env.length; i++) {
int pos = env[i].indexOf('=');
// Get key including "="
String key = env[i].substring(0, pos+1);
int size = osEnv.size();
for (int j = 0; j < size; j++) {
if ((osEnv.elementAt(j)).startsWith(key)) {
osEnv.removeElementAt(j);
break;
}
}
osEnv.addElement(env[i]);
}
String[] result = new String[osEnv.size()];
osEnv.copyInto(result);
return result;
}
for (int i = 0; i < env.length; i++) {
int pos = env[i].indexOf('=');
// Get key including "="
String key = env[i].substring(0, pos + 1);
int size = osEnv.size();
for (int j = 0; j < size; j++) {
if ((osEnv.elementAt(j)).startsWith(key)) {
osEnv.removeElementAt(j);
break;
}
}
osEnv.addElement(env[i]);
}
String[] result = new String[osEnv.size()];
osEnv.copyInto(result);
return result;
}
public static int execute(Vector<String> envVars, String cmd, File baseDir ) {
Vector<String> v = new Vector<String>();
StringTokenizer st=new StringTokenizer( cmd, " " );
while( st.hasMoreTokens() ) {
v.addElement( st.nextToken() );
}
public static int execute(Vector<String> envVars, String cmd, File baseDir) {
Vector<String> v = new Vector<String>();
StringTokenizer st = new StringTokenizer(cmd, " ");
while (st.hasMoreTokens()) {
v.addElement(st.nextToken());
}
return execute( envVars, v, baseDir );
}
public static int execute(Vector<String> envVars, Vector<String> cmd, File baseDir) {
return execute( envVars, cmd, baseDir, 10000 /* default time to wait */);
}
return execute(envVars, v, baseDir);
}
/** Wrapper for common execution patterns
* @param envVars Environment variables to execute with (optional)
* @param cmd a vector of the commands to execute
* @param baseDir the base directory to run from (optional)
* @param timeToWait milliseconds to wait for completion
*/
public static int execute(Vector<String> envVars, Vector<String> cmd, File baseDir, int timeToWait) {
try {
// We can collect the out or provide in if needed
ExecuteWatchdog watchdog=new ExecuteWatchdog( timeToWait );
watchdog.setDontkill( true );
PumpStreamHandler out=new PumpStreamHandler();
Execute exec=new Execute(out,watchdog);
public static int execute(Vector<String> envVars, Vector<String> cmd,
File baseDir) {
return execute(envVars, cmd, baseDir, 10000 /* default time to wait */);
}
String cmdA[]=new String[ cmd.size() ];
cmd.toArray( cmdA );
if( log.isDebugEnabled() ) {
StringBuffer sb=new StringBuffer();
for(int i=0; i<cmdA.length; i++ ) {
sb.append(cmdA[i] + " " );
}
log.debug( "Exec: " + sb.toString());
}
exec.setCommandline( cmdA );
/**
* Wrapper for common execution patterns
*
* @param envVars
* Environment variables to execute with (optional)
* @param cmd
* a vector of the commands to execute
* @param baseDir
* the base directory to run from (optional)
* @param timeToWait
* milliseconds to wait for completion
*/
public static int execute(Vector<String> envVars, Vector<String> cmd,
File baseDir, int timeToWait) {
try {
// We can collect the out or provide in if needed
ExecuteWatchdog watchdog = new ExecuteWatchdog(timeToWait);
watchdog.setDontkill(true);
PumpStreamHandler out = new PumpStreamHandler();
Execute exec = new Execute(out, watchdog);
if( envVars!=null ) {
String env[]=new String[envVars.size()];
envVars.toArray( env );
exec.setEnvironment( env );
}
String cmdA[] = new String[cmd.size()];
cmd.toArray(cmdA);
if (log.isDebugEnabled()) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < cmdA.length; i++) {
sb.append(cmdA[i] + " ");
}
log.debug("Exec: " + sb.toString());
}
exec.setCommandline(cmdA);
exec.setNewenvironment( false );
if( baseDir!=null)
exec.setWorkingDirectory( baseDir );
if (envVars != null) {
String env[] = new String[envVars.size()];
envVars.toArray(env);
exec.setEnvironment(env);
}
exec.execute();
int status=exec.getExitValue();
log.debug("Exit value " + status );
return status;
} catch( Exception ex ) {
// ex.printStackTrace();
System.err.println("An error has occurred in Execute.");
return -1;
}
}
exec.setNewenvironment(false);
if (baseDir != null)
exec.setWorkingDirectory(baseDir);
exec.execute();
int status = exec.getExitValue();
log.debug("Exit value " + status);
return status;
} catch (Exception ex) {
// ex.printStackTrace();
System.err.println("An error has occurred in Execute.");
return -1;
}
}
private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
.getLog(Execute.class);
private static org.apache.commons.logging.Log log=
org.apache.commons.logging.LogFactory.getLog( Execute.class );
}