if (null != node.getAttributes().get(SCRIPT_ATTRIBUTE)) {
scriptargs = node.getAttributes().get(SCRIPT_ATTRIBUTE);
}
if (null == scriptargs) {
throw new FileCopierException(
"[script-copy file copier] no attribute " + SCRIPT_ATTRIBUTE + " was found on node: "
+ node
.getNodename() + ", and no " + SCRIPT_COPY_DEFAULT_COMMAND_PROPERTY
+ " property was configured for the project or framework.",
StepFailureReason.ConfigurationFailure
);
}
dirstring = framework.getProjectProperty(executionContext.getFrameworkProject(),
SCRIPT_COPY_DEFAULT_DIR_PROPERTY);
if (null != node.getAttributes().get(DIR_ATTRIBUTE)) {
dirstring = node.getAttributes().get(DIR_ATTRIBUTE);
}
if (null != dirstring && !"".equals(dirstring)) {
workingdir = new File(dirstring);
}
final File srcFile =
null != file ?
file :
BaseFileCopier.writeTempFile(executionContext, file, input, content);
//create context data with node attributes
Map<String, Map<String, String>> newDataContext;
final Map<String, Map<String, String>> nodeContext =
DataContextUtils.addContext("node", DataContextUtils.nodeData(node), executionContext.getDataContext());
final HashMap<String, String> scptexec = new HashMap<String, String>(){{
//set filename of source file
put("filename", srcFile.getName());
put("file", srcFile.getAbsolutePath());
//add file, dir, destination to the file-copy data
}};
if (null != workingdir) {
//set up the data context to include the working dir
scptexec.put("dir", workingdir.getAbsolutePath());
}
newDataContext = DataContextUtils.addContext("file-copy", scptexec, nodeContext);
//expand remote filepath if we are copying a script
String copiedFilepath;
if (null == remotePath) {
copiedFilepath = framework.getProjectProperty(executionContext.getFrameworkProject(),
SCRIPT_COPY_DEFAULT_REMOTE_FILEPATH_PROPERTY);
if (null != node.getAttributes().get(REMOTE_FILEPATH_ATTRIBUTE)) {
copiedFilepath = node.getAttributes().get(REMOTE_FILEPATH_ATTRIBUTE);
}
if (null != copiedFilepath) {
if (!(copiedFilepath.contains("${file-copy.filename}")
|| copiedFilepath.contains("${file-copy.file}"))
&& !copiedFilepath.endsWith("/")) {
copiedFilepath += "/";
}
copiedFilepath = DataContextUtils.replaceDataReferences(copiedFilepath, newDataContext);
}
} else {
//we are copying to a specific destination
copiedFilepath = remotePath;
}
//put file in a directory
if (null != copiedFilepath && copiedFilepath.endsWith("/")) {
copiedFilepath += srcFile.getName();
}
scptexec.put("destination", null != copiedFilepath ? copiedFilepath : "");
newDataContext = DataContextUtils.addContext("file-copy", scptexec, nodeContext);
final Process exec;
String remoteShell = framework.getProjectProperty(executionContext.getFrameworkProject(),
SCRIPT_COPY_DEFAULT_REMOTE_SHELL);
if (null != node.getAttributes().get(SHELL_ATTRIBUTE)) {
remoteShell = node.getAttributes().get(SHELL_ATTRIBUTE);
}
try {
if (null != remoteShell) {
exec = ScriptUtil.execShellProcess(executionContext.getExecutionListener(), workingdir, scriptargs,
nodeContext, newDataContext, remoteShell, "script-copy");
} else {
exec = ScriptUtil.execProcess(executionContext.getExecutionListener(), workingdir, scriptargs,
nodeContext,
newDataContext, "script-copy");
}
} catch (IOException e) {
throw new FileCopierException(e.getMessage(), StepFailureReason.IOFailure, e);
}
final Thread errthread;
Thread outthread = null;
final int result;
final boolean success;
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
errthread = Streams.copyStreamThread(exec.getErrorStream(), System.err);
if (null == copiedFilepath) {
outthread = Streams.copyStreamThread(exec.getInputStream(), byteArrayOutputStream);
}
errthread.start();
if (null != outthread) {
outthread.start();
}
exec.getOutputStream().close();
result = exec.waitFor();
errthread.join();
if (null != outthread) {
outthread.join();
}
success = 0 == result;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FileCopierException(e.getMessage(), StepFailureReason.Interrupted, e);
} catch (IOException e) {
throw new FileCopierException(e.getMessage(), StepFailureReason.IOFailure, e);
}
if (!success) {
if (scriptargs.contains("${file-copy.destination}") && null == copiedFilepath) {
executionContext.getExecutionListener().log(0,
"[script-copy]: ${file-copy.destination} is referenced in the file-copy script, but its value " +
"could not be determined. " +
"The node " + node.getNodename() + " may need a " + REMOTE_FILEPATH_ATTRIBUTE
+ " attribute.");
}
throw new FileCopierException("[script-copy]: external script failed with exit code: " + result,
NodeStepFailureReason.NonZeroResultCode);
}
if (null != copiedFilepath) {
return copiedFilepath;
}
//load string of output from outputstream
final String output = byteArrayOutputStream.toString();
if (null == output || output.length() < 1) {
throw new FileCopierException("[script-copy]: No output from external script",
Reason.ScriptFileCopierPluginExpectedOutputMissing);
}
//TODO: require any specific format for the data?
//look for first line of output
final String[] split1 = output.split("(\\r?\\n)");
if (split1.length < 1) {
throw new FileCopierException("[script-copy]: No output from external script",
Reason.ScriptFileCopierPluginExpectedOutputMissing);
}
final String remotefilepath = split1[0];
executionContext.getExecutionListener().log(3, "[script-copy]: result filepath: " + remotefilepath);