http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java new file mode 100644 index 0000000..184c7b5 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java @@ -0,0 +1,1100 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.admin; + +import static org.taverna.server.master.admin.Paths.ALLOW_NEW; +import static org.taverna.server.master.admin.Paths.ARGS; +import static org.taverna.server.master.admin.Paths.EXEC_WF; +import static org.taverna.server.master.admin.Paths.EXITCODE; +import static org.taverna.server.master.admin.Paths.FACTORIES; +import static org.taverna.server.master.admin.Paths.GEN_PROV; +import static org.taverna.server.master.admin.Paths.INVOKES; +import static org.taverna.server.master.admin.Paths.JAR_FORKER; +import static org.taverna.server.master.admin.Paths.JAR_WORKER; +import static org.taverna.server.master.admin.Paths.JAVA; +import static org.taverna.server.master.admin.Paths.LIFE; +import static org.taverna.server.master.admin.Paths.LOG_EXN; +import static org.taverna.server.master.admin.Paths.LOG_WFS; +import static org.taverna.server.master.admin.Paths.OPERATING; +import static org.taverna.server.master.admin.Paths.OP_LIMIT; +import static org.taverna.server.master.admin.Paths.PASSFILE; +import static org.taverna.server.master.admin.Paths.PERM_WF; +import static org.taverna.server.master.admin.Paths.REG_HOST; +import static org.taverna.server.master.admin.Paths.REG_JAR; +import static org.taverna.server.master.admin.Paths.REG_POLL; +import static org.taverna.server.master.admin.Paths.REG_PORT; +import static org.taverna.server.master.admin.Paths.REG_WAIT; +import static org.taverna.server.master.admin.Paths.ROOT; +import static org.taverna.server.master.admin.Paths.RUNS; +import static org.taverna.server.master.admin.Paths.RUN_LIMIT; +import static org.taverna.server.master.admin.Paths.STARTUP; +import static org.taverna.server.master.admin.Paths.TOTAL_RUNS; +import static org.taverna.server.master.admin.Paths.URS; +import static org.taverna.server.master.admin.Paths.UR_FILE; +import static org.taverna.server.master.admin.Paths.USER; +import static org.taverna.server.master.admin.Paths.USERS; +import static org.taverna.server.master.admin.Types.JSON; +import static org.taverna.server.master.admin.Types.PLAIN; +import static org.taverna.server.master.admin.Types.XML; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nonnull; +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.UriInfo; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +import org.apache.cxf.jaxrs.model.wadl.Description; +import org.ogf.usage.JobUsageRecord; +import org.taverna.server.master.common.Uri; +import org.taverna.server.master.common.VersionedElement; + +/** + * The administration interface for Taverna Server. + * + * @author Donal Fellows + */ +@Description("Administration interface for Taverna Server.") +public interface Admin { + /** + * Get a simple administration user interface. + * + * @return The description document in a response. + * @throws IOException + */ + @GET + @Path(ROOT) + @Produces("text/html") + @Nonnull + Response getUserInterface() throws IOException; + + /** + * Gets support resources for the administration user interface. + * + * @param file + * The name of the static resource to provide. + * @return The requested document in a response. + * @throws IOException + */ + @GET + @Path("static/{file}") + @Produces("*/*") + Response getStaticResource(@PathParam("file") String file) + throws IOException; + + /** + * Get a description of the administration interface. + * + * @param ui + * What URI was used to access this resource? + * @return The description document. + */ + @GET + @Path(ROOT) + @Produces({ XML, JSON }) + @Nonnull + AdminDescription getDescription(@Context UriInfo ui); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(ROOT) + Response optionsRoot(); + + /** + * Get whether to allow new workflow runs to be created. + * + * @return The current setting. + */ + @GET + @Path(ALLOW_NEW) + @Produces(PLAIN) + @Description("Whether to allow new workflow runs to be created.") + boolean getAllowNew(); + + /** + * Set whether to allow new workflow runs to be created. + * + * @param newValue + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(ALLOW_NEW) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("Whether to allow new workflow runs to be created.") + boolean setAllowNew(boolean newValue); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(ALLOW_NEW) + @Description("Whether to allow new workflow runs to be created.") + Response optionsAllowNew(); + + /** + * Get whether to log the workflows submitted. + * + * @return The current setting. + */ + @GET + @Path(LOG_WFS) + @Produces(PLAIN) + @Description("Whether to log the workflows submitted.") + boolean getLogWorkflows(); + + /** + * Set whether to log the workflows submitted. + * + * @param logWorkflows + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(LOG_WFS) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("Whether to log the workflows submitted.") + boolean setLogWorkflows(boolean logWorkflows); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(LOG_WFS) + @Description("Whether to log the workflows submitted.") + Response optionsLogWorkflows(); + + /** + * Get whether to log the user-directed faults. + * + * @return The current setting. + */ + @GET + @Path(LOG_EXN) + @Produces(PLAIN) + @Description("Whether to log the user-directed faults.") + boolean getLogFaults(); + + /** + * Set whether to log the user-directed faults. + * + * @param logFaults + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(LOG_EXN) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("Whether to log the user-directed faults.") + boolean setLogFaults(boolean logFaults); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(LOG_EXN) + @Description("Whether to log the user-directed faults.") + Response optionsLogFaults(); + + /** + * Get what file to dump usage records to. + * + * @return The current setting. + */ + @GET + @Path(UR_FILE) + @Produces(PLAIN) + @Description("What file to dump usage records to.") + @Nonnull + String getURFile(); + + /** + * Set what file to dump usage records to. + * + * @param urFile + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(UR_FILE) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What file to dump usage records to.") + @Nonnull + String setURFile(@Nonnull String urFile); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(UR_FILE) + @Description("What file to dump usage records to.") + Response optionsURFile(); + + /** + * The property for the number of times the service methods have been + * invoked. + * + * @return The property value (read-only). + */ + @GET + @Path(INVOKES) + @Produces(PLAIN) + @Description("How many times have the service methods been invoked.") + int invokeCount(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(INVOKES) + @Description("How many times have the service methods been invoked.") + Response optionsInvokationCount(); + + /** + * The property for the number of runs that are currently in existence. + * + * @return The property value (read-only). + */ + @GET + @Path(TOTAL_RUNS) + @Produces(PLAIN) + @Description("How many runs are currently in existence.") + int runCount(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(TOTAL_RUNS) + @Description("How many runs are currently in existence.") + Response optionsRunCount(); + + /** + * The property for the number of runs that are currently running. + * + * @return The property value (read-only). + */ + @GET + @Path(OPERATING) + @Produces(PLAIN) + @Description("How many runs are currently actually running.") + int operatingCount(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(OPERATING) + @Description("How many runs are currently actually running.") + Response optionsOperatingCount(); + + /** + * Get the full pathname of the RMI registry's JAR. + * + * @return The current setting. + */ + @GET + @Path(REG_JAR) + @Produces(PLAIN) + @Description("What is the full pathname of the server's custom RMI registry executable JAR file?") + @Nonnull + String getRegistryJar(); + + /** + * Set the full pathname of the RMI registry's JAR. + * + * @param registryJar + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(REG_JAR) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the full pathname of the server's custom RMI registry executable JAR file?") + @Nonnull + String setRegistryJar(@Nonnull String registryJar); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(REG_JAR) + @Description("What is the full pathname of the server's special custom RMI registry executable JAR file?") + Response optionsRegistryJar(); + + /** + * Get the location of the RMI registry. + * + * @return The current setting. + */ + @GET + @Path(REG_HOST) + @Produces(PLAIN) + @Description("Where is the RMI registry?") + @Nonnull + String getRegistryHost(); + + /** + * Set the location of the RMI registry. + * + * @param registryHost + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(REG_HOST) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("Where is the RMI registry?") + @Nonnull + String setRegistryHost(@Nonnull String registryHost); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(REG_HOST) + @Description("Where is the RMI registry?") + Response optionsRegistryHost(); + + /** + * Get the port of the RMI registry. + * + * @return The current setting. + */ + @GET + @Path(REG_PORT) + @Produces(PLAIN) + @Description("On what port is the RMI registry?") + int getRegistryPort(); + + /** + * Set the port of the RMI registry. + * + * @param registryPort + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(REG_PORT) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("On what port is the RMI registry?") + int setRegistryPort(int registryPort); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(REG_PORT) + @Description("On what port is the RMI registry?") + Response optionsRegistryPort(); + + /** + * Get the maximum number of simultaneous runs. + * + * @return The current setting. + */ + @GET + @Path(RUN_LIMIT) + @Produces(PLAIN) + @Description("What is the maximum number of simultaneous runs?") + int getRunLimit(); + + /** + * Set the maximum number of simultaneous runs. + * + * @param runLimit + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(RUN_LIMIT) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the maximum number of simultaneous runs?") + int setRunLimit(int runLimit); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(RUN_LIMIT) + @Description("What is the maximum number of simultaneous runs?") + Response optionsRunLimit(); + + /** + * Get the maximum number of simultaneous executing runs. + * + * @return The current setting. + */ + @GET + @Path(OP_LIMIT) + @Produces(PLAIN) + @Description("What is the maximum number of simultaneous executing runs?") + int getOperatingLimit(); + + /** + * Set the maximum number of simultaneous executing runs. + * + * @param operatingLimit + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(OP_LIMIT) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the maximum number of simultaneous executing runs?") + int setOperatingLimit(int operatingLimit); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(OP_LIMIT) + @Description("What is the maximum number of simultaneous executing runs?") + Response optionsOperatingLimit(); + + /** + * Get the default lifetime of workflow runs. + * + * @return The current setting. + */ + @GET + @Path(LIFE) + @Produces(PLAIN) + @Description("What is the default lifetime of workflow runs, in seconds?") + int getDefaultLifetime(); + + /** + * Set the default lifetime of workflow runs. + * + * @param defaultLifetime + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(LIFE) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the default lifetime of workflow runs, in seconds?") + int setDefaultLifetime(int defaultLifetime); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(LIFE) + @Description("What is the default lifetime of workflow runs, in seconds?") + Response optionsDefaultLifetime(); + + /** + * The property for the list of IDs of current runs. + * + * @return The property value (read-only). + */ + @GET + @Path(RUNS) + @Produces({ XML, JSON }) + @Description("List the IDs of all current runs.") + StringList currentRuns(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(RUNS) + @Description("List the IDs of all current runs.") + Response optionsCurrentRuns(); + + /** + * Get the Java binary to be used for execution of subprocesses. + * + * @return The current setting. + */ + @GET + @Path(JAVA) + @Produces(PLAIN) + @Description("Which Java binary should be used for execution of subprocesses?") + @Nonnull + String getJavaBinary(); + + /** + * Set the Java binary to be used for execution of subprocesses. + * + * @param javaBinary + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(JAVA) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("Which Java binary should be used for execution of subprocesses?") + @Nonnull + String setJavaBinary(@Nonnull String javaBinary); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(JAVA) + @Description("Which Java binary should be used for execution of subprocesses?") + Response optionsJavaBinary(); + + /** + * Get the extra arguments to be supplied to Java subprocesses. + * + * @return The current setting. + */ + @GET + @Path(ARGS) + @Produces({ XML, JSON }) + @Description("What extra arguments should be supplied to Java subprocesses?") + @Nonnull + StringList getExtraArguments(); + + /** + * Set the extra arguments to be supplied to Java subprocesses. + * + * @param extraArguments + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(ARGS) + @Consumes(XML) + @Produces({ XML, JSON }) + @Description("What extra arguments should be supplied to Java subprocesses?") + @Nonnull + StringList setExtraArguments(@Nonnull StringList extraArguments); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(ARGS) + @Description("What extra arguments should be supplied to Java subprocesses?") + Response optionsExtraArguments(); + + /** + * Get the full pathname of the worker JAR file. + * + * @return The current setting. + */ + @GET + @Path(JAR_WORKER) + @Produces(PLAIN) + @Description("What is the full pathname of the server's per-user worker executable JAR file?") + @Nonnull + String getServerWorkerJar(); + + /** + * Set the full pathname of the worker JAR file. + * + * @param serverWorkerJar + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(JAR_WORKER) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the full pathname of the server's per-user worker executable JAR file?") + @Nonnull + String setServerWorkerJar(@Nonnull String serverWorkerJar); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(JAR_WORKER) + @Description("What is the full pathname of the server's per-user worker executable JAR file?") + Response optionsServerWorkerJar(); + + /** + * Get the full pathname of the executeWorkflow.sh file. + * + * @return The current setting. + */ + @GET + @Path(EXEC_WF) + @Produces(PLAIN) + @Description("What is the full pathname of the core Taverna executeWorkflow script?") + @Nonnull + String getExecuteWorkflowScript(); + + /** + * Set the full pathname of the executeWorkflow.sh file. + * + * @param executeWorkflowScript + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(EXEC_WF) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the full pathname of the core Taverna executeWorkflow script?") + @Nonnull + String setExecuteWorkflowScript(@Nonnull String executeWorkflowScript); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(EXEC_WF) + @Description("What is the full pathname of the core Taverna executeWorkflow script?") + Response optionsExecuteWorkflowScript(); + + /** + * Get the total duration of time to wait for the start of the forker + * process. + * + * @return The current setting. + */ + @GET + @Path(REG_WAIT) + @Produces(PLAIN) + @Description("How long in total should the core wait for registration of the \"forker\" process, in seconds.") + int getRegistrationWaitSeconds(); + + /** + * Set the total duration of time to wait for the start of the forker + * process. + * + * @param registrationWaitSeconds + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(REG_WAIT) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("How long in total should the core wait for registration of the \"forker\" process, in seconds.") + int setRegistrationWaitSeconds(int registrationWaitSeconds); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(REG_WAIT) + @Description("How long in total should the core wait for registration of the \"forker\" process, in seconds.") + Response optionsRegistrationWaitSeconds(); + + /** + * Get the interval between checks for registration of the forker process. + * + * @return The current setting. + */ + @GET + @Path(REG_POLL) + @Produces(PLAIN) + @Description("What is the interval between checks for registration of the \"forker\" process, in milliseconds.") + int getRegistrationPollMillis(); + + /** + * Set the interval between checks for registration of the forker process. + * + * @param registrationPollMillis + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(REG_POLL) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the interval between checks for registration of the \"forker\" process, in milliseconds.") + int setRegistrationPollMillis(int registrationPollMillis); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(REG_POLL) + @Description("What is the interval between checks for registration of the \"forker\" process, in milliseconds.") + Response optionsRegistrationPollMillis(); + + /** + * Get the full pathname of the file containing the impersonation + * credentials for the forker process. + * + * @return The current setting. + */ + @GET + @Path(PASSFILE) + @Produces(PLAIN) + @Description("What is the full pathname of the file containing the password used for impersonating other users? (On Unix, this is the password for the deployment user to use \"sudo\".)") + @Nonnull + String getRunasPasswordFile(); + + /** + * Set the full pathname of the file containing the impersonation + * credentials for the forker process. + * + * @param runasPasswordFile + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(PASSFILE) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the full pathname of the file containing the password used for impersonating other users? (On Unix, this is the password for the deployment user to use \"sudo\".)") + @Nonnull + String setRunasPasswordFile(@Nonnull String runasPasswordFile); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(PASSFILE) + @Description("What is the full pathname of the file containing the password used for impersonating other users? (On Unix, this is the password for the deployment user to use \"sudo\".)") + Response optionsRunasPasswordFile(); + + /** + * Get the full pathname of the forker's JAR. + * + * @return The current setting. + */ + @GET + @Path(JAR_FORKER) + @Produces(PLAIN) + @Description("What is the full pathname of the server's special authorized \"forker\" executable JAR file?") + @Nonnull + String getServerForkerJar(); + + /** + * Set the full pathname of the forker's JAR. + * + * @param serverForkerJar + * What to set it to. + * @return The new setting. + */ + @PUT + @Path(JAR_FORKER) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("What is the full pathname of the server's special authorized \"forker\" executable JAR file?") + @Nonnull + String setServerForkerJar(@Nonnull String serverForkerJar); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(JAR_FORKER) + @Description("What is the full pathname of the server's special authorized \"forker\" executable JAR file?") + Response optionsServerForkerJar(); + + /** + * The property for the length of time it took to start the forker. + * + * @return The property value (read-only). + */ + @GET + @Path(STARTUP) + @Produces(PLAIN) + @Description("How long did it take for the back-end \"forker\" to set itself up, in seconds.") + int startupTime(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(STARTUP) + @Description("How long did it take for the back-end \"forker\" to set itself up, in seconds.") + Response optionsStartupTime(); + + /** + * The property for the last exit code of the forker process. + * + * @return The property value (read-only). + */ + @GET + @Path(EXITCODE) + @Produces(PLAIN) + @Description("What was the last exit code of the \"forker\"? If null, no exit has ever been recorded.") + Integer lastExitCode(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(EXITCODE) + @Description("What was the last exit code of the \"forker\"? If null, no exit has ever been recorded.") + Response optionsLastExitCode(); + + /** + * The property for the mapping of usernames to factory process handles. + * + * @return The property value (read-only). + */ + @GET + @Path(FACTORIES) + @Produces({ XML, JSON }) + @Description("What is the mapping of local usernames to factory process RMI IDs?") + StringList factoryProcessMapping(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(FACTORIES) + @Description("What is the mapping of local usernames to factory process RMI IDs?") + Response optionsFactoryProcessMapping(); + + /** + * The property for the list of usage records collected. + * + * @return The property value (read-only). + */ + @GET + @Path(URS) + @Produces(XML) + @Description("What is the list of usage records that have been collected?") + URList usageRecords(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(URS) + @Description("What is the list of usage records that have been collected?") + Response optionsUsageRecords(); + + /** + * What are the current list of workflow URIs that may be started? Empty + * means allow any, including user-supplied workflows. + * + * @return List of URIs, encoded as strings. + */ + @GET + @Path(PERM_WF) + @Produces({ XML, JSON }) + @Description("What are the current list of workflow URIs that may be started? Empty means allow any, including user-supplied workflows.") + StringList getPermittedWorkflowURIs(); + + /** Do we turn on the generate provenance option by default? */ + @GET + @Path(GEN_PROV) + @Produces(PLAIN) + @Description("Do we turn on the generate provenance option by default? (boolean)") + String getGenerateProvenance(); + + /** Do we turn on the generate provenance option by default? */ + @PUT + @Path(GEN_PROV) + @Consumes(PLAIN) + @Produces(PLAIN) + @Description("Do we turn on the generate provenance option by default? (boolean)") + String setGenerateProvenance(String newValue); + + /** Do we turn on the generate provenance option by default? */ + @OPTIONS + @Path(GEN_PROV) + @Description("Do we turn on the generate provenance option by default? (boolean)") + Response optionsGenerateProvenance(); + + /** + * What are the current list of workflow URIs that may be started? Empty + * means allow any, including user-supplied workflows. + * + * @param permitted + * List of URIs, encoded as strings. + * @return List of URIs, encoded as strings. + */ + @PUT + @Path(PERM_WF) + @Consumes(XML) + @Produces({ XML, JSON }) + @Description("What are the current list of workflow URIs that may be started? Empty means allow any, including user-supplied workflows.") + StringList setPermittedWorkflowURIs(@Nonnull StringList permitted); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(PERM_WF) + @Description("What are the current list of workflow URIs that may be started? Empty means allow any, including user-supplied workflows.") + Response optionsPermittedWorkflowURIs(); + + @GET + @Path(USERS) + @Produces({ XML, JSON }) + @Description("What users are known to the server?") + UserList users(@Context UriInfo ui); + + @GET + @Path(USER) + @Produces({ XML, JSON }) + @Description("What do we know about a particular user?") + UserDesc user(@PathParam("id") String username); + + @POST + @Path(USERS) + @Consumes(XML) + @Description("Create a user.") + Response useradd(UserDesc userdesc, @Nonnull @Context UriInfo ui); + + @PUT + @Path(USER) + @Produces({ XML, JSON }) + @Consumes(XML) + @Description("Update a user.") + UserDesc userset(@PathParam("id") String username, UserDesc userdesc); + + @DELETE + @Path(USER) + @Produces({ XML, JSON }) + @Description("What do we know about a particular user?") + Response userdel(@PathParam("id") String username); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(USERS) + @Description("What users are known to the server?") + Response optionsUsers(); + + /** What HTTP methods may we use? */ + @OPTIONS + @Path(USER) + @Description("What do we know about a particular user?") + Response optionsUser(@PathParam("id") String username); + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + /** + * The description of what properties are supported by the administration + * interface. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "description") + @XmlType(name = "Description") + public static class AdminDescription extends VersionedElement { + public Uri allowNew; + public Uri logWorkflows; + public Uri logFaults; + public Uri usageRecordDumpFile; + public Uri invokationCount; + public Uri runCount; + public Uri registryHost; + public Uri registryPort; + public Uri runLimit; + public Uri defaultLifetime; + public Uri currentRuns; + public Uri javaBinary; + public Uri extraArguments; + public Uri serverWorkerJar; + public Uri serverForkerJar; + public Uri executeWorkflowScript; + public Uri registrationWaitSeconds; + public Uri registrationPollMillis; + public Uri runasPasswordFile; + public Uri startupTime; + public Uri lastExitCode; + public Uri factoryProcessMapping; + public Uri usageRecords; + public Uri users; + public Uri operatingLimit; + public Uri operatingCount; + public Uri permittedWorkflowURIs; + public Uri generateProvenance; + + public AdminDescription() { + } + + public AdminDescription(UriInfo ui) { + allowNew = new Uri(ui, ALLOW_NEW); + logWorkflows = new Uri(ui, LOG_WFS); + logFaults = new Uri(ui, LOG_EXN); + usageRecordDumpFile = new Uri(ui, UR_FILE); + invokationCount = new Uri(ui, INVOKES); + runCount = new Uri(ui, TOTAL_RUNS); + registryHost = new Uri(ui, REG_HOST); + registryPort = new Uri(ui, REG_PORT); + runLimit = new Uri(ui, RUN_LIMIT); + defaultLifetime = new Uri(ui, LIFE); + currentRuns = new Uri(ui, RUNS); + javaBinary = new Uri(ui, JAVA); + extraArguments = new Uri(ui, ARGS); + serverWorkerJar = new Uri(ui, JAR_WORKER); + serverForkerJar = new Uri(ui, JAR_FORKER); + executeWorkflowScript = new Uri(ui, EXEC_WF); + registrationWaitSeconds = new Uri(ui, REG_WAIT); + registrationPollMillis = new Uri(ui, REG_POLL); + runasPasswordFile = new Uri(ui, PASSFILE); + startupTime = new Uri(ui, STARTUP); + lastExitCode = new Uri(ui, EXITCODE); + factoryProcessMapping = new Uri(ui, FACTORIES); + usageRecords = new Uri(ui, URS); + users = new Uri(ui, USERS); + operatingLimit = new Uri(ui, OP_LIMIT); + operatingCount = new Uri(ui, OPERATING); + permittedWorkflowURIs = new Uri(ui, PERM_WF); + generateProvenance = new Uri(ui, GEN_PROV); + } + } + + /** + * A list of strings, as XML. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "stringList") + @XmlType(name = "StringList") + public static class StringList { + @XmlElement + public List<String> string = new ArrayList<>(); + } + + /** + * A list of users, as XML. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "userList") + @XmlType(name = "UserList") + public static class UserList { + @XmlElement + public List<URI> user = new ArrayList<>(); + } + + @XmlRootElement(name = "userDesc") + @XmlType(name = "UserDesc") + public static class UserDesc { + @XmlElement + public String username; + @XmlElement + public String password; + @XmlElement + public String localUserId; + @XmlElement + public Boolean enabled; + @XmlElement + public Boolean admin; + } + + /** + * A list of usage records, as XML. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "usageRecordList") + @XmlType(name = "UsageRecords") + public static class URList { + @XmlElement + public List<JobUsageRecord> usageRecord; + } +} + +interface Paths { + static final String ROOT = "/"; + static final String ALLOW_NEW = "allowNew"; + static final String LOG_WFS = "logWorkflows"; + static final String LOG_EXN = "logFaults"; + static final String UR_FILE = "usageRecordDumpFile"; + static final String INVOKES = "invokationCount"; + static final String TOTAL_RUNS = "runCount"; + static final String OPERATING = "operatingCount"; + static final String REG_HOST = "registryHost"; + static final String REG_PORT = "registryPort"; + static final String REG_JAR = "registryJar"; + static final String RUN_LIMIT = "runLimit"; + static final String OP_LIMIT = "operatingLimit"; + static final String LIFE = "defaultLifetime"; + static final String RUNS = "currentRuns"; + static final String JAVA = "javaBinary"; + static final String ARGS = "extraArguments"; + static final String JAR_WORKER = "serverWorkerJar"; + static final String JAR_FORKER = "serverForkerJar"; + static final String EXEC_WF = "executeWorkflowScript"; + static final String REG_WAIT = "registrationWaitSeconds"; + static final String REG_POLL = "registrationPollMillis"; + static final String PASSFILE = "runasPasswordFile"; + static final String STARTUP = "startupTime"; + static final String EXITCODE = "lastExitCode"; + static final String FACTORIES = "factoryProcessMapping"; + static final String URS = "usageRecords"; + static final String PERM_WF = "permittedWorkflowURIs"; + static final String GEN_PROV = "generateProvenance"; + static final String USERS = "users"; + static final String USER = USERS + "/{id}"; +} + +interface Types { + static final String PLAIN = "text/plain"; + static final String XML = "application/xml"; + static final String JSON = "application/json"; +}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java new file mode 100644 index 0000000..b83d88f --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.admin; + +import static java.util.Arrays.asList; +import static java.util.UUID.randomUUID; +import static javax.ws.rs.core.Response.created; +import static javax.ws.rs.core.Response.noContent; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static org.taverna.server.master.common.Roles.ADMIN; +import static org.taverna.server.master.common.Uri.secure; +import static org.taverna.server.master.utils.RestUtils.opt; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.security.RolesAllowed; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Required; +import org.taverna.server.master.api.ManagementModel; +import org.taverna.server.master.exceptions.GeneralFailureException; +import org.taverna.server.master.factories.ConfigurableRunFactory; +import org.taverna.server.master.identity.User; +import org.taverna.server.master.identity.UserStoreAPI; +import org.taverna.server.master.usage.UsageRecordRecorder; +import org.taverna.server.master.utils.InvocationCounter; +import org.taverna.server.master.worker.RunDBSupport; +import org.taverna.server.master.worker.WorkerModel; + +/** + * The administration interface to Taverna Server. + * + * @author Donal Fellows + */ +public class AdminBean implements Admin { + @Required + public void setState(ManagementModel state) { + this.state = state; + } + + @Required + public void setCounter(InvocationCounter counter) { + this.counter = counter; + } + + @Required + public void setRunDB(RunDBSupport runDB) { + this.runDB = runDB; + } + + @Required + public void setFactory(ConfigurableRunFactory factory) { + this.factory = factory; + } + + @Required + public void setUsageRecords(UsageRecordRecorder usageRecords) { + this.usageRecords = usageRecords; + } + + @Required + public void setUserStore(UserStoreAPI userStore) { + this.userStore = userStore; + } + + @Required + public void setLocalWorkerModel(WorkerModel worker) { + localWorker = worker; + } + + public void setAdminHtmlFile(String filename) { + this.adminHtmlFile = filename; + } + + public void setResourceRoot(String root) { + this.resourceRoot = root; + } + + protected byte[] getResource(String name) throws IOException { + if (AdminBean.class.getResource(name) == null) + throw new FileNotFoundException(name); + return IOUtils.toByteArray(AdminBean.class.getResourceAsStream(name)); + } + + private ManagementModel state; + private InvocationCounter counter; + private RunDBSupport runDB; + private ConfigurableRunFactory factory; + private UsageRecordRecorder usageRecords; + private UserStoreAPI userStore; + private WorkerModel localWorker; + private String adminHtmlFile = "/admin.html"; + private String resourceRoot = "/static/"; + + @RolesAllowed(ADMIN) + @Override + public Response getUserInterface() throws IOException { + return Response.ok(getResource(adminHtmlFile), "text/html").build(); + } + + @Override + @RolesAllowed(ADMIN) + public Response getStaticResource(String file) throws IOException { + if (file.matches("^[-_.a-zA-Z0-9]+$")) { + String type = "application/octet-stream"; + if (file.endsWith(".html")) + type = "text/html"; + else if (file.endsWith(".js")) + type = "text/javascript"; + else if (file.endsWith(".jpg")) + type = "image/jpeg"; + else if (file.endsWith(".gif")) + type = "image/gif"; + else if (file.endsWith(".png")) + type = "image/png"; + else if (file.endsWith(".svg")) + type = "image/svg+xml"; + else if (file.endsWith(".css")) + type = "text/css"; + try { + return Response.ok(getResource(resourceRoot + file), type) + .build(); + } catch (IOException e) { + // ignore; we just treat as 404 + } + } + return Response.status(NOT_FOUND).entity("no such resource").build(); + } + + @RolesAllowed(ADMIN) + @Override + public AdminDescription getDescription(UriInfo ui) { + return new AdminDescription(ui); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsRoot() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public boolean getAllowNew() { + return state.getAllowNewWorkflowRuns(); + } + + @RolesAllowed(ADMIN) + @Override + public boolean setAllowNew(boolean newValue) { + state.setAllowNewWorkflowRuns(newValue); + return state.getAllowNewWorkflowRuns(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsAllowNew() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public boolean getLogWorkflows() { + return state.getLogIncomingWorkflows(); + } + + @RolesAllowed(ADMIN) + @Override + public boolean setLogWorkflows(boolean newValue) { + state.setLogIncomingWorkflows(newValue); + return state.getLogIncomingWorkflows(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsLogWorkflows() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public boolean getLogFaults() { + return state.getLogOutgoingExceptions(); + } + + @RolesAllowed(ADMIN) + @Override + public boolean setLogFaults(boolean newValue) { + state.setLogOutgoingExceptions(newValue); + return state.getLogOutgoingExceptions(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsLogFaults() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getURFile() { + return state.getUsageRecordLogFile(); + } + + @RolesAllowed(ADMIN) + @Override + public String setURFile(String newValue) { + state.setUsageRecordLogFile(newValue); + return state.getUsageRecordLogFile(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsURFile() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int invokeCount() { + return counter.getCount(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public Response optionsInvokationCount() { + return opt(); + } + + @RolesAllowed(ADMIN) + @Override + public int runCount() { + return runDB.countRuns(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsRunCount() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getRegistryHost() { + return factory.getRegistryHost(); + } + + @RolesAllowed(ADMIN) + @Override + public String setRegistryHost(String newValue) { + factory.setRegistryHost(newValue); + return factory.getRegistryHost(); + } + + @Override + public Response optionsRegistryHost() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int getRegistryPort() { + return factory.getRegistryPort(); + } + + @RolesAllowed(ADMIN) + @Override + public int setRegistryPort(int newValue) { + factory.setRegistryPort(newValue); + return factory.getRegistryPort(); + } + + @Override + public Response optionsRegistryPort() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getRegistryJar() { + return factory.getRmiRegistryJar(); + } + + @RolesAllowed(ADMIN) + @Override + public String setRegistryJar(String registryJar) { + factory.setRmiRegistryJar(registryJar); + return factory.getRmiRegistryJar(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsRegistryJar() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int getRunLimit() { + return factory.getMaxRuns(); + } + + @RolesAllowed(ADMIN) + @Override + public int setRunLimit(int newValue) { + factory.setMaxRuns(newValue); + return factory.getMaxRuns(); + } + + @Override + public Response optionsRunLimit() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int getDefaultLifetime() { + return factory.getDefaultLifetime(); + } + + @RolesAllowed(ADMIN) + @Override + public int setDefaultLifetime(int newValue) { + factory.setDefaultLifetime(newValue); + return factory.getDefaultLifetime(); + } + + @Override + public Response optionsDefaultLifetime() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public StringList currentRuns() { + StringList result = new StringList(); + result.string = runDB.listRunNames(); + return result; + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsCurrentRuns() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getJavaBinary() { + return factory.getJavaBinary(); + } + + @RolesAllowed(ADMIN) + @Override + public String setJavaBinary(String newValue) { + factory.setJavaBinary(newValue); + return factory.getJavaBinary(); + } + + @Override + public Response optionsJavaBinary() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public StringList getExtraArguments() { + String[] xargs = factory.getExtraArguments(); + StringList result = new StringList(); + result.string = asList(xargs == null ? new String[0] : xargs); + return result; + } + + @RolesAllowed(ADMIN) + @Override + public StringList setExtraArguments(StringList newValue) { + if (newValue == null || newValue.string == null) + factory.setExtraArguments(new String[0]); + else + factory.setExtraArguments(newValue.string + .toArray(new String[newValue.string.size()])); + StringList result = new StringList(); + result.string = asList(factory.getExtraArguments()); + return result; + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsExtraArguments() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getServerWorkerJar() { + return factory.getServerWorkerJar(); + } + + @RolesAllowed(ADMIN) + @Override + public String setServerWorkerJar(String newValue) { + factory.setServerWorkerJar(newValue); + return factory.getServerWorkerJar(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsServerWorkerJar() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getExecuteWorkflowScript() { + return factory.getExecuteWorkflowScript(); + } + + @RolesAllowed(ADMIN) + @Override + public String setExecuteWorkflowScript(String newValue) { + factory.setExecuteWorkflowScript(newValue); + return factory.getExecuteWorkflowScript(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsExecuteWorkflowScript() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int getRegistrationWaitSeconds() { + return factory.getWaitSeconds(); + } + + @RolesAllowed(ADMIN) + @Override + public int setRegistrationWaitSeconds(int newValue) { + factory.setWaitSeconds(newValue); + return factory.getWaitSeconds(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsRegistrationWaitSeconds() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int getRegistrationPollMillis() { + return factory.getSleepTime(); + } + + @RolesAllowed(ADMIN) + @Override + public int setRegistrationPollMillis(int newValue) { + factory.setSleepTime(newValue); + return factory.getSleepTime(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsRegistrationPollMillis() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getRunasPasswordFile() { + return factory.getPasswordFile(); + } + + @RolesAllowed(ADMIN) + @Override + public String setRunasPasswordFile(String newValue) { + factory.setPasswordFile(newValue); + return factory.getPasswordFile(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsRunasPasswordFile() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getServerForkerJar() { + return factory.getServerForkerJar(); + } + + @RolesAllowed(ADMIN) + @Override + public String setServerForkerJar(String newValue) { + factory.setServerForkerJar(newValue); + return factory.getServerForkerJar(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsServerForkerJar() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int startupTime() { + return factory.getLastStartupCheckCount(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsStartupTime() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public Integer lastExitCode() { + return factory.getLastExitCode(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsLastExitCode() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public StringList factoryProcessMapping() { + StringList result = new StringList(); + result.string = asList(factory.getFactoryProcessMapping()); + return result; + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsFactoryProcessMapping() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public URList usageRecords() { + URList result = new URList(); + result.usageRecord = usageRecords.getUsageRecords(); + return result; + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsUsageRecords() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public UserList users(UriInfo ui) { + UserList ul = new UserList(); + UriBuilder ub = secure(ui).path("{id}"); + for (String user : userStore.getUserNames()) + ul.user.add(ub.build(user)); + return ul; + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsUsers() { + return opt("POST"); + } + + @RolesAllowed(ADMIN) + @Override + public UserDesc user(String username) { + UserDesc desc = new UserDesc(); + User u = userStore.getUser(username); + desc.username = u.getUsername(); + desc.localUserId = u.getLocalUsername(); + desc.admin = u.isAdmin(); + desc.enabled = u.isEnabled(); + return desc; + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsUser(String username) { + return opt("PUT", "DELETE"); + } + + @RolesAllowed(ADMIN) + @Override + public Response useradd(UserDesc userdesc, UriInfo ui) { + if (userdesc.username == null) + throw new IllegalArgumentException("no user name supplied"); + if (userdesc.password == null) + userdesc.password = randomUUID().toString(); + userStore.addUser(userdesc.username, userdesc.password, false); + if (userdesc.localUserId != null) + userStore.setUserLocalUser(userdesc.username, userdesc.localUserId); + if (userdesc.admin != null && userdesc.admin) + userStore.setUserAdmin(userdesc.username, true); + if (userdesc.enabled != null && userdesc.enabled) + userStore.setUserEnabled(userdesc.username, true); + return created(secure(ui).path("{id}").build(userdesc.username)) + .build(); + } + + @RolesAllowed(ADMIN) + @Override + public UserDesc userset(String username, UserDesc userdesc) { + if (userdesc.password != null) + userStore.setUserPassword(username, userdesc.password); + if (userdesc.localUserId != null) + userStore.setUserLocalUser(username, userdesc.localUserId); + if (userdesc.admin != null) + userStore.setUserAdmin(username, userdesc.admin); + if (userdesc.enabled != null) + userStore.setUserEnabled(username, userdesc.enabled); + userdesc = null; // Stop reuse! + + UserDesc desc = new UserDesc(); + User u = userStore.getUser(username); + desc.username = u.getUsername(); + desc.localUserId = u.getLocalUsername(); + desc.admin = u.isAdmin(); + desc.enabled = u.isEnabled(); + return desc; + } + + @RolesAllowed(ADMIN) + @Override + public Response userdel(String username) { + userStore.deleteUser(username); + return noContent().build(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int operatingCount() { + try { + return factory.getOperatingCount(); + } catch (Exception e) { + throw new GeneralFailureException(e); + } + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsOperatingCount() { + return opt(); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public int getOperatingLimit() { + return factory.getOperatingLimit(); + } + + @RolesAllowed(ADMIN) + @Override + public int setOperatingLimit(int operatingLimit) { + factory.setOperatingLimit(operatingLimit); + return factory.getOperatingLimit(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsOperatingLimit() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + @RolesAllowed(ADMIN) + @Override + public StringList getPermittedWorkflowURIs() { + StringList sl = new StringList(); + List<URI> uris = localWorker.getPermittedWorkflowURIs(); + if (uris != null) + for (URI uri : uris) + sl.string.add(uri.toString()); + return sl; + } + + private static final URI myExp = URI.create("http://www.myexperment.org/"); + + @RolesAllowed(ADMIN) + @Override + public StringList setPermittedWorkflowURIs(StringList permitted) { + List<URI> uris = new ArrayList<>(); + for (String uri : permitted.string) + try { + uris.add(myExp.resolve(uri)); + } catch (Exception e) { + // Ignore + } + localWorker.setPermittedWorkflowURIs(uris); + return getPermittedWorkflowURIs(); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsPermittedWorkflowURIs() { + return opt("PUT"); + } + + // ///////////////////////////////////////////////////// + + @RolesAllowed(ADMIN) + @Override + public String getGenerateProvenance() { + return Boolean.toString(localWorker.getGenerateProvenance()); + } + + @RolesAllowed(ADMIN) + @Override + public String setGenerateProvenance(String newValue) { + boolean b = Boolean.parseBoolean(newValue); + localWorker.setGenerateProvenance(b); + return Boolean.toString(localWorker.getGenerateProvenance()); + } + + @RolesAllowed(ADMIN) + @Override + public Response optionsGenerateProvenance() { + return opt("PUT"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java new file mode 100644 index 0000000..930fd75 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * This package contains the RESTful administration interface to Taverna Server. + * @author Donal Fellows + */ +@XmlSchema(namespace = ADMIN, elementFormDefault = QUALIFIED, attributeFormDefault = QUALIFIED, xmlns = { + @XmlNs(prefix = "xlink", namespaceURI = XLINK), + @XmlNs(prefix = "ts", namespaceURI = SERVER), + @XmlNs(prefix = "ts-rest", namespaceURI = SERVER_REST), + @XmlNs(prefix = "ts-soap", namespaceURI = SERVER_SOAP), + @XmlNs(prefix = "feed", namespaceURI = FEED), + @XmlNs(prefix = "admin", namespaceURI = ADMIN), + @XmlNs(prefix = "ur", namespaceURI = UR), + @XmlNs(prefix = "ds", namespaceURI = XSIG) }) +package org.taverna.server.master.admin; + +import static javax.xml.bind.annotation.XmlNsForm.QUALIFIED; +import static org.taverna.server.master.common.Namespaces.ADMIN; +import static org.taverna.server.master.common.Namespaces.FEED; +import static org.taverna.server.master.common.Namespaces.SERVER; +import static org.taverna.server.master.common.Namespaces.SERVER_REST; +import static org.taverna.server.master.common.Namespaces.SERVER_SOAP; +import static org.taverna.server.master.common.Namespaces.UR; +import static org.taverna.server.master.common.Namespaces.XLINK; +import static org.taverna.server.master.common.Namespaces.XSIG; + +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlSchema; + http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java new file mode 100644 index 0000000..1a89b8d --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.api; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; +import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE; +import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE; + +import java.util.List; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Variant; + +/** + * The content types supported at various points in the REST interface. + * + * @author Donal Fellows + */ +public interface ContentTypes { + /** "application/zip" */ + public static final MediaType APPLICATION_ZIP_TYPE = new MediaType( + "application", "zip"); + + /** "application/vnd.taverna.baclava+xml" */ + public static final MediaType BACLAVA_MEDIA_TYPE = new MediaType( + "application", "vnd.taverna.baclava+xml"); + + /** + * The media types that we are willing to serve up directories as. Note that + * we <i>only</i> serve directories up as these. + */ + public static final List<Variant> DIRECTORY_VARIANTS = asList(new Variant( + APPLICATION_XML_TYPE, (String) null, "UTF-8"), new Variant( + APPLICATION_JSON_TYPE, (String) null, "UTF-8"), new Variant( + APPLICATION_ZIP_TYPE, (String) null, null)); + + /** + * The baseline set of media types that we are willing to serve up files as. + * Note that we <i>also</i> serve files up as their auto-detected media + * type. In all cases, this means we just shovel the bytes (or characters, + * in the case of <tt>text/*</tt> subtypes) back at the client. + */ + public static final List<Variant> INITIAL_FILE_VARIANTS = singletonList(new Variant( + APPLICATION_OCTET_STREAM_TYPE, (String) null, null)); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java new file mode 100644 index 0000000..8fa5c78 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java @@ -0,0 +1,16 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.rest.TavernaServerDirectoryREST; +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.utils.FilenameUtils; + +/** + * Description of properties supported by {@link DirectoryREST}. + * + * @author Donal Fellows + */ +public interface DirectoryBean extends SupportAware { + void setFileUtils(FilenameUtils fileUtils); + + TavernaServerDirectoryREST connect(TavernaRun run); +} \ 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/api/FeedBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java new file mode 100644 index 0000000..5ace6a3 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java @@ -0,0 +1,13 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.InteractionFeed; +import org.taverna.server.master.interaction.InteractionFeedSupport; + +/** + * Description of properties supported by {@link InteractionFeed}. + * + * @author Donal Fellows + */ +public interface FeedBean { + void setInteractionFeedSupport(InteractionFeedSupport feed); +} \ 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/api/InputBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java new file mode 100644 index 0000000..eecea44 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java @@ -0,0 +1,21 @@ +package org.taverna.server.master.api; + +import javax.ws.rs.core.UriInfo; + +import org.taverna.server.master.ContentsDescriptorBuilder; +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.rest.TavernaServerInputREST; +import org.taverna.server.master.utils.FilenameUtils; + +/** + * Description of properties supported by {@link InputREST}. + * + * @author Donal Fellows + */ +public interface InputBean extends SupportAware { + TavernaServerInputREST connect(TavernaRun run, UriInfo ui); + + void setCdBuilder(ContentsDescriptorBuilder cd); + + void setFileUtils(FilenameUtils fn); +} \ 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/api/ListenerPropertyBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java new file mode 100644 index 0000000..5c480d4 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java @@ -0,0 +1,15 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.interfaces.Listener; +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.rest.TavernaServerListenersREST; + +/** + * Description of properties supported by {@link ListenerPropertyREST}. + * + * @author Donal Fellows + */ +public interface ListenerPropertyBean extends SupportAware { + TavernaServerListenersREST.Property connect(Listener listen, + TavernaRun run, String propertyName); +} \ 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/api/ListenersBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java new file mode 100644 index 0000000..c02bf62 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java @@ -0,0 +1,13 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.rest.TavernaServerListenersREST; + +/** + * Description of properties supported by {@link ListenersREST}. + * + * @author Donal Fellows + */ +public interface ListenersBean extends SupportAware { + TavernaServerListenersREST connect(TavernaRun run); +} \ 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/api/ManagementModel.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java new file mode 100644 index 0000000..6bc6058 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.api; + +/** + * The model of the webapp's state Java Bean. + * + * @author Donal Fellows + */ +public interface ManagementModel { + /** + * @return whether we allow the creation of new workflow runs. + */ + boolean getAllowNewWorkflowRuns(); + + /** + * @return whether we should log all workflows sent to us. + */ + boolean getLogIncomingWorkflows(); + + /** + * @return whether outgoing exceptions should be logged before being + * converted to responses. + */ + boolean getLogOutgoingExceptions(); + + /** + * @return the file that all usage records should be appended to, or + * <tt>null</tt> if they should be just dropped. + */ + String getUsageRecordLogFile(); + + /** + * @param logIncomingWorkflows + * whether we should log all workflows sent to us. + */ + void setLogIncomingWorkflows(boolean logIncomingWorkflows); + + /** + * @param allowNewWorkflowRuns + * whether we allow the creation of new workflow runs. + */ + void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns); + + /** + * @param logOutgoingExceptions + * whether outgoing exceptions should be logged before being + * converted to responses. + */ + void setLogOutgoingExceptions(boolean logOutgoingExceptions); + + /** + * @param usageRecordLogFile + * the file that all usage records should be appended to, or + * <tt>null</tt> if they should be just dropped. + */ + void setUsageRecordLogFile(String usageRecordLogFile); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java new file mode 100644 index 0000000..9f80a12 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java @@ -0,0 +1,14 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.interfaces.Listener; +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.rest.TavernaServerListenersREST.TavernaServerListenerREST; + +/** + * Description of properties supported by {@link InputREST}. + * + * @author Donal Fellows + */ +public interface OneListenerBean { + TavernaServerListenerREST connect(Listener listen, TavernaRun run); +} \ 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/api/RunBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java new file mode 100644 index 0000000..4903ea9 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java @@ -0,0 +1,17 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.ContentsDescriptorBuilder; +import org.taverna.server.master.interfaces.TavernaRun; + +/** + * Description of properties supported by {@link RunREST}. + * + * @author Donal Fellows + */ +public interface RunBean extends SupportAware { + void setCdBuilder(ContentsDescriptorBuilder cdBuilder); + + void setRun(TavernaRun run); + + void setRunName(String runName); +} \ 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/api/SecurityBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java new file mode 100644 index 0000000..04fbd6e --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java @@ -0,0 +1,14 @@ +package org.taverna.server.master.api; + +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.interfaces.TavernaSecurityContext; +import org.taverna.server.master.rest.TavernaServerSecurityREST; + +/** + * Description of properties supported by {@link RunSecurityREST}. + * + * @author Donal Fellows + */ +public interface SecurityBean extends SupportAware { + TavernaServerSecurityREST connect(TavernaSecurityContext context, TavernaRun run); +} \ 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/api/SupportAware.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java new file mode 100644 index 0000000..c632657 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java @@ -0,0 +1,21 @@ +package org.taverna.server.master.api; + +import org.springframework.beans.factory.annotation.Required; +import org.taverna.server.master.TavernaServerSupport; + +/** + * Indicates that this is a class that wants to be told by Spring about the + * main support bean. + * + * @author Donal Fellows + */ +public interface SupportAware { + /** + * How to tell the bean about the support bean. + * + * @param support + * Reference to the support bean. + */ + @Required + void setSupport(TavernaServerSupport support); +} \ 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/api/TavernaServerBean.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java new file mode 100644 index 0000000..5a14fb6 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.api; + +import javax.annotation.Nonnull; + +import org.springframework.beans.factory.annotation.Required; +import org.taverna.server.master.ContentsDescriptorBuilder; +import org.taverna.server.master.TavernaServerSupport; +import org.taverna.server.master.interfaces.Policy; +import org.taverna.server.master.interfaces.RunStore; +import org.taverna.server.master.interfaces.TavernaSecurityContext; +import org.taverna.server.master.interfaces.UriBuilderFactory; +import org.taverna.server.master.notification.NotificationEngine; +import org.taverna.server.master.notification.atom.EventDAO; +import org.taverna.server.master.rest.TavernaServerREST; +import org.taverna.server.master.soap.TavernaServerSOAP; +import org.taverna.server.master.utils.FilenameUtils; + +/** + * The methods of the webapp that are accessed by beans other than itself or + * those which are told directly about it. This exists so that an AOP proxy can + * be installed around it. + * + * @author Donal Fellows + */ +public interface TavernaServerBean extends TavernaServerSOAP, TavernaServerREST, + UriBuilderFactory { + /** + * @param policy + * The policy being installed by Spring. + */ + @Required + void setPolicy(@Nonnull Policy policy); + + /** + * @param runStore + * The run store being installed by Spring. + */ + @Required + void setRunStore(@Nonnull RunStore runStore); + + /** + * @param converter + * The filename converter being installed by Spring. + */ + @Required + void setFileUtils(@Nonnull FilenameUtils converter); + + /** + * @param cdBuilder + * The contents descriptor builder being installed by Spring. + */ + @Required + void setContentsDescriptorBuilder( + @Nonnull ContentsDescriptorBuilder cdBuilder); + + /** + * @param notificationEngine + * The notification engine being installed by Spring. + */ + @Required + void setNotificationEngine(@Nonnull NotificationEngine notificationEngine); + + /** + * @param support + * The support bean being installed by Spring. + */ + @Required + void setSupport(@Nonnull TavernaServerSupport support); + + /** + * @param eventSource + * The event source bean being installed by Spring. + */ + @Required + void setEventSource(@Nonnull EventDAO eventSource); + + /** + * The nastier parts of security initialisation in SOAP calls, which we want + * to go away. + * + * @param context + * The context to configure. + * @return True if we did <i>not</i> initialise things. + */ + boolean initObsoleteSOAPSecurity(@Nonnull TavernaSecurityContext context); + + /** + * The nastier parts of security initialisation in REST calls, which we want + * to go away. + * + * @param context + * The context to configure. + * @return True if we did <i>not</i> initialise things. + */ + boolean initObsoleteRESTSecurity(@Nonnull TavernaSecurityContext context); +} \ 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/api/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/api/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/package-info.java new file mode 100644 index 0000000..fe76a09 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/api/package-info.java @@ -0,0 +1,6 @@ +/** + * API <tt>interface</tt>s for the main service classes. + * + * @author Donal Fellows + */ +package org.taverna.server.master.api; \ 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/common/Capability.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Capability.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Capability.java new file mode 100644 index 0000000..034d489 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Capability.java @@ -0,0 +1,22 @@ +package org.taverna.server.master.common; + +import java.net.URI; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + +/** + * Describes a single capability supported by Taverna Server's workflow + * execution core. + * + * @author Donal Fellows + */ +@XmlType(name = "Capability") +public class Capability { + @XmlAttribute + @XmlSchemaType(name = "anyURI") + public URI capability; + @XmlAttribute + public String version; +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Credential.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Credential.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Credential.java new file mode 100644 index 0000000..5c16e79 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Credential.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2011-2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static org.taverna.server.master.common.Namespaces.XLINK; + +import java.io.Serializable; +import java.net.URI; +import java.security.Key; +import java.security.cert.Certificate; + +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.XmlSeeAlso; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +import javax.annotation.Nonnull; + +/** + * A description of a private credential. This description is characterised by a + * file visible to the workflow run that contains a particular key-pair. + * + * @author Donal Fellows + */ +@XmlType(name = "CredentialDescriptor") +@XmlSeeAlso({ Credential.KeyPair.class, Credential.Password.class }) +@SuppressWarnings("serial") +public abstract class Credential implements Serializable { + /** The location of this descriptor in the REST world. */ + @XmlAttribute(namespace = XLINK) + public String href; + /** + * The location of this descriptor in the SOAP world. Must match corrected + * with the {@link #href} field. + */ + @XmlTransient + public String id; + /** + * The service URI to use this credential with. If omitted, this represents + * the <i>default</i> credential to use. + */ + @XmlElement + @XmlSchemaType(name = "anyURI") + public URI serviceURI; + /** The key extracted from the keystore. */ + public transient Key loadedKey; + /** The trust chain of the key extracted from the keystore. */ + public transient Certificate[] loadedTrustChain; + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public final boolean equals(Object o) { + if (o == null || !(o instanceof Credential)) + return false; + return equals((Credential) o); + } + + protected boolean equals(@Nonnull Credential c) { + return id.equals(c.id); + } + + /** + * A description of a credential that is a public/private key-pair in some + * kind of key store. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "keypair") + @XmlType(name = "KeyPairCredential") + public static class KeyPair extends Credential { + /** The name of the credential within its store, i.e., it's alias. */ + @XmlElement(required = true) + public String credentialName; + /** + * The keystore file containing the credential. This is resolved with + * respect to the workflow run working directory. + */ + @XmlElement + public String credentialFile; + /** + * The type of keystore file. Defaults to <tt>JKS</tt> if unspecified. + */ + @XmlElement + public String fileType; + /** + * The password used to unlock the keystore file. It is assumed that the + * same password is used for unlocking the credential within, or that + * the inner password is empty. + */ + @XmlElement + public String unlockPassword; + /** + * The encoded serialized keystore containing the credential. + */ + @XmlElement + public byte[] credentialBytes; + + @Override + public String toString() { + return "keypair(id=" + id + ")"; + } + } + + /** + * A description of a credential that is a username and password. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "userpass") + @XmlType(name = "PasswordCredential") + public static class Password extends Credential { + @XmlElement(required = true) + public String username; + @XmlElement(required = true) + public String password; + + @Override + public String toString() { + return "userpass(id=" + id + ")"; + } + } + + /** + * A credential that is just used for deleting credentials by ID. Cannot be + * marshalled as XML. + * + * @author Donal Fellows + */ + public static class Dummy extends Credential { + public Dummy(String id) { + this.id = id; + } + + @Override + public String toString() { + return "dummy(id=" + id + ")"; + } + } +} \ 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/common/DirEntryReference.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java new file mode 100644 index 0000000..318ae4f --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static org.taverna.server.master.common.Namespaces.XLINK; + +import java.net.URI; + +import javax.ws.rs.core.UriBuilder; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +import org.taverna.server.master.interfaces.Directory; +import org.taverna.server.master.interfaces.DirectoryEntry; + +/** + * A reference to something that is in a directory below the working directory + * of a workflow run, described using JAXB. Note that when creating an XML + * document containing one of these in a client, it is <i>not</i> necessary to + * supply any attribute. + * + * @author Donal Fellows + */ +@XmlType(name = "DirectoryEntry") +@XmlSeeAlso( { DirEntryReference.DirectoryReference.class, + DirEntryReference.FileReference.class }) +public class DirEntryReference { + /** A link to the entry. Ignored on input. */ + @XmlAttribute(name = "href", namespace = XLINK) + @XmlSchemaType(name = "anyURI") + public URI link; + /** The last, user-displayable part of the name. Ignored on input. */ + @XmlAttribute + public String name; + /** The path of the entry. */ + @XmlValue + public String path; + + /** + * Return the directory entry reference instance subclass suitable for the + * given directory entry. + * + * @param entry + * The entry to characterise. + * @return An object that describes the directory entry. + */ + public static DirEntryReference newInstance(DirectoryEntry entry) { + return newInstance(null, entry); + } + + /** + * Return the directory entry reference instance subclass suitable for the + * given directory entry. + * + * @param ub + * Used for constructing URIs. The {@link #link} field is not + * filled in if this is <tt>null</tt>. + * @param entry + * The entry to characterise. + * @return An object that describes the directory entry. + */ + // Really returns a subclass, so cannot be constructor + public static DirEntryReference newInstance(UriBuilder ub, + DirectoryEntry entry) { + DirEntryReference de = (entry instanceof Directory) ? new DirectoryReference() + : new FileReference(); + de.name = entry.getName(); + String fullname = entry.getFullName(); + de.path = fullname.startsWith("/") ? fullname.substring(1) : fullname; + if (ub != null) + de.link = ub.build(entry.getName()); + return de; + } + + /** A reference to a directory, done with JAXB. */ + @XmlRootElement(name = "dir") + @XmlType(name = "DirectoryReference") + public static class DirectoryReference extends DirEntryReference { + } + + /** A reference to a file, done with JAXB. */ + @XmlRootElement(name = "file") + @XmlType(name = "FileReference") + public static class FileReference extends DirEntryReference { + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java new file mode 100644 index 0000000..bb98d6d --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +import org.taverna.server.master.interfaces.Input; +import org.taverna.server.master.interfaces.TavernaRun; + +/** + * A description of the inputs to a workflow, described using JAXB. + * + * @author Donal Fellows + */ +@XmlRootElement(name = "inputConfiguration") +@XmlType(name = "InputConfigurationDescription") +public class InputDescription extends VersionedElement { + /** + * The Baclava file handling the description of the elements. May be + * omitted/<tt>null</tt>. + */ + @XmlElement(required = false) + public String baclavaFile; + /** + * The port/value assignment. + */ + @XmlElement(nillable = false) + public List<Port> port = new ArrayList<>(); + + /** + * Make a blank input description. + */ + public InputDescription() { + } + + /** + * Make an input description suitable for the given workflow run. + * + * @param run + */ + public InputDescription(TavernaRun run) { + super(true); + baclavaFile = run.getInputBaclavaFile(); + if (baclavaFile == null) + for (Input i : run.getInputs()) + port.add(new Port(i)); + } + + /** + * The type of a single port description. + * + * @author Donal Fellows + */ + @XmlType(name = "PortConfigurationDescription") + public static class Port { + /** + * The name of this port. + */ + @XmlAttribute(name = "portName", required = true) + public String name; + /** + * The file assigned to this port. + */ + @XmlAttribute(name = "portFile", required = false) + public String file; + /** + * The file assigned to this port. + */ + @XmlAttribute(name = "listDelimiter", required = false) + public String delimiter; + /** + * The value assigned to this port. + */ + @XmlValue + public String value; + + /** + * Make a blank port description. + */ + public Port() { + } + + /** + * Make a port description suitable for the given input. + * + * @param input + */ + public Port(Input input) { + name = input.getName(); + if (input.getFile() != null) { + file = input.getFile(); + value = ""; + } else { + file = null; + value = input.getValue(); + } + delimiter = input.getDelimiter(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java new file mode 100644 index 0000000..1311272 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +/** + * A convenient place to keep the names of URIs so that they can be got right + * <i>once</i>. + * + * @author Donal Fellows + */ +public interface Namespaces { + /** + * The XLink specification's namespace name. + */ + public static final String XLINK = "http://www.w3.org/1999/xlink"; + /** + * The XML Digital Signature specification's namespace name. + */ + public static final String XSIG = "http://www.w3.org/2000/09/xmldsig#"; + /** + * The Usage Record specification's namespace name. + */ + public static final String UR = "http://schema.ogf.org/urf/2003/09/urf"; + /** + * The T2flow document format's namespace name. + */ + public static final String T2FLOW = "http://taverna.sf.net/2008/xml/t2flow"; + /** + * The namespace for the server. + */ + public static final String SERVER = "http://ns.taverna.org.uk/2010/xml/server/"; + public static final String SERVER_REST = SERVER + "rest/"; + public static final String SERVER_SOAP = SERVER + "soap/"; + public static final String FEED = SERVER + "feed/"; + public static final String ADMIN = SERVER + "admin/"; +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Permission.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Permission.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Permission.java new file mode 100644 index 0000000..258bfd0 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Permission.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + +/** + * Description of a permission to access a particular workflow run. Note that + * users always have full access to their own runs, as does any user with the " + * <tt>{@value org.taverna.server.master.common.Roles#ADMIN}</tt>" ability. + * + * @author Donal Fellows + */ +@XmlType(name = "Permission") +@XmlEnum +public enum Permission { + /** Indicates that a user cannot see the workflow run at all. */ + @XmlEnumValue("none") + None, + /** + * Indicates that a user can see the workflow run and its contents, but + * can't modify anything. + */ + @XmlEnumValue("read") + Read, + /** + * Indicates that a user can update most aspects of a workflow, but cannot + * work with either its security features or its lifetime. + */ + @XmlEnumValue("update") + Update, + /** + * Indicates that a user can update almost all aspects of a workflow, with + * only its security features being shrouded. + */ + @XmlEnumValue("destroy") + Destroy +} \ No newline at end of file
