http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/pom.xml ---------------------------------------------------------------------- diff --git a/taverna-server-client/pom.xml b/taverna-server-client/pom.xml new file mode 100644 index 0000000..d16b07a --- /dev/null +++ b/taverna-server-client/pom.xml @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.taverna.server</groupId> + <artifactId>taverna-server</artifactId> + <version>3.1.0-incubating-SNAPSHOT</version> + </parent> + <artifactId>taverna-server-client</artifactId> + <packaging>bundle</packaging> + <name>Apache Taverna Server Client OSGi Module</name> + + <dependencies> + <dependency> + <groupId>org.jvnet.ws.wadl</groupId> + <artifactId>wadl-core</artifactId> + <version>1.1.6</version> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-client</artifactId> + <version>1.8</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.4</version> + </dependency> + <dependency> + <groupId>org.apache.tika</groupId> + <artifactId>tika-core</artifactId> + <version>1.5</version> + </dependency> + <dependency> + <groupId>${project.parent.groupId}</groupId> + <artifactId>taverna-server-usagerecord</artifactId> + <version>${project.parent.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package>uk.org.taverna.server.client</Export-Package> + <Private-Package>uk.org.taverna.server.client.*</Private-Package> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.jvnet.ws.wadl</groupId> + <artifactId>wadl-client-plugin</artifactId> + <version>1.1.6</version> + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + <configuration> + <packageName>org.taverna.server.client.wadl</packageName> + <includes>*.wadl</includes> + <customClassNames> + <property> + <name>http://example.com/taverna/rest</name> + <value>TavernaServer</value> + </property> + </customClassNames> + </configuration> + </plugin> + </plugins> + <pluginManagement> + <plugins> + <!--This plugin's configuration is used to store Eclipse m2e settings + only. It has no influence on the Maven build itself. --> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>1.0.0</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId> + org.jvnet.ws.wadl + </groupId> + <artifactId> + wadl-client-plugin + </artifactId> + <versionRange> + [1.1.6,) + </versionRange> + <goals> + <goal>generate</goal> + </goals> + </pluginExecutionFilter> + <action> + <execute /> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> +</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java new file mode 100644 index 0000000..263034c --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java new file mode 100644 index 0000000..267707d --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java new file mode 100644 index 0000000..38dc394 --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java new file mode 100644 index 0000000..0287afb --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java new file mode 100644 index 0000000..0e6542f --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java new file mode 100644 index 0000000..5c6875e --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java new file mode 100644 index 0000000..9c375ad --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java new file mode 100644 index 0000000..7c0dcdd --- /dev/null +++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java @@ -0,0 +1,128 @@ +package uk.org.taverna.server.client; + +import static java.nio.file.Files.readAllBytes; +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.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.taverna.server.client.wadl.TavernaServer.Root; + +import uk.org.taverna.server.client.generic.Capability; +import uk.org.taverna.server.client.generic.TavernaRun; +import uk.org.taverna.server.client.generic.VersionedElement; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; + +public class TavernaServer extends Connected { + final Root root; + private final URI location; + private final boolean authenticated; + + TavernaServer(URI serviceRoot) { + root = root(createClient(), location = serviceRoot); + authenticated = false; + } + + TavernaServer(URI serviceRoot, String username, String password) { + Client client = createClient(); + client.addFilter(new HTTPBasicAuthFilter(username, password)); + authenticated = true; + root = root(client, location = serviceRoot); + } + + TavernaServer(TavernaServer service, String username, String password) { + Client client = createClient(); + client.addFilter(new HTTPBasicAuthFilter(username, password)); + 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() { + return root.policy().capabilities().getAsCapabilitiesXml() + .getCapability(); + } + + public int getRunLimit() { + return root.policy().runLimit().getAsTextPlain(Integer.class); + } + + public int getOperatingLimit() { + return root.policy().operatingLimit().getAsTextPlain(Integer.class); + } + + public List<String> getPermittedWorkflows() { + return root.policy().permittedWorkflows().getAsPermittedWorkflowsXml() + .getWorkflow(); + } + + public List<Run> getExistingRuns() { + List<Run> runs = new ArrayList<>(); + for (TavernaRun run : root.runs().getAsRunListXml().getRun()) + runs.add(new Run(this, run.getValue())); + return runs; + } + + public VersionedElement getServerVersionInfo() { + return root.getAsServerDescriptionXml(); + } + + private Run response2run(ClientResponse response) throws ClientException, ServerException { + checkError(response); + if (response.getClientResponseStatus().getStatusCode() == 201) { + String[] path = response.getLocation().getPath().split("/"); + return new Run(this, path[path.length - 1]); + } + return null; + } + + public Run createWorkflowRun(byte[] t2flowBytes) throws ClientException, ServerException { + return response2run(root.runs().postVndTavernaT2flowXmlAsOctetStream( + t2flowBytes, ClientResponse.class)); + } + + public Run createWorkflowRun(File t2flowFile) throws IOException, ClientException, ServerException { + return createWorkflowRun(readAllBytes(t2flowFile.toPath())); + } + + 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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java new file mode 100644 index 0000000..b00b075 --- /dev/null +++ b/taverna-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/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java new file mode 100644 index 0000000..59e809d --- /dev/null +++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java @@ -0,0 +1,5 @@ +/** + * Implementation of a basic client for Taverna Server. + * @author Donal Fellows + */ +package uk.org.taverna.server.client; \ No newline at end of file
