ProcessBuilder createProcessBuilder()

in taverna-server-worker/src/main/java/org/apache/taverna/server/localworker/impl/WorkerCore.java [310:465]


	ProcessBuilder createProcessBuilder(@Nonnull LocalWorker local,
			@Nonnull String executeWorkflowCommand, @Nonnull byte[] workflow,
			@Nonnull File workingDir, @Nullable File inputBaclava,
			@Nonnull Map<String, File> inputFiles,
			@Nonnull Map<String, String> inputValues,
			@Nonnull Map<String, String> inputDelimiters,
			@Nullable File outputBaclava, @Nonnull File securityDir,
			@Nonnull char[] password, boolean generateProvenance,
			@Nonnull Map<String, String> environment, @Nonnull String token,
			@Nonnull List<String> runtime) throws IOException,
			UnsupportedEncodingException, FileNotFoundException {
		ProcessBuilder pb = new ProcessBuilder();
		pb.command().add(TIME);
		/*
		 * WARNING! HERE THERE BE DRAGONS! BE CAREFUL HERE!
		 * 
		 * Work around _Maven_ bug with permissions in zip files! The executable
		 * bit is stripped by Maven's handling of file permissions, and there's
		 * no practical way to work around it without massively increasing the
		 * pain in other ways. Only want this on Unix - Windows isn't affected
		 * by this - so we use the file separator as a proxy for whether this is
		 * a true POSIX system. Ugly! Ugly ugly ugly...
		 * 
		 * http://jira.codehaus.org/browse/MASSEMBLY-337 is relevant, but not
		 * the whole story as we don't want to use a non-standard packaging
		 * method as there's a real chance of it going wrong in an unexpected
		 * way then. Other parts of the story are that the executable bit isn't
		 * preserved when unpacking with the dependency plugin, and there's no
		 * way to be sure that the servlet container will preserve the bit
		 * either (as that's probably using a Java-based ZIP engine).
		 */
		if (File.separatorChar == '/')
			pb.command().add("/bin/sh");
		pb.command().add(executeWorkflowCommand);
		if (runtime != null)
			pb.command().addAll(runtime);

		// Enable verbose logging
		pb.command().add("-logfile");
		pb.command().add(
				new File(new File(workingDir, "logs"), "detail.log")
						.getAbsolutePath());

		if (securityDir != null) {
			pb.command().add(CREDENTIAL_MANAGER_DIRECTORY);
			pb.command().add(securityDir.getAbsolutePath());
			out.println("security dir location: " + securityDir);
		}
		if (password != null) {
			pb.command().add(CREDENTIAL_MANAGER_PASSWORD);
			out.println("password of length " + password.length
					+ " will be written to subprocess stdin");
		}

		// Add arguments denoting inputs
		if (inputBaclava != null) {
			pb.command().add("-inputdoc");
			pb.command().add(inputBaclava.getAbsolutePath());
			if (!inputBaclava.exists())
				throw new IOException("input baclava file doesn't exist");
		} else {
			for (Entry<String, File> port : inputFiles.entrySet()) {
				if (port.getValue() == null)
					continue;
				pb.command().add("-inputfile");
				pb.command().add(port.getKey());
				pb.command().add(port.getValue().getAbsolutePath());
				if (!port.getValue().exists())
					throw new IOException("input file for port \"" + port
							+ "\" doesn't exist");
			}
			for (Entry<String, String> port : inputValues.entrySet()) {
				if (port.getValue() == null)
					continue;
				pb.command().add("-inputfile");
				pb.command().add(port.getKey());
				File f = createTempFile(".tav_in_", null, workingDir);
				pb.command().add(f.getAbsolutePath());
				write(f, port.getValue(), "UTF-8");
			}
			for (Entry<String, String> delim : inputDelimiters.entrySet()) {
				if (delim.getValue() == null)
					continue;
				pb.command().add("-inputdelimiter");
				pb.command().add(delim.getKey());
				pb.command().add(delim.getValue());
			}
		}

		// Add arguments denoting outputs
		if (outputBaclava != null) {
			pb.command().add("-outputdoc");
			pb.command().add(outputBaclava.getAbsolutePath());
			if (!outputBaclava.getParentFile().exists())
				throw new IOException(
						"parent directory of output baclava file does not exist");
			if (outputBaclava.exists())
				throw new IOException("output baclava file exists");
			// Provenance cannot be supported when using baclava output
		} else {
			File out = new File(workingDir, "out");
			if (!out.mkdir())
				throw new IOException("failed to make output directory \"out\"");
			// Taverna needs the dir to *not* exist now
			forceDelete(out);
			pb.command().add("-outputdir");
			pb.command().add(out.getAbsolutePath());
			// Enable provenance generation
			if (generateProvenance) {
				pb.command().add("-embedded");
				pb.command().add("-provenance");
				pb.command().add("-provbundle");
				pb.command().add("out.bundle.zip");
			}
		}

		// Add an argument holding the workflow
		File tmp = createTempFile(".wf_", ".scufl2", workingDir);
		try (OutputStream os = new FileOutputStream(tmp)) {
			os.write(workflow);
		}
		pb.command().add(workflowFile.getAbsolutePath());

		// Indicate what working directory to use
		pb.directory(workingDir);
		wd = workingDir;

		Map<String, String> env = pb.environment();
		for (String name : ENVIRONMENT_TO_REMOVE)
			env.remove(name);

		// Merge any options we have had imposed on us from outside
		env.putAll(environment);

		// Patch the environment to deal with TAVUTILS-17
		assert env.get("PATH") != null;
		env.put("PATH", new File(System.getProperty("java.home"), "bin")
				+ pathSeparator + env.get("PATH"));
		// Patch the environment to deal with TAVSERV-189
		env.put("TAVERNA_APPHOME", workingDir.getCanonicalPath());
		// Patch the environment to deal with TAVSERV-224
		env.put("TAVERNA_RUN_ID", token);
		if (interactionHost != null || local.interactionFeedURL != null
				|| local.webdavURL != null) {
			env.put("INTERACTION_HOST", makeInterHost(local.interactionFeedURL));
			env.put("INTERACTION_PORT", makeInterPort(local.interactionFeedURL));
			env.put("INTERACTION_FEED", makeInterPath(local.interactionFeedURL));
			env.put("INTERACTION_WEBDAV",
					local.webdavURL != null ? local.webdavURL.getPath()
							: interactionWebdavPath);
			String pub = makeInterPublish(local.publishURL);
			if (pub != null && !pub.isEmpty())
				env.put("INTERACTION_PUBLISH", pub);
		}
		return pb;
	}