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 16:37:13 UTC
[13/49] incubator-taverna-server git commit: taverna-* module names
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java
new file mode 100644
index 0000000..e9b067e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static org.taverna.server.master.common.Namespaces.XLINK;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.rest.ContentTypes.JSON;
+import static org.taverna.server.master.rest.ContentTypes.TEXT;
+import static org.taverna.server.master.rest.ContentTypes.XML;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.taverna.server.master.common.Uri;
+import org.taverna.server.master.common.VersionedElement;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Listener;
+
+/**
+ * This represents <i>all</i> the event listeners attached to a workflow run.
+ *
+ * @author Donal Fellows
+ * @see TavernaServerListenerREST
+ */
+@RolesAllowed(USER)
+@Description("This represents all the event listeners attached to a workflow "
+ + "run.")
+public interface TavernaServerListenersREST {
+ /**
+ * Get the listeners installed in the workflow run.
+ *
+ * @param ui
+ * About how this method was called.
+ * @return A list of descriptions of listeners.
+ */
+ @GET
+ @Path("/")
+ @Produces({ XML, JSON })
+ @Description("Get the listeners installed in the workflow run.")
+ @Nonnull
+ Listeners getDescription(@Nonnull @Context UriInfo ui);
+
+ /**
+ * Add a new event listener to the named workflow run.
+ *
+ * @param typeAndConfiguration
+ * What type of run should be created, and how should it be
+ * configured.
+ * @param ui
+ * About how this method was called.
+ * @return An HTTP response to the creation request.
+ * @throws NoUpdateException
+ * If the user is not permitted to update the run.
+ * @throws NoListenerException
+ * If no listener with the given type exists, or if the
+ * configuration is unacceptable in some way.
+ */
+ @POST
+ @Path("/")
+ @Consumes({ XML, JSON })
+ @Description("Add a new event listener to the named workflow run.")
+ @Nonnull
+ Response addListener(@Nonnull ListenerDefinition typeAndConfiguration,
+ @Nonnull @Context UriInfo ui) throws NoUpdateException,
+ NoListenerException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("/")
+ @Description("Produces the description of the run listeners' operations.")
+ Response listenersOptions();
+
+ /**
+ * Resolve a particular listener from its name.
+ *
+ * @param name
+ * The name of the listener to look up.
+ * @return The listener's delegate in the REST world.
+ * @throws NoListenerException
+ * If no listener with the given name exists.
+ */
+ @Path("{name}")
+ @Description("Resolve a particular listener from its name.")
+ @Nonnull
+ TavernaServerListenerREST getListener(
+ @Nonnull @PathParam("name") String name) throws NoListenerException;
+
+ /**
+ * This represents a single event listener attached to a workflow run.
+ *
+ * @author Donal Fellows
+ * @see TavernaServerListenersREST
+ * @see Property
+ */
+ @RolesAllowed(USER)
+ @Description("This represents a single event listener attached to a "
+ + "workflow run.")
+ public interface TavernaServerListenerREST {
+ /**
+ * Get the description of this listener.
+ *
+ * @param ui
+ * Information about this request.
+ * @return A description document.
+ */
+ @GET
+ @Path("/")
+ @Produces({ XML, JSON })
+ @Description("Get the description of this listener.")
+ @Nonnull
+ ListenerDescription getDescription(@Nonnull @Context UriInfo ui);
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("/")
+ @Description("Produces the description of one run listener's operations.")
+ Response listenerOptions();
+
+ /**
+ * Get the configuration for the given event listener that is attached
+ * to a workflow run.
+ *
+ * @return The configuration of the listener.
+ */
+ @GET
+ @Path("configuration")
+ @Produces(TEXT)
+ @Description("Get the configuration for the given event listener that "
+ + "is attached to a workflow run.")
+ @Nonnull
+ String getConfiguration();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("configuration")
+ @Description("Produces the description of one run listener's "
+ + "configuration's operations.")
+ Response configurationOptions();
+
+ /**
+ * Get the list of properties supported by a given event listener
+ * attached to a workflow run.
+ *
+ * @param ui
+ * Information about this request.
+ * @return The list of property names.
+ */
+ @GET
+ @Path("properties")
+ @Produces({ XML, JSON })
+ @Description("Get the list of properties supported by a given event "
+ + "listener attached to a workflow run.")
+ @Nonnull
+ Properties getProperties(@Nonnull @Context UriInfo ui);
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("properties")
+ @Description("Produces the description of one run listener's "
+ + "properties' operations.")
+ Response propertiesOptions();
+
+ /**
+ * Get an object representing a particular property.
+ *
+ * @param propertyName
+ * @return The property delegate.
+ * @throws NoListenerException
+ * If there is no such property.
+ */
+ @Path("properties/{propertyName}")
+ @Description("Get an object representing a particular property.")
+ @Nonnull
+ Property getProperty(
+ @Nonnull @PathParam("propertyName") String propertyName)
+ throws NoListenerException;
+ }
+
+ /**
+ * This represents a single property attached of an event listener.
+ *
+ * @author Donal Fellows
+ */
+ @RolesAllowed(USER)
+ @Description("This represents a single property attached of an event "
+ + "listener.")
+ public interface Property {
+ /**
+ * Get the value of the particular property of an event listener
+ * attached to a workflow run.
+ *
+ * @return The value of the property.
+ */
+ @GET
+ @Path("/")
+ @Produces(TEXT)
+ @Description("Get the value of the particular property of an event "
+ + "listener attached to a workflow run.")
+ @Nonnull
+ String getValue();
+
+ /**
+ * Set the value of the particular property of an event listener
+ * attached to a workflow run. Changing the value of the property may
+ * cause the listener to alter its behaviour significantly.
+ *
+ * @param value
+ * The value to set the property to.
+ * @return The value of the property after being set.
+ * @throws NoUpdateException
+ * If the user is not permitted to update the run.
+ * @throws NoListenerException
+ * If the property is in the wrong format.
+ */
+ @PUT
+ @Path("/")
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Description("Set the value of the particular property of an event "
+ + "listener attached to a workflow run.")
+ @Nonnull
+ String setValue(@Nonnull String value) throws NoUpdateException,
+ NoListenerException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("/")
+ @Description("Produces the description of one run listener's "
+ + "property's operations.")
+ Response options();
+ }
+
+ /**
+ * A description of an event listener that is attached to a workflow run.
+ * Done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "ListenerDescription")
+ public class ListenerDescription extends VersionedElement {
+ /** Where this listener is located. */
+ @XmlAttribute(name = "href", namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI location;
+ /** The (arbitrary) name of the event listener. */
+ @XmlAttribute
+ public String name;
+ /** The type of the event listener. */
+ @XmlAttribute
+ public String type;
+ /**
+ * The location of the configuration document for the event listener.
+ */
+ public Uri configuration;
+ /**
+ * The name and location of the properties supported by the event
+ * listener.
+ */
+ @XmlElementWrapper(name = "properties", nillable = false)
+ @XmlElement(name = "property", nillable = false)
+ public List<PropertyDescription> properties;
+
+ /**
+ * Make a blank listener description.
+ */
+ public ListenerDescription() {
+ }
+
+ /**
+ * Make a listener description that characterizes the given listener.
+ *
+ * @param listener
+ * The listener to describe.
+ * @param ub
+ * The factory for URIs. Must have already been secured.
+ */
+ public ListenerDescription(Listener listener, UriBuilder ub) {
+ super(true);
+ name = listener.getName();
+ type = listener.getType();
+ configuration = new Uri(ub.clone().path("configuration"));
+ UriBuilder ub2 = ub.clone().path("properties/{prop}");
+ String[] props = listener.listProperties();
+ properties = new ArrayList<>(props.length);
+ for (String propName : props)
+ properties.add(new PropertyDescription(propName, ub2));
+ }
+ }
+
+ /**
+ * The description of a single property, done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "PropertyDescription")
+ public static class PropertyDescription extends Uri {
+ /**
+ * The name of the property.
+ */
+ @XmlAttribute
+ String name;
+
+ /**
+ * Make an empty description of a property.
+ */
+ public PropertyDescription() {
+ }
+
+ /**
+ * Make a description of a property.
+ *
+ * @param listenerName
+ * The name of the listener whose property this is.
+ * @param propName
+ * The name of the property.
+ * @param ub
+ * The factory for URIs. Must have already been secured.
+ */
+ PropertyDescription(String propName, UriBuilder ub) {
+ super(ub, propName);
+ this.name = propName;
+ }
+ }
+
+ /**
+ * The list of descriptions of listeners attached to a run. Done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class Listeners extends VersionedElement {
+ /**
+ * The listeners for a workflow run.
+ */
+ @XmlElement(name = "listener")
+ public List<ListenerDescription> listener;
+
+ /**
+ * Make a blank description of listeners.
+ */
+ public Listeners() {
+ listener = new ArrayList<>();
+ }
+
+ /**
+ * Make a description of the whole group out of the given list of
+ * listener descriptions.
+ *
+ * @param listeners
+ * The collection of (partial) listener descriptions.
+ * @param ub
+ * How to build the location of the listeners. Must have
+ * already been secured.
+ */
+ public Listeners(List<ListenerDescription> listeners, UriBuilder ub) {
+ super(true);
+ listener = listeners;
+ for (ListenerDescription ld : listeners)
+ ld.location = ub.build(ld.name);
+ }
+ }
+
+ /**
+ * The list of properties of a listener. Done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class Properties extends VersionedElement {
+ /**
+ * The references to the properties of a listener.
+ */
+ @XmlElement
+ public List<PropertyDescription> property;
+
+ /**
+ * Make an empty description of the properties of a listener.
+ */
+ public Properties() {
+ }
+
+ /**
+ * Make the description of the properties of a listener.
+ *
+ * @param ub
+ * The factory for URIs, configured. Must have already been
+ * secured.
+ * @param properties
+ * The names of the properties.
+ */
+ public Properties(UriBuilder ub, String[] properties) {
+ super(true);
+ property = new ArrayList<>(properties.length);
+ for (String propName : properties)
+ property.add(new PropertyDescription(propName, ub));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java
new file mode 100644
index 0000000..62158bb
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static org.taverna.server.master.common.Namespaces.SERVER;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.rest.ContentTypes.JSON;
+import static org.taverna.server.master.rest.ContentTypes.URI_LIST;
+import static org.taverna.server.master.rest.ContentTypes.XML;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL_CAPABILITIES;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL_NOTIFIERS;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL_OP_LIMIT;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL_PERM_LIST;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL_PERM_WF;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.POL_RUN_LIMIT;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.ROOT;
+import static org.taverna.server.master.rest.TavernaServerREST.PathNames.RUNS;
+import static org.taverna.server.master.rest.handler.Scufl2DocumentHandler.SCUFL2;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.taverna.server.master.common.Capability;
+import org.taverna.server.master.common.RunReference;
+import org.taverna.server.master.common.Uri;
+import org.taverna.server.master.common.VersionedElement;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.common.version.Version;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.soap.TavernaServerSOAP;
+
+/**
+ * The REST service interface to Taverna 3 Server.
+ *
+ * @author Donal Fellows
+ * @see TavernaServerSOAP
+ */
+@RolesAllowed(USER)
+@Description("This is REST service interface to Taverna " + Version.JAVA
+ + " Server.")
+public interface TavernaServerREST {
+ /**
+ * Produces the description of the service.
+ *
+ * @param ui
+ * About the URI being accessed.
+ * @return The description.
+ */
+ @GET
+ @Path(ROOT)
+ @Produces({ XML, JSON })
+ @Description("Produces the description of the service.")
+ @Nonnull
+ ServerDescription describeService(@Nonnull @Context UriInfo ui);
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ROOT)
+ @Description("Produces the description of the service.")
+ Response serviceOptions();
+
+ /**
+ * Produces a description of the list of runs.
+ *
+ * @param ui
+ * About the URI being accessed.
+ * @return A description of the list of runs that are available.
+ */
+ @GET
+ @Path(RUNS)
+ @Produces({ XML, JSON })
+ @RolesAllowed(USER)
+ @Description("Produces a list of all runs visible to the user.")
+ @Nonnull
+ RunList listUsersRuns(@Nonnull @Context UriInfo ui);
+
+ /**
+ * Accepts (or not) a request to create a new run executing the given
+ * workflow.
+ *
+ * @param workflow
+ * The workflow document to execute.
+ * @param ui
+ * About the URI being accessed.
+ * @return A response to the POST describing what was created.
+ * @throws NoUpdateException
+ * If the POST failed.
+ */
+ @POST
+ @Path(RUNS)
+ @Consumes({ T2FLOW, SCUFL2, XML })
+ @RolesAllowed(USER)
+ @Description("Accepts (or not) a request to create a new run executing "
+ + "the given workflow.")
+ @Nonnull
+ Response submitWorkflow(@Nonnull Workflow workflow,
+ @Nonnull @Context UriInfo ui) throws NoUpdateException;
+
+ /**
+ * Accepts (or not) a request to create a new run executing the workflow at
+ * the given location.
+ *
+ * @param workflowReference
+ * The wrapped URI to workflow document to execute.
+ * @param ui
+ * About the URI being POSTed to.
+ * @return A response to the POST describing what was created.
+ * @throws NoUpdateException
+ * If the POST failed.
+ * @throw NoCreateException If the workflow couldn't be read into the server
+ * or the engine rejects it.
+ */
+ @POST
+ @Path(RUNS)
+ @Consumes(URI_LIST)
+ @RolesAllowed(USER)
+ @Description("Accepts a URL to a workflow to download and run. The URL "
+ + "must be hosted on a publicly-accessible service.")
+ @Nonnull
+ Response submitWorkflowByURL(@Nonnull List<URI> referenceList,
+ @Nonnull @Context UriInfo ui) throws NoCreateException,
+ NoUpdateException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(RUNS)
+ @Description("Produces the description of the operations on the "
+ + "collection of runs.")
+ Response runsOptions();
+
+ /**
+ * @return A description of the policies supported by this server.
+ */
+ @Path(POL)
+ @Description("The policies supported by this server.")
+ @Nonnull
+ PolicyView getPolicyDescription();
+
+ /**
+ * Get a particular named run resource.
+ *
+ * @param runName
+ * The name of the run.
+ * @param uriInfo
+ * About the URI used to access this run.
+ * @return A RESTful delegate for the run.
+ * @throws UnknownRunException
+ * If the run handle is unknown to the current user.
+ */
+ @Path(RUNS + "/{runName}")
+ @RolesAllowed(USER)
+ @Description("Get a particular named run resource to dispatch to.")
+ @Nonnull
+ TavernaServerRunREST getRunResource(
+ @Nonnull @PathParam("runName") String runName,
+ @Nonnull @Context UriInfo uriInfo) throws UnknownRunException;
+
+ /**
+ * Factored out path names used in the {@link TavernaServerREST} interface
+ * and related places.
+ *
+ * @author Donal Fellows
+ */
+ interface PathNames {
+ public static final String ROOT = "/";
+ public static final String RUNS = "runs";
+ public static final String POL = "policy";
+ public static final String POL_CAPABILITIES = "capabilities";
+ public static final String POL_RUN_LIMIT = "runLimit";
+ public static final String POL_OP_LIMIT = "operatingLimit";
+ public static final String POL_PERM_WF = "permittedWorkflows";
+ public static final String POL_PERM_LIST = "permittedListenerTypes";
+ public static final String POL_NOTIFIERS = "enabledNotificationFabrics";
+ }
+
+ /**
+ * Helper class for describing the server's user-facing management API via
+ * JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class ServerDescription extends VersionedElement {
+ /**
+ * References to the collection of runs (known about by the current
+ * user) in this server.
+ */
+ public Uri runs;
+ /**
+ * Reference to the policy description part of this server.
+ */
+ public Uri policy;
+ /**
+ * Reference to the Atom event feed produced by this server.
+ */
+ public Uri feed;
+ /**
+ * Reference to the interaction feed for this server.
+ */
+ public Uri interactionFeed;
+
+ /** Make a blank server description. */
+ public ServerDescription() {
+ }
+
+ /**
+ * Make a description of the server.
+ *
+ * @param ui
+ * The factory for URIs.
+ */
+ public ServerDescription(UriInfo ui, String interactionFeed) {
+ super(true);
+ String base = ui.getBaseUri().toString();
+ runs = new Uri(ui, RUNS);
+ policy = new Uri(ui, false, POL);
+ feed = new Uri(java.net.URI.create(base.replaceFirst("/rest$",
+ "/feed")));
+ if (interactionFeed != null && !interactionFeed.isEmpty())
+ this.interactionFeed = new Uri(
+ java.net.URI.create(interactionFeed));
+ }
+ }
+
+ /**
+ * How to discover the publicly-visible policies supported by this server.
+ *
+ * @author Donal Fellows
+ */
+ public interface PolicyView {
+ /**
+ * Describe the URIs in this view of the server's policies.
+ *
+ * @param ui
+ * About the URI used to retrieve the description.
+ * @return The description, which may be serialised as XML or JSON.
+ */
+ @GET
+ @Path(ROOT)
+ @Produces({ XML, JSON })
+ @Description("Describe the parts of this policy.")
+ @Nonnull
+ public PolicyDescription getDescription(@Nonnull @Context UriInfo ui);
+
+ /**
+ * Gets the maximum number of simultaneous runs that the user may
+ * create. The <i>actual</i> number they can create may be lower than
+ * this. If this number is lower than the number they currently have,
+ * they will be unable to create any runs at all.
+ *
+ * @return The maximum number of existing runs.
+ */
+ @GET
+ @Path(POL_RUN_LIMIT)
+ @Produces("text/plain")
+ @RolesAllowed(USER)
+ @Description("Gets the maximum number of simultaneous runs in any "
+ + "state that the user may create.")
+ @Nonnull
+ public int getMaxSimultaneousRuns();
+
+ /**
+ * Gets the maximum number of simultaneous
+ * {@linkplain org.taverna.server.master.common.Status.Operating
+ * operating} runs that the user may create. The <i>actual</i> number
+ * they can start may be lower than this. If this number is lower than
+ * the number they currently have, they will be unable to start any runs
+ * at all.
+ *
+ * @return The maximum number of operating runs.
+ */
+ @GET
+ @Path(POL_OP_LIMIT)
+ @Produces("text/plain")
+ @RolesAllowed(USER)
+ @Description("Gets the maximum number of simultaneously operating "
+ + "runs that the user may have. Note that this is often a "
+ + "global limit; it does not represent a promise that a "
+ + "particular user may be able to have that many operating "
+ + "runs at once.")
+ public int getMaxOperatingRuns();
+
+ /**
+ * Gets the list of permitted workflows. Any workflow may be submitted
+ * if the list is empty, otherwise it must be one of the workflows on
+ * this list.
+ *
+ * @return The list of workflow documents.
+ */
+ @GET
+ @Path(POL_PERM_WF)
+ @Produces({ XML, JSON })
+ @RolesAllowed(USER)
+ @Description("Gets the list of permitted workflows.")
+ @Nonnull
+ public PermittedWorkflows getPermittedWorkflows();
+
+ /**
+ * Gets the list of permitted event listener types. All event listeners
+ * must be of a type described on this list.
+ *
+ * @return The types of event listeners allowed.
+ */
+ @GET
+ @Path(POL_PERM_LIST)
+ @Produces({ XML, JSON })
+ @RolesAllowed(USER)
+ @Description("Gets the list of permitted event listener types.")
+ @Nonnull
+ public PermittedListeners getPermittedListeners();
+
+ /**
+ * Gets the list of supported, enabled notification fabrics. Each
+ * corresponds (approximately) to a protocol, e.g., email.
+ *
+ * @return List of notifier names; each is the scheme of a notification
+ * destination URI.
+ */
+ @GET
+ @Path(POL_NOTIFIERS)
+ @Produces({ XML, JSON })
+ @RolesAllowed(USER)
+ @Description("Gets the list of supported, enabled notification "
+ + "fabrics. Each corresponds (approximately) to a protocol, "
+ + "e.g., email.")
+ @Nonnull
+ public EnabledNotificationFabrics getEnabledNotifiers();
+
+ @GET
+ @Path(POL_CAPABILITIES)
+ @Produces({ XML, JSON })
+ @RolesAllowed(USER)
+ @Description("Gets a description of the capabilities supported by "
+ + "this installation of Taverna Server.")
+ @Nonnull
+ public CapabilityList getCapabilities();
+
+ /**
+ * A description of the parts of a server policy.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class PolicyDescription extends VersionedElement {
+ /**
+ * Where to go to find out about the maximum number of runs.
+ */
+ public Uri runLimit;
+ /**
+ * Where to go to find out about the maximum number of operating
+ * runs.
+ */
+ public Uri operatingLimit;
+ /**
+ * Where to go to find out about what workflows are allowed.
+ */
+ public Uri permittedWorkflows;
+ /**
+ * Where to go to find out about what listeners are allowed.
+ */
+ public Uri permittedListenerTypes;
+ /**
+ * How notifications may be sent.
+ */
+ public Uri enabledNotificationFabrics;
+
+ public Uri capabilities;
+
+ /** Make a blank server description. */
+ public PolicyDescription() {
+ }
+
+ /**
+ * Make a server description.
+ *
+ * @param ui
+ * About the URI used to access this description.
+ */
+ public PolicyDescription(UriInfo ui) {
+ super(true);
+ runLimit = new Uri(ui, false, POL_RUN_LIMIT);
+ operatingLimit = new Uri(ui, false, POL_OP_LIMIT);
+ permittedWorkflows = new Uri(ui, false, POL_PERM_WF);
+ permittedListenerTypes = new Uri(ui, false, POL_PERM_LIST);
+ enabledNotificationFabrics = new Uri(ui, false, POL_NOTIFIERS);
+ capabilities = new Uri(ui, false, POL_CAPABILITIES);
+ }
+ }
+
+ /**
+ * A list of Taverna Server capabilities.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "capabilities")
+ @XmlType(name = "")
+ public static class CapabilityList {
+ @XmlElement(name = "capability", namespace = SERVER)
+ public List<Capability> capability = new ArrayList<>();
+ }
+ }
+
+ /**
+ * Helper class for describing the workflows that are allowed via JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class PermittedWorkflows {
+ /** The workflows that are permitted. */
+ @XmlElement
+ public List<URI> workflow;
+
+ /**
+ * Make an empty list of permitted workflows.
+ */
+ public PermittedWorkflows() {
+ workflow = new ArrayList<>();
+ }
+
+ /**
+ * Make a list of permitted workflows.
+ *
+ * @param permitted
+ */
+ public PermittedWorkflows(List<URI> permitted) {
+ if (permitted == null)
+ workflow = new ArrayList<>();
+ else
+ workflow = new ArrayList<>(permitted);
+ }
+ }
+
+ /**
+ * Helper class for describing the listener types that are allowed via JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class PermittedListeners {
+ /** The listener types that are permitted. */
+ @XmlElement
+ public List<String> type;
+
+ /**
+ * Make an empty list of permitted listener types.
+ */
+ public PermittedListeners() {
+ type = new ArrayList<>();
+ }
+
+ /**
+ * Make a list of permitted listener types.
+ *
+ * @param listenerTypes
+ */
+ public PermittedListeners(List<String> listenerTypes) {
+ type = listenerTypes;
+ }
+ }
+
+ /**
+ * Helper class for describing the workflow runs.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class RunList {
+ /** The references to the workflow runs. */
+ @XmlElement
+ public List<RunReference> run;
+
+ /**
+ * Make an empty list of run references.
+ */
+ public RunList() {
+ run = new ArrayList<>();
+ }
+
+ /**
+ * Make a list of references to workflow runs.
+ *
+ * @param runs
+ * The mapping of runs to describe.
+ * @param ub
+ * How to construct URIs to the runs. Must have already been
+ * secured as it needs to have its pattern applied.
+ */
+ public RunList(Map<String, TavernaRun> runs, UriBuilder ub) {
+ run = new ArrayList<>(runs.size());
+ for (String name : runs.keySet())
+ run.add(new RunReference(name, ub));
+ }
+ }
+
+ /**
+ * Helper class for describing the listener types that are allowed via JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class EnabledNotificationFabrics {
+ /** The notification fabrics that are enabled. */
+ @XmlElement
+ public List<String> notifier;
+
+ /**
+ * Make an empty list of enabled notifiers.
+ */
+ public EnabledNotificationFabrics() {
+ notifier = new ArrayList<>();
+ }
+
+ /**
+ * Make a list of enabled notifiers.
+ *
+ * @param enabledNodifiers
+ */
+ public EnabledNotificationFabrics(List<String> enabledNodifiers) {
+ notifier = enabledNodifiers;
+ }
+ }
+
+ /**
+ * The interface exposed by the Atom feed of events.
+ *
+ * @author Donal Fellows
+ */
+ @RolesAllowed(USER)
+ public interface EventFeed {
+ /**
+ * @return the feed of events for the current user.
+ */
+ @GET
+ @Path("/")
+ @Produces("application/atom+xml;type=feed")
+ @Description("Get an Atom feed for the user's events.")
+ @Nonnull
+ Feed getFeed(@Context UriInfo ui);
+
+ /**
+ * @param id
+ * The identifier for a particular event.
+ * @return the details about the given event.
+ */
+ @GET
+ @Path("{id}")
+ @Produces("application/atom+xml;type=entry")
+ @Description("Get a particular Atom event.")
+ @Nonnull
+ Entry getEvent(@Nonnull @PathParam("id") String id);
+ }
+
+ /**
+ * A reference to a workflow hosted on some public HTTP server.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "workflowurl")
+ @XmlType(name = "WorkflowReference")
+ public static class WorkflowReference {
+ @XmlValue
+ @XmlSchemaType(name = "anyURI")
+ public URI url;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java
new file mode 100644
index 0000000..2b328fd
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java
@@ -0,0 +1,797 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static javax.ws.rs.core.UriBuilder.fromUri;
+import static org.joda.time.format.ISODateTimeFormat.basicDateTime;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.rest.handler.Scufl2DocumentHandler.SCUFL2;
+import static org.taverna.server.master.interaction.InteractionFeedSupport.FEED_URL_DIR;
+import static org.taverna.server.master.rest.ContentTypes.JSON;
+import static org.taverna.server.master.rest.ContentTypes.ROBUNDLE;
+import static org.taverna.server.master.rest.ContentTypes.TEXT;
+import static org.taverna.server.master.rest.ContentTypes.XML;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.DIR;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.GENERATE_PROVENANCE;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.IN;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.LISTEN;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.LOG;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.NAME;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.OUT;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.PROFILE;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.ROOT;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.RUNBUNDLE;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.SEC;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.STATUS;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.STDERR;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.STDOUT;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.T_CREATE;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.T_EXPIRE;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.T_FINISH;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.T_START;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.USAGE;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.WF;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.joda.time.format.DateTimeFormatter;
+import org.taverna.server.master.common.Namespaces;
+import org.taverna.server.master.common.ProfileList;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Uri;
+import org.taverna.server.master.common.VersionedElement;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.exceptions.NotOwnerException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.port_description.OutputDescription;
+
+/**
+ * This represents how a Taverna Server workflow run looks to a RESTful API.
+ *
+ * @author Donal Fellows.
+ */
+@Description("This represents how a Taverna Server workflow run looks to a "
+ + "RESTful API.")
+@RolesAllowed(USER)
+public interface TavernaServerRunREST {
+ /**
+ * Describes a workflow run.
+ *
+ * @param ui
+ * About the URI used to access this resource.
+ * @return The description.
+ */
+ @GET
+ @Path(ROOT)
+ @Description("Describes a workflow run.")
+ @Produces({ XML, JSON })
+ @Nonnull
+ public RunDescription getDescription(@Nonnull @Context UriInfo ui);
+
+ /**
+ * Deletes a workflow run.
+ *
+ * @return An HTTP response to the deletion.
+ * @throws NoUpdateException
+ * If the user may see the handle but may not delete it.
+ */
+ @DELETE
+ @Path(ROOT)
+ @Description("Deletes a workflow run.")
+ @Nonnull
+ public Response destroy() throws NoUpdateException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ROOT)
+ @Description("Produces the description of the run.")
+ Response runOptions();
+
+ /**
+ * Returns the workflow document used to create the workflow run.
+ *
+ * @return The workflow document.
+ */
+ @GET
+ @Path(WF)
+ @Produces({ T2FLOW, SCUFL2, XML, JSON })
+ @Description("Gives the workflow document used to create the workflow run.")
+ @Nonnull
+ public Workflow getWorkflow();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(WF)
+ @Description("Produces the description of the run workflow.")
+ Response workflowOptions();
+
+ /** Get the workflow name. */
+ @GET
+ @Path(NAME)
+ @Produces(TEXT)
+ @Description("Gives the descriptive name of the workflow run.")
+ @Nonnull
+ public String getName();
+
+ /**
+ * Set the workflow name.
+ *
+ * @throws NoUpdateException
+ * If the user is not permitted to change the workflow.
+ */
+ @PUT
+ @Path(NAME)
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Description("Set the descriptive name of the workflow run. Note that "
+ + "this value may be arbitrarily truncated by the implementation.")
+ @Nonnull
+ public String setName(String name) throws NoUpdateException;
+
+ /** Produce the workflow name HTTP operations. */
+ @OPTIONS
+ @Path(NAME)
+ @Description("Produces the description of the operations on the run's "
+ + "descriptive name.")
+ @Nonnull
+ Response nameOptions();
+
+ /**
+ * Produces the name of the workflow's main profile.
+ *
+ * @return The main profile name, or the empty string if there is no such
+ * profile.
+ */
+ @GET
+ @Path(PROFILE)
+ @Produces(TEXT)
+ @Description("Gives the name of the workflow's main profile, or the empty string if none is defined.")
+ @Nonnull
+ String getMainProfileName();
+
+ /**
+ * Get a description of the profiles supported by the workflow document used
+ * to create this run.
+ *
+ * @return A description of the supported profiles.
+ */
+ @GET
+ @Path(PROFILE)
+ @Produces({ XML, JSON })
+ @Description("Describes what profiles exist on the workflow.")
+ @Nonnull
+ ProfileList getProfiles();
+
+ /** Produce the workflow profile HTTP operations. */
+ @OPTIONS
+ @Path(PROFILE)
+ @Description("Produces the description of the operations on the run's "
+ + "profile.")
+ @Nonnull
+ Response profileOptions();
+
+ /**
+ * Returns a resource that represents the workflow run's security
+ * properties. These may only be accessed by the owner.
+ *
+ * @return The security resource.
+ * @throws NotOwnerException
+ * If the accessing principal isn't the owning principal.
+ */
+ @Path(SEC)
+ @Description("Access the workflow run's security.")
+ @Nonnull
+ public TavernaServerSecurityREST getSecurity() throws NotOwnerException;
+
+ /**
+ * Returns the time when the workflow run becomes eligible for automatic
+ * deletion.
+ *
+ * @return When the run expires.
+ */
+ @GET
+ @Path(T_EXPIRE)
+ @Produces(TEXT)
+ @Description("Gives the time when the workflow run becomes eligible for "
+ + "automatic deletion.")
+ @Nonnull
+ public String getExpiryTime();
+
+ /**
+ * Sets the time when the workflow run becomes eligible for automatic
+ * deletion.
+ *
+ * @param expiry
+ * When the run will expire.
+ * @return When the run will actually expire.
+ * @throws NoUpdateException
+ * If the current user is not permitted to manage the lifetime
+ * of the run.
+ */
+ @PUT
+ @Path(T_EXPIRE)
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Description("Sets the time when the workflow run becomes eligible for "
+ + "automatic deletion.")
+ @Nonnull
+ public String setExpiryTime(@Nonnull String expiry)
+ throws NoUpdateException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(T_EXPIRE)
+ @Description("Produces the description of the run expiry.")
+ Response expiryOptions();
+
+ /**
+ * Returns the time when the workflow run was created.
+ *
+ * @return When the run was first submitted to the server.
+ */
+ @GET
+ @Path(T_CREATE)
+ @Produces(TEXT)
+ @Description("Gives the time when the workflow run was first submitted "
+ + "to the server.")
+ @Nonnull
+ public String getCreateTime();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(T_CREATE)
+ @Description("Produces the description of the run create time.")
+ Response createTimeOptions();
+
+ /**
+ * Returns the time when the workflow run was started (through a user-driven
+ * state change).
+ *
+ * @return When the run was started, or <tt>null</tt>.
+ */
+ @GET
+ @Path(T_START)
+ @Produces(TEXT)
+ @Description("Gives the time when the workflow run was started, or an "
+ + "empty string if the run has not yet started.")
+ @Nonnull
+ public String getStartTime();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(T_START)
+ @Description("Produces the description of the run start time.")
+ Response startTimeOptions();
+
+ /**
+ * Returns the time when the workflow run was detected to have finished.
+ *
+ * @return When the run finished, or <tt>null</tt>.
+ */
+ @GET
+ @Path(T_FINISH)
+ @Produces(TEXT)
+ @Description("Gives the time when the workflow run was first detected as "
+ + "finished, or an empty string if it has not yet finished "
+ + "(including if it has never started).")
+ @Nonnull
+ public String getFinishTime();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(T_FINISH)
+ @Description("Produces the description of the run finish time.")
+ Response finishTimeOptions();
+
+ /**
+ * Gets the current status of the workflow run.
+ *
+ * @return The status code.
+ */
+ @GET
+ @Path(STATUS)
+ @Produces(TEXT)
+ @Description("Gives the current status of the workflow run.")
+ @Nonnull
+ public String getStatus();
+
+ /**
+ * Sets the status of the workflow run. This does nothing if the status code
+ * is the same as the run's current state.
+ *
+ * @param status
+ * The new status code.
+ * @return Description of what status the run is actually in, or a 202 to
+ * indicate that things are still changing.
+ * @throws NoUpdateException
+ * If the current user is not permitted to update the run.
+ * @throws BadStateChangeException
+ * If the state cannot be modified in the manner requested.
+ */
+ @PUT
+ @Path(STATUS)
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Description("Attempts to update the status of the workflow run.")
+ @Nonnull
+ public Response setStatus(@Nonnull String status) throws NoUpdateException,
+ BadStateChangeException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(STATUS)
+ @Description("Produces the description of the run status.")
+ Response statusOptions();
+
+ /**
+ * Get the working directory of this workflow run.
+ *
+ * @return A RESTful delegate for the working directory.
+ */
+ @Path(DIR)
+ @Description("Get the working directory of this workflow run.")
+ @Nonnull
+ public TavernaServerDirectoryREST getWorkingDirectory();
+
+ /**
+ * Get the event listeners attached to this workflow run.
+ *
+ * @return A RESTful delegate for the list of listeners.
+ */
+ @Path(LISTEN)
+ @Description("Get the event listeners attached to this workflow run.")
+ @Nonnull
+ public TavernaServerListenersREST getListeners();
+
+ /**
+ * Get a delegate for working with the inputs to this workflow run.
+ *
+ * @param ui
+ * About the URI used to access this resource.
+ * @return A RESTful delegate for the inputs.
+ */
+ @Path(IN)
+ @Description("Get the inputs to this workflow run.")
+ @Nonnull
+ public TavernaServerInputREST getInputs(@Nonnull @Context UriInfo ui);
+
+ /**
+ * Get the output Baclava file for this workflow run.
+ *
+ * @return The filename, or empty string to indicate that the outputs will
+ * be written to the <tt>out</tt> directory.
+ */
+ @GET
+ @Path(OUT)
+ @Produces(TEXT)
+ @Description("Gives the Baclava file where output will be written; empty "
+ + "means use multiple simple files in the out directory.")
+ @Nonnull
+ public String getOutputFile();
+
+ /**
+ * Get a description of the outputs.
+ *
+ * @param ui
+ * About the URI used to access this operation.
+ * @return A description of the outputs (higher level than the filesystem).
+ * @throws BadStateChangeException
+ * If the run is in the {@link Status#Initialized Initialized}
+ * state.
+ * @throws FilesystemAccessException
+ * If problems occur when accessing the filesystem.
+ * @throws NoDirectoryEntryException
+ * If things are odd in the filesystem.
+ */
+ @GET
+ @Path(OUT)
+ @Produces({ XML, JSON })
+ @Description("Gives a description of the outputs, as currently understood")
+ @Nonnull
+ public OutputDescription getOutputDescription(@Nonnull @Context UriInfo ui)
+ throws BadStateChangeException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Set the output Baclava file for this workflow run.
+ *
+ * @param filename
+ * The Baclava file to use, or empty to make the outputs be
+ * written to individual files in the <tt>out</tt> subdirectory
+ * of the working directory.
+ * @return The Baclava file as actually set.
+ * @throws NoUpdateException
+ * If the current user is not permitted to update the run.
+ * @throws FilesystemAccessException
+ * If the filename is invalid (starts with <tt>/</tt> or
+ * contains a <tt>..</tt> segment).
+ * @throws BadStateChangeException
+ * If the workflow is not in the Initialized state.
+ */
+ @PUT
+ @Path(OUT)
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Description("Sets the Baclava file where output will be written; empty "
+ + "means use multiple simple files in the out directory.")
+ @Nonnull
+ public String setOutputFile(@Nonnull String filename)
+ throws NoUpdateException, FilesystemAccessException,
+ BadStateChangeException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(OUT)
+ @Description("Produces the description of the run output.")
+ Response outputOptions();
+
+ /**
+ * Get a handle to the interaction feed.
+ *
+ * @return
+ */
+ @Path(FEED_URL_DIR)
+ @Description("Access the interaction feed for the workflow run.")
+ @Nonnull
+ InteractionFeedREST getInteractionFeed();
+
+ /**
+ * @return The stdout for the workflow run, or empty string if the run has
+ * not yet started.
+ * @throws NoListenerException
+ */
+ @GET
+ @Path(STDOUT)
+ @Description("Return the stdout for the workflow run.")
+ @Produces(TEXT)
+ @Nonnull
+ String getStdout() throws NoListenerException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(STDOUT)
+ @Description("Return the stdout for the workflow run.")
+ Response stdoutOptions();
+
+ /**
+ * @return The stderr for the workflow run, or empty string if the run has
+ * not yet started.
+ * @throws NoListenerException
+ */
+ @GET
+ @Path(STDERR)
+ @Description("Return the stderr for the workflow run.")
+ @Produces(TEXT)
+ @Nonnull
+ String getStderr() throws NoListenerException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(STDERR)
+ @Description("Return the stderr for the workflow run.")
+ Response stderrOptions();
+
+ /**
+ * @return The usage record for the workflow run, wrapped in a Response, or
+ * "empty content" if the run has not yet finished.
+ * @throws NoListenerException
+ * @throws JAXBException
+ */
+ @GET
+ @Path(USAGE)
+ @Description("Return the usage record for the workflow run.")
+ @Produces(XML)
+ @Nonnull
+ Response getUsage() throws NoListenerException, JAXBException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(USAGE)
+ @Description("Return the usage record for the workflow run.")
+ Response usageOptions();
+
+ /**
+ * @return The log for the workflow run, or empty string if the run has not
+ * yet started.
+ */
+ @GET
+ @Path(LOG)
+ @Description("Return the log for the workflow run.")
+ @Produces(TEXT)
+ @Nonnull
+ Response getLogContents();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(LOG)
+ @Description("Return the log for the workflow run.")
+ Response logOptions();
+
+ /**
+ * @return The log for the workflow run, or empty string if the run has not
+ * yet started.
+ */
+ @GET
+ @Path(RUNBUNDLE)
+ @Description("Return the run bundle for the workflow run.")
+ @Produces(ROBUNDLE)
+ @Nonnull
+ Response getRunBundle();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(RUNBUNDLE)
+ @Description("Return the run bundle for the workflow run.")
+ Response runBundleOptions();
+
+ /**
+ * @return Whether to create the run bundle for the workflow run. Only
+ * usefully set-able before the start of the run.
+ */
+ @GET
+ @Path(GENERATE_PROVENANCE)
+ @Description("Whether to create the run bundle for the workflow run.")
+ @Produces(TEXT)
+ @Nonnull
+ boolean getGenerateProvenance();
+
+ /**
+ * @param provenanceFlag
+ * Whether to create the run bundle for the workflow run. Only
+ * usefully set-able before the start of the run.
+ * @return What it was actually set to.
+ * @throws NoUpdateException
+ */
+ @PUT
+ @Path(GENERATE_PROVENANCE)
+ @Description("Whether to create the run bundle for the workflow run.")
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Nonnull
+ boolean setGenerateProvenance(boolean provenanceFlag) throws NoUpdateException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(GENERATE_PROVENANCE)
+ @Description("Whether to create the run bundle for the workflow run.")
+ Response generateProvenanceOptions();
+
+ /**
+ * Factored out path names used in the {@link TavernaServerRunREST}
+ * interface and related places.
+ *
+ * @author Donal Fellows
+ */
+ interface PathNames {
+ public static final String ROOT = "/";
+ public static final String WF = "workflow";
+ public static final String DIR = "wd";
+ public static final String NAME = "name";
+ public static final String T_EXPIRE = "expiry";
+ public static final String T_CREATE = "createTime";
+ public static final String T_START = "startTime";
+ public static final String T_FINISH = "finishTime";
+ public static final String STATUS = "status";
+ public static final String IN = "input";
+ public static final String OUT = "output";
+ public static final String PROFILE = "profile";
+ public static final String LISTEN = "listeners";
+ public static final String SEC = "security";
+ public static final String STDOUT = "stdout";
+ public static final String STDERR = "stderr";
+ public static final String USAGE = "usage";
+ public static final String LOG = "log";
+ public static final String RUNBUNDLE = "run-bundle";
+ public static final String GENERATE_PROVENANCE = "generate-provenance";
+ }
+
+ /**
+ * The description of where everything is in a RESTful view of a workflow
+ * run. Done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement
+ @XmlType(name = "")
+ public static class RunDescription extends VersionedElement {
+ /** The identity of the owner of the workflow run. */
+ @XmlAttribute(namespace = Namespaces.SERVER_REST)
+ public String owner;
+ /** The description of the expiry. */
+ public Expiry expiry;
+ /** The location of the creation workflow description. */
+ public Uri creationWorkflow;
+ /** The location of the creation time property. */
+ public Uri createTime;
+ /** The location of the start time property. */
+ public Uri startTime;
+ /** The location of the finish time property. */
+ public Uri finishTime;
+ /** The location of the status description. */
+ public Uri status;
+ /** The location of the working directory. */
+ public Uri workingDirectory;
+ /** The location of the inputs. */
+ public Uri inputs;
+ /** The location of the Baclava output. */
+ public Uri output;
+ /** The location of the security context. */
+ public Uri securityContext;
+ /** The list of listeners. */
+ public ListenerList listeners;
+ /** The location of the interaction feed. */
+ public Uri interaction;
+ /** The name of the run. */
+ public Uri name;
+ /** The stdout of the run. */
+ public Uri stdout;
+ /** The stderr of the run. */
+ public Uri stderr;
+ /** The usage record for the run. */
+ public Uri usage;
+ /** The log from the run. */
+ public Uri log;
+ /** The bundle describing the run. */
+ @XmlElement(name = RUNBUNDLE)
+ public Uri runBundle;
+ /** Whether to generate a bundle describing the run. */
+ @XmlElement(name = GENERATE_PROVENANCE)
+ public Uri generateProvenance;
+
+ /**
+ * How to describe a run's expiry.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "")
+ public static class Expiry {
+ /**
+ * Where to go to read the exiry
+ */
+ @XmlAttribute(name = "href", namespace = Namespaces.XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI ref;
+ /**
+ * What the expiry currently is.
+ */
+ @XmlValue
+ public String timeOfDeath;
+
+ /**
+ * Make a blank expiry description.
+ */
+ public Expiry() {
+ }
+
+ private static DateTimeFormatter dtf;
+
+ Expiry(TavernaRun r, UriInfo ui, String path, String... parts) {
+ ref = fromUri(new Uri(ui, true, path, parts).ref).build();
+ if (dtf == null)
+ dtf = basicDateTime();
+ timeOfDeath = dtf.print(r.getExpiry().getTime());
+ }
+ }
+
+ /**
+ * The description of a list of listeners attached to a run.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "")
+ public static class ListenerList extends Uri {
+ /**
+ * The references to the individual listeners.
+ */
+ public List<Uri> listener;
+
+ /**
+ * An empty description of listeners.
+ */
+ public ListenerList() {
+ listener = new ArrayList<>();
+ }
+
+ /**
+ * @param r
+ * The run whose listeners we're talking about.
+ * @param ub
+ * Uri factory; must've been secured
+ */
+ private ListenerList(TavernaRun r, UriBuilder ub) {
+ super(ub);
+ listener = new ArrayList<>(r.getListeners().size());
+ UriBuilder pathUB = ub.clone().path("{name}");
+ for (Listener l : r.getListeners())
+ listener.add(new Uri(pathUB.build(l.getName())));
+ }
+
+ /**
+ * @param run
+ * The run whose listeners we're talking about.
+ * @param ui
+ * The source of information about URIs.
+ * @param path
+ * Where we are relative to the URI source.
+ * @param parts
+ * Anything required to fill out the path.
+ */
+ ListenerList(TavernaRun run, UriInfo ui, String path,
+ String... parts) {
+ this(run, secure(fromUri(new Uri(ui, path, parts).ref)));
+ }
+ }
+
+ /**
+ * An empty description of a run.
+ */
+ public RunDescription() {
+ }
+
+ /**
+ * A description of a particular run.
+ *
+ * @param run
+ * The run to describe.
+ * @param ui
+ * The factory for URIs.
+ */
+ public RunDescription(TavernaRun run, UriInfo ui) {
+ super(true);
+ creationWorkflow = new Uri(ui, WF);
+ expiry = new Expiry(run, ui, T_EXPIRE);
+ status = new Uri(ui, STATUS);
+ workingDirectory = new Uri(ui, DIR);
+ listeners = new ListenerList(run, ui, LISTEN);
+ securityContext = new Uri(ui, SEC);
+ inputs = new Uri(ui, IN);
+ output = new Uri(ui, OUT);
+ createTime = new Uri(ui, T_CREATE);
+ startTime = new Uri(ui, T_START);
+ finishTime = new Uri(ui, T_FINISH);
+ interaction = new Uri(ui, FEED_URL_DIR);
+ name = new Uri(ui, NAME);
+ owner = run.getSecurityContext().getOwner().getName();
+ stdout = new Uri(ui, STDOUT);
+ stderr = new Uri(ui, STDERR);
+ usage = new Uri(ui, USAGE);
+ log = new Uri(ui, LOG);
+ runBundle = new Uri(ui, RUNBUNDLE);
+ generateProvenance = new Uri(ui, GENERATE_PROVENANCE);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java
new file mode 100644
index 0000000..73000e8
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java
@@ -0,0 +1,775 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static java.util.Collections.emptyList;
+import static org.taverna.server.master.common.Namespaces.SERVER;
+import static org.taverna.server.master.common.Namespaces.XLINK;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.rest.ContentTypes.JSON;
+import static org.taverna.server.master.rest.ContentTypes.TEXT;
+import static org.taverna.server.master.rest.ContentTypes.XML;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.CREDS;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.ONE_CRED;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.ONE_PERM;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.ONE_TRUST;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.OWNER;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.PERMS;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.ROOT;
+import static org.taverna.server.master.rest.TavernaServerSecurityREST.PathNames.TRUSTS;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.Permission;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.common.Uri;
+import org.taverna.server.master.common.VersionedElement;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.exceptions.NoCredentialException;
+
+/**
+ * Manages the security of the workflow run. In general, only the owner of a run
+ * may access this resource. Many of these security-related resources may only
+ * be changed before the run is set to operating.
+ *
+ * @author Donal Fellows
+ */
+@RolesAllowed(USER)
+@Description("Manages the security of the workflow run. In general, only the "
+ + "owner of a run may access this resource.")
+public interface TavernaServerSecurityREST {
+ interface PathNames {
+ final String ROOT = "/";
+ final String OWNER = "owner";
+ final String CREDS = "credentials";
+ final String ONE_CRED = CREDS + "/{id}";
+ final String TRUSTS = "trusts";
+ final String ONE_TRUST = TRUSTS + "/{id}";
+ final String PERMS = "permissions";
+ final String ONE_PERM = PERMS + "/{id}";
+ }
+
+ /**
+ * Gets a description of the security information supported by the workflow
+ * run.
+ *
+ * @param ui
+ * About the URI used to access this resource.
+ * @return A description of the security information.
+ */
+ @GET
+ @Path(ROOT)
+ @Produces({ XML, JSON })
+ @Description("Gives a description of the security information supported "
+ + "by the workflow run.")
+ @Nonnull
+ Descriptor describe(@Nonnull @Context UriInfo ui);
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ROOT)
+ @Description("Produces the description of the run security.")
+ Response descriptionOptions();
+
+ /**
+ * Gets the identity of who owns the workflow run.
+ *
+ * @return The name of the owner of the run.
+ */
+ @GET
+ @Path(OWNER)
+ @Produces(TEXT)
+ @Description("Gives the identity of who owns the workflow run.")
+ @Nonnull
+ String getOwner();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(OWNER)
+ @Description("Produces the description of the run owner.")
+ Response ownerOptions();
+
+ /*
+ * @PUT @Path("/") @Consumes(ContentTypes.BYTES) @CallCounted @Nonnull
+ * public void set(@Nonnull InputStream contents, @Nonnull @Context UriInfo
+ * ui);
+ */
+
+ /**
+ * @return A list of credentials supplied to this workflow run.
+ */
+ @GET
+ @Path(CREDS)
+ @Produces({ XML, JSON })
+ @Description("Gives a list of credentials supplied to this workflow run.")
+ @Nonnull
+ CredentialList listCredentials();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(CREDS)
+ @Description("Produces the description of the run credentials' operations.")
+ Response credentialsOptions();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ONE_CRED)
+ @Description("Produces the description of one run credential's operations.")
+ Response credentialOptions(@PathParam("id") String id);
+
+ /**
+ * Describe a particular credential.
+ *
+ * @param id
+ * The id of the credential to fetch.
+ * @return The description of the credential.
+ * @throws NoCredentialException
+ * If the credential doesn't exist.
+ */
+ @GET
+ @Path(ONE_CRED)
+ @Produces({ XML, JSON })
+ @Description("Describes a particular credential.")
+ @Nonnull
+ CredentialHolder getParticularCredential(@Nonnull @PathParam("id") String id)
+ throws NoCredentialException;
+
+ /**
+ * Update a particular credential.
+ *
+ * @param id
+ * The id of the credential to update.
+ * @param c
+ * The details of the credential to use in the update.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return Description of the updated credential.
+ * @throws InvalidCredentialException
+ * If the credential description isn't valid.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @PUT
+ @Path(ONE_CRED)
+ @Consumes({ XML, JSON })
+ @Produces({ XML, JSON })
+ @Description("Updates a particular credential.")
+ @Nonnull
+ CredentialHolder setParticularCredential(
+ @Nonnull @PathParam("id") String id, @Nonnull CredentialHolder c,
+ @Nonnull @Context UriInfo ui) throws InvalidCredentialException,
+ BadStateChangeException;
+
+ /**
+ * Adds a new credential.
+ *
+ * @param c
+ * The details of the credential to create.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return Description of the created credential.
+ * @throws InvalidCredentialException
+ * If the credential description isn't valid.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @POST
+ @Path(CREDS)
+ @Consumes({ XML, JSON })
+ @Description("Creates a new credential.")
+ @Nonnull
+ Response addCredential(@Nonnull CredentialHolder c,
+ @Nonnull @Context UriInfo ui) throws InvalidCredentialException,
+ BadStateChangeException;
+
+ /**
+ * Deletes all credentials associated with a run.
+ *
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return A characterisation of a successful delete.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @DELETE
+ @Path(CREDS)
+ @Description("Deletes all credentials.")
+ @Nonnull
+ Response deleteAllCredentials(@Nonnull @Context UriInfo ui)
+ throws BadStateChangeException;
+
+ /**
+ * Deletes one credential associated with a run.
+ *
+ * @param id
+ * The identity of the credential to delete.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return A characterisation of a successful delete.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @DELETE
+ @Path(ONE_CRED)
+ @Description("Deletes a particular credential.")
+ @Nonnull
+ Response deleteCredential(@Nonnull @PathParam("id") String id,
+ @Nonnull @Context UriInfo ui) throws BadStateChangeException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(TRUSTS)
+ @Description("Produces the description of the run trusted certificates' "
+ + "operations.")
+ Response trustsOptions();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ONE_TRUST)
+ @Description("Produces the description of one run trusted certificate's "
+ + "operations.")
+ Response trustOptions(@PathParam("id") String id);
+
+ /**
+ * @return A list of trusted identities supplied to this workflow run.
+ */
+ @GET
+ @Path(TRUSTS)
+ @Produces({ XML, JSON })
+ @Description("Gives a list of trusted identities supplied to this "
+ + "workflow run.")
+ @Nonnull
+ TrustList listTrusted();
+
+ /**
+ * Describe a particular trusted identity.
+ *
+ * @param id
+ * The id of the trusted identity to fetch.
+ * @return The description of the trusted identity.
+ * @throws NoCredentialException
+ * If the trusted identity doesn't exist.
+ */
+ @GET
+ @Path(ONE_TRUST)
+ @Produces({ XML, JSON })
+ @Description("Describes a particular trusted identity.")
+ @Nonnull
+ Trust getParticularTrust(@Nonnull @PathParam("id") String id)
+ throws NoCredentialException;
+
+ /**
+ * Update a particular trusted identity.
+ *
+ * @param id
+ * The id of the trusted identity to update.
+ * @param t
+ * The details of the trusted identity to use in the update.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return Description of the updated trusted identity.
+ * @throws InvalidCredentialException
+ * If the trusted identity description isn't valid.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @PUT
+ @Path(ONE_TRUST)
+ @Consumes({ XML, JSON })
+ @Produces({ XML, JSON })
+ @Description("Updates a particular trusted identity.")
+ @Nonnull
+ Trust setParticularTrust(@Nonnull @PathParam("id") String id,
+ @Nonnull Trust t, @Nonnull @Context UriInfo ui)
+ throws InvalidCredentialException, BadStateChangeException;
+
+ /**
+ * Adds a new trusted identity.
+ *
+ * @param t
+ * The details of the trusted identity to create.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return Description of the created trusted identity.
+ * @throws InvalidCredentialException
+ * If the trusted identity description isn't valid.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @POST
+ @Path(TRUSTS)
+ @Consumes({ XML, JSON })
+ @Description("Adds a new trusted identity.")
+ @Nonnull
+ Response addTrust(@Nonnull Trust t, @Nonnull @Context UriInfo ui)
+ throws InvalidCredentialException, BadStateChangeException;
+
+ /**
+ * Deletes all trusted identities associated with a run.
+ *
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return A characterisation of a successful delete.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @DELETE
+ @Path(TRUSTS)
+ @Description("Deletes all trusted identities.")
+ @Nonnull
+ Response deleteAllTrusts(@Nonnull @Context UriInfo ui)
+ throws BadStateChangeException;
+
+ /**
+ * Deletes one trusted identity associated with a run.
+ *
+ * @param id
+ * The identity of the trusted identity to delete.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return A characterisation of a successful delete.
+ * @throws BadStateChangeException
+ * If the workflow run is not in the initialising state.
+ */
+ @DELETE
+ @Path(ONE_TRUST)
+ @Description("Deletes a particular trusted identity.")
+ @Nonnull
+ Response deleteTrust(@Nonnull @PathParam("id") String id,
+ @Nonnull @Context UriInfo ui) throws BadStateChangeException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(PERMS)
+ @Description("Produces the description of the run permissions' operations.")
+ Response permissionsOptions();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ONE_PERM)
+ @Description("Produces the description of one run permission's operations.")
+ Response permissionOptions(@PathParam("id") String id);
+
+ /**
+ * @return A list of (non-default) permissions associated with this workflow
+ * run.
+ * @param ui
+ * Information about the URI used to access this resource.
+ */
+ @GET
+ @Path(PERMS)
+ @Produces({ XML, JSON })
+ @Description("Gives a list of all non-default permissions associated with "
+ + "the enclosing workflow run. By default, nobody has any access "
+ + "at all except for the owner of the run.")
+ @Nonnull
+ PermissionsDescription describePermissions(@Nonnull @Context UriInfo ui);
+
+ /**
+ * Describe the particular permission granted to a user.
+ *
+ * @param id
+ * The name of the user whose permissions are to be described.
+ * @return The permission they are granted.
+ */
+ @GET
+ @Path(ONE_PERM)
+ @Produces(TEXT)
+ @Description("Describes the permission granted to a particular user.")
+ @Nonnull
+ Permission describePermission(@Nonnull @PathParam("id") String id);
+
+ /**
+ * Update the permission granted to a user.
+ *
+ * @param id
+ * The name of the user whose permissions are to be updated. Note
+ * that the owner always has full permissions.
+ * @param perm
+ * The permission level to set.
+ * @return The permission level that has actually been set.
+ */
+ @PUT
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Path(ONE_PERM)
+ @Description("Updates the permissions granted to a particular user.")
+ @Nonnull
+ Permission setPermission(@Nonnull @PathParam("id") String id,
+ @Nonnull Permission perm);
+
+ /**
+ * Delete the permissions associated with a user, which restores them to the
+ * default (no access unless they are the owner or have admin privileges).
+ *
+ * @param id
+ * The name of the user whose permissions are to be revoked.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return An indication that the delete has been successful (or not).
+ */
+ @DELETE
+ @Path(ONE_PERM)
+ @Description("Deletes (by resetting to default) the permissions "
+ + "associated with a particular user.")
+ @Nonnull
+ Response deletePermission(@Nonnull @PathParam("id") String id,
+ @Nonnull @Context UriInfo ui);
+
+ /**
+ * Manufacture a permission setting for a previously-unknown user.
+ *
+ * @param desc
+ * A description of the name of the user and the permission level
+ * to grant them.
+ * @param ui
+ * Information about the URI used to access this resource.
+ * @return An indication that the create has been successful (or not).
+ */
+ @POST
+ @Path(PERMS)
+ @Consumes({ XML, JSON })
+ @Description("Creates a new assignment of permissions to a particular user.")
+ @Nonnull
+ Response makePermission(@Nonnull PermissionDescription desc,
+ @Nonnull @Context UriInfo ui);
+
+ /**
+ * A description of the security resources associated with a workflow run.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "securityDescriptor")
+ @XmlType(name = "SecurityDescriptor")
+ public static final class Descriptor extends VersionedElement {
+ /** The identity of the owner of the enclosing workflow run. */
+ @XmlElement
+ public String owner;
+ /** Where to get the permissions on the run. */
+ @XmlElement
+ public Uri permissions;
+
+ /** Characterisation of the credentials attached to the run. */
+ @XmlElement
+ public Credentials credentials;
+ /** Characterisation of the trusted certificates attached to the run. */
+ @XmlElement
+ public Trusts trusts;
+
+ public Descriptor() {
+ }
+
+ /**
+ * Initialise a description of the security context.
+ *
+ * @param ub
+ * How to build URIs.
+ * @param owner
+ * Who owns the context.
+ * @param credential
+ * The credentials associated with the context.
+ * @param trust
+ * The trusted certificates associated with the context.
+ */
+ public Descriptor(@Nonnull UriBuilder ub, @Nonnull String owner,
+ @Nonnull Credential[] credential, @Nonnull Trust[] trust) {
+ super(true);
+ this.owner = owner;
+ this.permissions = new Uri(ub, PERMS);
+ this.credentials = new Credentials(new Uri(ub, CREDS).ref,
+ credential);
+ this.trusts = new Trusts(new Uri(ub, TRUSTS).ref, trust);
+ }
+
+ /**
+ * A description of credentials associated with a workflow run.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "CredentialCollection")
+ public static final class Credentials {
+ /** Reference to the collection of credentials */
+ @XmlAttribute(name = "href", namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI href;
+ /** Descriptions of the credentials themselves. */
+ @XmlElement
+ public List<CredentialHolder> credential = new ArrayList<>();
+
+ public Credentials() {
+ }
+
+ /**
+ * Initialise a description of the credentials.
+ *
+ * @param uri
+ * the URI of the collection.
+ * @param credential
+ * The credentials in the collection.
+ */
+ public Credentials(@Nonnull URI uri,
+ @Nonnull Credential[] credential) {
+ this.href = uri;
+ for (Credential c : credential)
+ this.credential.add(new CredentialHolder(c));
+ }
+ }
+
+ /**
+ * A description of trusted certificates associated with a workflow run.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "TrustCollection")
+ public static final class Trusts {
+ /** Reference to the collection of trusted certs */
+ @XmlAttribute(name = "href", namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI href;
+ /** Descriptions of the trusted certs themselves. */
+ @XmlElement
+ public Trust[] trust;
+
+ public Trusts() {
+ }
+
+ /**
+ * Initialise a description of the trusted certificates.
+ *
+ * @param uri
+ * the URI of the collection.
+ * @param trust
+ * The trusted certificates in the collection.
+ */
+ public Trusts(@Nonnull URI uri, @Nonnull Trust[] trust) {
+ this.href = uri;
+ this.trust = trust.clone();
+ }
+ }
+ }
+
+ /**
+ * A container for a credential, used to work around issues with type
+ * inference in CXF's REST service handling and JAXB.
+ *
+ * @see Credential.KeyPair
+ * @see Credential.Password
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "credential")
+ @XmlType(name = "Credential")
+ public static final class CredentialHolder {
+ /**
+ * The credential inside this holder.
+ */
+ @XmlElements({
+ @XmlElement(name = "keypair", namespace = SERVER, type = Credential.KeyPair.class, required = true),
+ @XmlElement(name = "userpass", namespace = SERVER, type = Credential.Password.class, required = true) })
+ public Credential credential;
+
+ public CredentialHolder() {
+ }
+
+ public CredentialHolder(Credential credential) {
+ this.credential = credential;
+ }
+
+ /**
+ * Convenience accessor function.
+ *
+ * @return The keypair credential held in this holder.
+ */
+ @XmlTransient
+ public Credential.KeyPair getKeypair() {
+ return (Credential.KeyPair) this.credential;
+ }
+
+ /**
+ * Convenience accessor function.
+ *
+ * @return The userpass credential held in this holder.
+ */
+ @XmlTransient
+ public Credential.Password getUserpass() {
+ return (Credential.Password) this.credential;
+ }
+ }
+
+ /**
+ * A simple list of credential descriptions.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "credentials")
+ public static final class CredentialList extends VersionedElement {
+ /** The descriptions of the credentials */
+ @XmlElement
+ @Nonnull
+ public List<CredentialHolder> credential = new ArrayList<>();
+
+ public CredentialList() {
+ }
+
+ /**
+ * Initialise the list of credentials.
+ *
+ * @param credential
+ * The descriptions of individual credentials.
+ */
+ public CredentialList(@Nonnull Credential[] credential) {
+ super(true);
+ for (Credential c : credential)
+ this.credential.add(new CredentialHolder(c));
+ }
+ }
+
+ /**
+ * A simple list of trusted certificate descriptions.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "trustedIdentities")
+ public static final class TrustList extends VersionedElement {
+ /** The descriptions of the trusted certificates */
+ @XmlElement
+ public Trust[] trust;
+
+ public TrustList() {
+ }
+
+ /**
+ * Initialise the list of trusted certificates.
+ *
+ * @param trust
+ * The descriptions of individual certificates.
+ */
+ public TrustList(@Nonnull Trust[] trust) {
+ super(true);
+ this.trust = trust.clone();
+ }
+ }
+
+ /**
+ * A description of the permissions granted to others by the owner of a
+ * workflow run.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "permissionsDescriptor")
+ public static class PermissionsDescription extends VersionedElement {
+ /**
+ * A description of the permissions granted to one user by the owner of
+ * a workflow run.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "userPermission")
+ public static class LinkedPermissionDescription extends Uri {
+ /** Who is this granted to? */
+ @XmlElement
+ public String userName;
+ /** What are they granted? */
+ @XmlElement
+ public Permission permission;
+
+ public LinkedPermissionDescription() {
+ }
+
+ /**
+ * Initialise a description of one user's permissions.
+ *
+ * @param ub
+ * How to build the URI to this permission. Already
+ * secured.
+ * @param userName
+ * Who this relates to.
+ * @param permission
+ * What permission is granted.
+ * @param strings
+ * Parameters to the URI builder.
+ */
+ LinkedPermissionDescription(@Nonnull UriBuilder ub,
+ @Nonnull String userName, @Nonnull Permission permission,
+ String... strings) {
+ super(ub, strings);
+ this.userName = userName;
+ this.permission = permission;
+ }
+ }
+
+ /** List of descriptions of permissions. */
+ @XmlElement
+ public List<LinkedPermissionDescription> permission;
+
+ public PermissionsDescription() {
+ permission = emptyList();
+ }
+
+ /**
+ * Initialise the description of a collection of permissions.
+ *
+ * @param ub
+ * How to build URIs to this collection. Must have already
+ * been secured.
+ * @param permissionMap
+ * The permissions to describe.
+ */
+ public PermissionsDescription(@Nonnull UriBuilder ub,
+ @Nonnull Map<String, Permission> permissionMap) {
+ permission = new ArrayList<>();
+ List<String> userNames = new ArrayList<>(permissionMap.keySet());
+ Collections.sort(userNames);
+ for (String user : userNames)
+ permission.add(new LinkedPermissionDescription(ub, user,
+ permissionMap.get(user), user));
+ }
+ }
+
+ /**
+ * An instruction to update the permissions for a user.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "permissionUpdate")
+ public static class PermissionDescription {
+ /** Who to set the permission for? */
+ @XmlElement
+ public String userName;
+ /** What permission to grant them? */
+ @XmlElement
+ public Permission permission;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java
new file mode 100644
index 0000000..8b9c75f
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static javax.ws.rs.core.Response.Status.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.springframework.security.access.AccessDeniedException;
+
+public class AccessDeniedHandler extends HandlerCore implements
+ ExceptionMapper<AccessDeniedException> {
+ @Override
+ public Response toResponse(AccessDeniedException exception) {
+ return respond(FORBIDDEN, exception);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java
new file mode 100644
index 0000000..254382b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.BadInputPortNameException;
+
+@Provider
+public class BadInputPortNameHandler extends HandlerCore implements
+ ExceptionMapper<BadInputPortNameException> {
+ @Override
+ public Response toResponse(BadInputPortNameException exn) {
+ return respond(NOT_FOUND, exn);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java
new file mode 100644
index 0000000..6ded568
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+
+@Provider
+public class BadPropertyValueHandler extends HandlerCore implements
+ ExceptionMapper<BadPropertyValueException> {
+ @Override
+ public Response toResponse(BadPropertyValueException exn) {
+ return respond(BAD_REQUEST, exn);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java
new file mode 100644
index 0000000..9501923
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.BadStateChangeException;
+
+@Provider
+public class BadStateChangeHandler extends HandlerCore implements
+ ExceptionMapper<BadStateChangeException> {
+ @Override
+ public Response toResponse(BadStateChangeException exn) {
+ return respond(BAD_REQUEST, exn);
+ }
+}
\ No newline at end of file