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/17 12:29:45 UTC
[41/50] [abbrv] incubator-taverna-server git commit: Rewrite code,
pass back parsed URs.
Rewrite code, pass back parsed URs.
Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/commit/a1c27cd9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/tree/a1c27cd9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/diff/a1c27cd9
Branch: refs/heads/master
Commit: a1c27cd94e45bde58693df30472e2b34fcf1e07b
Parents: e5bc8be
Author: Donal Fellows <do...@manchester.ac.uk>
Authored: Tue Jul 1 14:18:21 2014 +0100
Committer: Donal Fellows <do...@manchester.ac.uk>
Committed: Tue Jul 1 14:18:21 2014 +0100
----------------------------------------------------------------------
server-client/pom.xml | 5 +
.../uk/org/taverna/server/client/Connected.java | 20 +
.../uk/org/taverna/server/client/DirEntry.java | 39 ++
.../uk/org/taverna/server/client/Directory.java | 94 ++++
.../java/uk/org/taverna/server/client/File.java | 95 ++++
.../uk/org/taverna/server/client/Property.java | 18 +
.../java/uk/org/taverna/server/client/Run.java | 215 ++++++++
.../uk/org/taverna/server/client/Status.java | 36 ++
.../taverna/server/client/TavernaServer.java | 493 ++-----------------
.../client/TavernaServerConnectionFactory.java | 23 +
.../main/java/org/ogf/usage/JobUsageRecord.java | 23 +-
11 files changed, 617 insertions(+), 444 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/pom.xml
----------------------------------------------------------------------
diff --git a/server-client/pom.xml b/server-client/pom.xml
index 397f102..bac3ea5 100644
--- a/server-client/pom.xml
+++ b/server-client/pom.xml
@@ -30,6 +30,11 @@
<artifactId>tika-core</artifactId>
<version>1.5</version>
</dependency>
+ <dependency>
+ <groupId>uk.org.taverna.server</groupId>
+ <artifactId>server-usagerecord</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/Connected.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Connected.java b/server-client/src/main/java/uk/org/taverna/server/client/Connected.java
new file mode 100644
index 0000000..263034c
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/Connected.java
@@ -0,0 +1,20 @@
+package uk.org.taverna.server.client;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+abstract class Connected {
+ void checkError(ClientResponse response) throws ClientException,
+ ServerException {
+ ClientResponse.Status s = response.getClientResponseStatus();
+ if (s.getStatusCode() == 401)
+ throw new TavernaServer.AuthorizationException("not authorized",
+ null);
+ if (s.getStatusCode() >= 500)
+ throw new TavernaServer.ServerException(s.getReasonPhrase(), null);
+ if (s.getStatusCode() >= 400)
+ throw new TavernaServer.ClientException(s.getReasonPhrase(), null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java b/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
new file mode 100644
index 0000000..267707d
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
@@ -0,0 +1,39 @@
+package uk.org.taverna.server.client;
+
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd.Path2;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public abstract class DirEntry extends Connected {
+ final Path2 handle;
+ final String path;
+ final Run run;
+
+ protected DirEntry(Run run, String path) {
+ this.run = run;
+ this.path = path.replaceFirst("/+$", "");
+ this.handle = run.run.wd().path2(this.path);
+ }
+
+ public void delete() throws ClientException, ServerException {
+ checkError(handle.deleteAsXml(ClientResponse.class));
+ }
+
+ String path(ClientResponse response) throws ClientException, ServerException {
+ checkError(response);
+ String[] bits = response.getLocation().getPath().split("/");
+ return concat(bits[bits.length - 1]);
+ }
+
+ String localName() {
+ String[] bits = path.split("/");
+ return bits[bits.length - 1];
+ }
+
+ String concat(String name) {
+ return path + "/" + name.split("/", 2)[0];
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/Directory.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Directory.java b/server-client/src/main/java/uk/org/taverna/server/client/Directory.java
new file mode 100644
index 0000000..38dc394
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/Directory.java
@@ -0,0 +1,94 @@
+package uk.org.taverna.server.client;
+
+import static java.io.File.createTempFile;
+import static javax.ws.rs.client.Entity.entity;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipFile;
+
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+import uk.org.taverna.server.client.generic.DirectoryEntry;
+import uk.org.taverna.server.client.generic.DirectoryReference;
+import uk.org.taverna.server.client.generic.FileReference;
+import uk.org.taverna.server.client.rest.DirectoryContents;
+import uk.org.taverna.server.client.rest.MakeDirectory;
+import uk.org.taverna.server.client.rest.UploadFile;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public class Directory extends DirEntry {
+ private final Wd wd;
+
+ Directory(Run run) {
+ super(run, "");
+ this.wd = run.run.wd();
+ }
+
+ Directory(Run run, String path) {
+ super(run, path);
+ this.wd = run.run.wd();
+ }
+
+ public List<DirEntry> list() {
+ List<DirEntry> result = new ArrayList<>();
+ for (DirectoryEntry de : wd.path3(path)
+ .getAsXml(DirectoryContents.class).getDirOrFile())
+ if (de instanceof DirectoryReference)
+ result.add(new Directory(run, de.getValue()));
+ else if (de instanceof FileReference)
+ result.add(new File(run, de.getValue()));
+ return result;
+ }
+
+ public File createFile(String name, byte[] content) throws ClientException,
+ ServerException {
+ UploadFile uf = new UploadFile();
+ uf.setName(name);
+ uf.setValue(content);
+ return new File(run, path(wd.path(path).putAsXml(uf,
+ ClientResponse.class)));
+ }
+
+ public File createFile(String name, java.io.File content)
+ throws ClientException, ServerException {
+ return new File(run, path(wd.path(concat(name)).putOctetStreamAsXml(
+ entity(content, APPLICATION_OCTET_STREAM_TYPE),
+ ClientResponse.class)));
+ }
+
+ public File createFile(String name, URI source) throws ClientException,
+ ServerException {
+ return new File(run, path(wd.path(concat(name)).postTextUriListAsXml(
+ source.toString(), ClientResponse.class)));
+ }
+
+ public Directory createDirectory(String name) throws ClientException,
+ ServerException {
+ MakeDirectory mkdir = new MakeDirectory();
+ mkdir.setName(name);
+ return new Directory(run, path(wd.path(path).putAsXml(mkdir,
+ ClientResponse.class)));
+ }
+
+ public byte[] getZippedContents() {
+ return wd.path3(path).getAsZip(byte[].class);
+ }
+
+ public ZipFile getZip() throws IOException {
+ byte[] contents = getZippedContents();
+ java.io.File tmp = createTempFile(localName(), ".zip");
+ try (OutputStream os = new FileOutputStream(tmp)) {
+ os.write(contents);
+ }
+ return new ZipFile(tmp);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/File.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/File.java b/server-client/src/main/java/uk/org/taverna/server/client/File.java
new file mode 100644
index 0000000..0287afb
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/File.java
@@ -0,0 +1,95 @@
+package uk.org.taverna.server.client;
+
+import static java.io.File.createTempFile;
+import static javax.ws.rs.client.Entity.entity;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
+import static org.apache.commons.io.IOUtils.copy;
+import static org.apache.tika.mime.MimeTypes.getDefaultMimeTypes;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
+import org.apache.tika.mime.MimeTypeException;
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+
+public class File extends DirEntry {
+ private final Wd wd;
+
+ File(Run run, String path) {
+ super(run, path);
+ wd = run.run.wd();
+ }
+
+ public InputStream getAsStream() {
+ return wd.path3(path).getAsOctetStream(InputStream.class);
+ }
+
+ public byte[] get() {
+ return wd.path3(path).getAsOctetStream(byte[].class);
+ }
+
+ public String get(Charset encoding) {
+ return new String(wd.path3(path).getAsOctetStream(byte[].class),
+ encoding);
+ }
+
+ public java.io.File getAsFile() throws ClientHandlerException,
+ UniformInterfaceException, IOException, MimeTypeException,
+ ClientException, ServerException {
+ ClientResponse cr = wd.path3(path).getAsOctetStream(
+ ClientResponse.class);
+ checkError(cr);
+ String[] bits = localName().split("[.]");
+ String ext = getDefaultMimeTypes().forName(
+ cr.getHeaders().getFirst("Content-Type")).getExtension();
+ if (ext == null)
+ ext = bits[bits.length - 1];
+ java.io.File tmp = createTempFile(bits[0], ext);
+ try (OutputStream os = new FileOutputStream(tmp);
+ InputStream is = cr.getEntity(InputStream.class)) {
+ copy(is, os);
+ }
+ return tmp;
+ }
+
+ public void setContents(byte[] newContents) throws ClientException,
+ ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(newContents,
+ ClientResponse.class));
+ }
+
+ public void setContents(String newContents) throws ClientException,
+ ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(newContents,
+ ClientResponse.class));
+ }
+
+ public void setContents(String newContents, Charset encoding)
+ throws ClientException, ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(
+ newContents.getBytes(encoding), ClientResponse.class));
+ }
+
+ public void setContents(InputStream newContents) throws ClientException,
+ ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(newContents,
+ ClientResponse.class));
+ }
+
+ public void setContents(java.io.File newContents) throws IOException,
+ ClientException, ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(
+ entity(newContents, APPLICATION_OCTET_STREAM_TYPE),
+ ClientResponse.class));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/Property.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Property.java b/server-client/src/main/java/uk/org/taverna/server/client/Property.java
new file mode 100644
index 0000000..0e6542f
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/Property.java
@@ -0,0 +1,18 @@
+package uk.org.taverna.server.client;
+
+public enum Property {
+ STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
+ "readyToNotify"), EMAIL("notificationAddress"), USAGE(
+ "usageRecord");
+
+ private String s;
+
+ private Property(String s) {
+ this.s = s;
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/Run.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Run.java b/server-client/src/main/java/uk/org/taverna/server/client/Run.java
new file mode 100644
index 0000000..5c6875e
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/Run.java
@@ -0,0 +1,215 @@
+package uk.org.taverna.server.client;
+
+import static org.joda.time.format.ISODateTimeFormat.dateTime;
+import static org.joda.time.format.ISODateTimeFormat.dateTimeParser;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.ogf.usage.JobUsageRecord;
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName;
+import org.w3c.dom.Element;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+import uk.org.taverna.server.client.generic.KeyPairCredential;
+import uk.org.taverna.server.client.generic.PasswordCredential;
+import uk.org.taverna.server.client.generic.port.InputPort;
+import uk.org.taverna.server.client.generic.port.OutputPort;
+import uk.org.taverna.server.client.rest.InputDescription;
+import uk.org.taverna.server.client.rest.InputDescription.Value;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public class Run extends Connected {
+ RunsRunName run;
+
+ Run(TavernaServer server, String value) {
+ run = server.root.runsRunName(value);
+ }
+
+ public String getName() {
+ return run.name().getAsTextPlain(ClientResponse.class)
+ .getEntity(String.class);
+ }
+
+ public void setName(String name) {
+ run.name().putTextPlain(name, String.class);
+ }
+
+ public Date getExpiry() {
+ return dateTimeParser().parseDateTime(
+ run.expiry().getAsTextPlain(String.class)).toDate();
+ }
+
+ public void setExpiry(Date expiryTimestamp) {
+ run.expiry().putTextPlain(
+ dateTime().print(new DateTime(expiryTimestamp)), String.class);
+ }
+
+ public Date getCreate() {
+ String timestamp = run.createTime().getAsTextPlain(String.class);
+ if (timestamp == null || timestamp.trim().isEmpty())
+ return null;
+ return dateTimeParser().parseDateTime(timestamp).toDate();
+ }
+
+ public Date getStart() {
+ String timestamp = run.startTime().getAsTextPlain(String.class);
+ if (timestamp == null || timestamp.trim().isEmpty())
+ return null;
+ return dateTimeParser().parseDateTime(timestamp).toDate();
+ }
+
+ public Date getFinish() {
+ String timestamp = run.finishTime().getAsTextPlain(String.class);
+ if (timestamp == null || timestamp.trim().isEmpty())
+ return null;
+ return dateTimeParser().parseDateTime(timestamp).toDate();
+ }
+
+ public Status getStatus() {
+ return Status.valueOf(run.status().getAsTextPlain(String.class));
+ }
+
+ public void setStatus(Status status) {
+ run.status().putTextPlain(status, String.class);
+ }
+
+ public void start() {
+ setStatus(Status.Operating);
+ }
+
+ public void kill() {
+ setStatus(Status.Finished);
+ }
+
+ public boolean isRunning() {
+ return getStatus() == Status.Operating;
+ }
+
+ public String getStandardOutput() {
+ return run.stdout().getAsTextPlain(String.class);
+ }
+
+ public String getStandardError() {
+ return run.stderr().getAsTextPlain(String.class);
+ }
+
+ public String getLog() {
+ return run.log().getAsTextPlain(String.class);
+ }
+
+ public Integer getExitCode() {
+ String code = run.listeners().name("io")
+ .propertiesPropertyName("exitCode")
+ .getAsTextPlain(String.class);
+ if (code == null || code.trim().isEmpty())
+ return null;
+ return Integer.parseInt(code);
+ }
+
+ public String getProperty(Property prop) {
+ return run.listeners().name("io")
+ .propertiesPropertyName(prop.toString())
+ .getAsTextPlain(String.class);
+ }
+
+ public void setGenerateRunBundle(boolean generateRunBundle) {
+ run.generateProvenance().putTextPlain(generateRunBundle, String.class);
+ }
+
+ public byte[] getRunBundle() {
+ return run.runBundle().getAsVndWf4everRobundleZip(byte[].class);
+ }
+
+ public List<InputPort> getInputs() {
+ return run.input().expected().getAsInputDescriptionXml().getInput();
+ }
+
+ public List<OutputPort> getOutputs() {
+ return run.output().getAsOutputDescriptionXml().getOutput();
+ }
+
+ public void setInput(String name, String value) {
+ Value v = new Value();
+ v.setValue(value);
+ InputDescription idesc = new InputDescription();
+ idesc.setValue(v);
+ run.input().inputName(name).putXmlAsInputDescription(idesc);
+ }
+
+ public void setInput(String name, String value, char listSeparator) {
+ Value v = new Value();
+ v.setValue(value);
+ InputDescription idesc = new InputDescription();
+ idesc.setValue(v);
+ idesc.setListDelimiter(new String(new char[] { listSeparator }));
+ run.input().inputName(name).putXmlAsInputDescription(idesc);
+ }
+
+ public byte[] getWorkflow() {
+ return run.workflow().getAsVndTavernaT2flowXml(byte[].class);
+ }
+
+ // TODO Consider better ways to do this
+ public Element getInteractionFeed() {
+ return run.interaction().getAsAtomXml(Element.class);
+ }
+
+ public Element getInteractionEntry(String id) {
+ return run.interaction().id(id).getAsAtomXml(Element.class);
+ }
+
+ public JobUsageRecord getUsageRecord() throws JAXBException {
+ return JobUsageRecord.unmarshal(run.usage().getAsXml(Element.class));
+ }
+
+ public Directory getWorkingDirectory() {
+ return new Directory(this);
+ }
+
+ public String getOwner() {
+ return run.security().owner().getAsTextPlain(String.class);
+ }
+
+ // TODO permissions
+
+ public void grantPasswordCredential(URI contextService, String username,
+ String password) throws ClientException, ServerException {
+ PasswordCredential pc = new PasswordCredential();
+ pc.setServiceURI(contextService.toString());
+ pc.setUsername(username);
+ pc.setPassword(password);
+ checkError(run.security().credentials()
+ .postXmlAsOctetStream(pc, ClientResponse.class));
+ }
+
+ public void grantKeyCredential(URI contextService, java.io.File source,
+ String unlockPassword, String aliasEntry) throws IOException,
+ ClientException, ServerException {
+ KeyPairCredential kpc = new KeyPairCredential();
+ kpc.setServiceURI(contextService.toString());
+ try (InputStream in = new FileInputStream(source)) {
+ byte[] buffer = new byte[(int) source.length()];
+ IOUtils.read(in, buffer);
+ kpc.setCredentialBytes(buffer);
+ }
+ if (source.getName().endsWith(".p12"))
+ kpc.setFileType("PKCS12");
+ else
+ kpc.setFileType("JKS");
+ kpc.setCredentialName(aliasEntry);
+ kpc.setUnlockPassword(unlockPassword);
+ checkError(run.security().credentials()
+ .postXmlAsOctetStream(kpc, ClientResponse.class));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/Status.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Status.java b/server-client/src/main/java/uk/org/taverna/server/client/Status.java
new file mode 100644
index 0000000..9c375ad
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/Status.java
@@ -0,0 +1,36 @@
+package uk.org.taverna.server.client;
+
+/**
+ * States of a workflow run. They are {@link #Initialized Initialized},
+ * {@link #Operating Operating}, {@link #Stopped Stopped}, and
+ * {@link #Finished Finished}. Conceptually, there is also a
+ * <tt>Destroyed</tt> state, but the workflow run does not exist (and hence
+ * can't have its state queried or set) in that case.
+ *
+ * @author Donal Fellows
+ */
+public enum Status {
+ /**
+ * The workflow run has been created, but is not yet running. The run
+ * will need to be manually moved to {@link #Operating Operating} when
+ * ready.
+ */
+ Initialized,
+ /**
+ * The workflow run is going, reading input, generating output, etc.
+ * Will eventually either move automatically to {@link #Finished
+ * Finished} or can be moved manually to {@link #Stopped Stopped} (where
+ * supported).
+ */
+ Operating,
+ /**
+ * The workflow run is paused, and will need to be moved back to
+ * {@link #Operating Operating} manually.
+ */
+ Stopped,
+ /**
+ * The workflow run has ceased; data files will continue to exist until
+ * the run is destroyed (which may be manual or automatic).
+ */
+ Finished
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java b/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
index 3ceb208..7c0dcdd 100644
--- a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
+++ b/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
@@ -1,467 +1,54 @@
package uk.org.taverna.server.client;
-import static java.io.File.createTempFile;
import static java.nio.file.Files.readAllBytes;
-import static javax.ws.rs.client.Entity.entity;
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
-import static org.apache.commons.io.IOUtils.copy;
-import static org.apache.tika.mime.MimeTypes.getDefaultMimeTypes;
-import static org.joda.time.format.ISODateTimeFormat.dateTime;
-import static org.joda.time.format.ISODateTimeFormat.dateTimeParser;
import static org.taverna.server.client.wadl.TavernaServer.createClient;
import static org.taverna.server.client.wadl.TavernaServer.root;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.net.URI;
-import java.nio.charset.Charset;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
-import java.util.zip.ZipFile;
-import org.apache.commons.io.IOUtils;
-import org.apache.tika.mime.MimeTypeException;
-import org.joda.time.DateTime;
import org.taverna.server.client.wadl.TavernaServer.Root;
-import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName;
-import org.w3c.dom.Element;
-import uk.org.taverna.server.client.generic.port.InputPort;
-import uk.org.taverna.server.client.generic.port.OutputPort;
import uk.org.taverna.server.client.generic.Capability;
-import uk.org.taverna.server.client.generic.DirectoryEntry;
-import uk.org.taverna.server.client.generic.DirectoryReference;
-import uk.org.taverna.server.client.generic.FileReference;
-import uk.org.taverna.server.client.generic.KeyPairCredential;
-import uk.org.taverna.server.client.generic.PasswordCredential;
import uk.org.taverna.server.client.generic.TavernaRun;
import uk.org.taverna.server.client.generic.VersionedElement;
-import uk.org.taverna.server.client.rest.DirectoryContents;
-import uk.org.taverna.server.client.rest.InputDescription;
-import uk.org.taverna.server.client.rest.InputDescription.Value;
-import uk.org.taverna.server.client.rest.MakeDirectory;
-import uk.org.taverna.server.client.rest.UploadFile;
import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
-public class TavernaServer {
- private Root root;
+public class TavernaServer extends Connected {
+ final Root root;
+ private final URI location;
+ private final boolean authenticated;
- /**
- * States of a workflow run. They are {@link #Initialized Initialized},
- * {@link #Operating Operating}, {@link #Stopped Stopped}, and
- * {@link #Finished Finished}. Conceptually, there is also a
- * <tt>Destroyed</tt> state, but the workflow run does not exist (and hence
- * can't have its state queried or set) in that case.
- *
- * @author Donal Fellows
- */
- public static enum Status {
- /**
- * The workflow run has been created, but is not yet running. The run
- * will need to be manually moved to {@link #Operating Operating} when
- * ready.
- */
- Initialized,
- /**
- * The workflow run is going, reading input, generating output, etc.
- * Will eventually either move automatically to {@link #Finished
- * Finished} or can be moved manually to {@link #Stopped Stopped} (where
- * supported).
- */
- Operating,
- /**
- * The workflow run is paused, and will need to be moved back to
- * {@link #Operating Operating} manually.
- */
- Stopped,
- /**
- * The workflow run has ceased; data files will continue to exist until
- * the run is destroyed (which may be manual or automatic).
- */
- Finished
+ TavernaServer(URI serviceRoot) {
+ root = root(createClient(), location = serviceRoot);
+ authenticated = false;
}
- public static enum Property {
- STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
- "readyToNotify"), EMAIL("notificationAddress"), USAGE(
- "usageRecord");
-
- private String s;
-
- private Property(String s) {
- this.s = s;
- }
-
- @Override
- public String toString() {
- return s;
- }
- }
-
- public class Run {
- private RunsRunName run;
-
- Run(String value) {
- run = root.runsRunName(value);
- }
-
- public String getName() {
- return run.name().getAsTextPlain(String.class);
- }
-
- public void setName(String name) {
- run.name().putTextPlain(name, String.class);
- }
-
- public Date getExpiry() {
- return dateTimeParser().parseDateTime(
- run.expiry().getAsTextPlain(String.class)).toDate();
- }
-
- public void setExpiry(Date expiryTimestamp) {
- run.expiry().putTextPlain(
- dateTime().print(new DateTime(expiryTimestamp)),
- String.class);
- }
-
- public Date getCreate() {
- String timestamp = run.createTime().getAsTextPlain(String.class);
- if (timestamp == null || timestamp.trim().isEmpty())
- return null;
- return dateTimeParser().parseDateTime(timestamp).toDate();
- }
-
- public Date getStart() {
- String timestamp = run.startTime().getAsTextPlain(String.class);
- if (timestamp == null || timestamp.trim().isEmpty())
- return null;
- return dateTimeParser().parseDateTime(timestamp).toDate();
- }
-
- public Date getFinish() {
- String timestamp = run.finishTime().getAsTextPlain(String.class);
- if (timestamp == null || timestamp.trim().isEmpty())
- return null;
- return dateTimeParser().parseDateTime(timestamp).toDate();
- }
-
- public Status getStatus() {
- return Status.valueOf(run.status().getAsTextPlain(String.class));
- }
-
- public void setStatus(Status status) {
- run.status().putTextPlain(status, String.class);
- }
-
- public void start() {
- setStatus(Status.Operating);
- }
-
- public void kill() {
- setStatus(Status.Finished);
- }
-
- public boolean isRunning() {
- return getStatus() == Status.Operating;
- }
-
- public String getStandardOutput() {
- return run.stdout().getAsTextPlain(String.class);
- }
-
- public String getStandardError() {
- return run.stderr().getAsTextPlain(String.class);
- }
-
- public String getLog() {
- return run.log().getAsTextPlain(String.class);
- }
-
- public Integer getExitCode() {
- String code = run.listeners().name("io")
- .propertiesPropertyName("exitCode")
- .getAsTextPlain(String.class);
- if (code == null || code.trim().isEmpty())
- return null;
- return Integer.parseInt(code);
- }
-
- public String getProperty(Property prop) {
- return run.listeners().name("io")
- .propertiesPropertyName(prop.toString())
- .getAsTextPlain(String.class);
- }
-
- public void setGenerateRunBundle(boolean generateRunBundle) {
- run.generateProvenance().putTextPlain(generateRunBundle,
- String.class);
- }
-
- public byte[] getRunBundle() {
- return run.runBundle().getAsVndWf4everRobundleZip(byte[].class);
- }
-
- public List<InputPort> getInputs() {
- return run.input().expected().getAsInputDescriptionXml().getInput();
- }
-
- public List<OutputPort> getOutputs() {
- return run.output().getAsOutputDescriptionXml().getOutput();
- }
-
- public void setInput(String name, String value) {
- Value v = new Value();
- v.setValue(value);
- InputDescription idesc = new InputDescription();
- idesc.setValue(v);
- run.input().inputName(name).putXmlAsInputDescription(idesc);
- }
-
- public void setInput(String name, String value, char listSeparator) {
- Value v = new Value();
- v.setValue(value);
- InputDescription idesc = new InputDescription();
- idesc.setValue(v);
- idesc.setListDelimiter(new String(new char[] { listSeparator }));
- run.input().inputName(name).putXmlAsInputDescription(idesc);
- }
-
- public byte[] getWorkflow() {
- return run.workflow().getAsVndTavernaT2flowXml(byte[].class);
- }
-
- // TODO Consider better ways to do this
- public Element getInteractionFeed() {
- return run.interaction().getAsAtomXml(Element.class);
- }
-
- public Element getInteractionEntry(String id) {
- return run.interaction().id(id).getAsAtomXml(Element.class);
- }
-
- public Element getUsageRecord() {
- return run.usage().getAsXml(Element.class);
- }
-
- public Directory getWorkingDirectory() {
- return new Directory();
- }
-
- public abstract class DirEntry {
- final String path;
-
- protected DirEntry(String path) {
- this.path = path.replaceFirst("/+$", "");
- }
-
- public void delete() {
- run.wd().path2(path).deleteAsXml(ClientResponse.class);
- }
-
- String path(ClientResponse response) {
- String[] bits = response.getLocation().getPath().split("/");
- return concat(bits[bits.length - 1]);
- }
-
- String localName() {
- String[] bits = path.split("/");
- return bits[bits.length - 1];
- }
-
- String concat(String name) {
- return path + "/" + name.split("/", 2)[0];
- }
- }
-
- public class Directory extends DirEntry {
- Directory() {
- super("");
- }
-
- Directory(String path) {
- super(path);
- }
-
- public List<DirEntry> list() {
- List<DirEntry> result = new ArrayList<>();
- for (DirectoryEntry de : run.wd().path3(path)
- .getAsXml(DirectoryContents.class).getDirOrFile())
- if (de instanceof DirectoryReference)
- result.add(new Directory(de.getValue()));
- else if (de instanceof FileReference)
- result.add(new File(de.getValue()));
- return result;
- }
-
- public File createFile(String name, byte[] content) {
- UploadFile uf = new UploadFile();
- uf.setName(name);
- uf.setValue(content);
- return new File(path(run.wd().path(path)
- .putAsXml(uf, ClientResponse.class)));
- }
-
- public File createFile(String name, java.io.File content) {
- return new File(path(run
- .wd()
- .path(concat(name))
- .putOctetStreamAsXml(
- entity(content, APPLICATION_OCTET_STREAM_TYPE),
- ClientResponse.class)));
- }
-
- public File createFile(String name, URI source) {
- return new File(path(run
- .wd()
- .path(concat(name))
- .postTextUriListAsXml(source.toString(),
- ClientResponse.class)));
- }
-
- public Directory createDirectory(String name) {
- MakeDirectory mkdir = new MakeDirectory();
- mkdir.setName(name);
- return new Directory(path(run.wd().path(path)
- .putAsXml(mkdir, ClientResponse.class)));
- }
-
- public byte[] getZippedContents() {
- return run.wd().path3(path).getAsZip(byte[].class);
- }
-
- public ZipFile getZip() throws IOException {
- byte[] contents = getZippedContents();
- java.io.File tmp = createTempFile(localName(), ".zip");
- try (OutputStream os = new FileOutputStream(tmp)) {
- os.write(contents);
- }
- return new ZipFile(tmp);
- }
- }
-
- public class File extends DirEntry {
- File(String path) {
- super(path);
- }
-
- public InputStream getAsStream() {
- return run.wd().path3(path).getAsOctetStream(InputStream.class);
- }
-
- public byte[] get() {
- return run.wd().path3(path).getAsOctetStream(byte[].class);
- }
-
- public String get(Charset encoding) {
- return new String(run.wd().path3(path)
- .getAsOctetStream(byte[].class), encoding);
- }
-
- public java.io.File getAsFile() throws ClientHandlerException,
- UniformInterfaceException, IOException, MimeTypeException {
- ClientResponse cr = run.wd().path3(path)
- .getAsOctetStream(ClientResponse.class);
- String[] bits = localName().split("[.]");
- String ext = getDefaultMimeTypes().forName(
- cr.getHeaders().getFirst("Content-Type"))
- .getExtension();
- if (ext == null)
- ext = bits[bits.length-1];
- java.io.File tmp = createTempFile(bits[0], ext);
- try (OutputStream os = new FileOutputStream(tmp);
- InputStream is = cr.getEntity(InputStream.class)) {
- copy(is, os);
- }
- return tmp;
- }
-
- public void setContents(byte[] newContents) {
- run.wd().path(path)
- .putOctetStreamAsXml(newContents, ClientResponse.class);
- }
-
- public void setContents(String newContents) {
- run.wd().path(path)
- .putOctetStreamAsXml(newContents, ClientResponse.class);
- }
-
- public void setContents(String newContents, Charset encoding) {
- run.wd()
- .path(path)
- .putOctetStreamAsXml(newContents.getBytes(encoding),
- ClientResponse.class);
- }
-
- public void setContents(InputStream newContents) {
- run.wd().path(path)
- .putOctetStreamAsXml(newContents, ClientResponse.class);
- }
-
- public void setContents(java.io.File newContents)
- throws IOException {
- run.wd()
- .path(path)
- .putOctetStreamAsXml(
- entity(newContents,
- APPLICATION_OCTET_STREAM_TYPE),
- ClientResponse.class);
- }
- }
-
- public String getOwner() {
- return run.security().owner().getAsTextPlain(String.class);
- }
-
- // TODO permissions
-
- public void grantPasswordCredential(URI contextService,
- String username, String password) {
- PasswordCredential pc = new PasswordCredential();
- pc.setServiceURI(contextService.toString());
- pc.setUsername(username);
- pc.setPassword(password);
- run.security().credentials()
- .postXmlAsOctetStream(pc, ClientResponse.class);
- }
-
- public void grantKeyCredential(URI contextService, java.io.File source,
- String unlockPassword, String aliasEntry) throws IOException {
- KeyPairCredential kpc = new KeyPairCredential();
- kpc.setServiceURI(contextService.toString());
- try (InputStream in = new FileInputStream(source)) {
- byte[] buffer = new byte[(int) source.length()];
- IOUtils.read(in, buffer);
- kpc.setCredentialBytes(buffer);
- }
- if (source.getName().endsWith(".p12"))
- kpc.setFileType("PKCS12");
- else
- kpc.setFileType("JKS");
- kpc.setCredentialName(aliasEntry);
- kpc.setUnlockPassword(unlockPassword);
- run.security().credentials()
- .postXmlAsOctetStream(kpc, ClientResponse.class);
- }
- }
-
- public TavernaServer(URI serviceRoot) {
- root = root(createClient(), serviceRoot);
+ TavernaServer(URI serviceRoot, String username, String password) {
+ Client client = createClient();
+ client.addFilter(new HTTPBasicAuthFilter(username, password));
+ authenticated = true;
+ root = root(client, location = serviceRoot);
}
- public TavernaServer(URI serviceRoot, String username, String password) {
+ TavernaServer(TavernaServer service, String username, String password) {
Client client = createClient();
client.addFilter(new HTTPBasicAuthFilter(username, password));
- root = root(client, serviceRoot);
+ authenticated = true;
+ root = root(client, location = service.location);
+ getServerVersionInfo();
+ }
+
+ public TavernaServer upgradeToAuth(String username, String password) {
+ if (authenticated)
+ throw new IllegalStateException("may only upgrade an unauthenticated connection");
+ return new TavernaServer(this, username, password);
}
public List<Capability> getCapabilities() {
@@ -485,7 +72,7 @@ public class TavernaServer {
public List<Run> getExistingRuns() {
List<Run> runs = new ArrayList<>();
for (TavernaRun run : root.runs().getAsRunListXml().getRun())
- runs.add(new Run(run.getValue()));
+ runs.add(new Run(this, run.getValue()));
return runs;
}
@@ -493,25 +80,49 @@ public class TavernaServer {
return root.getAsServerDescriptionXml();
}
- private Run response2run(ClientResponse response) {
+ private Run response2run(ClientResponse response) throws ClientException, ServerException {
+ checkError(response);
if (response.getClientResponseStatus().getStatusCode() == 201) {
String[] path = response.getLocation().getPath().split("/");
- return new Run(path[path.length - 1]);
+ return new Run(this, path[path.length - 1]);
}
return null;
}
- public Run createWorkflowRun(byte[] t2flowBytes) {
+ public Run createWorkflowRun(byte[] t2flowBytes) throws ClientException, ServerException {
return response2run(root.runs().postVndTavernaT2flowXmlAsOctetStream(
t2flowBytes, ClientResponse.class));
}
- public Run createWorkflowRun(File t2flowFile) throws IOException {
+ public Run createWorkflowRun(File t2flowFile) throws IOException, ClientException, ServerException {
return createWorkflowRun(readAllBytes(t2flowFile.toPath()));
}
- public Run createWorkflowRun(URI t2flowUri) {
+ public Run createWorkflowRun(URI t2flowUri) throws ClientException, ServerException {
return response2run(root.runs().postTextUriListAsOctetStream(
t2flowUri.toString(), ClientResponse.class));
}
+
+
+ public static class ClientException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ ClientException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+ public static class AuthorizationException extends ClientException {
+ private static final long serialVersionUID = 1L;
+
+ AuthorizationException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+ static class ServerException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ ServerException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java b/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
new file mode 100644
index 0000000..b00b075
--- /dev/null
+++ b/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
@@ -0,0 +1,23 @@
+package uk.org.taverna.server.client;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TavernaServerConnectionFactory {
+ private Map<URI, TavernaServer> cache = new HashMap<>();
+
+ public synchronized TavernaServer connectNoAuth(URI uri) {
+ TavernaServer conn = cache.get(uri);
+ if (conn == null)
+ cache.put(uri, conn = new TavernaServer(uri));
+ return conn;
+ }
+
+ public TavernaServer connectAuth(URI uri, String username, String password) {
+ TavernaServer conn = new TavernaServer(uri, username, password);
+ // Force a check of the credentials by getting the server version
+ conn.getServerVersionInfo();
+ return conn;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/a1c27cd9/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
----------------------------------------------------------------------
diff --git a/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java b/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
index cf7799a..d12d3d8 100644
--- a/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
+++ b/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
@@ -19,6 +19,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
+import javax.xml.transform.dom.DOMSource;
import org.ogf.usage.v1_0.Charge;
import org.ogf.usage.v1_0.ConsumableResourceType;
@@ -45,6 +46,7 @@ import org.ogf.usage.v1_0.TimeDuration;
import org.ogf.usage.v1_0.TimeInstant;
import org.ogf.usage.v1_0.UserIdentity;
import org.ogf.usage.v1_0.WallDuration;
+import org.w3c.dom.Element;
@XmlRootElement(name = "UsageRecord", namespace = "http://schema.ogf.org/urf/2003/09/urf")
public class JobUsageRecord extends org.ogf.usage.v1_0.UsageRecordType {
@@ -277,10 +279,25 @@ public class JobUsageRecord extends org.ogf.usage.v1_0.UsageRecordType {
return writer.toString();
}
+ private static JAXBContext context;
+ static {
+ try {
+ context = JAXBContext.newInstance(JobUsageRecord.class);
+ } catch (JAXBException e) {
+ throw new RuntimeException("failed to handle JAXB annotated class",
+ e);
+ }
+ }
+
public static JobUsageRecord unmarshal(String s) throws JAXBException {
- StringReader reader = new StringReader(s);
- return (JobUsageRecord) JAXBContext.newInstance(JobUsageRecord.class)
- .createUnmarshaller().unmarshal(reader);
+ return (JobUsageRecord) context.createUnmarshaller().unmarshal(
+ new StringReader(s));
+ }
+
+ public static JobUsageRecord unmarshal(Element elem) throws JAXBException {
+ return context.createUnmarshaller()
+ .unmarshal(new DOMSource(elem), JobUsageRecord.class)
+ .getValue();
}
// TODO: Add signing support