/*
* Copyright 2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.impl.exec.posix;
import org.rioproject.impl.exec.AbstractShell;
import org.rioproject.exec.ExecDescriptor;
import org.rioproject.impl.exec.ProcessManager;
import org.rioproject.impl.exec.Util;
import org.rioproject.impl.util.FileUtils;
import org.rioproject.util.PropertyHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.URL;
/**
* A Shell implementation that forks commands for posix compliant systems
*
* @author Dennis Reedy
*/
public class PosixShell extends AbstractShell {
private static final String DEFAULT_EXEC_SCRIPT="classpath:exec-template.sh";
static final Logger logger = LoggerFactory.getLogger(PosixShell.class);
public PosixShell() {
super(DEFAULT_EXEC_SCRIPT);
}
@Override
protected String getRedirection(final ExecDescriptor execDescriptor) {
StringBuilder redirection = new StringBuilder();
if (execDescriptor.getStdOutFileName() != null) {
String stdOutFileName = PropertyHelper.expandProperties(execDescriptor.getStdOutFileName());
redirection.append(" > ").append(stdOutFileName);
}
if (execDescriptor.getStdErrFileName() != null) {
String stdErrFileName = PropertyHelper.expandProperties(execDescriptor.getStdErrFileName());
redirection.append(" 2> ").append(stdErrFileName);
}
return redirection.toString();
}
/**
* @see org.rioproject.impl.exec.Shell#exec(org.rioproject.exec.ExecDescriptor)
*/
public ProcessManager exec(final ExecDescriptor execDescriptor) throws IOException {
String workingDirectory = execDescriptor.getWorkingDirectory();
String commandLine = buildCommandLine(execDescriptor);
String originalCommand = execDescriptor.getCommandLine();
File pidFile = File.createTempFile("exec-", ".pid");
File generatedShellScript = File.createTempFile("exec-", ".sh");
/* Delete the generated file on exit */
generatedShellScript.deleteOnExit();
logger.debug("Generated exec script here: {}", generatedShellScript.getPath());
URL url = getTemplateURL();
StringBuilder sb = new StringBuilder();
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
str = Util.replace(str, "${command}", originalCommand);
str = Util.replace(str, "${pidFile}", FileUtils.getFilePath(pidFile));
str = Util.replace(str, "${commandLine}", commandLine);
sb.append(str).append("\n");
}
in.close();
Util.writeFile(sb.toString(), generatedShellScript);
Util.chmodX(generatedShellScript);
String toExec = FileUtils.getFilePath(generatedShellScript);
logger.debug("Generated command line: [{}]", commandLine);
ProcessBuilder processBuilder = createProcessBuilder(workingDirectory, execDescriptor, toExec);
Process process = processBuilder.start();
/* Started process, wait for pid file ... */
while(pidFile.length()==0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
in = new BufferedReader(new FileReader(pidFile));
String s = in.readLine();
int pid = Integer.parseInt(s);
in.close();
if(!pidFile.delete())
logger.warn("Non fatal, could not delete {}", FileUtils.getFilePath(pidFile));
PosixProcessManager processManager = new PosixProcessManager(process,
pid,
execDescriptor.getStdOutFileName(),
execDescriptor.getStdErrFileName());
processManager.setCommandFile(generatedShellScript);
processManager.setCommandLine(commandLine);
return processManager;
}
}