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
