You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 11:17:07 UTC
[26/28] incubator-taverna-common-activities git commit: Revert
"temporarily empty repository"
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/local/LocalUseCaseInvocation.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/local/LocalUseCaseInvocation.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/local/LocalUseCaseInvocation.java
new file mode 100755
index 0000000..3541b8f
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/local/LocalUseCaseInvocation.java
@@ -0,0 +1,563 @@
+/* Part of the KnowARC Janitor Use-case processor for taverna
+ * written 2007-2010 by Hajo Nils Krabbenhoeft and Steffen Moeller
+ * University of Luebeck, Institute for Neuro- and Bioinformatics
+ * University of Luebeck, Institute for Dermatolgy
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this package; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package de.uni_luebeck.inb.knowarc.usecases.invocation.local;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+import net.sf.taverna.t2.reference.AbstractExternalReference;
+import net.sf.taverna.t2.reference.ErrorDocument;
+import net.sf.taverna.t2.reference.ExternalReferenceSPI;
+import net.sf.taverna.t2.reference.Identified;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.ReferenceSet;
+import net.sf.taverna.t2.reference.ReferencedDataNature;
+import net.sf.taverna.t2.reference.T2Reference;
+import net.sf.taverna.t2.reference.impl.external.file.FileReference;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+
+import de.uni_luebeck.inb.knowarc.usecases.ScriptInput;
+import de.uni_luebeck.inb.knowarc.usecases.ScriptOutput;
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.InvocationException;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.UseCaseInvocation;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.ssh.SshNode;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.ssh.SshNodeFactory;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.ssh.SshUrl;
+
+/**
+ * The job is executed locally, i.e. not via the grid.
+ * @author Hajo Krabbenhoeft
+ */
+public class LocalUseCaseInvocation extends UseCaseInvocation {
+
+ private static Logger logger = Logger.getLogger(LocalUseCaseInvocation.class);
+
+ private final File tempDir;
+
+ public static String LOCAL_USE_CASE_INVOCATION_TYPE = "789663B8-DA91-428A-9F7D-B3F3DA185FD4";
+
+ private Process running;
+
+ private final String shellPrefix;
+
+ private final String linkCommand;
+
+ private Reader stdInReader = null;
+
+ private static Map<String, Set<String>> runIdToTempDir = Collections.synchronizedMap(new HashMap<String, Set<String>> ());
+
+ private static String LOCAL_INVOCATION_FILE = "localInvocations";
+
+ public LocalUseCaseInvocation(UseCaseDescription desc, boolean retrieveData, String mainTempDirectory, String shellPrefix, String linkCommand) throws IOException {
+
+ usecase = desc;
+ setRetrieveData(retrieveData);
+ this.shellPrefix = shellPrefix;
+ this.linkCommand = linkCommand;
+
+ if (mainTempDirectory != null) {
+
+ File mainTempDir = new File(mainTempDirectory);
+
+ tempDir = File.createTempFile("usecase", "dir", mainTempDir);
+ } else {
+ tempDir = File.createTempFile("usecase", "dir");
+ }
+ tempDir.delete();
+ tempDir.mkdir();
+ logger.info("mainTempDirectory is " + mainTempDirectory);
+ logger.info("Using tempDir " + tempDir.getAbsolutePath());
+
+ }
+
+ void recDel(File c) {
+ File[] files = c.listFiles();
+ if (files != null) {
+ for (File cc : files)
+ recDel(cc);
+ }
+ c.delete();
+ }
+
+ private String setOneBinaryInput(ReferenceService referenceService,
+ T2Reference t2Reference, ScriptInput input, String targetSuffix)
+ throws InvocationException {
+
+ if (input.isFile() || input.isTempFile()) {
+ // Try to get it as a file
+ String target = tempDir.getAbsolutePath() + "/" + targetSuffix;
+ FileReference fileRef = getAsFileReference(referenceService,
+ t2Reference);
+ if (fileRef != null) {
+
+ if (!input.isForceCopy()) {
+ if (linkCommand != null) {
+ String source = fileRef.getFile().getAbsolutePath();
+ String actualLinkCommand = getActualOsCommand(
+ linkCommand, source, targetSuffix, target);
+ logger.info("Link command is " + actualLinkCommand);
+ String[] splitCmds = actualLinkCommand.split(" ");
+ ProcessBuilder builder = new ProcessBuilder(splitCmds);
+ builder.directory(tempDir);
+ try {
+ int code = builder.start().waitFor();
+ if (code == 0) {
+ return target;
+ } else {
+ logger.error("Link command gave errorcode: "
+ + code);
+ }
+
+ } catch (InterruptedException e) {
+ // go through
+ } catch (IOException e) {
+ // go through
+ }
+
+ }
+ }
+ }
+
+ InputStream is = null;
+ OutputStream os = null;
+ is = getAsStream(referenceService, t2Reference);
+
+ try {
+ os = new FileOutputStream(target);
+ } catch (FileNotFoundException e) {
+ throw new InvocationException(e);
+ }
+
+ try {
+ IOUtils.copyLarge(is, os);
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ try {
+ is.close();
+ os.close();
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ return target;
+ } else {
+ String value = (String) referenceService.renderIdentifier(
+ t2Reference, String.class, this.getContext());
+ return value;
+ }
+ }
+
+ @Override
+ public String setOneInput(ReferenceService referenceService,
+ T2Reference t2Reference, ScriptInput input)
+ throws InvocationException {
+
+ if (input.getCharsetName() == null) {
+ input.setCharsetName(Charset.defaultCharset().name());
+ }
+ String target = null;
+ String targetSuffix = null;
+ if (input.isFile()) {
+ targetSuffix = input.getTag();
+ } else if (input.isTempFile()) {
+ targetSuffix = "tempfile." + (nTempFiles++) + ".tmp";
+ }
+
+ if (input.isBinary()) {
+ return setOneBinaryInput(referenceService, t2Reference, input,
+ targetSuffix);
+ }
+
+ logger.info("Target is " + target);
+ if (input.isFile() || input.isTempFile()) {
+ target = tempDir.getAbsolutePath() + "/" + targetSuffix;
+ // Try to get it as a file
+ Reader r;
+ Writer w;
+ FileReference fileRef = getAsFileReference(referenceService,
+ t2Reference);
+ if (fileRef != null) {
+
+ if (!input.isForceCopy()) {
+ if (linkCommand != null) {
+ String source = fileRef.getFile().getAbsolutePath();
+ String actualLinkCommand = getActualOsCommand(
+ linkCommand, source, targetSuffix, target);
+ logger.info("Link command is " + actualLinkCommand);
+ String[] splitCmds = actualLinkCommand.split(" ");
+ ProcessBuilder builder = new ProcessBuilder(splitCmds);
+ builder.directory(tempDir);
+ try {
+ int code = builder.start().waitFor();
+ if (code == 0) {
+ return target;
+ } else {
+ logger.error("Link command gave errorcode: "
+ + code);
+ }
+
+ } catch (InterruptedException e) {
+ // go through
+ } catch (IOException e) {
+ // go through
+ }
+
+ }
+ }
+
+ if (fileRef.getDataNature().equals(ReferencedDataNature.TEXT)) {
+ r = new InputStreamReader(fileRef.openStream(this
+ .getContext()), Charset.forName(fileRef
+ .getCharset()));
+ } else {
+ try {
+ r = new FileReader(fileRef.getFile());
+ } catch (FileNotFoundException e) {
+ throw new InvocationException(e);
+ }
+ }
+ } else {
+ r = new InputStreamReader(getAsStream(referenceService,
+ t2Reference));
+ }
+ try {
+ w = new OutputStreamWriter(new FileOutputStream(target), input
+ .getCharsetName());
+ } catch (UnsupportedEncodingException e) {
+ throw new InvocationException(e);
+ } catch (FileNotFoundException e) {
+ throw new InvocationException(e);
+ }
+ try {
+ IOUtils.copyLarge(r, w);
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ try {
+ r.close();
+ w.close();
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ return target;
+ } else {
+ String value = (String) referenceService.renderIdentifier(
+ t2Reference, String.class, this.getContext());
+ return value;
+ }
+ }
+
+ private void forgetRun() {
+ Set<String> directories = runIdToTempDir.get(getRunId());
+ try {
+ directories.remove(tempDir.getCanonicalPath());
+ } catch (IOException e) {
+ logger.error(e);
+ }
+ }
+
+ private static void deleteDirectory(String location) {
+ try {
+ FileUtils.deleteDirectory(new File(location));
+ } catch (IOException e) {
+ logger.error("Problem deleting " + location, e);
+ }
+ }
+
+ public static void cleanup(String runId) {
+ Set<String> tempDirectories = runIdToTempDir.get(runId);
+ if (tempDirectories != null) {
+ for (String tempDir : tempDirectories) {
+ deleteDirectory(tempDir);
+ }
+ runIdToTempDir.remove(runId);
+ }
+ }
+
+ @Override
+ protected void submit_generate_job_inner() throws InvocationException {
+ tags.put("uniqueID", "" + getSubmissionID());
+ String command = usecase.getCommand();
+ for (String cur : tags.keySet()) {
+ command = command.replaceAll("\\Q%%" + cur + "%%\\E", Matcher.quoteReplacement(tags.get(cur)));
+ }
+
+ List<String> cmds = new ArrayList<String>();
+ if ((shellPrefix != null) && !shellPrefix.isEmpty()) {
+ String[] prefixCmds = shellPrefix.split(" ");
+ for (int i = 0; i < prefixCmds.length; i++) {
+ cmds.add(prefixCmds[i]);
+ }
+ cmds.add(command);
+ } else {
+ String[] splitCmds = command.split(" ");
+ for (int i = 0; i < splitCmds.length; i++) {
+ cmds.add(splitCmds[i]);
+ }
+ }
+
+ ProcessBuilder builder = new ProcessBuilder(cmds);
+ builder.directory(tempDir);
+
+ for (int i = 0; i < cmds.size(); i++) {
+ logger.info("cmds[" + i + "] = " + cmds.get(i));
+ }
+ logger.info("Command is " + command + " in directory " + tempDir);
+ try {
+ running = builder.start();
+ if (stdInReader != null) {
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(running.getOutputStream()));
+ IOUtils.copyLarge(stdInReader, writer);
+ writer.close();
+ }
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ }
+
+ private void copy_stream(InputStream read, OutputStream write) throws IOException {
+ int a = read.available();
+ if (a > 0) {
+ byte[] buf = new byte[a];
+ read.read(buf);
+ write.write(buf);
+ }
+ }
+
+ @Override
+ public HashMap<String, Object> submit_wait_fetch_results(ReferenceService referenceService) throws InvocationException {
+ ByteArrayOutputStream stdout_buf = new ByteArrayOutputStream();
+ ByteArrayOutputStream stderr_buf = new ByteArrayOutputStream();
+ while (true) {
+ try {
+ copy_stream(running.getInputStream(), stdout_buf);
+ copy_stream(running.getErrorStream(), stderr_buf);
+ } catch (IOException e1) {
+ throw new InvocationException(e1);
+ }
+ try {
+ int exitcode = running.exitValue();
+ if (!usecase.getValidReturnCodes().contains(exitcode)) {
+ try {
+ throw new InvocationException("Invalid exit code " + exitcode + ":" + stderr_buf.toString("US-ASCII"));
+ } catch (UnsupportedEncodingException e) {
+ throw new InvocationException("Invalid exit code " + exitcode + ":" + stderr_buf.toString());
+ }
+ }
+ else
+ break;
+ } catch (IllegalThreadStateException e) {
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e1) {
+ throw new InvocationException(e);
+ }
+
+ }
+ }
+
+ HashMap<String, Object> results = new HashMap<String, Object>();
+ results.put("STDOUT", stdout_buf.toByteArray());
+ results.put("STDERR", stderr_buf.toByteArray());
+
+ for (Map.Entry<String, ScriptOutput> cur : usecase.getOutputs().entrySet()) {
+ ScriptOutput scriptOutput = cur.getValue();
+ File result = new File(tempDir.getAbsoluteFile() + "/" + cur.getValue().getPath());
+ if (result.exists()) {
+ AbstractExternalReference ref;
+ if (isRetrieveData()) {
+ FileInputStream is;
+ try {
+ is = new FileInputStream(result);
+ } catch (FileNotFoundException e) {
+ throw new InvocationException(e);
+ }
+ if (scriptOutput.isBinary()) {
+ ref = inlineByteArrayReferenceBuilder.createReference(is, null);
+ } else {
+ ref = inlineStringReferenceBuilder.createReference(is, null);
+ }
+ try {
+ is.close();
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ }
+ else {
+ ref = new FileReference(result);
+ if (scriptOutput.isBinary()) {
+ ((FileReference) ref)
+ .setDataNature(ReferencedDataNature.BINARY);
+ } else {
+ ((FileReference) ref)
+ .setDataNature(ReferencedDataNature.TEXT);
+ ((FileReference) ref).setCharset("UTF-8");
+ }
+ }
+ results.put(cur.getKey(), ref);
+ } else {
+ ErrorDocument ed = referenceService.getErrorDocumentService().registerError("No result for " + cur.getKey(), 0, getContext());
+ results.put(cur.getKey(), ed);
+ }
+ }
+
+ if (isRetrieveData()) {
+ forgetRun();
+ try {
+ deleteDirectory(tempDir.getCanonicalPath());
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ }
+
+ return results;
+ }
+
+ private FileReference getAsFileReference(ReferenceService referenceService, T2Reference t2Reference) {
+ Identified identified = referenceService.resolveIdentifier(t2Reference, null, null);
+ if (identified instanceof ReferenceSet) {
+ for (ExternalReferenceSPI ref : ((ReferenceSet) identified).getExternalReferences()) {
+ if (ref instanceof FileReference) {
+ return (FileReference) ref;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void setStdIn(ReferenceService referenceService,
+ T2Reference t2Reference) {
+ stdInReader = new BufferedReader(new InputStreamReader(getAsStream(referenceService, t2Reference)));
+ }
+
+ @Override
+ public void rememberRun(String runId) {
+ this.setRunId(runId);
+ Set<String> directories = runIdToTempDir.get(runId);
+ if (directories == null) {
+ directories = Collections.synchronizedSet(new HashSet<String> ());
+ runIdToTempDir.put(runId, directories);
+ }
+ try {
+ directories.add(tempDir.getCanonicalPath());
+ } catch (IOException e) {
+ logger.error("Unable to record temporary directory: " + tempDir, e);
+ }
+ }
+
+ public static void load(File directory) {
+ File invocationsFile = new File(directory, LOCAL_INVOCATION_FILE);
+ if (!invocationsFile.exists()) {
+ return;
+ }
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(invocationsFile));
+ String line = reader.readLine();
+ while (line != null) {
+ String[] parts = line.split(" ");
+ if (parts.length != 2) {
+ break;
+ }
+ String runId = parts[0];
+ String tempDirString = parts[1];
+ Set<String> tempDirs = runIdToTempDir.get(runId);
+ if (tempDirs == null) {
+ tempDirs = new HashSet<String>();
+ runIdToTempDir.put(runId, tempDirs);
+ }
+ tempDirs.add(tempDirString);
+ line = reader.readLine();
+ }
+ } catch (FileNotFoundException e) {
+ logger.error(e);
+ } catch (IOException e) {
+ logger.error(e);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ logger.error(e);
+ }
+ }
+ }
+ }
+
+ public static void persist(File directory) {
+ File invocationsFile = new File(directory, LOCAL_INVOCATION_FILE);
+ BufferedWriter writer = null;
+ try {
+ writer = new BufferedWriter(new FileWriter(invocationsFile));
+ for (String runId : runIdToTempDir.keySet()) {
+ for (String tempDir : runIdToTempDir.get(runId)) {
+ writer.write(runId);
+ writer.write(" ");
+ writer.write(tempDir);
+ writer.newLine();
+ }
+ }
+ } catch (IOException e) {
+ logger.error(e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ logger.error(e);
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshAutoLoginTrustEveryone.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshAutoLoginTrustEveryone.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshAutoLoginTrustEveryone.java
new file mode 100644
index 0000000..60d3bec
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshAutoLoginTrustEveryone.java
@@ -0,0 +1,72 @@
+/* Part of the KnowARC Janitor Use-case processor for taverna
+ * written 2007-2010 by Hajo Nils Krabbenhoeft and Steffen Moeller
+ * University of Luebeck, Institute for Neuro- and Bioinformatics
+ * University of Luebeck, Institute for Dermatolgy
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this package; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import org.apache.log4j.Logger;
+
+import com.jcraft.jsch.UIKeyboardInteractive;
+import com.jcraft.jsch.UserInfo;
+
+import de.uni_luebeck.inb.knowarc.usecases.invocation.AskUserForPw;
+
+final class SshAutoLoginTrustEveryone implements UserInfo, UIKeyboardInteractive {
+
+ private static Logger logger = Logger.getLogger(SshAutoLoginTrustEveryone.class);
+
+ private final AskUserForPw askUserForPw;
+
+ public SshAutoLoginTrustEveryone(AskUserForPw askUserForPw) {
+ super();
+ this.askUserForPw = askUserForPw;
+ }
+
+ public void showMessage(String arg0) {
+ logger.info(arg0);
+ }
+
+ public boolean promptYesNo(String arg0) {
+ if (arg0.startsWith("The authenticity of host"))
+ return true;
+ return false;
+ }
+
+ public boolean promptPassword(String arg0) {
+ return true;
+ }
+
+ public boolean promptPassphrase(String arg0) {
+ return true;
+ }
+
+ public String getPassword() {
+ return askUserForPw.getPassword();
+ }
+
+ public String getPassphrase() {
+ return askUserForPw.getPassphrase();
+ }
+
+ public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
+ if (prompt.length >= 1 && prompt[0].toLowerCase().startsWith("password"))
+ return new String[] { askUserForPw.getPassword() };
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNode.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNode.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNode.java
new file mode 100644
index 0000000..92b065e
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNode.java
@@ -0,0 +1,159 @@
+/* Part of the KnowARC Janitor Use-case processor for taverna
+ * written 2007-2010 by Hajo Nils Krabbenhoeft and Steffen Moeller
+ * University of Luebeck, Institute for Neuro- and Bioinformatics
+ * University of Luebeck, Institute for Dermatolgy
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this package; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanism;
+
+public class SshNode {
+
+ public static String DEFAULT_HOST = "127.0.0.1";
+ public static int DEFAULT_PORT = 22;
+ public static String DEFAULT_DIRECTORY = "/tmp/";
+
+ private String host = DEFAULT_HOST;
+ private int port = DEFAULT_PORT;
+ private String directory = DEFAULT_DIRECTORY;
+
+ private SshUrl url;
+
+ private String linkCommand = null;
+ private String copyCommand = null;
+ private boolean retrieveData = false;
+
+ /**
+ *
+ */
+ SshNode() {
+ super();
+ linkCommand = InvocationMechanism.UNIX_LINK;
+ copyCommand = InvocationMechanism.UNIX_COPY;
+
+ }
+ /**
+ * @param directory the directory to set
+ */
+ public void setDirectory(String directory) {
+ if ((directory != null) && !directory.isEmpty()) {
+ if (!directory.endsWith("/")) {
+ directory = directory + "/";
+ }
+ this.directory = directory;
+ }
+ }
+
+ /**
+ * @return the directory
+ */
+ public String getDirectory() {
+ return directory;
+ }
+
+ /**
+ * @param host the host to set
+ */
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * @return the host
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * @param port the port to set
+ */
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ /**
+ * @return the port
+ */
+ public int getPort() {
+ return port;
+ }
+
+ SshUrl getUrl() {
+ if (url == null) {
+ url = new SshUrl(this);
+ }
+ return url;
+ }
+
+ public int hashCode() {
+ return getUrl().hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj == null) || !(obj instanceof SshNode)) {
+ return false;
+ }
+ return (this.hashCode() == obj.hashCode());
+ }
+ /**
+ * @return the linkCommand
+ */
+ public String getLinkCommand() {
+ return linkCommand;
+ }
+ /**
+ * @param linkCommand the linkCommand to set
+ */
+ public void setLinkCommand(String linkCommand) {
+ if ((linkCommand != null) && linkCommand.isEmpty()) {
+ this.linkCommand = null;
+ } else {
+ this.linkCommand = linkCommand;
+ } }
+ /**
+ * @return the copyCommand
+ */
+ public String getCopyCommand() {
+ return copyCommand;
+ }
+ /**
+ * @param copyCommand the copyCommand to set
+ */
+ public void setCopyCommand(String copyCommand) {
+ if ((copyCommand != null) && copyCommand.isEmpty()) {
+ this.copyCommand = null;
+ } else {
+ this.copyCommand = copyCommand;
+ }
+ }
+
+ /**
+ * @return the retrieveData
+ */
+ public boolean isRetrieveData() {
+ return retrieveData;
+ }
+ /**
+ * @param retrieveData the retrieveData to set
+ */
+ public void setRetrieveData(boolean retrieveData) {
+ this.retrieveData = retrieveData;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNodeFactory.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNodeFactory.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNodeFactory.java
new file mode 100644
index 0000000..2d8f4bb
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshNodeFactory.java
@@ -0,0 +1,56 @@
+/**
+ *
+ */
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author alanrw
+ *
+ */
+public class SshNodeFactory {
+
+ private Map<String, SshNode> nodeMap = Collections.synchronizedMap(new HashMap<String, SshNode> ());
+
+ private static SshNodeFactory INSTANCE = new SshNodeFactory();
+
+ private SshNode defaultNode;
+
+ private SshNodeFactory() {
+ defaultNode = getSshNode(SshNode.DEFAULT_HOST, SshNode.DEFAULT_PORT, SshNode.DEFAULT_DIRECTORY);
+ }
+
+ public SshNode getDefaultNode() {
+ return defaultNode;
+ }
+
+ public static SshNodeFactory getInstance() {
+ return INSTANCE;
+ }
+
+ public SshNode getSshNode(String host, int port, String directory) {
+ String url = makeUrl(host, port, directory);
+ if (nodeMap.containsKey(url)) {
+ return nodeMap.get(url);
+ }
+ else {
+ SshNode newNode = new SshNode();
+ newNode.setHost(host);
+ newNode.setPort(port);
+ newNode.setDirectory(directory);
+ nodeMap.put(url, newNode);
+ return newNode;
+ }
+ }
+
+ public boolean containsSshNode(String host, int port, String directory) {
+ return nodeMap.containsKey(makeUrl(host, port, directory));
+ }
+
+ public static String makeUrl(String host, int port, String directory) {
+ return ("ssh://" + host + ":" + port + directory);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshPool.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshPool.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshPool.java
new file mode 100755
index 0000000..c6a5851
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshPool.java
@@ -0,0 +1,148 @@
+/**
+ *
+ */
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+import de.uni_luebeck.inb.knowarc.usecases.RuntimeEnvironmentConstraint;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.AskUserForPw;
+
+/**
+ * @author alanrw
+ *
+ */
+public class SshPool {
+
+ private static Logger logger = Logger.getLogger(SshPool.class);
+
+
+ private static JSch jsch = new JSch();
+
+ private static int CONNECT_TIMEOUT = 10000; // milliseconds
+
+ private static Map<SshNode, Session> sessionMap = Collections.synchronizedMap(new HashMap<SshNode, Session> ());
+ private static Map<Session, ChannelSftp> sftpGetMap = Collections.synchronizedMap(new HashMap<Session, ChannelSftp> ());
+ private static Map<Session, ChannelSftp> sftpPutMap = Collections.synchronizedMap(new HashMap<Session, ChannelSftp> ());
+
+ public static Session getSshSession(final SshUrl sshUrl, final AskUserForPw askUserForPw) throws JSchException {
+ return getSshSession(sshUrl.getSshNode(), askUserForPw);
+ }
+
+ public static synchronized Session getSshSession(final SshNode sshNode, final AskUserForPw askUserForPw) throws JSchException {
+
+ Session s = sessionMap.get(sshNode);
+ if ((s != null) && s.isConnected()) {
+ logger.info("Reusing session");
+ return s;
+ }
+ if (s != null) {
+ logger.info("Session was not connected");
+ }
+ if (s == null) {
+ logger.info("No session found for " + sshNode.toString());
+ }
+
+ if (askUserForPw.getKeyfile().length() > 0) {
+ jsch.addIdentity(askUserForPw.getKeyfile());
+ }
+ logger.info("Using host is " + sshNode.getHost() + " and port " + sshNode.getPort());
+ Session sshSession = jsch.getSession(askUserForPw.getUsername(), sshNode.getHost(), sshNode.getPort());
+ sshSession.setUserInfo(new SshAutoLoginTrustEveryone(askUserForPw));
+ sshSession.connect(CONNECT_TIMEOUT);
+
+ askUserForPw.authenticationSucceeded();
+ sessionMap.put(sshNode, sshSession);
+ if (sshSession == null) {
+ logger.error("Returning a null session");
+ }
+ return sshSession;
+ }
+
+ public static ChannelSftp getSftpGetChannel(SshNode sshNode, final AskUserForPw askUserForPw) throws JSchException {
+ return getSftpGetChannel(getSshSession(sshNode, askUserForPw));
+ }
+
+ private static synchronized ChannelSftp getSftpGetChannel(Session session) throws JSchException {
+ ChannelSftp result = sftpGetMap.get(session);
+ if (!session.isConnected()) {
+ logger.warn("Session is not connected");
+ }
+ if (result == null) {
+ logger.info("Creating new sftp channel");
+ result = (ChannelSftp) session.openChannel("sftp");
+ sftpGetMap.put(session, result);
+ }
+ else {
+ logger.info("Reusing sftp channel");
+ }
+ if (!result.isConnected()) {
+ logger.info("Connecting");
+ result.connect();
+ } else {
+ logger.info("Already connected");
+ }
+ return result;
+ }
+
+ public static ChannelSftp getSftpPutChannel(SshNode sshNode, final AskUserForPw askUserForPw) throws JSchException {
+ return getSftpPutChannel(getSshSession(sshNode, askUserForPw));
+ }
+
+ private static synchronized ChannelSftp getSftpPutChannel(Session session) throws JSchException {
+ ChannelSftp result = null;
+ synchronized(sftpPutMap) {
+ result = sftpPutMap.get(session);
+ if (!session.isConnected()) {
+ logger.info("Session is not connected");
+ }
+ if (result == null) {
+ logger.info("Creating new sftp channel");
+ result = (ChannelSftp) session.openChannel("sftp");
+ sftpPutMap.put(session, result);
+ }
+ else {
+ logger.info("Reusing sftp channel");
+ }
+ }
+ if (!result.isConnected()) {
+ logger.info("Connecting");
+ result.connect(CONNECT_TIMEOUT);
+ } else {
+ logger.info("Already connected");
+ }
+ return result;
+ }
+
+ public static synchronized ChannelExec openExecChannel(SshNode sshNode, final AskUserForPw askUserForPw) throws JSchException {
+ return (ChannelExec) getSshSession(sshNode, askUserForPw).openChannel("exec");
+ }
+
+ private static synchronized ChannelExec openExecChannel(Session session) throws JSchException {
+ return (ChannelExec) session.openChannel("exec");
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshReference.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshReference.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshReference.java
new file mode 100644
index 0000000..0431153
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshReference.java
@@ -0,0 +1,208 @@
+/**
+ *
+ */
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import java.io.InputStream;
+
+import net.sf.taverna.t2.activities.externaltool.RetrieveLoginFromTaverna;
+import net.sf.taverna.t2.reference.AbstractExternalReference;
+import net.sf.taverna.t2.reference.DereferenceException;
+import net.sf.taverna.t2.reference.ExternalReferenceSPI;
+import net.sf.taverna.t2.reference.ReferenceContext;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.reference.ReferencedDataNature;
+
+import org.apache.log4j.Logger;
+
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.SftpException;
+
+/**
+ * @author alanrw
+ *
+ */
+public class SshReference extends AbstractExternalReference implements
+ ExternalReferenceSPI {
+
+ private static Logger logger = Logger.getLogger(SshReference.class);
+
+
+ private String host = "127.0.0.1";
+ private int port = 22;
+ private String directory = "/tmp/";
+ private String subDirectory;
+ private String fileName;
+
+ private CredentialManager credentialManager;
+
+ private int dataNatureInteger = ReferencedDataNature.UNKNOWN.ordinal();
+ private String charset = "UTF-8";
+
+ public SshReference() {
+ super();
+ }
+
+ public SshReference(SshUrl url) {
+ super();
+ this.host = url.getSshNode().getHost();
+ this.port = url.getSshNode().getPort();
+ this.directory = url.getSshNode().getDirectory();
+ this.subDirectory = url.getSubDirectory();
+ this.fileName = url.getFileName();
+ this.setDataNature(url.getDataNature());
+ this.setCharset(url.getCharset());
+ }
+
+ /* (non-Javadoc)
+ * @see net.sf.taverna.t2.reference.ExternalReferenceSPI#getApproximateSizeInBytes()
+ */
+ @Override
+ public Long getApproximateSizeInBytes() {
+ return 10000L;
+ }
+
+ /* (non-Javadoc)
+ * @see net.sf.taverna.t2.reference.ExternalReferenceSPI#openStream(net.sf.taverna.t2.reference.ReferenceContext)
+ */
+ @Override
+ public InputStream openStream(ReferenceContext context)
+ throws DereferenceException {
+ try {
+ SshNode node = SshNodeFactory.getInstance().getSshNode(this.getHost(), this.getPort(), this.getDirectory());
+ String fullPath = getDirectory() + getSubDirectory() + "/" + getFileName();
+ ChannelSftp channel = SshPool.getSftpGetChannel(node, new RetrieveLoginFromTaverna(new SshUrl(node).toString(), credentialManager));
+ logger.info("Opening stream on " + fullPath);
+ return (channel.get(fullPath));
+ } catch (JSchException e) {
+ //TODO
+ logger.error(e);
+ } catch (SftpException e) {
+ // TODO Auto-generated catch block
+ logger.error(e);
+ }
+ return null;
+ }
+
+ /**
+ * @return the host
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * @param host the host to set
+ */
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * @return the port
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * @param port the port to set
+ */
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ /**
+ * @return the directory
+ */
+ public String getDirectory() {
+ return directory;
+ }
+
+ /**
+ * @param directory the directory to set
+ */
+ public void setDirectory(String directory) {
+ this.directory = directory;
+ }
+
+ /**
+ * @return the subDirectory
+ */
+ public String getSubDirectory() {
+ return subDirectory;
+ }
+
+ /**
+ * @param subDirectory the subDirectory to set
+ */
+ public void setSubDirectory(String subDirectory) {
+ this.subDirectory = subDirectory;
+ }
+
+ /**
+ * @return the fileName
+ */
+ public String getFileName() {
+ return fileName;
+ }
+
+ /**
+ * @param fileName the fileName to set
+ */
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public String getFullPath() {
+ return getDirectory() + "/" + getSubDirectory() + "/" + getFileName();
+ }
+
+ public ReferencedDataNature getDataNature() {
+ return ReferencedDataNature.values()[dataNatureInteger];
+ }
+
+ public void setDataNature(ReferencedDataNature dataNature) {
+ this.dataNatureInteger = dataNature.ordinal();
+ }
+
+ public String getCharset() {
+ return charset;
+ }
+
+ public void setCredentialManager(CredentialManager credentialManager) {
+ this.credentialManager = credentialManager;
+ }
+
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+ /**
+ * @return the dataNatureInteger
+ */
+ public int getDataNatureInteger() {
+ return dataNatureInteger;
+ }
+
+ /**
+ * @param dataNatureInteger the dataNatureInteger to set
+ */
+ public void setDataNatureInteger(int dataNatureInteger) {
+ this.dataNatureInteger = dataNatureInteger;
+ }
+
+ public SshReference clone() {
+ SshReference result = new SshReference();
+ result.setHost(this.getHost());
+ result.setPort(this.getPort());
+ result.setDirectory(this.getDirectory());
+ result.setSubDirectory(this.getSubDirectory());
+ result.setFileName(this.getFileName());
+ result.setDataNature(this.getDataNature());
+ result.setCharset(this.getCharset());
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrl.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrl.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrl.java
new file mode 100644
index 0000000..eb5f269
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrl.java
@@ -0,0 +1,153 @@
+/**
+ *
+ */
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import net.sf.taverna.t2.reference.ReferencedDataNature;
+
+/**
+ * @author alanrw
+ *
+ */
+public class SshUrl {
+
+ private SshNode sshNode;
+ private String subDirectory;
+ private String fileName;
+
+ private ReferencedDataNature dataNature = ReferencedDataNature.UNKNOWN;
+ private String charset = "UTF-8";
+
+
+ public SshUrl(SshNode sshNode) {
+ this.setSshNode(sshNode);
+ }
+
+
+ /**
+ * @return the host
+ */
+ public String getHost() {
+ return getSshNode().getHost();
+ }
+ /**
+ * @param host the host to set
+ */
+ public void setHost(String host) {
+ getSshNode().setHost(host);
+ }
+ /**
+ * @return the port
+ */
+ public int getPort() {
+ return getSshNode().getPort();
+ }
+ /**
+ * @param port the port to set
+ */
+ public void setPort(int port) {
+ getSshNode().setPort(port);
+ }
+ /**
+ * @return the directory
+ */
+ public String getDirectory() {
+ return getSshNode().getDirectory();
+ }
+ /**
+ * @param directory the directory to set
+ */
+ public void setDirectory(String directory) {
+ getSshNode().setDirectory(directory);
+ }
+ /**
+ * @return the subDirectory
+ */
+ public String getSubDirectory() {
+ return subDirectory;
+ }
+ /**
+ * @param subDirectory the subDirectory to set
+ */
+ public void setSubDirectory(String subDirectory) {
+ this.subDirectory = subDirectory;
+ }
+ /**
+ * @return the fileName
+ */
+ public String getFileName() {
+ return fileName;
+ }
+ /**
+ * @param fileName the fileName to set
+ */
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public String toString() {
+ String result = SshNodeFactory.makeUrl(getHost(), getPort(), getDirectory());
+ if (getSubDirectory() != null) {
+ result += getSubDirectory();
+ }
+ if (getFileName() != null) {
+ result += "/" + getFileName();
+ }
+ return result;
+ }
+
+ public int hashCode() {
+ return toString().hashCode();
+
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj == null) || !(obj instanceof SshUrl)) {
+ return false;
+ }
+ return (this.hashCode() == obj.hashCode());
+ }
+
+ public SshUrl getBaseUrl() {
+ SshUrl result = new SshUrl(this.getSshNode());
+ return result;
+ }
+
+
+ /**
+ * @return the sshNode
+ */
+ public SshNode getSshNode() {
+ return sshNode;
+ }
+
+
+ /**
+ * @param sshNode the sshNode to set
+ */
+ public void setSshNode(SshNode sshNode) {
+ this.sshNode = sshNode;
+ }
+
+ public ReferencedDataNature getDataNature() {
+ return dataNature;
+ }
+
+
+ public void setDataNature(ReferencedDataNature dataNature) {
+ this.dataNature = dataNature;
+ }
+
+
+ public String getCharset() {
+ return charset;
+ }
+
+
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrlToSshReference.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrlToSshReference.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrlToSshReference.java
new file mode 100644
index 0000000..6a9b2dc
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUrlToSshReference.java
@@ -0,0 +1,43 @@
+/**
+ *
+ */
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import net.sf.taverna.t2.reference.ExternalReferenceSPI;
+import net.sf.taverna.t2.reference.ReferenceContext;
+import net.sf.taverna.t2.reference.ValueToReferenceConversionException;
+import net.sf.taverna.t2.reference.ValueToReferenceConverterSPI;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+
+/**
+ * @author alanrw
+ *
+ */
+public class SshUrlToSshReference implements ValueToReferenceConverterSPI {
+
+ private CredentialManager credentialManager;
+
+ /* (non-Javadoc)
+ * @see net.sf.taverna.t2.reference.ValueToReferenceConverterSPI#canConvert(java.lang.Object, net.sf.taverna.t2.reference.ReferenceContext)
+ */
+ @Override
+ public boolean canConvert(Object o, ReferenceContext context) {
+ return (o instanceof SshUrl);
+ }
+
+ /* (non-Javadoc)
+ * @see net.sf.taverna.t2.reference.ValueToReferenceConverterSPI#convert(java.lang.Object, net.sf.taverna.t2.reference.ReferenceContext)
+ */
+ @Override
+ public ExternalReferenceSPI convert(Object o, ReferenceContext context)
+ throws ValueToReferenceConversionException {
+ SshReference result = new SshReference((SshUrl) o);
+ result.setCredentialManager(credentialManager);
+ return result;
+ }
+
+ public void setCredentialManager(CredentialManager credentialManager) {
+ this.credentialManager = credentialManager;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUseCaseInvocation.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUseCaseInvocation.java b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUseCaseInvocation.java
new file mode 100755
index 0000000..29e475d
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/de/uni_luebeck/inb/knowarc/usecases/invocation/ssh/SshUseCaseInvocation.java
@@ -0,0 +1,563 @@
+/* Part of the KnowARC Janitor Use-case processor for taverna
+ * written 2007-2010 by Hajo Nils Krabbenhoeft and Steffen Moeller
+ * University of Luebeck, Institute for Neuro- and Bioinformatics
+ * University of Luebeck, Institute for Dermatolgy
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this package; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package de.uni_luebeck.inb.knowarc.usecases.invocation.ssh;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.Vector;
+import java.util.regex.Matcher;
+
+import net.sf.taverna.t2.activities.externaltool.RetrieveLoginFromTaverna;
+import net.sf.taverna.t2.reference.AbstractExternalReference;
+import net.sf.taverna.t2.reference.ErrorDocument;
+import net.sf.taverna.t2.reference.ErrorDocumentServiceException;
+import net.sf.taverna.t2.reference.ExternalReferenceSPI;
+import net.sf.taverna.t2.reference.Identified;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.ReferenceSet;
+import net.sf.taverna.t2.reference.ReferencedDataNature;
+import net.sf.taverna.t2.reference.T2Reference;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+
+import org.apache.log4j.Logger;
+
+import com.jcraft.jsch.ChannelExec;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpException;
+import com.jcraft.jsch.ChannelSftp.LsEntry;
+
+import de.uni_luebeck.inb.knowarc.usecases.ScriptInput;
+import de.uni_luebeck.inb.knowarc.usecases.ScriptOutput;
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.AskUserForPw;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.InvocationException;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.UseCaseInvocation;
+
+/**
+ * The job is executed by connecting to a worker pc using ssh, i.e. not via the
+ * grid.
+ *
+ * @author Hajo Krabbenhoeft
+ */
+public class SshUseCaseInvocation extends UseCaseInvocation {
+
+ private static Logger logger = Logger.getLogger(SshUseCaseInvocation.class);
+
+ private SshUrl location = null;
+
+ private InputStream stdInputStream = null;
+
+ public static final String SSH_USE_CASE_INVOCATION_TYPE = "D0A4CDEB-DD10-4A8E-A49C-8871003083D8";
+ private String tmpname;
+ private final SshNode workerNode;
+ private final AskUserForPw askUserForPw;
+
+ private ChannelExec running;
+
+ private List<String> precedingCommands = new ArrayList<String>();
+
+ private final ByteArrayOutputStream stdout_buf = new ByteArrayOutputStream();
+ private final ByteArrayOutputStream stderr_buf = new ByteArrayOutputStream();
+
+ private static Map<String, Object> nodeLock = Collections
+ .synchronizedMap(new HashMap<String, Object>());
+
+ private static Map<String, Set<SshUrl>> runIdToTempDir = Collections
+ .synchronizedMap(new HashMap<String, Set<SshUrl>>());
+
+ private static String SSH_INVOCATION_FILE = "sshInvocations";
+
+ private final CredentialManager credentialManager;
+
+ public static String test(final SshNode workerNode,
+ final AskUserForPw askUserForPw) {
+ try {
+ Session sshSession = SshPool
+ .getSshSession(workerNode, askUserForPw);
+
+ ChannelSftp sftpTest = (ChannelSftp) sshSession.openChannel("sftp");
+ sftpTest.connect();
+ sftpTest.cd(workerNode.getDirectory());
+ sftpTest.disconnect();
+ sshSession.disconnect();
+ } catch (JSchException e) {
+ return e.toString();
+ } catch (SftpException e) {
+ return e.toString();
+ }
+ return null;
+ }
+
+ public SshUseCaseInvocation(UseCaseDescription desc, SshNode workerNodeA,
+ AskUserForPw askUserForPwA, CredentialManager credentialManager)
+ throws JSchException, SftpException {
+ this.workerNode = workerNodeA;
+ this.credentialManager = credentialManager;
+
+ setRetrieveData(workerNodeA.isRetrieveData());
+ this.askUserForPw = askUserForPwA;
+ usecase = desc;
+
+ ChannelSftp sftp = SshPool.getSftpPutChannel(workerNode, askUserForPw);
+ synchronized (getNodeLock(workerNode)) {
+
+ logger.info("Changing remote directory to "
+ + workerNode.getDirectory());
+ sftp.cd(workerNode.getDirectory());
+ Random rnd = new Random();
+ while (true) {
+ tmpname = "usecase" + rnd.nextLong();
+ try {
+ sftp.lstat(workerNode.getDirectory() + tmpname);
+ continue;
+ } catch (Exception e) {
+ // file seems to not exist :)
+ }
+ sftp.mkdir(workerNode.getDirectory() + tmpname);
+ sftp.cd(workerNode.getDirectory() + tmpname);
+ break;
+ }
+ }
+ }
+
+ private static void recursiveDelete(ChannelSftp sftp, String path)
+ throws SftpException, JSchException {
+ Vector<?> entries = sftp.ls(path);
+ for (Object object : entries) {
+ LsEntry entry = (LsEntry) object;
+ if (entry.getFilename().equals(".")
+ || entry.getFilename().equals("..")) {
+ continue;
+ }
+ if (entry.getAttrs().isDir()) {
+ recursiveDelete(sftp, path + entry.getFilename() + "/");
+ } else {
+ sftp.rm(path + entry.getFilename());
+ }
+ }
+ sftp.rmdir(path);
+ }
+
+ private static void deleteDirectory(SshUrl directory,
+ CredentialManager credentialManager) throws InvocationException {
+ URI uri;
+ try {
+ uri = new URI(directory.toString());
+
+ ChannelSftp sftp;
+ SshNode workerNode;
+ String fullPath = uri.getPath();
+ String path = fullPath.substring(0, fullPath.lastIndexOf("/"));
+ String tempDir = fullPath.substring(fullPath.lastIndexOf("/"));
+ try {
+ workerNode = SshNodeFactory.getInstance().getSshNode(
+ uri.getHost(), uri.getPort(), path);
+
+ sftp = SshPool.getSftpPutChannel(workerNode,
+ new RetrieveLoginFromTaverna(workerNode.getUrl()
+ .toString(), credentialManager));
+ } catch (JSchException e) {
+ throw new InvocationException(e);
+ }
+ synchronized (getNodeLock(workerNode)) {
+ try {
+ sftp.cd(path);
+ recursiveDelete(sftp, path + "/" + tempDir + "/");
+ } catch (SftpException e) {
+ throw new InvocationException(e);
+ } catch (JSchException e) {
+ throw new InvocationException(e);
+ }
+ }
+ } catch (URISyntaxException e1) {
+ throw new InvocationException(e1);
+ }
+ }
+
+ public static void cleanup(String runId, CredentialManager credentialManager)
+ throws InvocationException {
+ Set<SshUrl> tempDirectories = runIdToTempDir.get(runId);
+ if (tempDirectories != null) {
+ for (SshUrl tempUrl : tempDirectories) {
+ deleteDirectory(tempUrl, credentialManager);
+ }
+ runIdToTempDir.remove(runId);
+ }
+ }
+
+ @Override
+ protected void submit_generate_job_inner() throws InvocationException {
+ tags.put("uniqueID", "" + getSubmissionID());
+ String command = usecase.getCommand();
+ for (String cur : tags.keySet()) {
+ command = command.replaceAll("\\Q%%" + cur + "%%\\E",
+ Matcher.quoteReplacement(tags.get(cur)));
+ }
+ String fullCommand = "cd " + workerNode.getDirectory() + tmpname;
+ for (String preceding : precedingCommands) {
+ fullCommand += " && " + preceding;
+ }
+ fullCommand += " && " + command;
+
+ logger.info("Full command is " + fullCommand);
+
+ try {
+ running = SshPool.openExecChannel(workerNode, askUserForPw);
+ running.setCommand(fullCommand);
+ running.setOutputStream(stdout_buf);
+ running.setErrStream(stderr_buf);
+ if (stdInputStream != null) {
+ running.setInputStream(stdInputStream);
+ }
+ running.connect();
+ } catch (JSchException e) {
+ throw new InvocationException(e);
+ }
+
+ }
+
+ @Override
+ public HashMap<String, Object> submit_wait_fetch_results(
+ ReferenceService referenceService) throws InvocationException {
+ while (!running.isClosed()) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ throw new InvocationException("Invocation interrupted:"
+ + e.getMessage());
+ }
+ }
+
+ int exitcode = running.getExitStatus();
+ if (!usecase.getValidReturnCodes().contains(exitcode)) {
+ try {
+ throw new InvocationException("Invalid exit code " + exitcode
+ + ":" + stderr_buf.toString("US-ASCII"));
+ } catch (UnsupportedEncodingException e) {
+ throw new InvocationException("Invalid exit code " + exitcode
+ + ":" + stderr_buf.toString());
+ }
+ }
+
+ HashMap<String, Object> results = new HashMap<String, Object>();
+
+ results.put("STDOUT", stdout_buf.toByteArray());
+ results.put("STDERR", stderr_buf.toByteArray());
+ try {
+ stdout_buf.close();
+ stderr_buf.close();
+ } catch (IOException e2) {
+ throw new InvocationException(e2);
+ }
+
+ try {
+ ChannelSftp sftp = SshPool.getSftpPutChannel(workerNode,
+ askUserForPw);
+ synchronized (getNodeLock(workerNode)) {
+ for (Map.Entry<String, ScriptOutput> cur : usecase.getOutputs()
+ .entrySet()) {
+ ScriptOutput scriptOutput = cur.getValue();
+ String fullPath = workerNode.getDirectory() + tmpname + "/"
+ + scriptOutput.getPath();
+ try {
+ if (sftp.stat(fullPath) != null) {
+ SshUrl url = new SshUrl(workerNode);
+ url.setSubDirectory(tmpname);
+ url.setFileName(scriptOutput.getPath());
+ if (scriptOutput.isBinary()) {
+ url.setDataNature(ReferencedDataNature.BINARY);
+ } else {
+ url.setDataNature(ReferencedDataNature.TEXT);
+ url.setCharset("UTF-8");
+ }
+ if (isRetrieveData()) {
+ SshReference urlRef = new SshReference(url);
+ InputStream is = urlRef.openStream(null);
+ AbstractExternalReference ref;
+ if (scriptOutput.isBinary()) {
+ ref = inlineByteArrayReferenceBuilder
+ .createReference(is, null);
+ } else {
+ ref = inlineStringReferenceBuilder
+ .createReference(is, null);
+ }
+ try {
+ is.close();
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ results.put(cur.getKey(), ref);
+ } else {
+ results.put(cur.getKey(), url);
+ }
+ } else {
+ ErrorDocument ed = referenceService
+ .getErrorDocumentService().registerError(
+ "No result for " + cur.getKey(), 0,
+ getContext());
+ results.put(cur.getKey(), ed);
+ }
+ } catch (SftpException e) {
+ ErrorDocument ed = referenceService
+ .getErrorDocumentService().registerError(
+ "No result for " + cur.getKey(), 0,
+ getContext());
+ results.put(cur.getKey(), ed);
+
+ }
+ }
+ }
+ } catch (JSchException e1) {
+ throw new InvocationException(e1);
+ } catch (ErrorDocumentServiceException e) {
+ throw new InvocationException(e);
+ }
+
+ if (running != null) {
+ running.disconnect();
+ }
+ if (stdInputStream != null) {
+ try {
+ stdInputStream.close();
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ }
+
+ if (isRetrieveData()) {
+ forgetRun();
+ deleteDirectory(location, credentialManager);
+
+ }
+ return results;
+ }
+
+ @Override
+ public String setOneInput(ReferenceService referenceService,
+ T2Reference t2Reference, ScriptInput input)
+ throws InvocationException {
+ String target = null;
+ String remoteName = null;
+ if (input.isFile()) {
+ remoteName = input.getTag();
+ } else if (input.isTempFile()) {
+ remoteName = "tempfile." + (nTempFiles++) + ".tmp";
+
+ }
+ if (input.isFile() || input.isTempFile()) {
+ SshReference sshRef = getAsSshReference(referenceService,
+ t2Reference, workerNode);
+ target = workerNode.getDirectory() + tmpname + "/" + remoteName;
+ logger.info("Target is " + target);
+ if (sshRef != null) {
+ if (!input.isForceCopy()) {
+ String linkCommand = workerNode.getLinkCommand();
+ if (linkCommand != null) {
+ String actualLinkCommand = getActualOsCommand(
+ linkCommand, sshRef.getFullPath(), remoteName,
+ target);
+ precedingCommands.add(actualLinkCommand);
+ return target;
+
+ }
+ }
+ String copyCommand = workerNode.getCopyCommand();
+ if (copyCommand != null) {
+ String actualCopyCommand = getActualOsCommand(copyCommand,
+ sshRef.getFullPath(), remoteName, target);
+ precedingCommands.add(actualCopyCommand);
+ return target;
+ }
+ }
+ try {
+ ChannelSftp sftp = SshPool.getSftpPutChannel(workerNode,
+ askUserForPw);
+ synchronized (getNodeLock(workerNode)) {
+ InputStream r = getAsStream(referenceService, t2Reference);
+ sftp.put(r, target);
+ r.close();
+ }
+ } catch (SftpException e) {
+ throw new InvocationException(e);
+ } catch (JSchException e) {
+ throw new InvocationException(e);
+ } catch (IOException e) {
+ throw new InvocationException(e);
+ }
+ return target;
+ } else {
+ String value = (String) referenceService.renderIdentifier(
+ t2Reference, String.class, this.getContext());
+ return value;
+
+ }
+ }
+
+ public SshReference getAsSshReference(ReferenceService referenceService,
+ T2Reference t2Reference, SshNode workerNode) {
+ Identified identified = referenceService.resolveIdentifier(t2Reference,
+ null, null);
+ if (identified instanceof ReferenceSet) {
+ for (ExternalReferenceSPI ref : ((ReferenceSet) identified)
+ .getExternalReferences()) {
+ if (ref instanceof SshReference) {
+ SshReference sshRef = (SshReference) ref;
+ if (sshRef.getHost().equals(workerNode.getHost())) {
+ return sshRef;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static Object getNodeLock(final SshNode node) {
+ return getNodeLock(node.getHost());
+ }
+
+ private static synchronized Object getNodeLock(String hostName) {
+ if (!nodeLock.containsKey(hostName)) {
+ nodeLock.put(hostName, new Object());
+ }
+ return nodeLock.get(hostName);
+ }
+
+ @Override
+ public void setStdIn(ReferenceService referenceService,
+ T2Reference t2Reference) {
+ stdInputStream = new BufferedInputStream(getAsStream(referenceService,
+ t2Reference));
+ }
+
+ @Override
+ public void rememberRun(String runId) {
+ this.setRunId(runId);
+ Set<SshUrl> directories = runIdToTempDir.get(runId);
+ if (directories == null) {
+ directories = Collections.synchronizedSet(new HashSet<SshUrl>());
+ runIdToTempDir.put(runId, directories);
+ }
+ location = new SshUrl(workerNode);
+ location.setSubDirectory(tmpname);
+ directories.add(location);
+ }
+
+ private void forgetRun() {
+ Set<SshUrl> directories = runIdToTempDir.get(getRunId());
+ directories.remove(location);
+ }
+
+ public static void load(File directory) {
+ File invocationsFile = new File(directory, SSH_INVOCATION_FILE);
+ if (!invocationsFile.exists()) {
+ return;
+ }
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(invocationsFile));
+ String line = reader.readLine();
+ while (line != null) {
+ String[] parts = line.split(" ");
+ if (parts.length != 2) {
+ break;
+ }
+ String runId = parts[0];
+ String urlString = parts[1];
+ Set<SshUrl> urls = runIdToTempDir.get(runId);
+ if (urls == null) {
+ urls = new HashSet<SshUrl>();
+ runIdToTempDir.put(runId, urls);
+ }
+ URI uri = new URI(urlString);
+ String fullPath = uri.getPath();
+ String path = fullPath.substring(0, fullPath.lastIndexOf("/"));
+ String tempDir = fullPath.substring(fullPath.lastIndexOf("/"));
+ SshNode node = SshNodeFactory.getInstance().getSshNode(
+ uri.getHost(), uri.getPort(), path);
+ SshUrl newUrl = new SshUrl(node);
+ newUrl.setSubDirectory(tempDir);
+ urls.add(newUrl);
+ line = reader.readLine();
+ }
+ } catch (FileNotFoundException e) {
+ logger.error(e);
+ } catch (URISyntaxException e) {
+ logger.error(e);
+ } catch (IOException e) {
+ logger.error(e);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ logger.error(e);
+ }
+ }
+ }
+ }
+
+ public static void persist(File directory) {
+ File invocationsFile = new File(directory, SSH_INVOCATION_FILE);
+ BufferedWriter writer = null;
+ try {
+ writer = new BufferedWriter(new FileWriter(invocationsFile));
+ for (String runId : runIdToTempDir.keySet()) {
+ for (SshUrl url : runIdToTempDir.get(runId)) {
+ writer.write(runId);
+ writer.write(" ");
+ writer.write(url.toString());
+ writer.newLine();
+ }
+ }
+ } catch (IOException e) {
+ logger.error(e);
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ logger.error(e);
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivity.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivity.java b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivity.java
new file mode 100755
index 0000000..1e6ef77
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivity.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (C) 2009 Hajo Nils Krabbenhoeft, INB, University of Luebeck
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+
+package net.sf.taverna.t2.activities.externaltool;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroup;
+import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanism;
+import net.sf.taverna.t2.annotation.Annotated;
+import net.sf.taverna.t2.annotation.annotationbeans.MimeType;
+import net.sf.taverna.t2.reference.ExternalReferenceSPI;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.T2Reference;
+import net.sf.taverna.t2.reference.WorkflowRunIdEntity;
+import net.sf.taverna.t2.workflowmodel.EditException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.AsynchronousActivityCallback;
+
+import org.apache.log4j.Logger;
+
+import de.uni_luebeck.inb.knowarc.usecases.ScriptInput;
+import de.uni_luebeck.inb.knowarc.usecases.ScriptInputUser;
+import de.uni_luebeck.inb.knowarc.usecases.ScriptOutput;
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.InvocationException;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.UseCaseInvocation;
+
+/**
+ * This is the main class of the use case activity plugin. Here we store the
+ * configuration and the description of a use case activity, configure the input
+ * and output port and provide use case activity invocation
+ *
+ * @author Hajo Nils Krabbenhoeft
+ */
+public class ExternalToolActivity extends AbstractAsynchronousActivity<ExternalToolActivityConfigurationBean> {
+
+ public static final String URI = "http://ns.taverna.org.uk/2010/activity/tool";
+
+ private static final String STDERR = "STDERR";
+
+ private static final String STDOUT = "STDOUT";
+
+ private static final String STDIN = "STDIN";
+
+ private static Logger logger = Logger.getLogger(ExternalToolActivity.class);
+
+ private ExternalToolActivityConfigurationBean configurationBean;
+ private UseCaseDescription mydesc;
+
+ private List<InvocationCreator> invocationCreators;
+
+ /**
+ * Add the given MIME types to the given input/output port.
+ *
+ * @param annotated
+ * The port to which to add the MIME types.
+ * @param mimeTypes
+ * A list of Strings specifying the MIME types to add.
+ */
+ private void addMimeTypes(Annotated<?> annotated, List<String> mimeTypes) {
+ for (String mimeType : mimeTypes) {
+ MimeType mimeTypeAnnotation = new MimeType();
+ mimeTypeAnnotation.setText(mimeType);
+ try {
+ getEdits().getAddAnnotationChainEdit(annotated, mimeTypeAnnotation).doEdit();
+ } catch (EditException e) {
+ Logger.getLogger(ExternalToolActivity.class).error(e);
+ }
+ }
+ }
+
+ /**
+ * Create a new input port with the given name, depth, element class and
+ * MIME types.
+ *
+ * @param portName
+ * Name of the new port
+ * @param portDepth
+ * Depth of the new port
+ * @param translatedElementClass
+ * Which class of elements would this port like?
+ * @param mimeTypes
+ * Accepted mime types for this port
+ */
+ private void addInputWithMime(String portName, int portDepth, Class<?> translatedElementClass, List<String> mimeTypes) {
+ List<Class<? extends ExternalReferenceSPI>> handledReferenceSchemes = Collections.emptyList();
+ ActivityInputPort inputPort = getEdits().createActivityInputPort(portName, portDepth, true, handledReferenceSchemes,
+ translatedElementClass);
+ inputPorts.add(inputPort);
+ if (mimeTypes != null) {
+ addMimeTypes(inputPort, mimeTypes);
+ }
+ }
+
+ /**
+ * Create a new output port with the given MIME types
+ *
+ * @param portName
+ * Name of the new port
+ * @param portDepth
+ * Depth of the new port
+ * @param mimeTypes
+ * Accepted mime types for this port
+ */
+ private void addOutputWithMime(String portName, int portDepth, List<String> mimeTypes) {
+ ActivityOutputPort outputPort = getEdits().createActivityOutputPort(portName, portDepth, portDepth);
+ outputPorts.add(outputPort);
+ addMimeTypes(outputPort, mimeTypes);
+ }
+
+ @Override
+ public void configure(ExternalToolActivityConfigurationBean bean) throws ActivityConfigurationException {
+ this.configurationBean = bean;
+
+ try {
+ mydesc = bean.getUseCaseDescription();
+
+ inputPorts.clear();
+ outputPorts.clear();
+
+ if (mydesc != null) {
+
+ // loop through all script inputs and add them as taverna activity
+ // input ports
+ for (Map.Entry<String, ScriptInput> cur : mydesc.getInputs().entrySet()) {
+ ScriptInputUser scriptInputUser = (ScriptInputUser) cur.getValue();
+ // if the input port is a list, depth is 1 otherwise it is a
+ // single element, therefore depth 0
+ // if the input port is binary, we would like byte arrays,
+ // otherwise we require strings
+ addInputWithMime(cur.getKey(), scriptInputUser.isList() ? 1 : 0, cur.getValue().isBinary() ? byte[].class : String.class, scriptInputUser.getMime());
+
+ }
+ // loop through all script outputs and add them to taverna
+ for (Map.Entry<String, ScriptOutput> cur : mydesc.getOutputs().entrySet()) {
+ addOutputWithMime(cur.getKey(), 0, cur.getValue().getMime());
+ }
+ }
+
+ if (mydesc.isIncludeStdIn()) {
+ addInputWithMime(STDIN, 0, byte[].class, null);
+ }
+ if (mydesc.isIncludeStdOut()) {
+ addOutput(STDOUT, 0);
+ }
+ if (mydesc.isIncludeStdErr()) {
+ addOutput(STDERR, 0);
+ }
+ } catch (Exception e) {
+ throw new ActivityConfigurationException("Couldn't create ExternalTool Activity", e);
+ }
+ }
+
+ @Override
+ public ExternalToolActivityConfigurationBean getConfiguration() {
+ if (configurationBean != null) {
+ InvocationGroup invocationGroup = configurationBean.getInvocationGroup();
+ if (invocationGroup == null) {
+ if (configurationBean.getMechanism() != null) {
+ configurationBean.convertMechanismToDetails();
+ }
+ } else {
+ if (invocationGroup.getMechanism() != null) {
+ invocationGroup.convertMechanismToDetails();
+ }
+ }
+ }
+ return configurationBean;
+ }
+
+ public ExternalToolActivityConfigurationBean getConfigurationNoConversion() {
+ return configurationBean;
+ }
+
+ public InvocationMechanism recreateMechanism() {
+ if (configurationBean.getInvocationGroup() != null) {
+ if (configurationBean.getInvocationGroup().getMechanism() == null) {
+ configurationBean.getInvocationGroup().convertDetailsToMechanism();
+ }
+ return configurationBean.getInvocationGroup().getMechanism();
+ } else {
+ if (configurationBean.getMechanism() == null) {
+ configurationBean.convertDetailsToMechanism();
+ }
+ return configurationBean.getMechanism();
+ }
+ }
+
+ @Override
+ public void executeAsynch(final Map<String, T2Reference> data, final AsynchronousActivityCallback callback) {
+
+ callback.requestRun(new Runnable() {
+
+ public void run() {
+ ReferenceService referenceService = callback.getContext().getReferenceService();
+ UseCaseInvocation invoke = null;
+
+ /**
+ * Note that retrying needs to be either done via Taverna's retry mechanism or as part of the specific invocation
+ */
+ try {
+
+ invoke = getInvocation(recreateMechanism(),
+ configurationBean.getUseCaseDescription(), data, referenceService);
+ if (invoke == null) {
+ logger.error("Invoke is null");
+ callback.fail("No invocation mechanism found");
+ }
+ String runId = callback.getContext()
+ .getEntities(WorkflowRunIdEntity.class).get(0)
+ .getWorkflowRunId();
+ logger.info("Run id is " + runId);
+ invoke.rememberRun(runId);
+
+ invoke.setContext(callback.getContext());
+
+ // look at every use dynamic case input
+ for (String cur : invoke.getInputs()) {
+ if (!cur.equals(STDIN)) {
+ invoke.setInput(cur, referenceService,
+ data.get(cur));
+ }
+ }
+
+ if (mydesc.isIncludeStdIn() && (data.get(STDIN) != null)) {
+ invoke.setStdIn(referenceService, data.get(STDIN));
+ }
+
+ // submit the use case to its invocation mechanism
+ invoke.submit_generate_job(referenceService);
+
+ // retrieve the result.
+ Map<String, Object> downloads = invoke
+ .submit_wait_fetch_results(referenceService);
+ Map<String, T2Reference> result = new HashMap<String, T2Reference>();
+ for (Map.Entry<String, Object> cur : downloads.entrySet()) {
+ Object value = cur.getValue();
+
+ // register the result value with taverna
+ T2Reference reference = referenceService.register(
+ value, 0, true, callback.getContext());
+
+ // store the reference into the activity result
+ // set
+ result.put(cur.getKey(), reference);
+ }
+ callback.receiveResult(result, new int[0]);
+ } catch (InvocationException e) {
+ callback.fail(e.getMessage(), e);
+ }
+ }
+
+ });
+
+ }
+
+ public void setInvocationCreators(List<InvocationCreator> invocationCreators) {
+ this.invocationCreators = invocationCreators;
+ }
+
+ private UseCaseInvocation getInvocation(InvocationMechanism mechanism, UseCaseDescription description, Map<String, T2Reference> data, ReferenceService referenceService) {
+ UseCaseInvocation result = null;
+ InvocationCreator creator = null;
+ for (InvocationCreator c : invocationCreators) {
+ if (c.canHandle(mechanism.getType())) {
+ creator = c;
+ break;
+ }
+ }
+ if (creator != null) {
+ result = creator.convert(mechanism, description, data, referenceService);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityConfigurationBean.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityConfigurationBean.java b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityConfigurationBean.java
new file mode 100755
index 0000000..ce3387b
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityConfigurationBean.java
@@ -0,0 +1,194 @@
+package net.sf.taverna.t2.activities.externaltool;
+
+import java.util.List;
+
+import net.sf.taverna.t2.activities.externaltool.manager.InvocationGroup;
+import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanism;
+import net.sf.taverna.t2.activities.externaltool.manager.MechanismCreator;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+
+@ConfigurationBean(uri = ExternalToolActivity.URI + "#Config")
+public final class ExternalToolActivityConfigurationBean {
+
+ private InvocationGroup group;
+
+ private String mechanismType;
+
+ private String mechanismName;
+
+ private String mechanismXML;
+
+ private transient InvocationMechanism mechanism;
+
+ protected String repositoryUrl;
+ protected String externaltoolid;
+ protected UseCaseDescription useCaseDescription = null;
+ private boolean edited = false;
+
+ private List<MechanismCreator> mechanismCreators;
+
+ public boolean isEdited() {
+ return edited;
+ }
+
+ public ExternalToolActivityConfigurationBean() {
+ }
+
+ public InvocationGroup getInvocationGroup() {
+ return group;
+ }
+
+ @ConfigurationProperty(name = "invocationGroup", label = "InvocationGroup", required=false)
+ public void setInvocationGroup(
+ InvocationGroup group) {
+ this.group = group;
+ clearMechanismInformation();
+ }
+
+ private void clearMechanismInformation() {
+ this.mechanismType = null;
+ this.mechanismName = null;
+ this.mechanismXML = null;
+ this.mechanism = null;
+ }
+
+ /**
+ * @return the repositoryUrl
+ */
+ public String getRepositoryUrl() {
+ return repositoryUrl;
+ }
+
+ /**
+ * @param repositoryUrl the repositoryUrl to set
+ */
+ @ConfigurationProperty(name = "repositoryUrl", label = "Repository URL", required=false)
+ public void setRepositoryUrl(String repositoryUrl) {
+ this.repositoryUrl = repositoryUrl;
+ }
+
+ /**
+ * @return the externaltoolid
+ */
+ public String getExternaltoolid() {
+ return externaltoolid;
+ }
+
+ /**
+ * @param externaltoolid the externaltoolid to set
+ */
+ @ConfigurationProperty(name = "toolId", label = "Tool ID")
+ public void setExternaltoolid(String externaltoolid) {
+ this.externaltoolid = externaltoolid;
+ }
+
+ /**
+ * @return the useCaseDescription
+ */
+ public UseCaseDescription getUseCaseDescription() {
+ return useCaseDescription;
+ }
+
+ /**
+ * @param useCaseDescription the useCaseDescription to set
+ */
+ @ConfigurationProperty(name = "toolDescription", label = "Tool Description")
+ public void setUseCaseDescription(UseCaseDescription useCaseDescription) {
+ this.useCaseDescription = useCaseDescription;
+ }
+
+ @ConfigurationProperty(name = "edited", label = "Edited", required=false)
+ public void setEdited(boolean b) {
+ this.edited = b;
+ }
+
+ /**
+ * Note this also sets the details
+ *
+ * @param mechanism the mechanism to set
+ */
+ public void setMechanism(InvocationMechanism mechanism) {
+ this.mechanism = mechanism;
+ convertMechanismToDetails();
+ this.group = null;
+ }
+
+ public void convertMechanismToDetails() {
+ if (mechanism != null) {
+ this.setMechanismXML(mechanism.getXML());
+ this.setMechanismName(mechanism.getName());
+ this.setMechanismType(mechanism.getType());
+ }
+ }
+
+ /**
+ * @param mechanismType the mechanismType to set
+ */
+ @ConfigurationProperty(name = "mechanismType", label = "Mechanism Type", required=false)
+ public void setMechanismType(String mechanismType) {
+ this.mechanismType = mechanismType;
+ }
+
+ /**
+ * @param mechanismName the mechanismName to set
+ */
+ @ConfigurationProperty(name = "mechanismName", label = "Mechanism Name", required=false)
+ public void setMechanismName(String mechanismName) {
+ this.mechanismName = mechanismName;
+ }
+
+ /**
+ * @param mechanismXML the mechanismXML to set
+ */
+ @ConfigurationProperty(name = "mechanismXML", label = "Mechanism XML", required=false)
+ public void setMechanismXML(String mechanismXML) {
+ this.mechanismXML = mechanismXML;
+ }
+
+ public void convertDetailsToMechanism() {
+ if (mechanismXML != null) {
+ for (MechanismCreator mc : mechanismCreators) {
+ if (mc.canHandle(getMechanismType())) {
+ mechanism = mc.convert(getMechanismXML(), getMechanismName());
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return the mechanism
+ */
+ public InvocationMechanism getMechanism() {
+
+ return mechanism;
+ }
+
+ /**
+ * @return the mechanismType
+ */
+ public String getMechanismType() {
+ return mechanismType;
+ }
+
+ /**
+ * @return the mechanismName
+ */
+ public String getMechanismName() {
+ return mechanismName;
+ }
+
+ /**
+ * @return the mechanismXML
+ */
+ public String getMechanismXML() {
+ return mechanismXML;
+ }
+
+ public void setMechanismCreators(List<MechanismCreator> mechanismCreators) {
+ this.mechanismCreators = mechanismCreators;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/390c286b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityFactory.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityFactory.java b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityFactory.java
new file mode 100644
index 0000000..dc27b11
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/net/sf/taverna/t2/activities/externaltool/ExternalToolActivityFactory.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.externaltool;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import net.sf.taverna.t2.activities.externaltool.manager.MechanismCreator;
+import net.sf.taverna.t2.workflowmodel.Edits;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityFactory;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
+
+/**
+ * An {@link ActivityFactory} for creating <code>ExternalToolActivity</code>.
+ *
+ * @author David Withers
+ */
+public class ExternalToolActivityFactory implements ActivityFactory {
+
+ private List<InvocationCreator> invocationCreators;
+
+ private List<MechanismCreator> mechanismCreators;
+
+ private Edits edits;
+
+ @Override
+ public ExternalToolActivity createActivity() {
+ ExternalToolActivity activity = new ExternalToolActivity();
+ activity.setInvocationCreators(invocationCreators);
+ activity.setEdits(edits);
+ return activity;
+ }
+
+ @Override
+ public URI getActivityType() {
+ return URI.create(ExternalToolActivity.URI);
+ }
+
+ @Override
+ public JsonNode getActivityConfigurationSchema() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ try {
+ return objectMapper.readTree(getClass().getResource("/schema.json"));
+ } catch (IOException e) {
+ return objectMapper.createObjectNode();
+ }
+ }
+
+ public void setInvocationCreators(List<InvocationCreator> invocationCreators) {
+ this.invocationCreators = invocationCreators;
+ }
+
+ public void setMechanismCreators(List<MechanismCreator> mechanismCreators) {
+ this.mechanismCreators = mechanismCreators;
+ }
+
+ @Override
+ public Set<ActivityInputPort> getInputPorts(JsonNode configuration)
+ throws ActivityConfigurationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Set<ActivityOutputPort> getOutputPorts(JsonNode configuration)
+ throws ActivityConfigurationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setEdits(Edits edits) {
+ this.edits = edits;
+ }
+
+}