You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 16:37:01 UTC
[01/49] incubator-taverna-server git commit: taverna-* module names
Repository: incubator-taverna-server
Updated Branches:
refs/heads/master 529e59d51 -> 8d121b2b0
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
new file mode 100644
index 0000000..adf3ea7
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
@@ -0,0 +1,769 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl;
+
+import static java.lang.Runtime.getRuntime;
+import static java.lang.System.getProperty;
+import static java.lang.System.out;
+import static java.lang.management.ManagementFactory.getRuntimeMXBean;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.UUID.randomUUID;
+import static org.apache.commons.io.FileUtils.forceDelete;
+import static org.apache.commons.io.FileUtils.forceMkdir;
+import static org.apache.commons.io.FileUtils.writeByteArrayToFile;
+import static org.apache.commons.io.FileUtils.writeLines;
+import static org.taverna.server.localworker.api.Constants.HELIO_TOKEN_NAME;
+import static org.taverna.server.localworker.api.Constants.KEYSTORE_FILE;
+import static org.taverna.server.localworker.api.Constants.KEYSTORE_PASSWORD;
+import static org.taverna.server.localworker.api.Constants.SECURITY_DIR_NAME;
+import static org.taverna.server.localworker.api.Constants.SHARED_DIR_PROP;
+import static org.taverna.server.localworker.api.Constants.SUBDIR_LIST;
+import static org.taverna.server.localworker.api.Constants.SYSTEM_ENCODING;
+import static org.taverna.server.localworker.api.Constants.TRUSTSTORE_FILE;
+import static org.taverna.server.localworker.impl.utils.FilenameVerifier.getValidatedFile;
+import static org.taverna.server.localworker.remote.RemoteStatus.Finished;
+import static org.taverna.server.localworker.remote.RemoteStatus.Initialized;
+import static org.taverna.server.localworker.remote.RemoteStatus.Operating;
+import static org.taverna.server.localworker.remote.RemoteStatus.Stopped;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.taverna.server.localworker.api.Worker;
+import org.taverna.server.localworker.api.WorkerFactory;
+import org.taverna.server.localworker.remote.IllegalStateTransitionException;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.localworker.remote.RemoteDirectory;
+import org.taverna.server.localworker.remote.RemoteInput;
+import org.taverna.server.localworker.remote.RemoteListener;
+import org.taverna.server.localworker.remote.RemoteSecurityContext;
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.localworker.remote.RemoteStatus;
+import org.taverna.server.localworker.remote.StillWorkingOnItException;
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+
+/**
+ * This class implements one side of the connection between the Taverna Server
+ * master server and this process. It delegates to a {@link Worker} instance the
+ * handling of actually running a workflow.
+ *
+ * @author Donal Fellows
+ * @see DirectoryDelegate
+ * @see FileDelegate
+ * @see WorkerCore
+ */
+@SuppressWarnings("serial")
+public class LocalWorker extends UnicastRemoteObject implements RemoteSingleRun {
+ // ----------------------- CONSTANTS -----------------------
+
+ /** Handle to the directory containing the security info. */
+ static final File SECURITY_DIR;
+ static final String SLASHTEMP;
+ static {
+ SLASHTEMP = getProperty("java.io.tmpdir");
+ File home = new File(getProperty("user.home"));
+ // If we can't write to $HOME (i.e., we're in an odd deployment) use
+ // the official version of /tmp/$PID as a fallback.
+ if (!home.canWrite())
+ home = new File(SLASHTEMP, getRuntimeMXBean().getName());
+ SECURITY_DIR = new File(home, SECURITY_DIR_NAME);
+ }
+
+ // ----------------------- VARIABLES -----------------------
+
+ /**
+ * Magic flag used to turn off problematic code when testing inside CI
+ * environment.
+ */
+ static boolean DO_MKDIR = true;
+
+ /** What to use to run a workflow engine. */
+ private final String executeWorkflowCommand;
+ /** What workflow to run. */
+ private final byte[] workflow;
+ /** The remote access object for the working directory. */
+ private final DirectoryDelegate baseDir;
+ /** What inputs to pass as files. */
+ final Map<String, String> inputFiles;
+ /** What inputs to pass as files (as file refs). */
+ final Map<String, File> inputRealFiles;
+ /** What inputs to pass as direct values. */
+ final Map<String, String> inputValues;
+ /** What delimiters to use. */
+ final Map<String, String> inputDelimiters;
+ /** The interface to the workflow engine subprocess. */
+ private final Worker core;
+ /** Our descriptor token (UUID). */
+ private final String masterToken;
+ /**
+ * The root working directory for a workflow run, or <tt>null</tt> if it has
+ * been deleted.
+ */
+ private File base;
+ /**
+ * When did this workflow start running, or <tt>null</tt> for
+ * "never/not yet".
+ */
+ private Date start;
+ /**
+ * When did this workflow finish running, or <tt>null</tt> for
+ * "never/not yet".
+ */
+ private Date finish;
+ /** The cached status of the workflow run. */
+ RemoteStatus status;
+ /**
+ * The name of the input Baclava document, or <tt>null</tt> to not do it
+ * that way.
+ */
+ String inputBaclava;
+ /**
+ * The name of the output Baclava document, or <tt>null</tt> to not do it
+ * that way.
+ */
+ String outputBaclava;
+ /**
+ * The file containing the input Baclava document, or <tt>null</tt> to not
+ * do it that way.
+ */
+ private File inputBaclavaFile;
+ /**
+ * The file containing the output Baclava document, or <tt>null</tt> to not
+ * do it that way.
+ */
+ private File outputBaclavaFile;
+ /**
+ * Registered shutdown hook so that we clean up when this process is killed
+ * off, or <tt>null</tt> if that is no longer necessary.
+ */
+ Thread shutdownHook;
+ /** Location for security information to be written to. */
+ File securityDirectory;
+ /**
+ * Password to use to encrypt security information.
+ */
+ char[] keystorePassword = KEYSTORE_PASSWORD;
+ /** Additional server-specified environment settings. */
+ Map<String, String> environment = new HashMap<>();
+ /** Additional server-specified java runtime settings. */
+ List<String> runtimeSettings = new ArrayList<>();
+ URL interactionFeedURL;
+ URL webdavURL;
+ URL publishURL;//FIXME
+ private boolean doProvenance = true;
+
+ // ----------------------- METHODS -----------------------
+
+ /**
+ * @param executeWorkflowCommand
+ * The script used to execute workflows.
+ * @param workflow
+ * The workflow to execute.
+ * @param workerClass
+ * The class to instantiate as our local representative of the
+ * run.
+ * @param urReceiver
+ * The remote class to report the generated usage record(s) to.
+ * @param id
+ * The UUID to use, or <tt>null</tt> if we are to invent one.
+ * @param seedEnvironment
+ * The key/value pairs to seed the worker subprocess environment
+ * with.
+ * @param javaParams
+ * Parameters to pass to the worker subprocess java runtime
+ * itself.
+ * @param workerFactory
+ * How to make instances of the low-level worker objects.
+ * @throws RemoteException
+ * If registration of the worker fails.
+ * @throws ImplementationException
+ * If something goes wrong during local setup.
+ */
+ protected LocalWorker(String executeWorkflowCommand, byte[] workflow,
+ UsageRecordReceiver urReceiver, UUID id,
+ Map<String, String> seedEnvironment, List<String> javaParams,
+ WorkerFactory workerFactory) throws RemoteException,
+ ImplementationException {
+ super();
+ if (id == null)
+ id = randomUUID();
+ masterToken = id.toString();
+ this.workflow = workflow;
+ this.executeWorkflowCommand = executeWorkflowCommand;
+ String sharedDir = getProperty(SHARED_DIR_PROP, SLASHTEMP);
+ base = new File(sharedDir, masterToken);
+ out.println("about to create " + base);
+ try {
+ forceMkdir(base);
+ for (String subdir : SUBDIR_LIST) {
+ new File(base, subdir).mkdir();
+ }
+ } catch (IOException e) {
+ throw new ImplementationException(
+ "problem creating run working directory", e);
+ }
+ baseDir = new DirectoryDelegate(base, null);
+ inputFiles = new HashMap<>();
+ inputRealFiles = new HashMap<>();
+ inputValues = new HashMap<>();
+ inputDelimiters = new HashMap<>();
+ environment.putAll(seedEnvironment);
+ runtimeSettings.addAll(javaParams);
+ try {
+ core = workerFactory.makeInstance();
+ } catch (Exception e) {
+ out.println("problem when creating core worker implementation");
+ e.printStackTrace(out);
+ throw new ImplementationException(
+ "problem when creating core worker implementation", e);
+ }
+ core.setURReceiver(urReceiver);
+ Thread t = new Thread(new Runnable() {
+ /**
+ * Kill off the worker launched by the core.
+ */
+ @Override
+ public void run() {
+ try {
+ shutdownHook = null;
+ destroy();
+ } catch (ImplementationException e) {
+ // Absolutely nothing we can do here
+ }
+ }
+ });
+ getRuntime().addShutdownHook(t);
+ shutdownHook = t;
+ status = Initialized;
+ }
+
+ @Override
+ public void destroy() throws ImplementationException {
+ killWorkflowSubprocess();
+ removeFromShutdownHooks();
+ // Is this it?
+ deleteWorkingDirectory();
+ deleteSecurityManagerDirectory();
+ core.deleteLocalResources();
+ }
+
+ private void killWorkflowSubprocess() {
+ if (status != Finished && status != Initialized)
+ try {
+ core.killWorker();
+ if (finish == null)
+ finish = new Date();
+ } catch (Exception e) {
+ out.println("problem when killing worker");
+ e.printStackTrace(out);
+ }
+ }
+
+ private void removeFromShutdownHooks() throws ImplementationException {
+ try {
+ if (shutdownHook != null)
+ getRuntime().removeShutdownHook(shutdownHook);
+ } catch (RuntimeException e) {
+ throw new ImplementationException("problem removing shutdownHook",
+ e);
+ } finally {
+ shutdownHook = null;
+ }
+ }
+
+ private void deleteWorkingDirectory() throws ImplementationException {
+ try {
+ if (base != null)
+ forceDelete(base);
+ } catch (IOException e) {
+ out.println("problem deleting working directory");
+ e.printStackTrace(out);
+ throw new ImplementationException(
+ "problem deleting working directory", e);
+ } finally {
+ base = null;
+ }
+ }
+
+ private void deleteSecurityManagerDirectory()
+ throws ImplementationException {
+ try {
+ if (securityDirectory != null)
+ forceDelete(securityDirectory);
+ } catch (IOException e) {
+ out.println("problem deleting security directory");
+ e.printStackTrace(out);
+ throw new ImplementationException(
+ "problem deleting security directory", e);
+ } finally {
+ securityDirectory = null;
+ }
+ }
+
+ @Override
+ public void addListener(RemoteListener listener) throws RemoteException,
+ ImplementationException {
+ throw new ImplementationException("not implemented");
+ }
+
+ @Override
+ public String getInputBaclavaFile() {
+ return inputBaclava;
+ }
+
+ @Override
+ public List<RemoteInput> getInputs() throws RemoteException {
+ ArrayList<RemoteInput> result = new ArrayList<>();
+ for (String name : inputFiles.keySet())
+ result.add(new InputDelegate(name));
+ return result;
+ }
+
+ @Override
+ public List<String> getListenerTypes() {
+ return emptyList();
+ }
+
+ @Override
+ public List<RemoteListener> getListeners() {
+ return singletonList(core.getDefaultListener());
+ }
+
+ @Override
+ public String getOutputBaclavaFile() {
+ return outputBaclava;
+ }
+
+ class SecurityDelegate extends UnicastRemoteObject implements
+ RemoteSecurityContext {
+ private void setPrivatePerms(File dir) {
+ if (!dir.setReadable(false, false) || !dir.setReadable(true, true)
+ || !dir.setExecutable(false, false)
+ || !dir.setExecutable(true, true)
+ || !dir.setWritable(false, false)
+ || !dir.setWritable(true, true)) {
+ out.println("warning: "
+ + "failed to set permissions on security context directory");
+ }
+ }
+
+ protected SecurityDelegate(String token) throws IOException {
+ super();
+ if (DO_MKDIR) {
+ securityDirectory = new File(SECURITY_DIR, token);
+ forceMkdir(securityDirectory);
+ setPrivatePerms(securityDirectory);
+ }
+ }
+
+ /**
+ * Write some data to a given file in the context directory.
+ *
+ * @param name
+ * The name of the file to write.
+ * @param data
+ * The bytes to put in the file.
+ * @throws RemoteException
+ * If anything goes wrong.
+ * @throws ImplementationException
+ */
+ protected void write(String name, byte[] data) throws RemoteException,
+ ImplementationException {
+ try {
+ File f = new File(securityDirectory, name);
+ writeByteArrayToFile(f, data);
+ } catch (IOException e) {
+ throw new ImplementationException("problem writing " + name, e);
+ }
+ }
+
+ /**
+ * Write some data to a given file in the context directory.
+ *
+ * @param name
+ * The name of the file to write.
+ * @param data
+ * The lines to put in the file. The
+ * {@linkplain LocalWorker#SYSTEM_ENCODING system encoding}
+ * will be used to do the writing.
+ * @throws RemoteException
+ * If anything goes wrong.
+ * @throws ImplementationException
+ */
+ protected void write(String name, Collection<String> data)
+ throws RemoteException, ImplementationException {
+ try {
+ File f = new File(securityDirectory, name);
+ writeLines(f, SYSTEM_ENCODING, data);
+ } catch (IOException e) {
+ throw new ImplementationException("problem writing " + name, e);
+ }
+ }
+
+ /**
+ * Write some data to a given file in the context directory.
+ *
+ * @param name
+ * The name of the file to write.
+ * @param data
+ * The line to put in the file. The
+ * {@linkplain LocalWorker#SYSTEM_ENCODING system encoding}
+ * will be used to do the writing.
+ * @throws RemoteException
+ * If anything goes wrong.
+ * @throws ImplementationException
+ */
+ protected void write(String name, char[] data) throws RemoteException,
+ ImplementationException {
+ try {
+ File f = new File(securityDirectory, name);
+ writeLines(f, SYSTEM_ENCODING, asList(new String(data)));
+ } catch (IOException e) {
+ throw new ImplementationException("problem writing " + name, e);
+ }
+ }
+
+ @Override
+ public void setKeystore(byte[] keystore) throws RemoteException,
+ ImplementationException {
+ if (status != Initialized)
+ throw new RemoteException("not initializing");
+ if (keystore == null)
+ throw new IllegalArgumentException("keystore may not be null");
+ write(KEYSTORE_FILE, keystore);
+ }
+
+ @Override
+ public void setPassword(char[] password) throws RemoteException {
+ if (status != Initialized)
+ throw new RemoteException("not initializing");
+ if (password == null)
+ throw new IllegalArgumentException("password may not be null");
+ keystorePassword = password.clone();
+ }
+
+ @Override
+ public void setTruststore(byte[] truststore) throws RemoteException,
+ ImplementationException {
+ if (status != Initialized)
+ throw new RemoteException("not initializing");
+ if (truststore == null)
+ throw new IllegalArgumentException("truststore may not be null");
+ write(TRUSTSTORE_FILE, truststore);
+ }
+
+ @Override
+ public void setUriToAliasMap(Map<URI, String> uriToAliasMap)
+ throws RemoteException {
+ if (status != Initialized)
+ throw new RemoteException("not initializing");
+ if (uriToAliasMap == null)
+ return;
+ ArrayList<String> lines = new ArrayList<>();
+ for (Entry<URI, String> site : uriToAliasMap.entrySet())
+ lines.add(site.getKey().toASCIIString() + " " + site.getValue());
+ // write(URI_ALIAS_MAP, lines);
+ }
+
+ @Override
+ public void setHelioToken(String helioToken) throws RemoteException {
+ if (status != Initialized)
+ throw new RemoteException("not initializing");
+ out.println("registering HELIO CIS token for export");
+ environment.put(HELIO_TOKEN_NAME, helioToken);
+ }
+ }
+
+ @Override
+ public RemoteSecurityContext getSecurityContext() throws RemoteException,
+ ImplementationException {
+ try {
+ return new SecurityDelegate(masterToken);
+ } catch (RemoteException e) {
+ if (e.getCause() != null)
+ throw new ImplementationException(
+ "problem initializing security context", e.getCause());
+ throw e;
+ } catch (IOException e) {
+ throw new ImplementationException(
+ "problem initializing security context", e);
+ }
+ }
+
+ @Override
+ public RemoteStatus getStatus() {
+ // only state that can spontaneously change to another
+ if (status == Operating) {
+ status = core.getWorkerStatus();
+ if (status == Finished && finish == null)
+ finish = new Date();
+ }
+ return status;
+ }
+
+ @Override
+ public RemoteDirectory getWorkingDirectory() {
+ return baseDir;
+ }
+
+ File validateFilename(String filename) throws RemoteException {
+ if (filename == null)
+ throw new IllegalArgumentException("filename must be non-null");
+ try {
+ return getValidatedFile(base, filename.split("/"));
+ } catch (IOException e) {
+ throw new IllegalArgumentException("failed to validate filename", e);
+ }
+ }
+
+ class InputDelegate extends UnicastRemoteObject implements RemoteInput {
+ private String name;
+
+ InputDelegate(String name) throws RemoteException {
+ super();
+ this.name = name;
+ if (!inputFiles.containsKey(name)) {
+ if (status != Initialized)
+ throw new IllegalStateException("not initializing");
+ inputFiles.put(name, null);
+ inputRealFiles.put(name, null);
+ inputValues.put(name, null);
+ inputDelimiters.put(name, null);
+ }
+ }
+
+ @Override
+ public String getFile() {
+ return inputFiles.get(name);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getValue() {
+ return inputValues.get(name);
+ }
+
+ @Override
+ public String getDelimiter() throws RemoteException {
+ return inputDelimiters.get(name);
+ }
+
+ @Override
+ public void setFile(String file) throws RemoteException {
+ if (status != Initialized)
+ throw new IllegalStateException("not initializing");
+ inputRealFiles.put(name, validateFilename(file));
+ inputValues.put(name, null);
+ inputFiles.put(name, file);
+ inputBaclava = null;
+ }
+
+ @Override
+ public void setValue(String value) throws RemoteException {
+ if (status != Initialized)
+ throw new IllegalStateException("not initializing");
+ inputValues.put(name, value);
+ inputFiles.put(name, null);
+ inputRealFiles.put(name, null);
+ inputBaclava = null;
+ }
+
+ @Override
+ public void setDelimiter(String delimiter) throws RemoteException {
+ if (status != Initialized)
+ throw new IllegalStateException("not initializing");
+ if (inputBaclava != null)
+ throw new IllegalStateException("input baclava file set");
+ if (delimiter != null) {
+ if (delimiter.length() > 1)
+ throw new IllegalStateException(
+ "multi-character delimiter not permitted");
+ if (delimiter.charAt(0) == 0)
+ throw new IllegalStateException(
+ "may not use NUL for splitting");
+ if (delimiter.charAt(0) > 127)
+ throw new IllegalStateException(
+ "only ASCII characters supported for splitting");
+ }
+ inputDelimiters.put(name, delimiter);
+ }
+ }
+
+ @Override
+ public RemoteInput makeInput(String name) throws RemoteException {
+ return new InputDelegate(name);
+ }
+
+ @Override
+ public RemoteListener makeListener(String type, String configuration)
+ throws RemoteException {
+ throw new RemoteException("listener manufacturing unsupported");
+ }
+
+ @Override
+ public void setInputBaclavaFile(String filename) throws RemoteException {
+ if (status != Initialized)
+ throw new IllegalStateException("not initializing");
+ inputBaclavaFile = validateFilename(filename);
+ for (String input : inputFiles.keySet()) {
+ inputFiles.put(input, null);
+ inputRealFiles.put(input, null);
+ inputValues.put(input, null);
+ }
+ inputBaclava = filename;
+ }
+
+ @Override
+ public void setOutputBaclavaFile(String filename) throws RemoteException {
+ if (status != Initialized)
+ throw new IllegalStateException("not initializing");
+ if (filename != null)
+ outputBaclavaFile = validateFilename(filename);
+ else
+ outputBaclavaFile = null;
+ outputBaclava = filename;
+ }
+
+ @Override
+ public void setGenerateProvenance(boolean prov) {
+ doProvenance = prov;
+ }
+
+ @Override
+ public void setStatus(RemoteStatus newStatus)
+ throws IllegalStateTransitionException, RemoteException,
+ ImplementationException, StillWorkingOnItException {
+ if (status == newStatus)
+ return;
+
+ switch (newStatus) {
+ case Initialized:
+ throw new IllegalStateTransitionException(
+ "may not move back to start");
+ case Operating:
+ switch (status) {
+ case Initialized:
+ boolean started;
+ try {
+ started = createWorker();
+ } catch (Exception e) {
+ throw new ImplementationException(
+ "problem creating executing workflow", e);
+ }
+ if (!started)
+ throw new StillWorkingOnItException(
+ "workflow start in process");
+ break;
+ case Stopped:
+ try {
+ core.startWorker();
+ } catch (Exception e) {
+ throw new ImplementationException(
+ "problem continuing workflow run", e);
+ }
+ break;
+ case Finished:
+ throw new IllegalStateTransitionException("already finished");
+ default:
+ break;
+ }
+ status = Operating;
+ break;
+ case Stopped:
+ switch (status) {
+ case Initialized:
+ throw new IllegalStateTransitionException(
+ "may only stop from Operating");
+ case Operating:
+ try {
+ core.stopWorker();
+ } catch (Exception e) {
+ throw new ImplementationException(
+ "problem stopping workflow run", e);
+ }
+ break;
+ case Finished:
+ throw new IllegalStateTransitionException("already finished");
+ default:
+ break;
+ }
+ status = Stopped;
+ break;
+ case Finished:
+ switch (status) {
+ case Operating:
+ case Stopped:
+ try {
+ core.killWorker();
+ if (finish == null)
+ finish = new Date();
+ } catch (Exception e) {
+ throw new ImplementationException(
+ "problem killing workflow run", e);
+ }
+ default:
+ break;
+ }
+ status = Finished;
+ break;
+ }
+ }
+
+ private boolean createWorker() throws Exception {
+ start = new Date();
+ char[] pw = keystorePassword;
+ keystorePassword = null;
+ /*
+ * Do not clear the keystorePassword array here; its ownership is
+ * *transferred* to the worker core which doesn't copy it but *does*
+ * clear it after use.
+ */
+ return core.initWorker(this, executeWorkflowCommand, workflow, base,
+ inputBaclavaFile, inputRealFiles, inputValues, inputDelimiters,
+ outputBaclavaFile, securityDirectory, pw, doProvenance,
+ environment, masterToken, runtimeSettings);
+ }
+
+ @Override
+ public Date getFinishTimestamp() {
+ return finish == null ? null : new Date(finish.getTime());
+ }
+
+ @Override
+ public Date getStartTimestamp() {
+ return start == null ? null : new Date(start.getTime());
+ }
+
+ @Override
+ public void setInteractionServiceDetails(URL feed, URL webdav, URL publish) {
+ interactionFeedURL = feed;
+ webdavURL = webdav;
+ publishURL = publish;
+ }
+
+ @Override
+ public void ping() {
+ // Do nothing here; this *should* be empty
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
new file mode 100644
index 0000000..03ee69d
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl;
+
+import static java.lang.Runtime.getRuntime;
+import static java.lang.System.exit;
+import static java.lang.System.getProperty;
+import static java.lang.System.out;
+import static java.lang.System.setProperty;
+import static java.lang.System.setSecurityManager;
+import static java.rmi.registry.LocateRegistry.getRegistry;
+import static org.taverna.server.localworker.api.Constants.DEATH_DELAY;
+import static org.taverna.server.localworker.api.Constants.LOCALHOST;
+import static org.taverna.server.localworker.api.Constants.RMI_HOST_PROP;
+import static org.taverna.server.localworker.api.Constants.SECURITY_POLICY_FILE;
+import static org.taverna.server.localworker.api.Constants.SEC_POLICY_PROP;
+import static org.taverna.server.localworker.api.Constants.UNSECURE_PROP;
+
+import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.rmi.RMISecurityManager;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.taverna.server.localworker.api.RunAccounting;
+import org.taverna.server.localworker.api.Worker;
+import org.taverna.server.localworker.api.WorkerFactory;
+import org.taverna.server.localworker.remote.RemoteRunFactory;
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
+
+/**
+ * The registered factory for runs, this class is responsible for constructing
+ * runs that are suitable for particular users. It is also the entry point for
+ * this whole process.
+ *
+ * @author Donal Fellows
+ * @see LocalWorker
+ */
+@SuppressWarnings("serial")
+public class TavernaRunManager extends UnicastRemoteObject implements
+ RemoteRunFactory, RunAccounting, WorkerFactory {
+ String command;
+ Map<String, String> seedEnvironment = new HashMap<>();
+ List<String> javaInitParams = new ArrayList<>();
+ private WorkflowBundleIO io;
+ private int activeRuns = 0;
+ // Hacks!
+ public static String interactionHost;
+ public static String interactionPort;
+ public static String interactionWebdavPath;
+ public static String interactionFeedPath;
+
+ /**
+ * How to get the actual workflow document from the XML document that it is
+ * contained in.
+ *
+ * @param containerDocument
+ * The document sent from the web interface.
+ * @return The element describing the workflow, as expected by the Taverna
+ * command line executor.
+ */
+ protected Element unwrapWorkflow(Document containerDocument) {
+ return (Element) containerDocument.getDocumentElement().getFirstChild();
+ }
+
+ private static final String usage = "java -jar server.worker.jar workflowExecScript ?-Ekey=val...? ?-Jconfig? UUID";
+
+ /**
+ * An RMI-enabled factory for runs.
+ *
+ * @param command
+ * What command to call to actually run a run.
+ * @throws RemoteException
+ * If anything goes wrong during creation of the instance.
+ */
+ public TavernaRunManager(String command) throws RemoteException {
+ this.command = command;
+ this.io = new WorkflowBundleIO();
+ }
+
+ @Override
+ public RemoteSingleRun make(byte[] workflow, String creator,
+ UsageRecordReceiver urReceiver, UUID id) throws RemoteException {
+ if (creator == null)
+ throw new RemoteException("no creator");
+ try {
+ URI wfid = io.readBundle(new ByteArrayInputStream(workflow), null)
+ .getMainWorkflow().getWorkflowIdentifier();
+ out.println("Creating run from workflow <" + wfid + "> for <"
+ + creator + ">");
+ return new LocalWorker(command, workflow, urReceiver, id,
+ seedEnvironment, javaInitParams, this);
+ } catch (RemoteException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RemoteException("bad instance construction", e);
+ }
+ }
+
+ private static boolean shuttingDown;
+ private static String factoryName;
+ private static Registry registry;
+
+ static synchronized void unregisterFactory() {
+ if (!shuttingDown) {
+ shuttingDown = true;
+ try {
+ if (factoryName != null && registry != null)
+ registry.unbind(factoryName);
+ } catch (Exception e) {
+ e.printStackTrace(out);
+ }
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ unregisterFactory();
+ new Thread(new DelayedDeath()).start();
+ }
+
+ static class DelayedDeath implements Runnable {
+ @Override
+ public void run() {
+ try {
+ Thread.sleep(DEATH_DELAY);
+ } catch (InterruptedException e) {
+ } finally {
+ exit(0);
+ }
+ }
+ }
+
+ private void addArgument(String arg) {
+ if (arg.startsWith("-E")) {
+ String trimmed = arg.substring(2);
+ int idx = trimmed.indexOf('=');
+ if (idx > 0) {
+ addEnvironmentDefinition(trimmed.substring(0, idx),
+ trimmed.substring(idx + 1));
+ return;
+ }
+ } else if (arg.startsWith("-D")) {
+ if (arg.indexOf('=') > 0) {
+ addJavaParameter(arg);
+ return;
+ }
+ } else if (arg.startsWith("-J")) {
+ addJavaParameter(arg.substring(2));
+ return;
+ }
+ throw new IllegalArgumentException("argument \"" + arg
+ + "\" must start with -D, -E or -J; "
+ + "-D and -E must contain a \"=\"");
+ }
+
+ /**
+ * @param args
+ * The arguments from the command line invocation.
+ * @throws Exception
+ * If we can't connect to the RMI registry, or if we can't read
+ * the workflow, or if we can't build the worker instance, or
+ * register it. Also if the arguments are wrong.
+ */
+ public static void main(String[] args) throws Exception {
+ if (args.length < 2)
+ throw new Exception("wrong # args: must be \"" + usage + "\"");
+ if (!getProperty(UNSECURE_PROP, "no").equals("yes")) {
+ setProperty(SEC_POLICY_PROP, LocalWorker.class.getClassLoader()
+ .getResource(SECURITY_POLICY_FILE).toExternalForm());
+ setProperty(RMI_HOST_PROP, LOCALHOST);
+ }
+ setSecurityManager(new RMISecurityManager());
+ factoryName = args[args.length - 1];
+ TavernaRunManager man = new TavernaRunManager(args[0]);
+ for (int i = 1; i < args.length - 1; i++)
+ man.addArgument(args[i]);
+ registry = getRegistry(LOCALHOST);
+
+ registry.bind(factoryName, man);
+ getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ unregisterFactory();
+ }
+ });
+ out.println("registered RemoteRunFactory with ID " + factoryName);
+ }
+
+ private void addJavaParameter(String string) {
+ this.javaInitParams.add(string);
+ }
+
+ private void addEnvironmentDefinition(String key, String value) {
+ this.seedEnvironment.put(key, value);
+ }
+
+ @Override
+ public void setInteractionServiceDetails(String host, String port,
+ String webdavPath, String feedPath) throws RemoteException {
+ if (host == null || port == null || webdavPath == null
+ || feedPath == null)
+ throw new IllegalArgumentException("all params must be non-null");
+ interactionHost = host;
+ interactionPort = port;
+ interactionWebdavPath = webdavPath;
+ interactionFeedPath = feedPath;
+ }
+
+ @Override
+ public synchronized int countOperatingRuns() {
+ return (activeRuns < 0 ? 0 : activeRuns);
+ }
+
+ @Override
+ public synchronized void runStarted() {
+ activeRuns++;
+ }
+
+ @Override
+ public synchronized void runCeased() {
+ activeRuns--;
+ }
+
+ @Override
+ public Worker makeInstance() throws Exception {
+ return new WorkerCore(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
new file mode 100644
index 0000000..1a6cff8
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
@@ -0,0 +1,918 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl;
+
+import static java.io.File.createTempFile;
+import static java.io.File.pathSeparator;
+import static java.lang.Boolean.parseBoolean;
+import static java.lang.Double.parseDouble;
+import static java.lang.Integer.parseInt;
+import static java.lang.Long.parseLong;
+import static java.lang.Runtime.getRuntime;
+import static java.lang.System.out;
+import static java.net.InetAddress.getLocalHost;
+import static org.apache.commons.io.FileUtils.forceDelete;
+import static org.apache.commons.io.FileUtils.sizeOfDirectory;
+import static org.apache.commons.io.FileUtils.write;
+import static org.apache.commons.io.IOUtils.copy;
+import static org.taverna.server.localworker.api.Constants.CREDENTIAL_MANAGER_DIRECTORY;
+import static org.taverna.server.localworker.api.Constants.CREDENTIAL_MANAGER_PASSWORD;
+import static org.taverna.server.localworker.api.Constants.DEATH_TIME;
+import static org.taverna.server.localworker.api.Constants.DEFAULT_LISTENER_NAME;
+import static org.taverna.server.localworker.api.Constants.KEYSTORE_PASSWORD;
+import static org.taverna.server.localworker.api.Constants.START_WAIT_TIME;
+import static org.taverna.server.localworker.api.Constants.SYSTEM_ENCODING;
+import static org.taverna.server.localworker.api.Constants.TIME;
+import static org.taverna.server.localworker.impl.Status.Aborted;
+import static org.taverna.server.localworker.impl.Status.Completed;
+import static org.taverna.server.localworker.impl.Status.Failed;
+import static org.taverna.server.localworker.impl.Status.Held;
+import static org.taverna.server.localworker.impl.Status.Started;
+import static org.taverna.server.localworker.impl.TavernaRunManager.interactionFeedPath;
+import static org.taverna.server.localworker.impl.TavernaRunManager.interactionHost;
+import static org.taverna.server.localworker.impl.TavernaRunManager.interactionPort;
+import static org.taverna.server.localworker.impl.TavernaRunManager.interactionWebdavPath;
+import static org.taverna.server.localworker.impl.WorkerCore.pmap;
+import static org.taverna.server.localworker.remote.RemoteStatus.Finished;
+import static org.taverna.server.localworker.remote.RemoteStatus.Initialized;
+import static org.taverna.server.localworker.remote.RemoteStatus.Operating;
+import static org.taverna.server.localworker.remote.RemoteStatus.Stopped;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.ws.Holder;
+
+import org.ogf.usage.JobUsageRecord;
+import org.taverna.server.localworker.api.RunAccounting;
+import org.taverna.server.localworker.api.Worker;
+import org.taverna.server.localworker.impl.utils.TimingOutTask;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.localworker.remote.RemoteListener;
+import org.taverna.server.localworker.remote.RemoteStatus;
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+
+/**
+ * The core class that connects to a Taverna command-line workflow execution
+ * engine. This implementation always registers a single listener, &lquo;
+ * <tt>io</tt> &rquo;, with two properties representing the stdout and stderr of
+ * the run and one representing the exit code. The listener is
+ * remote-accessible. It does not support attaching any other listeners.
+ *
+ * @author Donal Fellows
+ */
+@SuppressWarnings("serial")
+public class WorkerCore extends UnicastRemoteObject implements Worker,
+ RemoteListener {
+ @Nonnull
+ static final Map<String, Property> pmap = new HashMap<>();
+ /**
+ * Regular expression to extract the detailed timing information from the
+ * output of /usr/bin/time
+ */
+ @Nonnull
+ private static final Pattern TimeRE;
+ static {
+ final String TIMERE = "([0-9.:]+)";
+ final String TERMS = "(real|user|system|sys|elapsed)";
+ TimeRE = Pattern.compile(TIMERE + " *" + TERMS + "[ \t]*" + TIMERE
+ + " *" + TERMS + "[ \t]*" + TIMERE + " *" + TERMS);
+ }
+
+ /**
+ * Environment variables to remove before any fork (because they're large or
+ * potentially leaky).
+ */
+ // TODO Conduct a proper survey of what to remove
+ @Nonnull
+ private static final String[] ENVIRONMENT_TO_REMOVE = { "SUDO_COMMAND",
+ "SUDO_USER", "SUDO_GID", "SUDO_UID", "DISPLAY", "LS_COLORS",
+ "XFILESEARCHPATH", "SSH_AGENT_PID", "SSH_AUTH_SOCK" };
+
+ @Nullable
+ Process subprocess;
+ @Nonnull
+ final StringWriter stdout;
+ @Nonnull
+ final StringWriter stderr;
+ @Nullable
+ Integer exitCode;
+ boolean readyToSendEmail;
+ @Nullable
+ String emailAddress;
+ @Nullable
+ Date start;
+ @Nonnull
+ final RunAccounting accounting;
+ @Nonnull
+ final Holder<Integer> pid;
+
+ private boolean finished;
+ @Nullable
+ private JobUsageRecord ur;
+ @Nullable
+ private File wd;
+ @Nullable
+ private UsageRecordReceiver urreceiver;
+ @Nullable
+ private File workflowFile;
+ private boolean stopped;
+
+ /**
+ * @param accounting
+ * Object that looks after how many runs are executing.
+ * @throws RemoteException
+ */
+ public WorkerCore(@Nonnull RunAccounting accounting) throws RemoteException {
+ super();
+ stdout = new StringWriter();
+ stderr = new StringWriter();
+ pid = new Holder<>();
+ this.accounting = accounting;
+ }
+
+ private int getPID() {
+ synchronized (pid) {
+ if (pid.value == null)
+ return -1;
+ return pid.value;
+ }
+ }
+
+ /**
+ * Fire up the workflow. This causes a transition into the operating state.
+ *
+ * @param executeWorkflowCommand
+ * The command to run to execute the workflow.
+ * @param workflow
+ * The workflow document to execute.
+ * @param workingDir
+ * What directory to use as the working directory.
+ * @param inputBaclava
+ * The baclava file to use for inputs, or <tt>null</tt> to use
+ * the other <b>input*</b> arguments' values.
+ * @param inputFiles
+ * A mapping of input names to files that supply them. Note that
+ * we assume that nothing mapped here will be mapped in
+ * <b>inputValues</b>.
+ * @param inputValues
+ * A mapping of input names to values to supply to them. Note
+ * that we assume that nothing mapped here will be mapped in
+ * <b>inputFiles</b>.
+ * @param outputBaclava
+ * What baclava file to write the output from the workflow into,
+ * or <tt>null</tt> to have it written into the <tt>out</tt>
+ * subdirectory.
+ * @param token
+ * The name of the workflow run.
+ * @return <tt>true</tt> if the worker started, or <tt>false</tt> if a
+ * timeout occurred.
+ * @throws IOException
+ * If any of quite a large number of things goes wrong.
+ */
+ @Override
+ public boolean initWorker(
+ @Nonnull final LocalWorker local,
+ @Nonnull final String executeWorkflowCommand,
+ @Nonnull final byte[] workflow,
+ @Nonnull final File workingDir,
+ @Nullable final File inputBaclava,
+ @Nonnull final Map<String, File> inputFiles,
+ @Nonnull final Map<String, String> inputValues,
+ @Nonnull final Map<String, String> inputDelimiters,
+ @Nullable final File outputBaclava,
+ @Nonnull final File securityDir,
+ @Nullable final char[] password,
+ final boolean generateProvenance,
+ @Nonnull final Map<String, String> environment,
+ @Nullable final String token,
+ @Nonnull final List<String> runtime) throws IOException {
+ try {
+ new TimingOutTask() {
+ @Override
+ public void doIt() throws IOException {
+ startExecutorSubprocess(
+ createProcessBuilder(local, executeWorkflowCommand,
+ workflow, workingDir, inputBaclava,
+ inputFiles, inputValues, inputDelimiters,
+ outputBaclava, securityDir, password,
+ generateProvenance, environment, token,
+ runtime), password);
+ }
+ }.doOrTimeOut(START_WAIT_TIME);
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ return subprocess != null;
+ }
+
+ private void startExecutorSubprocess(@Nonnull ProcessBuilder pb,
+ @Nullable char[] password) throws IOException {
+ // Start the subprocess
+ out.println("starting " + pb.command() + " in directory "
+ + pb.directory() + " with environment " + pb.environment());
+ subprocess = pb.start();
+ if (subprocess == null)
+ throw new IOException("unknown failure creating process");
+ start = new Date();
+ accounting.runStarted();
+
+ // Capture its stdout and stderr
+ new AsyncCopy(subprocess.getInputStream(), stdout, pid);
+ new AsyncCopy(subprocess.getErrorStream(), stderr);
+ if (password != null)
+ new PasswordWriterThread(subprocess, password);
+ }
+
+ /**
+ * Assemble the process builder. Does not launch the subprocess.
+ *
+ * @param local
+ * The local worker container.
+ * @param executeWorkflowCommand
+ * The reference to the workflow engine implementation.
+ * @param workflow
+ * The workflow to execute.
+ * @param workingDir
+ * The working directory to use.
+ * @param inputBaclava
+ * What file to read a baclava document from (or <tt>null</tt>)
+ * @param inputFiles
+ * The mapping from inputs to files.
+ * @param inputValues
+ * The mapping from inputs to literal values.
+ * @param outputBaclava
+ * What file to write a baclava document to (or <tt>null</tt>)
+ * @param securityDir
+ * The credential manager directory.
+ * @param password
+ * The password for the credential manager.
+ * @param environment
+ * The seed environment
+ * @param token
+ * The run identifier that the server wants to use.
+ * @param runtime
+ * Any runtime parameters to Java.
+ * @return The configured process builder.
+ * @throws IOException
+ * If file handling fails
+ * @throws UnsupportedEncodingException
+ * If we can't encode any text (unlikely)
+ * @throws FileNotFoundException
+ * If we can't write the workflow out (unlikely)
+ */
+ @Nonnull
+ ProcessBuilder createProcessBuilder(@Nonnull LocalWorker local,
+ @Nonnull String executeWorkflowCommand, @Nonnull byte[] workflow,
+ @Nonnull File workingDir, @Nullable File inputBaclava,
+ @Nonnull Map<String, File> inputFiles,
+ @Nonnull Map<String, String> inputValues,
+ @Nonnull Map<String, String> inputDelimiters,
+ @Nullable File outputBaclava, @Nonnull File securityDir,
+ @Nonnull char[] password, boolean generateProvenance,
+ @Nonnull Map<String, String> environment, @Nonnull String token,
+ @Nonnull List<String> runtime) throws IOException,
+ UnsupportedEncodingException, FileNotFoundException {
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command().add(TIME);
+ /*
+ * WARNING! HERE THERE BE DRAGONS! BE CAREFUL HERE!
+ *
+ * Work around _Maven_ bug with permissions in zip files! The executable
+ * bit is stripped by Maven's handling of file permissions, and there's
+ * no practical way to work around it without massively increasing the
+ * pain in other ways. Only want this on Unix - Windows isn't affected
+ * by this - so we use the file separator as a proxy for whether this is
+ * a true POSIX system. Ugly! Ugly ugly ugly...
+ *
+ * http://jira.codehaus.org/browse/MASSEMBLY-337 is relevant, but not
+ * the whole story as we don't want to use a non-standard packaging
+ * method as there's a real chance of it going wrong in an unexpected
+ * way then. Other parts of the story are that the executable bit isn't
+ * preserved when unpacking with the dependency plugin, and there's no
+ * way to be sure that the servlet container will preserve the bit
+ * either (as that's probably using a Java-based ZIP engine).
+ */
+ if (File.separatorChar == '/')
+ pb.command().add("/bin/sh");
+ pb.command().add(executeWorkflowCommand);
+ if (runtime != null)
+ pb.command().addAll(runtime);
+
+ // Enable verbose logging
+ pb.command().add("-logfile");
+ pb.command().add(
+ new File(new File(workingDir, "logs"), "detail.log")
+ .getAbsolutePath());
+
+ if (securityDir != null) {
+ pb.command().add(CREDENTIAL_MANAGER_DIRECTORY);
+ pb.command().add(securityDir.getAbsolutePath());
+ out.println("security dir location: " + securityDir);
+ }
+ if (password != null) {
+ pb.command().add(CREDENTIAL_MANAGER_PASSWORD);
+ out.println("password of length " + password.length
+ + " will be written to subprocess stdin");
+ }
+
+ // Add arguments denoting inputs
+ if (inputBaclava != null) {
+ pb.command().add("-inputdoc");
+ pb.command().add(inputBaclava.getAbsolutePath());
+ if (!inputBaclava.exists())
+ throw new IOException("input baclava file doesn't exist");
+ } else {
+ for (Entry<String, File> port : inputFiles.entrySet()) {
+ if (port.getValue() == null)
+ continue;
+ pb.command().add("-inputfile");
+ pb.command().add(port.getKey());
+ pb.command().add(port.getValue().getAbsolutePath());
+ if (!port.getValue().exists())
+ throw new IOException("input file for port \"" + port
+ + "\" doesn't exist");
+ }
+ for (Entry<String, String> port : inputValues.entrySet()) {
+ if (port.getValue() == null)
+ continue;
+ pb.command().add("-inputfile");
+ pb.command().add(port.getKey());
+ File f = createTempFile(".tav_in_", null, workingDir);
+ pb.command().add(f.getAbsolutePath());
+ write(f, port.getValue(), "UTF-8");
+ }
+ for (Entry<String, String> delim : inputDelimiters.entrySet()) {
+ if (delim.getValue() == null)
+ continue;
+ pb.command().add("-inputdelimiter");
+ pb.command().add(delim.getKey());
+ pb.command().add(delim.getValue());
+ }
+ }
+
+ // Add arguments denoting outputs
+ if (outputBaclava != null) {
+ pb.command().add("-outputdoc");
+ pb.command().add(outputBaclava.getAbsolutePath());
+ if (!outputBaclava.getParentFile().exists())
+ throw new IOException(
+ "parent directory of output baclava file does not exist");
+ if (outputBaclava.exists())
+ throw new IOException("output baclava file exists");
+ // Provenance cannot be supported when using baclava output
+ } else {
+ File out = new File(workingDir, "out");
+ if (!out.mkdir())
+ throw new IOException("failed to make output directory \"out\"");
+ // Taverna needs the dir to *not* exist now
+ forceDelete(out);
+ pb.command().add("-outputdir");
+ pb.command().add(out.getAbsolutePath());
+ // Enable provenance generation
+ if (generateProvenance) {
+ pb.command().add("-embedded");
+ pb.command().add("-provenance");
+ pb.command().add("-provbundle");
+ pb.command().add("out.bundle.zip");
+ }
+ }
+
+ // Add an argument holding the workflow
+ File tmp = createTempFile(".wf_", ".scufl2", workingDir);
+ try (OutputStream os = new FileOutputStream(tmp)) {
+ os.write(workflow);
+ }
+ pb.command().add(workflowFile.getAbsolutePath());
+
+ // Indicate what working directory to use
+ pb.directory(workingDir);
+ wd = workingDir;
+
+ Map<String, String> env = pb.environment();
+ for (String name : ENVIRONMENT_TO_REMOVE)
+ env.remove(name);
+
+ // Merge any options we have had imposed on us from outside
+ env.putAll(environment);
+
+ // Patch the environment to deal with TAVUTILS-17
+ assert env.get("PATH") != null;
+ env.put("PATH", new File(System.getProperty("java.home"), "bin")
+ + pathSeparator + env.get("PATH"));
+ // Patch the environment to deal with TAVSERV-189
+ env.put("TAVERNA_APPHOME", workingDir.getCanonicalPath());
+ // Patch the environment to deal with TAVSERV-224
+ env.put("TAVERNA_RUN_ID", token);
+ if (interactionHost != null || local.interactionFeedURL != null
+ || local.webdavURL != null) {
+ env.put("INTERACTION_HOST", makeInterHost(local.interactionFeedURL));
+ env.put("INTERACTION_PORT", makeInterPort(local.interactionFeedURL));
+ env.put("INTERACTION_FEED", makeInterPath(local.interactionFeedURL));
+ env.put("INTERACTION_WEBDAV",
+ local.webdavURL != null ? local.webdavURL.getPath()
+ : interactionWebdavPath);
+ String pub = makeInterPublish(local.publishURL);
+ if (pub != null && !pub.isEmpty())
+ env.put("INTERACTION_PUBLISH", pub);
+ }
+ return pb;
+ }
+
+ @Nullable
+ private static String makeInterHost(@Nullable URL url) {
+ if (url == null)
+ return interactionHost;
+ return url.getProtocol() + "://" + url.getHost();
+ }
+
+ @Nullable
+ private static String makeInterPort(@Nullable URL url) {
+ if (url == null)
+ return interactionPort;
+ int port = url.getPort();
+ if (port == -1)
+ port = url.getDefaultPort();
+ return Integer.toString(port);
+ }
+
+ @Nullable
+ private static String makeInterPublish(@Nullable URL url)
+ throws IOException {
+ if (url == null)
+ return null;
+ try {
+ URI uri = url.toURI();
+ int port = uri.getPort();
+ if (port == -1)
+ return uri.getScheme() + "://" + uri.getHost();
+ else
+ return uri.getScheme() + "://" + uri.getHost() + ":" + port;
+ } catch (URISyntaxException e) {
+ throw new IOException("problem constructing publication url", e);
+ }
+ }
+
+ @Nullable
+ private static String makeInterPath(@Nullable URL url) {
+ if (url == null)
+ return interactionFeedPath;
+ return url.getPath();
+ }
+
+ /**
+ * Kills off the subprocess if it exists and is alive.
+ */
+ @Override
+ public void killWorker() {
+ if (!finished && subprocess != null) {
+ final Holder<Integer> code = new Holder<>();
+ for (TimingOutTask tot : new TimingOutTask[] { new TimingOutTask() {
+ /** Check if the workflow terminated of its own accord */
+ @Override
+ public void doIt() throws IOException {
+ code.value = subprocess.exitValue();
+ accounting.runCeased();
+ buildUR(code.value == 0 ? Completed : Failed, code.value);
+ }
+ }, new TimingOutTask() {
+ /** Tell the workflow to stop */
+ @Override
+ public void doIt() throws IOException {
+ code.value = killNicely();
+ accounting.runCeased();
+ buildUR(code.value == 0 ? Completed : Aborted, code.value);
+ }
+ }, new TimingOutTask() {
+ /** Kill the workflow, kill it with fire */
+ @Override
+ public void doIt() throws IOException {
+ code.value = killHard();
+ accounting.runCeased();
+ buildUR(code.value == 0 ? Completed : Aborted, code.value);
+ }
+ } }) {
+ try {
+ tot.doOrTimeOut(DEATH_TIME);
+ } catch (Exception e) {
+ }
+ if (code.value != null)
+ break;
+ }
+ finished = true;
+ setExitCode(code.value);
+ readyToSendEmail = true;
+ }
+ }
+
+ /**
+ * Integrated spot to handle writing/logging of the exit code.
+ *
+ * @param code
+ * The exit code.
+ */
+ private void setExitCode(int code) {
+ exitCode = code;
+ if (code > 256 - 8) {
+ out.println("workflow aborted, Raven issue = " + (code - 256));
+ } else if (code > 128) {
+ out.println("workflow aborted, signal=" + (code - 128));
+ } else {
+ out.println("workflow exited, code=" + code);
+ }
+ }
+
+ @Nonnull
+ private JobUsageRecord newUR() throws DatatypeConfigurationException {
+ try {
+ if (wd != null)
+ return new JobUsageRecord(wd.getName());
+ } catch (RuntimeException e) {
+ }
+ return new JobUsageRecord("unknown");
+ }
+
+ /**
+ * Fills in the accounting information from the exit code and stderr.
+ *
+ * @param exitCode
+ * The exit code from the program.
+ */
+ private void buildUR(@Nonnull Status status, int exitCode) {
+ try {
+ Date now = new Date();
+ long user = -1, sys = -1, real = -1;
+ Matcher m = TimeRE.matcher(stderr.toString());
+ ur = newUR();
+ while (m.find())
+ for (int i = 1; i < 6; i += 2)
+ if (m.group(i + 1).equals("user"))
+ user = parseDuration(m.group(i));
+ else if (m.group(i + 1).equals("sys")
+ || m.group(i + 1).equals("system"))
+ sys = parseDuration(m.group(i));
+ else if (m.group(i + 1).equals("real")
+ || m.group(i + 1).equals("elapsed"))
+ real = parseDuration(m.group(i));
+ if (user != -1)
+ ur.addCpuDuration(user).setUsageType("user");
+ if (sys != -1)
+ ur.addCpuDuration(sys).setUsageType("system");
+ ur.addUser(System.getProperty("user.name"), null);
+ ur.addStartAndEnd(start, now);
+ if (real != -1)
+ ur.addWallDuration(real);
+ else
+ ur.addWallDuration(now.getTime() - start.getTime());
+ ur.setStatus(status.toString());
+ ur.addHost(getLocalHost().getHostName());
+ ur.addResource("exitcode", Integer.toString(exitCode));
+ ur.addDisk(sizeOfDirectory(wd)).setStorageUnit("B");
+ if (urreceiver != null)
+ urreceiver.acceptUsageRecord(ur.marshal());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private long parseDuration(@Nonnull String durationString) {
+ try {
+ return (long) (parseDouble(durationString) * 1000);
+ } catch (NumberFormatException nfe) {
+ // Not a double; maybe MM:SS.mm or HH:MM:SS.mm
+ }
+ long dur = 0;
+ for (String d : durationString.split(":"))
+ try {
+ dur = 60 * dur + parseLong(d);
+ } catch (NumberFormatException nfe) {
+ // Assume that only one thing is fractional, and that it is last
+ return 60000 * dur + (long) (parseDouble(d) * 1000);
+ }
+ return dur * 1000;
+ }
+
+ private void signal(@Nonnull String signal) throws Exception {
+ int pid = getPID();
+ if (pid > 0
+ && getRuntime().exec("kill -" + signal + " " + pid).waitFor() == 0)
+ return;
+ throw new Exception("failed to send signal " + signal + " to process "
+ + pid);
+ }
+
+ @Nullable
+ private Integer killNicely() {
+ try {
+ signal("TERM");
+ return subprocess.waitFor();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Nullable
+ private Integer killHard() {
+ try {
+ signal("QUIT");
+ return subprocess.waitFor();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Move the worker out of the stopped state and back to operating.
+ *
+ * @throws Exception
+ * if it fails.
+ */
+ @Override
+ public void startWorker() throws Exception {
+ signal("CONT");
+ stopped = false;
+ }
+
+ /**
+ * Move the worker into the stopped state from the operating state.
+ *
+ * @throws Exception
+ * if it fails.
+ */
+ @Override
+ public void stopWorker() throws Exception {
+ signal("STOP");
+ stopped = true;
+ }
+
+ /**
+ * @return The status of the workflow run. Note that this can be an
+ * expensive operation.
+ */
+ @Override
+ public RemoteStatus getWorkerStatus() {
+ if (subprocess == null)
+ return Initialized;
+ if (finished)
+ return Finished;
+ try {
+ setExitCode(subprocess.exitValue());
+ } catch (IllegalThreadStateException e) {
+ if (stopped)
+ return Stopped;
+ return Operating;
+ }
+ finished = true;
+ readyToSendEmail = true;
+ accounting.runCeased();
+ buildUR(exitCode.intValue() == 0 ? Completed : Failed, exitCode);
+ return Finished;
+ }
+
+ @Override
+ public String getConfiguration() {
+ return "";
+ }
+
+ @Override
+ public String getName() {
+ return DEFAULT_LISTENER_NAME;
+ }
+
+ @Override
+ public String getProperty(String propName) throws RemoteException {
+ switch (Property.is(propName)) {
+ case STDOUT:
+ return stdout.toString();
+ case STDERR:
+ return stderr.toString();
+ case EXIT_CODE:
+ return (exitCode == null) ? "" : exitCode.toString();
+ case EMAIL:
+ return emailAddress;
+ case READY_TO_NOTIFY:
+ return Boolean.toString(readyToSendEmail);
+ case USAGE:
+ try {
+ JobUsageRecord toReturn;
+ if (subprocess == null) {
+ toReturn = newUR();
+ toReturn.setStatus(Held.toString());
+ } else if (ur == null) {
+ toReturn = newUR();
+ toReturn.setStatus(Started.toString());
+ toReturn.addStartAndEnd(start, new Date());
+ toReturn.addUser(System.getProperty("user.name"), null);
+ } else {
+ toReturn = ur;
+ }
+ /*
+ * Note that this record is not to be pushed to the server. That
+ * is done elsewhere (when a proper record is produced)
+ */
+ return toReturn.marshal();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return "";
+ }
+ default:
+ throw new RemoteException("unknown property");
+ }
+ }
+
+ @Override
+ public String getType() {
+ return DEFAULT_LISTENER_NAME;
+ }
+
+ @Override
+ public String[] listProperties() {
+ return Property.names();
+ }
+
+ @Override
+ public void setProperty(String propName, String value)
+ throws RemoteException {
+ switch (Property.is(propName)) {
+ case EMAIL:
+ emailAddress = value;
+ return;
+ case READY_TO_NOTIFY:
+ readyToSendEmail = parseBoolean(value);
+ return;
+ case STDOUT:
+ case STDERR:
+ case EXIT_CODE:
+ case USAGE:
+ throw new RemoteException("property is read only");
+ default:
+ throw new RemoteException("unknown property");
+ }
+ }
+
+ @Override
+ public RemoteListener getDefaultListener() {
+ return this;
+ }
+
+ @Override
+ public void setURReceiver(@Nonnull UsageRecordReceiver receiver) {
+ urreceiver = receiver;
+ }
+
+ @Override
+ public void deleteLocalResources() throws ImplementationException {
+ try {
+ if (workflowFile != null && workflowFile.getParentFile().exists())
+ forceDelete(workflowFile);
+ } catch (IOException e) {
+ throw new ImplementationException("problem deleting workflow file",
+ e);
+ }
+ }
+}
+
+/**
+ * An engine for asynchronously copying from an {@link InputStream} to a
+ * {@link Writer}.
+ *
+ * @author Donal Fellows
+ */
+class AsyncCopy extends Thread {
+ @Nonnull
+ private BufferedReader from;
+ @Nonnull
+ private Writer to;
+ @Nullable
+ private Holder<Integer> pidHolder;
+
+ AsyncCopy(@Nonnull InputStream from, @Nonnull Writer to)
+ throws UnsupportedEncodingException {
+ this(from, to, null);
+ }
+
+ AsyncCopy(@Nonnull InputStream from, @Nonnull Writer to,
+ @Nullable Holder<Integer> pid) throws UnsupportedEncodingException {
+ this.from = new BufferedReader(new InputStreamReader(from,
+ SYSTEM_ENCODING));
+ this.to = to;
+ this.pidHolder = pid;
+ setDaemon(true);
+ start();
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (pidHolder != null) {
+ String line = from.readLine();
+ if (line.matches("^pid:\\d+$"))
+ synchronized (pidHolder) {
+ pidHolder.value = parseInt(line.substring(4));
+ }
+ else
+ to.write(line + System.getProperty("line.separator"));
+ }
+ copy(from, to);
+ } catch (IOException e) {
+ }
+ }
+}
+
+/**
+ * A helper for asynchronously writing a password to a subprocess's stdin.
+ *
+ * @author Donal Fellows
+ */
+class PasswordWriterThread extends Thread {
+ private OutputStream to;
+ private char[] chars;
+
+ PasswordWriterThread(@Nonnull Process to, @Nonnull char[] chars) {
+ this.to = to.getOutputStream();
+ assert chars != null;
+ this.chars = chars;
+ setDaemon(true);
+ start();
+ }
+
+ @Override
+ public void run() {
+ try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(to,
+ SYSTEM_ENCODING))) {
+ pw.println(chars);
+ } catch (UnsupportedEncodingException e) {
+ // Not much we can do here
+ e.printStackTrace();
+ } finally {
+ /*
+ * We don't trust GC to clear password from memory. We also take
+ * care not to clear the default password!
+ */
+ if (chars != KEYSTORE_PASSWORD)
+ Arrays.fill(chars, '\00');
+ }
+ }
+}
+
+enum Property {
+ STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
+ "readyToNotify"), EMAIL("notificationAddress"), USAGE("usageRecord");
+
+ private String s;
+
+ private Property(String s) {
+ this.s = s;
+ pmap.put(s, this);
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+
+ public static Property is(@Nonnull String s) {
+ return pmap.get(s);
+ }
+
+ @Nonnull
+ public static String[] names() {
+ return pmap.keySet().toArray(new String[pmap.size()]);
+ }
+}
+
+enum Status {
+ Aborted, Completed, Failed, Held, Queued, Started, Suspended
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
new file mode 100644
index 0000000..fbc3a72
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Utility class that handles filename validation on different target platforms.
+ *
+ * @author Donal Fellows.
+ */
+public abstract class FilenameVerifier {
+ private FilenameVerifier(){}
+
+ static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
+
+ @SuppressWarnings("serial")
+ private static final Set<String> ILLEGAL_NAMES = new HashSet<String>(){{
+ add("");
+ add("..");
+ add(".");
+ if (IS_WINDOWS) {
+ add("con");
+ add("prn");
+ add("nul");
+ add("aux");
+ for (int i = 1; i <= 9; i++) {
+ add("com" + i);
+ add("lpt" + i);
+ }
+ }
+ }};
+ @SuppressWarnings("serial")
+ private static final Set<Character> ILLEGAL_CHARS = new HashSet<Character>(){{
+ add('/');
+ for (char i=0 ; i<32 ; i++)
+ add(i);
+ if (IS_WINDOWS) {
+ add('\\');
+ add('>');
+ add('<');
+ add(':');
+ add('"');
+ add('|');
+ add('?');
+ add('*');
+ } else {
+ add(' '); // whitespace; too much trouble from these
+ add('\t');
+ add('\r');
+ add('\n');
+ }
+ }};
+ @SuppressWarnings("serial")
+ private static final Set<String> ILLEGAL_PREFIXES = new HashSet<String>(){{
+ if (IS_WINDOWS) {
+ add("con.");
+ add("prn.");
+ add("nul.");
+ add("aux.");
+ for (int i = 1; i <= 9; i++) {
+ add("com" + i + ".");
+ add("lpt" + i + ".");
+ }
+ }
+ }};
+ @SuppressWarnings("serial")
+ private static final Set<String> ILLEGAL_SUFFIXES = new HashSet<String>(){{
+ if (IS_WINDOWS) {
+ add(" ");
+ add(".");
+ }
+ }};
+
+ /**
+ * Construct a file handle, applying platform-specific filename validation
+ * rules in the process.
+ *
+ * @param dir
+ * The directory acting as a root, which is assumed to be
+ * correctly named. May be <tt>null</tt>.
+ * @param names
+ * The names of filename fragments to apply the checks to. Must
+ * have at least one value.
+ * @return The file handle. Never <tt>null</tt>.
+ * @throws IOException
+ * If validation fails.
+ */
+ public static File getValidatedFile(File dir, String... names)
+ throws IOException {
+ if (names.length == 0)
+ throw new IOException("empty filename");
+ File f = dir;
+ for (String name : names) {
+ String low = name.toLowerCase();
+ if (ILLEGAL_NAMES.contains(low))
+ throw new IOException("illegal filename");
+ for (char c : ILLEGAL_CHARS)
+ if (low.indexOf(c) >= 0)
+ throw new IOException("illegal filename");
+ for (String s : ILLEGAL_PREFIXES)
+ if (low.startsWith(s))
+ throw new IOException("illegal filename");
+ for (String s : ILLEGAL_SUFFIXES)
+ if (low.endsWith(s))
+ throw new IOException("illegal filename");
+ f = new File(f, name);
+ }
+ assert f != null;
+ return f;
+ }
+
+ /**
+ * Create a file handle where the underlying file must exist.
+ *
+ * @param dir
+ * The directory that will contain the file.
+ * @param name
+ * The name of the file; will be validated.
+ * @return The handle.
+ * @throws IOException
+ * If validation fails or the file doesn't exist.
+ */
+ public static File getValidatedExistingFile(File dir, String name)
+ throws IOException {
+ File f = getValidatedFile(dir, name);
+ if (!f.exists())
+ throw new IOException("doesn't exist");
+ return f;
+ }
+
+ /**
+ * Create a file handle where the underlying file must <i>not</i> exist.
+ *
+ * @param dir
+ * The directory that will contain the file.
+ * @param name
+ * The name of the file; will be validated.
+ * @return The handle. The file will not be created by this method.
+ * @throws IOException
+ * If validation fails or the file does exist.
+ */
+ public static File getValidatedNewFile(File dir, String name)
+ throws IOException {
+ File f = getValidatedFile(dir, name);
+ if (f.exists())
+ throw new IOException("already exists");
+ return f;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
new file mode 100644
index 0000000..3dd3ac1
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
@@ -0,0 +1,40 @@
+package org.taverna.server.localworker.impl.utils;
+
+import javax.annotation.Nullable;
+
+/**
+ * A class that handles running a task that can take some time.
+ *
+ * @author Donal Fellows
+ *
+ */
+public abstract class TimingOutTask extends Thread {
+ public abstract void doIt() throws Exception;
+
+ @Nullable
+ private Exception ioe;
+
+ @Override
+ public final void run() {
+ try {
+ doIt();
+ } catch (Exception ioe) {
+ this.ioe = ioe;
+ }
+ }
+
+ public TimingOutTask() {
+ this.setDaemon(true);
+ }
+
+ public void doOrTimeOut(long timeout) throws Exception {
+ start();
+ try {
+ join(timeout);
+ } catch (InterruptedException e) {
+ interrupt();
+ }
+ if (ioe != null)
+ throw ioe;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/resources/security.policy
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/resources/security.policy b/taverna-server-worker/src/main/resources/security.policy
new file mode 100644
index 0000000..5b5c322
--- /dev/null
+++ b/taverna-server-worker/src/main/resources/security.policy
@@ -0,0 +1,11 @@
+//keystore "signers.jks";
+//grant signedBy "taverna" {
+// permission java.util.PropertyPermission "*", "read,write";
+// permission java.lang.RuntimePermission "shutdownHooks";
+// permission java.lang.RuntimePermission "exitVM";
+// permission java.io.FilePermission "<<ALL FILES>>", "read,write,execute,delete";
+// permission java.net.SocketPermission "localhost:1024-" "accept,connect,listen";
+//};
+grant {
+ permission java.security.AllPermission "*:*";
+};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java b/taverna-server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
new file mode 100644
index 0000000..7bcd92e
--- /dev/null
+++ b/taverna-server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl;
+
+import static java.util.UUID.randomUUID;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.taverna.server.localworker.impl.LocalWorker.DO_MKDIR;
+
+import java.io.File;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.taverna.server.localworker.api.Worker;
+import org.taverna.server.localworker.api.WorkerFactory;
+import org.taverna.server.localworker.remote.IllegalStateTransitionException;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.localworker.remote.RemoteDirectory;
+import org.taverna.server.localworker.remote.RemoteInput;
+import org.taverna.server.localworker.remote.RemoteListener;
+import org.taverna.server.localworker.remote.RemoteStatus;
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+
+public class LocalWorkerTest {
+ LocalWorker lw;
+ static List<String> events;
+
+ public static RemoteStatus returnThisStatus = RemoteStatus.Operating;
+
+ static class DummyWorker implements Worker {
+ @Override
+ public RemoteListener getDefaultListener() {
+ return new RemoteListener() {
+ @Override
+ public String getConfiguration() {
+ return "RLCONFIG";
+ }
+
+ @Override
+ public String getName() {
+ return "RLNAME";
+ }
+
+ @Override
+ public String getProperty(String propName) {
+ return "RLPROP[" + propName + "]";
+ }
+
+ @Override
+ public String getType() {
+ return "RLTYPE";
+ }
+
+ @Override
+ public String[] listProperties() {
+ return new String[] { "RLP1", "RLP2" };
+ }
+
+ @Override
+ public void setProperty(String propName, String value) {
+ events.add("setProperty[");
+ events.add(propName);
+ events.add(value);
+ events.add("]");
+ }
+ };
+ }
+
+ @Override
+ public RemoteStatus getWorkerStatus() {
+ events.add("status=" + returnThisStatus);
+ return returnThisStatus;
+ }
+
+ @Override
+ public boolean initWorker(LocalWorker local,
+ String executeWorkflowCommand, byte[] workflow,
+ File workingDir, File inputBaclava,
+ Map<String, File> inputFiles, Map<String, String> inputValues,
+ Map<String, String> delimiters, File outputBaclava, File cmdir,
+ char[] cmpass, boolean doprov, Map<String, String> env,
+ String id, List<String> conf) throws Exception {
+ events.add("init[");
+ events.add(executeWorkflowCommand);
+ events.add(new String(workflow, "UTF-8"));
+ int dirLen = workingDir.getName().length();
+ events.add(Integer.toString(dirLen));
+ events.add(inputBaclava == null ? "<null>" : inputBaclava
+ .toString().substring(dirLen));
+ Map<String, String> in = new TreeMap<>();
+ for (Entry<String, File> name : inputFiles.entrySet())
+ in.put(name.getKey(), name.getValue() == null ? "<null>" : name
+ .getValue().getName());
+ events.add(in.toString());
+ events.add(new TreeMap<>(inputValues).toString());
+ events.add(outputBaclava == null ? "<null>" : outputBaclava
+ .getName());
+ // TODO: check cmdir and cmpass
+ // TODO: check doprov
+ // TODO: log env
+ // TODO: check delimiters
+ events.add("]");
+ return true;
+ }
+
+ @Override
+ public void killWorker() throws Exception {
+ events.add("kill");
+ }
+
+ @Override
+ public void startWorker() throws Exception {
+ events.add("start");
+ }
+
+ @Override
+ public void stopWorker() throws Exception {
+ events.add("stop");
+ }
+
+ @Override
+ public void setURReceiver(UsageRecordReceiver receiver) {
+ // We just ignore this
+ }
+
+ @Override
+ public void deleteLocalResources() throws ImplementationException {
+ // Nothing to do here
+ }
+ }
+
+ WorkerFactory factory = new WorkerFactory() {
+ @Override
+ public Worker makeInstance() throws Exception {
+ return new DummyWorker();
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ lw = new LocalWorker("XWC", "WF".getBytes("UTF-8"), null, randomUUID(),
+ new HashMap<String, String>(), new ArrayList<String>(), factory);
+ events = new ArrayList<>();
+ returnThisStatus = RemoteStatus.Operating;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ lw.destroy();
+ }
+
+ private List<String> l(String... strings) {
+ return Arrays.asList(strings);
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ @Test
+ public void testDestroy1() throws Exception {
+ lw.destroy();
+ assertEquals(l(), events);
+ }
+
+ @Test
+ public void testDestroy2() throws Exception {
+ lw.setStatus(RemoteStatus.Operating);
+ lw.destroy();
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "kill"), events);
+ }
+
+ @Test
+ public void testDestroy3() throws Exception {
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Stopped);
+ lw.destroy();
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "stop", "kill"), events);
+ }
+
+ @Test
+ public void testDestroy4() throws Exception {
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Finished);
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "kill"), events);
+ lw.destroy();
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "kill"), events);
+ }
+
+ @Test
+ public void testAddListener() {
+ Throwable t = null;
+ try {
+ lw.addListener(null);
+ } catch (Throwable caught) {
+ t = caught;
+ }
+ assertNotNull(t);
+ assertSame(ImplementationException.class, t.getClass());
+ assertNotNull(t.getMessage());
+ assertEquals("not implemented", t.getMessage());
+ }
+
+ @Test
+ public void testGetInputBaclavaFile() throws Exception {
+ assertNull(lw.getInputBaclavaFile());
+ lw.setInputBaclavaFile("IBaclava");
+ assertNotNull(lw.getInputBaclavaFile());
+ assertEquals("IBaclava", lw.getInputBaclavaFile());
+ lw.makeInput("FOO").setValue("BAR");
+ assertNull(lw.getInputBaclavaFile());
+ }
+
+ @Test
+ public void testGetInputsWithValue() throws Exception {
+ assertEquals(0, lw.getInputs().size());
+
+ lw.makeInput("FOO").setValue("BAR");
+
+ assertEquals(1, lw.getInputs().size());
+ assertEquals("FOO", lw.getInputs().get(0).getName());
+ assertNull(lw.getInputs().get(0).getFile());
+ assertNotNull(lw.getInputs().get(0).getValue());
+
+ lw.setInputBaclavaFile("BLAH");
+
+ assertEquals(1, lw.getInputs().size());
+ assertNull(lw.getInputs().get(0).getFile());
+ assertNull(lw.getInputs().get(0).getValue());
+ }
+
+ @Test
+ public void testGetInputsWithFile() throws Exception {
+ assertEquals(0, lw.getInputs().size());
+
+ lw.makeInput("BAR").setFile("FOO");
+
+ assertEquals(1, lw.getInputs().size());
+ assertEquals("BAR", lw.getInputs().get(0).getName());
+ assertNotNull(lw.getInputs().get(0).getFile());
+ assertNull(lw.getInputs().get(0).getValue());
+
+ lw.setInputBaclavaFile("BLAH");
+
+ assertEquals(1, lw.getInputs().size());
+ assertNull(lw.getInputs().get(0).getFile());
+ assertNull(lw.getInputs().get(0).getValue());
+ }
+
+ @Test
+ public void testGetListenerTypes() {
+ assertEquals("[]", lw.getListenerTypes().toString());
+ }
+
+ @Test
+ public void testGetListeners() throws Exception {
+ assertEquals(1, lw.getListeners().size());
+ RemoteListener rl = lw.getListeners().get(0);
+ assertEquals("RLNAME", rl.getName());
+ assertEquals("RLCONFIG", rl.getConfiguration());
+ assertEquals("RLTYPE", rl.getType());
+ assertEquals("[RLP1, RLP2]", Arrays.asList(rl.listProperties())
+ .toString());
+ assertEquals("RLPROP[RLP1]", rl.getProperty("RLP1"));
+ assertEquals("RLPROP[RLP2]", rl.getProperty("RLP2"));
+ rl.setProperty("FOOBAR", "BARFOO");
+ assertEquals(l("setProperty[", "FOOBAR", "BARFOO", "]"), events);
+ }
+
+ @Test
+ public void testGetOutputBaclavaFile() throws Exception {
+ assertNull(lw.getOutputBaclavaFile());
+ lw.setOutputBaclavaFile("notnull");
+ assertEquals("notnull", lw.getOutputBaclavaFile());
+ lw.setOutputBaclavaFile(null);
+ assertNull(lw.getOutputBaclavaFile());
+ }
+
+ @Test
+ public void testGetSecurityContext() throws Exception {
+ boolean md = DO_MKDIR;
+ LocalWorker.DO_MKDIR = false; // HACK! Work around Hudson problem...
+ try {
+ assertNotNull(lw.getSecurityContext());
+ } finally {
+ LocalWorker.DO_MKDIR = md;
+ }
+ }
+
+ @Test
+ public void testGetStatusInitial() {
+ assertEquals(RemoteStatus.Initialized, lw.getStatus());
+ }
+
+ @Test
+ public void testGetStatus() throws Exception {
+ assertEquals(RemoteStatus.Initialized, lw.getStatus());
+ returnThisStatus = RemoteStatus.Operating;
+ assertEquals(RemoteStatus.Initialized, lw.getStatus());
+ lw.setStatus(RemoteStatus.Operating);
+ assertEquals(RemoteStatus.Operating, lw.getStatus());
+ assertEquals(RemoteStatus.Operating, lw.getStatus());
+ returnThisStatus = RemoteStatus.Finished;
+ assertEquals(RemoteStatus.Finished, lw.getStatus());
+ returnThisStatus = RemoteStatus.Stopped;
+ assertEquals(RemoteStatus.Finished, lw.getStatus());
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "status=Operating", "status=Operating",
+ "status=Finished"), events);
+ }
+
+ @Test
+ public void testGetWorkingDirectory() throws Exception {
+ RemoteDirectory rd = lw.getWorkingDirectory();
+ assertNotNull(rd);
+ assertNotNull(rd.getContents());
+ assertNull(rd.getContainingDirectory());
+ assertNotNull(rd.getName());
+ assertEquals(-1, rd.getName().indexOf('/'));
+ assertFalse("..".equals(rd.getName()));
+ assertEquals("", rd.getName());
+ }
+
+ @Test
+ public void testValidateFilename() throws Exception {
+ lw.validateFilename("foobar");
+ lw.validateFilename("foo/bar");
+ lw.validateFilename("foo.bar");
+ lw.validateFilename("foo..bar");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidateFilenameBad0() throws Exception {
+ lw.validateFilename("./.");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidateFilenameBad1() throws Exception {
+ lw.validateFilename("/");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidateFilenameBad2() throws Exception {
+ lw.validateFilename("");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidateFilenameBad3() throws Exception {
+ lw.validateFilename(null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidateFilenameBad4() throws Exception {
+ lw.validateFilename("..");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testValidateFilenameBad5() throws Exception {
+ lw.validateFilename("foo/../bar");
+ }
+
+ @Test
+ public void testMakeInput() throws Exception {
+ assertEquals(0, lw.getInputs().size());
+
+ RemoteInput ri = lw.makeInput("TEST");
+
+ assertNotNull(ri);
+ assertEquals(1, lw.getInputs().size());
+ assertNotSame(ri, lw.getInputs().get(0)); // different delegates
+ assertEquals("TEST", ri.getName());
+ assertNull(ri.getFile());
+ assertNull(ri.getValue());
+
+ lw.setInputBaclavaFile("bad");
+ ri.setFile("good");
+ assertEquals("good", ri.getFile());
+ assertNull(lw.getInputBaclavaFile());
+ ri.setValue("very good");
+ assertEquals("very good", ri.getValue());
+ assertNull(ri.getFile());
+ assertNull(lw.getInputBaclavaFile());
+
+ lw.makeInput("TEST2");
+ assertEquals(2, lw.getInputs().size());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMakeInputFileSanity() throws Exception {
+ lw.makeInput("foo").setFile("/../bar");
+ }
+
+ @Test
+ public void testMakeListener() {
+ Throwable t = null;
+ try {
+ lw.makeListener("?", "?");
+ } catch (Throwable caught) {
+ t = caught;
+ }
+ assertNotNull(t);
+ assertSame(RemoteException.class, t.getClass());
+ assertNotNull(t.getMessage());
+ assertEquals("listener manufacturing unsupported", t.getMessage());
+ }
+
+ @Test
+ public void testSetInputBaclavaFile1() throws Exception {
+ assertNull(lw.getInputBaclavaFile());
+ lw.setInputBaclavaFile("eg");
+ assertEquals("eg", lw.getInputBaclavaFile());
+ }
+
+ @Test
+ public void testSetInputBaclavaFile2() throws Exception {
+ RemoteInput ri = lw.makeInput("foo");
+ ri.setValue("bar");
+ assertEquals("bar", ri.getValue());
+ lw.setInputBaclavaFile("eg");
+ assertNull(ri.getValue());
+ }
+
+ @Test
+ public void testSetOutputBaclavaFile1() throws Exception {
+ assertNull(lw.outputBaclava);
+ lw.setOutputBaclavaFile("foobar");
+ assertEquals("foobar", lw.outputBaclava);
+ assertEquals("foobar", lw.getOutputBaclavaFile());
+ lw.setOutputBaclavaFile("foo/bar");
+ assertEquals("foo/bar", lw.outputBaclava);
+ assertEquals("foo/bar", lw.getOutputBaclavaFile());
+ lw.setOutputBaclavaFile(null);
+ assertNull(lw.outputBaclava);
+ assertNull(lw.getOutputBaclavaFile());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetOutputBaclavaFile2() throws Exception {
+ lw.setOutputBaclavaFile("/foobar");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetOutputBaclavaFile3() throws Exception {
+ lw.setOutputBaclavaFile("foo/../bar");
+ }
+
+ @Test
+ public void testSetStatus0() throws Exception {
+ lw.setStatus(RemoteStatus.Initialized);
+ lw.setStatus(RemoteStatus.Initialized);
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Stopped);
+ lw.setStatus(RemoteStatus.Stopped);
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Finished);
+ lw.setStatus(RemoteStatus.Finished);
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "stop", "start", "kill"), events);
+ }
+
+ @Test
+ public void testSetStatus1() throws Exception {
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Stopped);
+ lw.setStatus(RemoteStatus.Finished);
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
+ "]", "stop", "kill"), events);
+ }
+
+ @Test
+ public void testSetStatus2() throws Exception {
+ lw.setStatus(RemoteStatus.Initialized);
+ lw.setStatus(RemoteStatus.Finished);
+ assertEquals(l(), events);
+ }
+
+ @Test(expected = IllegalStateTransitionException.class)
+ public void testSetStatus3() throws Exception {
+ lw.setStatus(RemoteStatus.Initialized);
+ lw.setStatus(RemoteStatus.Finished);
+ lw.setStatus(RemoteStatus.Initialized);
+ }
+
+ @Test(expected = IllegalStateTransitionException.class)
+ public void testSetStatus4() throws Exception {
+ lw.setStatus(RemoteStatus.Initialized);
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Initialized);
+ }
+
+ @Test(expected = IllegalStateTransitionException.class)
+ public void testSetStatus5() throws Exception {
+ lw.setStatus(RemoteStatus.Initialized);
+ lw.setStatus(RemoteStatus.Stopped);
+ }
+
+ @Test(expected = IllegalStateTransitionException.class)
+ public void testSetStatus6() throws Exception {
+ lw.setStatus(RemoteStatus.Finished);
+ lw.setStatus(RemoteStatus.Stopped);
+ }
+
+ @Test(expected = IllegalStateTransitionException.class)
+ public void testSetStatus7() throws Exception {
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Stopped);
+ lw.setStatus(RemoteStatus.Initialized);
+ }
+
+ @Test
+ public void testLifecycle() throws Exception {
+ lw.makeInput("foo").setFile("foofile");
+ lw.makeInput("bar").setValue("barvalue");
+ lw.setOutputBaclavaFile("spong");
+ lw.setOutputBaclavaFile("boo");
+ lw.setStatus(RemoteStatus.Operating);
+ lw.setStatus(RemoteStatus.Finished);
+ // Assumes order of map, so fragile but works...
+ assertEquals(
+ l("init[", "XWC", "WF", "36", "<null>",
+ "{bar=<null>, foo=foofile}",
+ "{bar=barvalue, foo=null}", "boo", "]", "kill"), events);
+ }
+}
[22/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-execution-delegate/src/test/java/SerializationTest.java
----------------------------------------------------------------------
diff --git a/taverna-server-execution-delegate/src/test/java/SerializationTest.java b/taverna-server-execution-delegate/src/test/java/SerializationTest.java
new file mode 100644
index 0000000..c4bf0b9
--- /dev/null
+++ b/taverna-server-execution-delegate/src/test/java/SerializationTest.java
@@ -0,0 +1,54 @@
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.taverna.server.execution_delegate.RemoteExecution.WorkflowReportDocument;
+
+public class SerializationTest {
+ private static final boolean PRINT = true;
+ SchemaOutputResolver sink;
+ StringWriter schema;
+
+ String schema() {
+ return schema.toString();
+ }
+
+ @Before
+ public void init() {
+ schema = new StringWriter();
+ sink = new SchemaOutputResolver() {
+ @Override
+ public Result createOutput(String namespaceUri,
+ String suggestedFileName) throws IOException {
+ StreamResult sr = new StreamResult(schema);
+ sr.setSystemId("/dev/null");
+ return sr;
+ }
+ };
+ assertEquals("", schema());
+ }
+
+ @Test
+ public void testSchemaGeneration() throws JAXBException, IOException {
+ JAXBContext.newInstance(WorkflowReportDocument.class).generateSchema(
+ sink);
+ assertFalse("generated schema must be non-empty", schema().isEmpty());
+ assertTrue(
+ "generated schema must define workflowReport element",
+ schema().contains(
+ "<xs:element name=\"workflowReport\" type=\"WorkflowReport\"/>\n"));
+ if (PRINT)
+ System.out.print(schema());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/.gitignore
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/.gitignore b/taverna-server-port-description/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/taverna-server-port-description/.gitignore
@@ -0,0 +1 @@
+/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/pom.xml b/taverna-server-port-description/pom.xml
new file mode 100644
index 0000000..99582ed
--- /dev/null
+++ b/taverna-server-port-description/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-port-description</artifactId>
+ <name>Apache Taverna Server Workflow Port Descriptor Types</name>
+ <description>The structural types used to describe ports on workflows, as exported by Taverna Server.</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <projectNameTemplate>[artifactId]-[version]</projectNameTemplate>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java
new file mode 100644
index 0000000..2ea392f
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "AbsentValue")
+public class AbsentValue extends AbstractValue {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java
new file mode 100644
index 0000000..e57c4f9
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlID;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.taverna.server.port_description.utils.IntAdapter;
+
+@XmlType(name = "Port")
+public class AbstractPort {
+ @XmlID
+ @XmlAttribute(required = true)
+ public String name;
+
+ @XmlAttribute
+ @XmlSchemaType(name = "int")
+ @XmlJavaTypeAdapter(IntAdapter.class)
+ public Integer depth;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java
new file mode 100644
index 0000000..7c3fe9a
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import java.net.URI;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "PortDescription")
+public abstract class AbstractPortDescription {
+ @XmlAttribute
+ public String workflowId;
+ @XmlAttribute
+ @XmlSchemaType(name = "anyURI")
+ public URI workflowRun;
+ @XmlAttribute
+ public String workflowRunId;
+
+ public void fillInBaseData(String docId, String runId, URI runUrl) {
+ this.workflowId = docId;
+ this.workflowRun = runUrl;
+ this.workflowRunId = runId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java
new file mode 100644
index 0000000..47232c2
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import static org.taverna.server.port_description.Namespaces.XLINK;
+
+import java.net.URI;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "Value")
+@XmlSeeAlso( { ErrorValue.class, LeafValue.class, ListValue.class, AbsentValue.class })
+public abstract class AbstractValue {
+ @XmlAttribute(namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI href;
+
+ public void setAddress(URI uri, String localAddress) {
+ if (uri.getPath().endsWith("/")) {
+ href = URI.create(uri + "wd/out/" + localAddress);
+ } else {
+ href = URI.create(uri + "/wd/out/" + localAddress);
+ }
+ //about = "out/" + localAddress;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java
new file mode 100644
index 0000000..0bb07b4
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.taverna.server.port_description.utils.IntAdapter;
+
+@XmlType(name = "ErrorValue")
+public class ErrorValue extends AbstractValue {
+ @XmlAttribute
+ @XmlSchemaType(name = "int")
+ @XmlJavaTypeAdapter(IntAdapter.class)
+ public Integer depth;
+ @XmlAttribute(name = "errorFile")
+ public String fileName;
+ @XmlAttribute(name = "errorByteLength")
+ public Long byteLength;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java
new file mode 100644
index 0000000..60b9353
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import static org.taverna.server.port_description.Namespaces.XLINK;
+
+import java.net.URI;
+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.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * A description of the inputs of a workflow run, as they are currently known
+ * about.
+ *
+ * @author Donal Fellows.
+ */
+@XmlRootElement
+public class InputDescription extends AbstractPortDescription {
+ @XmlElement
+ public List<InputPort> input = new ArrayList<>();
+
+ @XmlType(name = "InputPort")
+ public static class InputPort extends AbstractPort {
+ @XmlAttribute(namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI href;
+ }
+
+ /**
+ * Add an input port to the list of ports.
+ *
+ * @param name
+ * The name of the port to add.
+ * @return The port (so that its details may be set);
+ */
+ public InputPort addPort(String name) {
+ InputPort p = new InputPort();
+ p.name = name;
+ input.add(p);
+ return p;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java
new file mode 100644
index 0000000..052c0ef
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "LeafValue")
+public class LeafValue extends AbstractValue {
+ @XmlAttribute(name = "contentFile")
+ public String fileName;
+ @XmlAttribute(name = "contentType")
+ public String contentType;
+ @XmlAttribute(name = "contentByteLength")
+ public Long byteLength;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java
new file mode 100644
index 0000000..b14cdf1
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+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.XmlElements;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.taverna.server.port_description.utils.IntAdapter;
+
+@XmlType(name = "ListValue")
+public class ListValue extends AbstractValue {
+ @XmlAttribute
+ @XmlSchemaType(name = "int")
+ @XmlJavaTypeAdapter(IntAdapter.class)
+ public Integer length;
+ @XmlElements({
+ @XmlElement(name = "value", type = LeafValue.class, nillable = false),
+ @XmlElement(name = "list", type = ListValue.class, nillable = false),
+ @XmlElement(name = "error", type = ErrorValue.class, nillable = false),
+ @XmlElement(name = "absent", type = AbsentValue.class, nillable = false) })
+ public List<AbstractValue> contents = new ArrayList<>();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java
new file mode 100644
index 0000000..4003cdb
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+public interface Namespaces {
+ static final String DATA = "http://ns.taverna.org.uk/2010/port/";
+ static final String RUN = "http://ns.taverna.org.uk/2010/run/";
+ static final String XLINK = "http://www.w3.org/1999/xlink";
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java
new file mode 100644
index 0000000..0b94973
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * A description of the outputs of a workflow run, as they are currently known
+ * about.
+ *
+ * @author Donal Fellows
+ */
+@XmlRootElement(name = "workflowOutputs")
+public class OutputDescription extends AbstractPortDescription {
+ private static final AbsentValue ABSENT_VALUE = new AbsentValue();
+ @XmlElement(name = "output")
+ public List<OutputPort> ports = new ArrayList<>();
+
+ @XmlType(name = "OutputPort")
+ public static class OutputPort extends AbstractPort {
+ @XmlElements({
+ @XmlElement(name = "value", type = LeafValue.class, nillable = false, required = true),
+ @XmlElement(name = "list", type = ListValue.class, nillable = false, required = true),
+ @XmlElement(name = "error", type = ErrorValue.class, nillable = false, required = true),
+ @XmlElement(name = "absent", type = AbsentValue.class, nillable = false, required = true) })
+ public AbstractValue output;
+ }
+
+ /**
+ * Add an output port to the list of ports.
+ *
+ * @param name
+ * The name of the port to add.
+ * @return The port (so that its value may be set);
+ */
+ public OutputPort addPort(String name) {
+ OutputPort p = new OutputPort();
+ p.name = name;
+ p.output = ABSENT_VALUE;
+ ports.add(p);
+ return p;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/main/java/org/taverna/server/port_description/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/package-info.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/package-info.java
new file mode 100644
index 0000000..b1ac2c6
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+@XmlSchema(namespace = DATA, elementFormDefault = QUALIFIED, attributeFormDefault = QUALIFIED, xmlns = {
+ @XmlNs(prefix = "port", namespaceURI = DATA),
+ @XmlNs(prefix = "xlink", namespaceURI = XLINK),
+ @XmlNs(prefix = "run", namespaceURI = RUN) })
+package org.taverna.server.port_description;
+
+import static javax.xml.bind.annotation.XmlNsForm.QUALIFIED;
+import static org.taverna.server.port_description.Namespaces.DATA;
+import static org.taverna.server.port_description.Namespaces.RUN;
+import static org.taverna.server.port_description.Namespaces.XLINK;
+
+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-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java
new file mode 100644
index 0000000..8764176
--- /dev/null
+++ b/taverna-server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.port_description.utils;
+
+import static javax.xml.bind.DatatypeConverter.parseInt;
+import static javax.xml.bind.DatatypeConverter.printInt;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * A type conversion utility for use with JAXB.
+ *
+ * @author Donal Fellows
+ */
+public class IntAdapter extends XmlAdapter<String, Integer> {
+ @Override
+ public String marshal(Integer value) throws Exception {
+ if (value == null)
+ return null;
+ return printInt(value);
+ }
+
+ @Override
+ public Integer unmarshal(String value) throws Exception {
+ if (value == null)
+ return null;
+ return parseInt(value);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java b/taverna-server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java
new file mode 100644
index 0000000..c952ec2
--- /dev/null
+++ b/taverna-server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java
@@ -0,0 +1,98 @@
+package org.taverna.server.port_description;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This test file ensures that the JAXB bindings will work once deployed instead
+ * of mysteriously failing in service.
+ *
+ * @author Donal Fellows
+ */
+public class JaxbSanityTest {
+ SchemaOutputResolver sink;
+ StringWriter schema;
+
+ String schema() {
+ return schema.toString();
+ }
+
+ private String schemaTest(Class<?>... classes) throws IOException, JAXBException {
+ Assert.assertTrue(schema().isEmpty());
+ JAXBContext.newInstance(classes).generateSchema(sink);
+ Assert.assertFalse(schema().isEmpty());
+ return schema();
+ }
+
+ @Before
+ public void init() {
+ schema = new StringWriter();
+ sink = new SchemaOutputResolver() {
+ @Override
+ public Result createOutput(String namespaceUri,
+ String suggestedFileName) throws IOException {
+ StreamResult sr = new StreamResult(schema);
+ sr.setSystemId("/dev/null");
+ return sr;
+ }
+ };
+ }
+
+ @Test
+ public void testJAXBForInput() throws Exception {
+ schemaTest(InputDescription.InputPort.class);
+ }
+
+ @Test
+ public void testJAXBForInputDescription() throws Exception {
+ schemaTest(InputDescription.class);
+ }
+
+ @Test
+ public void testJAXBForAbsentValue() throws Exception {
+ schemaTest(AbstractValue.class);
+ }
+
+ @Test
+ public void testJAXBForAbstractValue() throws Exception {
+ schemaTest(AbstractValue.class);
+ }
+
+ @Test
+ public void testJAXBForErrorValue() throws Exception {
+ schemaTest(ErrorValue.class);
+ }
+
+ @Test
+ public void testJAXBForLeafValue() throws Exception {
+ schemaTest(LeafValue.class);
+ }
+
+ @Test
+ public void testJAXBForListValue() throws Exception {
+ schemaTest(ListValue.class);
+ }
+
+ @Test
+ public void testJAXBForOutputDescription() throws Exception {
+ schemaTest(OutputDescription.class);
+ }
+
+ @Test
+ public void testJAXBForEverythingAtOnce() throws Exception {
+ schemaTest(AbsentValue.class, AbstractValue.class, ListValue.class,
+ LeafValue.class, ErrorValue.class, OutputDescription.class,
+ InputDescription.InputPort.class, InputDescription.class);
+ // System.out.println(schema());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-rmidaemon/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-rmidaemon/pom.xml b/taverna-server-rmidaemon/pom.xml
new file mode 100644
index 0000000..0e2a565
--- /dev/null
+++ b/taverna-server-rmidaemon/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>taverna-server-rmidaemon</artifactId>
+ <name>Apache Taverna Server RMI registry daemon</name>
+ <description>Customised RMI registry that supports restricting to localhost.</description>
+
+ <properties>
+ <project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
+ <mainClass>org.taverna.server.rmidaemon.Registry</mainClass>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <archive>
+ <manifest>
+ <mainClass>${mainClass}</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java
----------------------------------------------------------------------
diff --git a/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java b/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java
new file mode 100644
index 0000000..4be7579
--- /dev/null
+++ b/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java
@@ -0,0 +1,72 @@
+package org.taverna.server.rmidaemon;
+
+import static java.lang.System.setProperty;
+import static java.net.InetAddress.getLocalHost;
+import static java.rmi.registry.LocateRegistry.createRegistry;
+import static java.rmi.registry.Registry.REGISTRY_PORT;
+import static java.rmi.server.RMISocketFactory.getDefaultSocketFactory;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.net.ServerSocket;
+import java.rmi.MarshalledObject;
+import java.rmi.server.RMIServerSocketFactory;
+
+/**
+ * Special version of <tt>rmiregistry</tt>.
+ *
+ * @author Donal Fellows
+ */
+public class Registry {
+ /**
+ * Run a registry. The first optional argument is the port for the registry
+ * to listen on, and the second optional argument is whether the registry
+ * should restrict itself to connections from localhost only.
+ *
+ * @param args
+ * Arguments to the program.
+ */
+ public static void main(String... args) {
+ try {
+ if (args.length > 0)
+ port = Integer.parseInt(args[0]);
+ } catch (Exception e) {
+ System.err.println("failed to parse port: " + e.getMessage());
+ System.exit(2);
+ }
+ try {
+ if (args.length > 1)
+ localhostOnly = Boolean.parseBoolean(args[1]);
+ } catch (Exception e) {
+ System.err.println("failed to parse boolean localhost flag: "
+ + e.getMessage());
+ System.exit(2);
+ }
+ try {
+ Object registryHandle = makeRegistry();
+ try (ObjectOutputStream oos = new ObjectOutputStream(System.out)) {
+ oos.writeObject(registryHandle);
+ }
+ } catch (Exception e) {
+ System.err.println("problem creating registry: " + e.getMessage());
+ System.exit(1);
+ }
+ }
+
+ private static int port = REGISTRY_PORT;
+ private static boolean localhostOnly = false;
+
+ private static MarshalledObject<java.rmi.registry.Registry> makeRegistry() throws IOException {
+ if (!localhostOnly)
+ return new MarshalledObject<>(createRegistry(port));
+ setProperty("java.rmi.server.hostname", "127.0.0.1");
+ return new MarshalledObject<>(createRegistry(port,
+ getDefaultSocketFactory(), new RMIServerSocketFactory() {
+ @Override
+ public ServerSocket createServerSocket(int port)
+ throws IOException {
+ return new ServerSocket(port, 0, getLocalHost());
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java b/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java
new file mode 100644
index 0000000..32144b5
--- /dev/null
+++ b/taverna-server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * RMI daemon implementation. A variation of an RMI registry.
+ * @author Donal Fellows
+ */
+package org.taverna.server.rmidaemon;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/.gitignore
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/.gitignore b/taverna-server-runinterface/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/taverna-server-runinterface/.gitignore
@@ -0,0 +1 @@
+/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/pom.xml b/taverna-server-runinterface/pom.xml
new file mode 100644
index 0000000..efd3763
--- /dev/null
+++ b/taverna-server-runinterface/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>taverna-server-runinterface</artifactId>
+ <name>Apache Taverna Server RMI Interface: Webapp <-> Worker</name>
+ <description>This is the implementation of the RMI interface between the workflow run factory and the web-app service front-end.</description>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/META-INF/MANIFEST.MF b/taverna-server-runinterface/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java
new file mode 100644
index 0000000..9f4bf50
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception that indicates where a change of a workflow run's status is
+ * illegal.
+ *
+ * @author Donal Fellows
+ * @see RemoteSingleRun#setStatus(RemoteStatus)
+ */
+@WebFault(name = "IllegalStateTransitionFault", targetNamespace = "http://ns.taverna.org.uk/2010/xml/server/worker/")
+public class IllegalStateTransitionException extends Exception {
+ private static final long serialVersionUID = 159673249162345L;
+
+ public IllegalStateTransitionException() {
+ this("illegal state transition");
+ }
+
+ public IllegalStateTransitionException(String message) {
+ super(message);
+ }
+
+ public IllegalStateTransitionException(Throwable cause) {
+ this("illegal state transition", cause);
+ }
+
+ public IllegalStateTransitionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java
new file mode 100644
index 0000000..a47d112
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception that indicates that the implementation has gone wrong in some
+ * unexpected way.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "ImplementationFault", targetNamespace = "http://ns.taverna.org.uk/2010/xml/server/worker/")
+@SuppressWarnings("serial")
+public class ImplementationException extends Exception {
+ public ImplementationException(String message) {
+ super(message);
+ }
+
+ public ImplementationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java
new file mode 100644
index 0000000..395842a
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Represents a directory that is the working directory of a workflow run, or a
+ * sub-directory of it.
+ *
+ * @author Donal Fellows
+ * @see RemoteFile
+ */
+public interface RemoteDirectory extends RemoteDirectoryEntry {
+ /**
+ * @return A list of the contents of the directory.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If anything goes wrong with listing the directory.
+ */
+ @Nonnull
+ public Collection<RemoteDirectoryEntry> getContents()
+ throws RemoteException, IOException;
+
+ /**
+ * Creates a sub-directory of this directory.
+ *
+ * @param name
+ * The name of the sub-directory.
+ * @return A handle to the newly-created directory.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If things go wrong with creating the subdirectory.
+ */
+ @Nonnull
+ public RemoteDirectory makeSubdirectory(@Nonnull String name)
+ throws RemoteException, IOException;
+
+ /**
+ * Creates an empty file in this directory.
+ *
+ * @param name
+ * The name of the file to create.
+ * @return A handle to the newly-created file.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If anything goes wrong with creating the file.
+ */
+ @Nonnull
+ public RemoteFile makeEmptyFile(@Nonnull String name)
+ throws RemoteException, IOException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java
new file mode 100644
index 0000000..1e04b44
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Date;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * An entry in a {@link RemoteDirectory} representing a file or sub-directory.
+ *
+ * @author Donal Fellows
+ * @see RemoteDirectory
+ * @see RemoteFile
+ */
+public interface RemoteDirectoryEntry extends Remote {
+ /**
+ * @return The "local" name of the entry. This will never be "<tt>..</tt>"
+ * or contain the character "<tt>/</tt>".
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public String getName() throws RemoteException;
+
+ /**
+ * @return The time when the entry was last modified.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public Date getModificationDate() throws RemoteException;
+
+ /**
+ * Gets the directory containing this directory entry.
+ *
+ * @return A directory handle, or <tt>null</tt> if called on the workflow
+ * run's working directory.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ public RemoteDirectory getContainingDirectory() throws RemoteException;
+
+ /**
+ * Destroy this directory entry, deleting the file or sub-directory. The
+ * workflow run's working directory can never be manually destroyed.
+ *
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If things go wrong when deleting the directory entry.
+ */
+ public void destroy() throws RemoteException, IOException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java
new file mode 100644
index 0000000..e09466d
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Represents a file in the working directory of a workflow instance run, or in
+ * some sub-directory of it.
+ *
+ * @author Donal Fellows
+ * @see RemoteDirectory
+ */
+public interface RemoteFile extends RemoteDirectoryEntry {
+ /**
+ * Read from the file.
+ *
+ * @param offset
+ * Where in the file to read the bytes from.
+ * @param length
+ * How much of the file to read; -1 for "to the end".
+ * @return The literal byte contents of the given section of the file.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If things go wrong reading the file.
+ */
+ @Nonnull
+ byte[] getContents(int offset, int length) throws RemoteException,
+ IOException;
+
+ /**
+ * Write the data to the file, totally replacing what was there before.
+ *
+ * @param data
+ * The literal bytes that will form the new contents of the file.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If things go wrong writing the contents.
+ */
+ void setContents(@Nonnull byte[] data) throws RemoteException, IOException;
+
+ /**
+ * Append the data to the file.
+ *
+ * @param data
+ * The literal bytes that will be appended.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If things go wrong writing the contents.
+ */
+ void appendContents(@Nonnull byte[] data) throws RemoteException,
+ IOException;
+
+ /**
+ * @return The length of the file, in bytes.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ long getSize() throws RemoteException;
+
+ /**
+ * Copy from another file to this one.
+ *
+ * @param sourceFile
+ * The other file to copy from.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws IOException
+ * If things go wrong during the copy.
+ */
+ void copy(@Nonnull RemoteFile sourceFile) throws RemoteException,
+ IOException;
+
+ /**
+ * @return The full native OS name for the file.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ String getNativeName() throws RemoteException;
+
+ /**
+ * @return The host holding the file.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ String getNativeHost() throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java
new file mode 100644
index 0000000..7a7510c
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * This represents the assignment of inputs to input ports of the workflow. Note
+ * that the <tt>file</tt> and <tt>value</tt> properties are never set at the
+ * same time.
+ *
+ * @author Donal Fellows
+ */
+public interface RemoteInput extends Remote {
+ /**
+ * @return The file currently assigned to this input port, or <tt>null</tt>
+ * if no file is assigned.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ String getFile() throws RemoteException;
+
+ /**
+ * @return The name of this input port. This may not be changed.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ String getName() throws RemoteException;
+
+ /**
+ * @return The value currently assigned to this input port, or <tt>null</tt>
+ * if no value is assigned.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ String getValue() throws RemoteException;
+
+ /**
+ * @return The delimiter currently used to split this input port's value
+ * into a list, or <tt>null</tt> if no delimiter is to be used
+ * (i.e., the value is a singleton).
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ String getDelimiter() throws RemoteException;
+
+ /**
+ * Sets the file to use for this input. This overrides the use of the
+ * previous file and any set value.
+ *
+ * @param file
+ * The filename to use. Must not start with a <tt>/</tt> or
+ * contain any <tt>..</tt> segments. Will be interpreted relative
+ * to the run's working directory.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void setFile(@Nonnull String file) throws RemoteException;
+
+ /**
+ * Sets the value to use for this input. This overrides the use of the
+ * previous value and any set file.
+ *
+ * @param value
+ * The value to use.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void setValue(@Nonnull String value) throws RemoteException;
+
+ /**
+ * Sets the delimiter used to split this input port's value into a list.
+ *
+ * @param delimiter
+ * The delimiter character, or <tt>null</tt> if no delimiter is
+ * to be used (i.e., the value is a singleton).
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void setDelimiter(@Nullable String delimiter) throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java
new file mode 100644
index 0000000..4001721
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import javax.annotation.Nonnull;
+
+/**
+ * An event listener that is attached to a {@link RemoteSingleRun}.
+ *
+ * @author Donal Fellows
+ */
+public interface RemoteListener extends Remote {
+ /**
+ * @return The name of the listener.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public String getName() throws RemoteException;
+
+ /**
+ * @return The type of the listener.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public String getType() throws RemoteException;
+
+ /**
+ * @return The configuration document for the listener.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public String getConfiguration() throws RemoteException;
+
+ /**
+ * @return The supported properties of the listener.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public String[] listProperties() throws RemoteException;
+
+ /**
+ * Get the value of a particular property, which should be listed in the
+ * {@link #listProperties()} method.
+ *
+ * @param propName
+ * The name of the property to read.
+ * @return The value of the property.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public String getProperty(@Nonnull String propName) throws RemoteException;
+
+ /**
+ * Set the value of a particular property, which should be listed in the
+ * {@link #listProperties()} method.
+ *
+ * @param propName
+ * The name of the property to write.
+ * @param value
+ * The value to set the property to.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ public void setProperty(@Nonnull String propName, @Nonnull String value)
+ throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java
new file mode 100644
index 0000000..eec4ab5
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.UUID;
+
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * The main RMI-enabled interface for creating runs.
+ *
+ * @author Donal Fellows
+ */
+public interface RemoteRunFactory extends Remote {
+ /**
+ * Makes a workflow run that will process a particular workflow document.
+ *
+ * @param workflow
+ * The (serialised) workflow to instantiate as a run.
+ * @param creator
+ * Who is this run created for?
+ * @param usageRecordReceiver
+ * Where to write any usage records. May be <tt>null</tt> to
+ * cause them to not be written.
+ * @param masterID
+ * The UUID of the run to use, or <tt>null</tt> if the execution
+ * engine is to manufacture a new one for itself.
+ * @return A remote handle for the run.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ RemoteSingleRun make(@Nonnull byte[] workflow, @Nonnull String creator,
+ @Nullable UsageRecordReceiver usageRecordReceiver,
+ @Nullable UUID masterID) throws RemoteException;
+
+ /**
+ * Asks this factory to unregister itself from the registry and cease
+ * operation.
+ *
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void shutdown() throws RemoteException;
+
+ /**
+ * Configures the details to use when setting up the workflow run's
+ * connnection to the interaction feed.
+ *
+ * @param host
+ * The host where the feed is located.
+ * @param port
+ * The port where the feed is located.
+ * @param webdavPath
+ * The path used for pushing web pages into the feed.
+ * @param feedPath
+ * The path used for reading and writing notifications on the
+ * feed.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void setInteractionServiceDetails(@Nonnull String host,
+ @Nonnull String port, @Nonnull String webdavPath,
+ @Nonnull String feedPath) throws RemoteException;
+
+ /**
+ * Gets a count of the number of {@linkplain RemoteSingleRun workflow runs}
+ * that this factor knows about that are in the
+ * {@link RemoteStatus#Operating Operating} state.
+ *
+ * @return A count of "running" workflow runs.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ int countOperatingRuns() throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java
new file mode 100644
index 0000000..35e6c09
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.net.URI;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Outline of the security context for a workflow run.
+ *
+ * @author Donal Fellows
+ */
+public interface RemoteSecurityContext extends Remote {
+ void setKeystore(@Nonnull byte[] keystore) throws RemoteException,
+ ImplementationException;
+
+ void setPassword(@Nonnull char[] password) throws RemoteException,
+ ImplementationException;
+
+ void setTruststore(@Nonnull byte[] truststore) throws RemoteException,
+ ImplementationException;
+
+ void setUriToAliasMap(@Nonnull Map<URI, String> uriToAliasMap)
+ throws RemoteException;
+
+ void setHelioToken(@Nonnull String helioToken) throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java
new file mode 100644
index 0000000..fa68b81
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+import java.net.URL;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Date;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public interface RemoteSingleRun extends Remote {
+ /**
+ * @return The name of the Baclava file to use for all inputs, or
+ * <tt>null</tt> if no Baclava file is set.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ public String getInputBaclavaFile() throws RemoteException;
+
+ /**
+ * Sets the Baclava file to use for all inputs. This overrides the use of
+ * individual inputs.
+ *
+ * @param filename
+ * The filename to use. Must not start with a <tt>/</tt> or
+ * contain any <tt>..</tt> segments. Will be interpreted relative
+ * to the run's working directory.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ public void setInputBaclavaFile(@Nonnull String filename)
+ throws RemoteException;
+
+ /**
+ * @return The list of input assignments.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public List<RemoteInput> getInputs() throws RemoteException;
+
+ /**
+ * Create an input assignment.
+ *
+ * @param name
+ * The name of the port that this will be an input for.
+ * @return The assignment reference.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public RemoteInput makeInput(@Nonnull String name) throws RemoteException;
+
+ /**
+ * @return The file (relative to the working directory) to write the outputs
+ * of the run to as a Baclava document, or <tt>null</tt> if they are
+ * to be written to non-Baclava files in a directory called
+ * <tt>out</tt>.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ public String getOutputBaclavaFile() throws RemoteException;
+
+ /**
+ * Sets where the output of the run is to be written to. This will cause the
+ * output to be generated as a Baclava document, rather than a collection of
+ * individual non-Baclava files in the subdirectory of the working directory
+ * called <tt>out</tt>.
+ *
+ * @param filename
+ * Where to write the Baclava file (or <tt>null</tt> to cause the
+ * output to be written to individual files); overwrites any
+ * previous setting of this value.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ public void setOutputBaclavaFile(@Nullable String filename)
+ throws RemoteException;
+
+ /**
+ * @return The current status of the run.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public RemoteStatus getStatus() throws RemoteException;
+
+ /**
+ * Set the status of the run, which should cause it to move into the given
+ * state. This may cause some significant changes.
+ *
+ * @param s
+ * The state to try to change to.
+ * @throws IllegalStateTransitionException
+ * If the requested state change is impossible. (Note that it is
+ * always legal to set the status to the current status.)
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws ImplementationException
+ * If something goes horribly wrong on the back end.
+ * @throws StillWorkingOnItException
+ * If the startup time of the workflow implementation exceeds a
+ * built-in threshold.
+ */
+ public void setStatus(@Nonnull RemoteStatus s)
+ throws IllegalStateTransitionException, RemoteException,
+ ImplementationException, StillWorkingOnItException;
+
+ /**
+ * @return When this workflow run was found to have finished, or
+ * <tt>null</tt> if it has never finished (either still running or
+ * never started).
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ public Date getFinishTimestamp() throws RemoteException;
+
+ /**
+ * @return When this workflow run was started, or <tt>null</tt> if it has
+ * never been started.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nullable
+ public Date getStartTimestamp() throws RemoteException;
+
+ /**
+ * @return Handle to the main working directory of the run.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public RemoteDirectory getWorkingDirectory() throws RemoteException;
+
+ /**
+ * @return The list of listener instances attached to the run.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public List<RemoteListener> getListeners() throws RemoteException;
+
+ /**
+ * Add a listener to the run.
+ *
+ * @param listener
+ * The listener to add.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws ImplementationException
+ * If something goes wrong when adding the listener.
+ */
+ public void addListener(@Nonnull RemoteListener listener)
+ throws RemoteException, ImplementationException;
+
+ /**
+ * @return The security context structure for this run.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws ImplementationException
+ * If something goes wrong when getting the context.
+ */
+ @Nonnull
+ public RemoteSecurityContext getSecurityContext() throws RemoteException,
+ ImplementationException;
+
+ /**
+ * Kill off this run, removing all resources which it consumes.
+ *
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ * @throws ImplementationException
+ * If something goes horribly wrong when destroying the run.
+ */
+ public void destroy() throws RemoteException, ImplementationException;
+
+ /**
+ * Get the types of listener supported by this run.
+ *
+ * @return A list of listener type names.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public List<String> getListenerTypes() throws RemoteException;
+
+ /**
+ * Create a listener that can be attached to this run.
+ *
+ * @param type
+ * The type name of the listener to create; it must be one of the
+ * names returned by the {@link #getListenerTypes()} operation.
+ * @param configuration
+ * The configuration document for this listener. The nature of
+ * the contents of this are determined by the type.
+ * @return A handle for the listener.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ @Nonnull
+ public RemoteListener makeListener(@Nonnull String type,
+ @Nonnull String configuration) throws RemoteException;
+
+ /**
+ * Configures the details to use when setting up the workflow run's
+ * connnection to the interaction feed.
+ *
+ * @param interactionFeed
+ * The location of the interaction feed. If <tt>null</tt>,
+ * defaults from the factory will be used instead.
+ * @param webdavPath
+ * The location used for pushing web pages to support the feed.
+ * If <tt>null</tt>, a default from the factory will be used
+ * instead.
+ * @param publishUrlBase
+ * Where to <i>actually</i> publish to, if this needs to be
+ * different from the location presented in the published HTML
+ * and Feed entries. Necessary in complex network scenarios.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void setInteractionServiceDetails(@Nonnull URL interactionFeed,
+ @Nonnull URL webdavPath, @Nullable URL publishUrlBase) throws RemoteException;
+
+ /**
+ * A do-nothing method, used to check the general reachability of the
+ * workflow run.
+ *
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void ping() throws RemoteException;
+
+ /**
+ * Sets whether we should generate provenance information from a run.
+ *
+ * @param generateProvenance
+ * Boolean flag, true for do the generation. Must be set before
+ * starting the run for this to have an effect.
+ * @throws RemoteException
+ * If anything goes wrong with the communication.
+ */
+ void setGenerateProvenance(boolean generateProvenance)
+ throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java
new file mode 100644
index 0000000..db039f0
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+/**
+ * States of a workflow run. They are {@link RemoteStatus#Initialized
+ * Initialized}, {@link RemoteStatus#Operating Operating},
+ * {@link RemoteStatus#Stopped Stopped}, and {@link RemoteStatus#Finished
+ * Finished}. Conceptually, there is also a <tt>Destroyed</tt> state, but the
+ * workflow run does not exist (and hence can't have its state queried or set)
+ * in that case.
+ *
+ * @author Donal Fellows
+ */
+public enum RemoteStatus {
+ /**
+ * The workflow run has been created, but is not yet running. The run will
+ * need to be manually moved to {@link #Operating} when ready.
+ */
+ Initialized,
+ /**
+ * The workflow run is going, reading input, generating output, etc. Will
+ * eventually either move automatically to {@link #Finished} or can be moved
+ * manually to {@link #Stopped} (where supported).
+ */
+ Operating,
+ /**
+ * The workflow run is paused, and will need to be moved back to
+ * {@link #Operating} manually.
+ */
+ Stopped,
+ /**
+ * The workflow run has ceased; data files will continue to exist until the
+ * run is destroyed (which may be manual or automatic).
+ */
+ Finished
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java
new file mode 100644
index 0000000..4643d5c
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.remote;
+
+/**
+ * Exception that indicates that the implementation is still working on
+ * processing the operation. Note that though this is an exception, it is <i>not
+ * a failure</i>.
+ *
+ * @author Donal Fellows
+ */
+@SuppressWarnings("serial")
+public class StillWorkingOnItException extends Exception {
+ public StillWorkingOnItException(String string) {
+ super(string);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java
new file mode 100644
index 0000000..9880a3b
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Interfaces exported by worker classes to the server.
+ */
+package org.taverna.server.localworker.remote;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java
new file mode 100644
index 0000000..89c29ae
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.server;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * Interface exported by (part of) the webapp to allow processes it creates to
+ * push in usage records.
+ *
+ * @author Donal Fellows
+ */
+public interface UsageRecordReceiver extends Remote {
+ /**
+ * Called to push in a usage record. Note that it is assumed that the usage
+ * record already contains all the information required to locate and
+ * process the job; there is no separate handle.
+ *
+ * @param usageRecord
+ * The serialised XML of the usage record.
+ * @throws RemoteException
+ * if anything goes wrong.
+ */
+ void acceptUsageRecord(String usageRecord) throws RemoteException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java
new file mode 100644
index 0000000..cdd592b
--- /dev/null
+++ b/taverna-server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Interfaces exported by the server to worker classes.
+ */
+package org.taverna.server.localworker.server;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-unix-forker/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-unix-forker/pom.xml b/taverna-server-unix-forker/pom.xml
new file mode 100644
index 0000000..a2beeb4
--- /dev/null
+++ b/taverna-server-unix-forker/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-unix-forker</artifactId>
+ <name>Apache Taverna Server Impersonation Module (Unix)</name>
+ <description>Manages the starting of the worker processes as different users. Unix-specific.</description>
+
+ <properties>
+ <project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
+ <forkerMainClass>org.taverna.server.unixforker.Forker</forkerMainClass>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <archive>
+ <manifest>
+ <mainClass>${forkerMainClass}</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java
----------------------------------------------------------------------
diff --git a/taverna-server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java b/taverna-server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java
new file mode 100644
index 0000000..f9dc632
--- /dev/null
+++ b/taverna-server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.unixforker;
+
+import static java.lang.System.err;
+import static java.lang.System.getProperty;
+import static java.lang.System.in;
+import static java.lang.System.out;
+import static java.util.Arrays.asList;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A simple class that forks off processes when asked to over its standard
+ * input. The one complication is that it forks them off as other users, through
+ * the use of the <tt>sudo</tt> utility. It is Unix-specific.
+ *
+ * @author Donal Fellows
+ */
+public class Forker extends Thread {
+ private static String password;
+ private static BufferedReader br;
+
+ /**
+ * Helper to make reading a password from a file clearer. The password must
+ * be the first line of the file.
+ *
+ * @param passwordFile
+ * The file to load from.
+ * @throws IOException
+ * If anything goes wrong.
+ */
+ private static void loadPassword(@Nonnull File passwordFile)
+ throws IOException {
+ try {
+ err.println("attempting to load password from " + passwordFile);
+ try (FileReader fr = new FileReader(passwordFile)) {
+ password = new BufferedReader(fr).readLine();
+ }
+ } catch (IOException e) {
+ err.println("failed to read password from file " + passwordFile
+ + "described in password.file property");
+ throw e;
+ }
+ }
+
+ /**
+ * Initialization code, which runs before the main loop starts processing.
+ *
+ * @param args
+ * The arguments to the program.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ public static void init(String[] args) throws Exception {
+ if (args.length < 1)
+ throw new IllegalArgumentException(
+ "wrong # args: must be \"program ?argument ...?\"");
+ if (getProperty("password.file") != null)
+ loadPassword(new File(getProperty("password.file")));
+ if (password == null)
+ err.println("no password.file property or empty file; "
+ + "assuming password-less sudo is configured");
+ else
+ err.println("password is of length " + password.length());
+ br = new BufferedReader(new InputStreamReader(in));
+ }
+
+ /**
+ * The body of the main loop of this program.
+ *
+ * @param args
+ * The arguments to use when running the other program.
+ * @return Whether to repeat the loop.
+ * @throws Exception
+ * If anything goes wrong. Note that the loop is repeated if an
+ * exception occurs in it.
+ */
+ public static boolean mainLoopBody(String[] args) throws Exception {
+ String line = br.readLine();
+ if (line == null)
+ return false;
+ List<String> vals = asList(line.split("[ \t]+"));
+ if (vals.size() != 2) {
+ out.println("wrong # values: must be \"username UUID\"");
+ return true;
+ }
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command()
+ .addAll(asList("sudo", "-u", vals.get(0), "-S", "-H", "--"));
+ pb.command().addAll(asList(args));
+ pb.command().add(vals.get(1));
+ Forker f = new Forker(pb);
+ f.setDaemon(true);
+ f.start();
+ return true;
+ }
+
+ /**
+ * The main code for this class, which turns this into an executable
+ * program. Runs the initialisation and then the main loop, in both cases
+ * with appropriate error handling.
+ *
+ * @param args
+ * Arguments to this program.
+ */
+ public static void main(String... args) {
+ try {
+ init(args);
+ while (true) {
+ try {
+ if (!mainLoopBody(args))
+ break;
+ } catch (Exception e) {
+ e.printStackTrace(err);
+ out.println(e.getClass().getName() + ": " + e.getMessage());
+ }
+ }
+ System.exit(0);
+ } catch (Exception e) {
+ e.printStackTrace(err);
+ System.exit(1);
+ }
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ public Forker(ProcessBuilder pb) throws IOException {
+ out.println("Starting subprocess: " + pb.command());
+ final Process p = pb.start();
+ abstract class ProcessAttachedDaemon extends Thread {
+ public ProcessAttachedDaemon() {
+ setDaemon(true);
+ start();
+ }
+
+ abstract void act() throws Exception;
+
+ @Override
+ public final void run() {
+ try {
+ act();
+ p.waitFor();
+ } catch (InterruptedException e) {
+ // Just drop
+ } catch (Exception e) {
+ p.destroy();
+ e.printStackTrace(err);
+ }
+ }
+ }
+ new ProcessAttachedDaemon() {
+ @Override
+ void act() throws Exception {
+ copyFromSudo("Subprocess(out):", p.getInputStream());
+ }
+ };
+ new ProcessAttachedDaemon() {
+ @Override
+ void act() throws Exception {
+ copyFromSudo("Subprocess(err):", p.getErrorStream());
+ }
+ };
+ new ProcessAttachedDaemon() {
+ @Override
+ void act() throws Exception {
+ interactWithSudo(p.getOutputStream());
+ }
+ };
+ }
+
+ protected void interactWithSudo(OutputStream os) throws Exception {
+ if (password != null) {
+ OutputStreamWriter osw = new OutputStreamWriter(os);
+ osw.write(password + "\n");
+ osw.flush();
+ }
+ os.close();
+ }
+
+ protected void copyFromSudo(String header, InputStream sudoStream)
+ throws Exception {
+ int b = '\n';
+ while (true) {
+ if (b == '\n')
+ out.print(header);
+ b = sudoStream.read();
+ if (b == -1)
+ break;
+ out.write(b);
+ out.flush();
+ }
+ sudoStream.close();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-usagerecord/.gitignore
----------------------------------------------------------------------
diff --git a/taverna-server-usagerecord/.gitignore b/taverna-server-usagerecord/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/taverna-server-usagerecord/.gitignore
@@ -0,0 +1 @@
+/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-usagerecord/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-usagerecord/pom.xml b/taverna-server-usagerecord/pom.xml
new file mode 100644
index 0000000..47ab732
--- /dev/null
+++ b/taverna-server-usagerecord/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-usagerecord</artifactId>
+ <name>Apache Taverna Server Usage Record Support</name>
+ <description>Basic Java bindings for the OGF Usage Record Format, version 1.0, plus a simple wrapper to make working with it easier.</description>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>jaxb2-maven-plugin</artifactId>
+ <version>1.3.1</version>
+ <executions>
+ <execution>
+ <id>xsd2java</id>
+ <goals>
+ <goal>xjc</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/generated-sources/xjc</outputDirectory>
+ <schemaDirectory>${basedir}/src/main/xsd</schemaDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>jaxb2-maven-plugin</artifactId>
+ <versionRange>[1.3.1,)</versionRange>
+ <goals>
+ <goal>xjc</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
[40/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java b/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java
deleted file mode 100644
index 06202dc..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package org.taverna.server.master.identity;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.security.authentication.AccountExpiredException;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.authentication.AuthenticationServiceException;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.CredentialsExpiredException;
-import org.springframework.security.authentication.DisabledException;
-import org.springframework.security.authentication.LockedException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-
-/**
- * A stripped down version of a
- * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider
- * DaoAuthenticationProvider}/
- * {@link org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
- * AbstractUserDetailsAuthenticationProvider} that avoids much of the overhead
- * associated with that class.
- */
-public class StrippedDownAuthProvider implements AuthenticationProvider {
- /**
- * The plaintext password used to perform
- * {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when
- * the user is not found to avoid SEC-2056.
- */
- private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
-
- /**
- * The password used to perform
- * {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when
- * the user is not found to avoid SEC-2056. This is necessary, because some
- * {@link PasswordEncoder} implementations will short circuit if the
- * password is not in a valid format.
- */
- private String userNotFoundEncodedPassword;
- private UserDetailsService userDetailsService;
- private PasswordEncoder passwordEncoder;
- private Map<String, AuthCacheEntry> authCache = new HashMap<>();
- protected final Log logger = LogFactory.getLog(getClass());
-
- private static class AuthCacheEntry {
- private String creds;
- private long timestamp;
- private static final long VALIDITY = 1000 * 60 * 20;
- AuthCacheEntry(String credentials) {
- creds = credentials;
- timestamp = System.currentTimeMillis();
- }
- boolean valid(String password) {
- return creds.equals(password) && timestamp+VALIDITY > System.currentTimeMillis();
- }
- }
-
- @PerfLogged
- @Override
- public Authentication authenticate(Authentication authentication)
- throws AuthenticationException {
-
- if (!(authentication instanceof UsernamePasswordAuthenticationToken))
- throw new IllegalArgumentException(
- "can only authenticate against username+password");
- UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
-
- // Determine username
- String username = (auth.getPrincipal() == null) ? "NONE_PROVIDED"
- : auth.getName();
-
- UserDetails user;
-
- try {
- user = retrieveUser(username, auth);
- if (user == null)
- throw new IllegalStateException(
- "retrieveUser returned null - a violation of the interface contract");
- } catch (UsernameNotFoundException notFound) {
- if (logger.isDebugEnabled())
- logger.debug("User '" + username + "' not found", notFound);
- throw new BadCredentialsException("Bad credentials");
- }
-
- // Pre-auth
- if (!user.isAccountNonLocked())
- throw new LockedException("User account is locked");
- if (!user.isEnabled())
- throw new DisabledException("User account is disabled");
- if (!user.isAccountNonExpired())
- throw new AccountExpiredException("User account has expired");
- Object credentials = auth.getCredentials();
- if (credentials == null) {
- logger.debug("Authentication failed: no credentials provided");
-
- throw new BadCredentialsException("Bad credentials");
- }
-
- String providedPassword = credentials.toString();
- boolean matched = false;
- synchronized (authCache) {
- AuthCacheEntry pw = authCache.get(username);
- if (pw != null && providedPassword != null) {
- if (pw.valid(providedPassword))
- matched = true;
- else
- authCache.remove(username);
- }
- }
- // Auth
- if (!matched) {
- if (!passwordEncoder.matches(providedPassword, user.getPassword())) {
- logger.debug("Authentication failed: password does not match stored value");
-
- throw new BadCredentialsException("Bad credentials");
- }
- if (providedPassword != null)
- synchronized (authCache) {
- authCache.put(username, new AuthCacheEntry(providedPassword));
- }
- }
-
- // Post-auth
- if (!user.isCredentialsNonExpired())
- throw new CredentialsExpiredException(
- "User credentials have expired");
-
- return createSuccessAuthentication(user, auth, user);
- }
-
- @PreDestroy
- void clearCache() {
- authCache.clear();
- }
-
- /**
- * Creates a successful {@link Authentication} object.
- * <p>
- * Protected so subclasses can override.
- * </p>
- * <p>
- * Subclasses will usually store the original credentials the user supplied
- * (not salted or encoded passwords) in the returned
- * <code>Authentication</code> object.
- * </p>
- *
- * @param principal
- * that should be the principal in the returned object (defined
- * by the {@link #isForcePrincipalAsString()} method)
- * @param authentication
- * that was presented to the provider for validation
- * @param user
- * that was loaded by the implementation
- *
- * @return the successful authentication token
- */
- private Authentication createSuccessAuthentication(Object principal,
- Authentication authentication, UserDetails user) {
- /*
- * Ensure we return the original credentials the user supplied, so
- * subsequent attempts are successful even with encoded passwords. Also
- * ensure we return the original getDetails(), so that future
- * authentication events after cache expiry contain the details
- */
- UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
- principal, authentication.getCredentials(),
- user.getAuthorities());
- result.setDetails(authentication.getDetails());
-
- return result;
- }
-
- @Override
- public boolean supports(Class<?> authentication) {
- return UsernamePasswordAuthenticationToken.class
- .isAssignableFrom(authentication);
- }
-
- /**
- * Allows subclasses to actually retrieve the <code>UserDetails</code> from
- * an implementation-specific location, with the option of throwing an
- * <code>AuthenticationException</code> immediately if the presented
- * credentials are incorrect (this is especially useful if it is necessary
- * to bind to a resource as the user in order to obtain or generate a
- * <code>UserDetails</code>).
- * <p>
- * Subclasses are not required to perform any caching, as the
- * <code>AbstractUserDetailsAuthenticationProvider</code> will by default
- * cache the <code>UserDetails</code>. The caching of
- * <code>UserDetails</code> does present additional complexity as this means
- * subsequent requests that rely on the cache will need to still have their
- * credentials validated, even if the correctness of credentials was assured
- * by subclasses adopting a binding-based strategy in this method.
- * Accordingly it is important that subclasses either disable caching (if
- * they want to ensure that this method is the only method that is capable
- * of authenticating a request, as no <code>UserDetails</code> will ever be
- * cached) or ensure subclasses implement
- * {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)}
- * to compare the credentials of a cached <code>UserDetails</code> with
- * subsequent authentication requests.
- * </p>
- * <p>
- * Most of the time subclasses will not perform credentials inspection in
- * this method, instead performing it in
- * {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)}
- * so that code related to credentials validation need not be duplicated
- * across two methods.
- * </p>
- *
- * @param username
- * The username to retrieve
- * @param authentication
- * The authentication request, which subclasses <em>may</em> need
- * to perform a binding-based retrieval of the
- * <code>UserDetails</code>
- *
- * @return the user information (never <code>null</code> - instead an
- * exception should the thrown)
- *
- * @throws AuthenticationException
- * if the credentials could not be validated (generally a
- * <code>BadCredentialsException</code>, an
- * <code>AuthenticationServiceException</code> or
- * <code>UsernameNotFoundException</code>)
- */
- private UserDetails retrieveUser(String username,
- UsernamePasswordAuthenticationToken authentication)
- throws AuthenticationException {
- try {
- return userDetailsService.loadUserByUsername(username);
- } catch (UsernameNotFoundException notFound) {
- if (authentication.getCredentials() != null) {
- String presentedPassword = authentication.getCredentials()
- .toString();
- passwordEncoder.matches(presentedPassword,
- userNotFoundEncodedPassword);
- }
- throw notFound;
- } catch (AuthenticationException e) {
- throw e;
- } catch (Exception repositoryProblem) {
- throw new AuthenticationServiceException(
- repositoryProblem.getMessage(), repositoryProblem);
- }
- }
-
- /**
- * Sets the PasswordEncoder instance to be used to encode and validate
- * passwords.
- */
- @Required
- public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
- if (passwordEncoder == null)
- throw new IllegalArgumentException("passwordEncoder cannot be null");
-
- this.passwordEncoder = passwordEncoder;
- this.userNotFoundEncodedPassword = passwordEncoder
- .encode(USER_NOT_FOUND_PASSWORD);
- }
-
- @Required
- public void setUserDetailsService(UserDetailsService userDetailsService) {
- if (userDetailsService == null)
- throw new IllegalStateException("A UserDetailsService must be set");
- this.userDetailsService = userDetailsService;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/User.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/User.java b/server-webapp/src/main/java/org/taverna/server/master/identity/User.java
deleted file mode 100644
index bdb6e40..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/User.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2011-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import static org.taverna.server.master.common.Roles.ADMIN;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.Query;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * The representation of a user in the database.
- * <p>
- * A user consists logically of a (non-ordered) tuple of items:
- * <ul>
- * <li>The {@linkplain #getUsername() user name},
- * <li>The {@linkplain #getPassword() user's password} (salted, encoded),
- * <li>Whether the user is {@linkplain #isEnabled() enabled} (i.e., able to log
- * in),
- * <li>Whether the user has {@linkplain #isAdmin() administrative privileges}, and
- * <li>What {@linkplain #getLocalUsername() system (Unix) account} the user's
- * workflows will run as; separation between different users that are mapped to
- * the same system account is nothing like as strongly enforced.
- * </ul>
- *
- * @author Donal Fellows
- */
-@PersistenceCapable(schema = "USERS", table = "LIST")
-@Query(name = "users", language = "SQL", value = "SELECT id FROM USERS.LIST ORDER BY id", resultClass = String.class)
-@XmlRootElement
-@XmlType(name = "User", propOrder = {})
-@SuppressWarnings("serial")
-public class User implements UserDetails {
- @XmlElement
- @Persistent
- private boolean disabled;
- @XmlElement(name = "username", required = true)
- @Persistent(primaryKey = "true")
- private String id;
- @XmlElement(name = "password", required = true)
- @Persistent(column = "password")
- private String encodedPassword;
- @XmlElement
- @Persistent
- private boolean admin;
- @XmlElement
- @Persistent
- private String localUsername;
-
- @Override
- public Collection<GrantedAuthority> getAuthorities() {
- List<GrantedAuthority> auths = new ArrayList<>();
- auths.add(new LiteralGrantedAuthority(USER));
- if (admin)
- auths.add(new LiteralGrantedAuthority(ADMIN));
- if (localUsername != null)
- auths.add(new LiteralGrantedAuthority(AUTHORITY_PREFIX
- + localUsername));
- return auths;
- }
-
- @Override
- public String getPassword() {
- return encodedPassword;
- }
-
- @Override
- public String getUsername() {
- return id;
- }
-
- @Override
- public boolean isAccountNonExpired() {
- return true;
- }
-
- @Override
- public boolean isAccountNonLocked() {
- return true;
- }
-
- @Override
- public boolean isCredentialsNonExpired() {
- return true;
- }
-
- @Override
- public boolean isEnabled() {
- return !disabled;
- }
-
- void setDisabled(boolean disabled) {
- this.disabled = disabled;
- }
-
- void setUsername(String username) {
- this.id = username;
- }
-
- void setEncodedPassword(String password) {
- this.encodedPassword = password;
- }
-
- void setAdmin(boolean admin) {
- this.admin = admin;
- }
-
- public boolean isAdmin() {
- return admin;
- }
-
- void setLocalUsername(String localUsername) {
- this.localUsername = localUsername;
- }
-
- public String getLocalUsername() {
- return localUsername;
- }
-}
-
-@SuppressWarnings("serial")
-class LiteralGrantedAuthority implements GrantedAuthority {
- private String auth;
-
- LiteralGrantedAuthority(String auth) {
- this.auth = auth;
- }
-
- @Override
- public String getAuthority() {
- return auth;
- }
-
- @Override
- public String toString() {
- return "AUTHORITY(" + auth + ")";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java b/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java
deleted file mode 100644
index 054d932..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) 2011-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-import static org.taverna.server.master.common.Roles.ADMIN;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.jdo.annotations.PersistenceAware;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.dao.DataAccessException;
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedOperation;
-import org.springframework.jmx.export.annotation.ManagedOperationParameter;
-import org.springframework.jmx.export.annotation.ManagedOperationParameters;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.core.userdetails.memory.UserAttribute;
-import org.springframework.security.core.userdetails.memory.UserAttributeEditor;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.JDOSupport;
-
-/**
- * The bean class that is responsible for managing the users in the database.
- *
- * @author Donal Fellows
- */
-@PersistenceAware
-@ManagedResource(objectName = JMX_ROOT + "Users", description = "The user database.")
-public class UserStore extends JDOSupport<User> implements UserDetailsService,
- UserStoreAPI {
- /** The logger for the user store. */
- private transient Log log = getLog("Taverna.Server.UserDB");
-
- public UserStore() {
- super(User.class);
- }
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- private Map<String, BootstrapUserInfo> base = new HashMap<>();
- private String defLocalUser;
- private PasswordEncoder encoder;
- private volatile int epoch;
-
- /**
- * Install the encoder that will be used to turn a plaintext password into
- * something that it is safe to store in the database.
- *
- * @param encoder
- * The password encoder bean to install.
- */
- public void setEncoder(PasswordEncoder encoder) {
- this.encoder = encoder;
- }
-
- public void setBaselineUserProperties(Properties props) {
- UserAttributeEditor parser = new UserAttributeEditor();
-
- for (Object name : props.keySet()) {
- String username = (String) name;
- String value = props.getProperty(username);
-
- // Convert value to a password, enabled setting, and list of granted
- // authorities
- parser.setAsText(value);
-
- UserAttribute attr = (UserAttribute) parser.getValue();
- if (attr != null && attr.isEnabled())
- base.put(username, new BootstrapUserInfo(username, attr));
- }
- }
-
- private void installPassword(User u, String password) {
- u.setEncodedPassword(encoder.encode(password));
- }
-
- public void setDefaultLocalUser(String defLocalUser) {
- this.defLocalUser = defLocalUser;
- }
-
- @SuppressWarnings("unchecked")
- private List<String> getUsers() {
- return (List<String>) namedQuery("users").execute();
- }
-
- @WithinSingleTransaction
- @PostConstruct
- void initDB() {
- if (base == null || base.isEmpty())
- log.warn("no baseline user collection");
- else if (!getUsers().isEmpty())
- log.info("using existing users from database");
- else
- for (String username : base.keySet()) {
- BootstrapUserInfo ud = base.get(username);
- if (ud == null)
- continue;
- User u = ud.get(encoder);
- if (u == null)
- continue;
- log.info("bootstrapping user " + username + " in the database");
- persist(u);
- }
- base = null;
- epoch++;
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedAttribute(description = "The list of server accounts known about.", currencyTimeLimit = 30)
- public List<String> getUserNames() {
- return getUsers();
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- public User getUser(String userName) {
- return detach(getById(userName));
- }
-
- /**
- * Get information about a server account.
- *
- * @param userName
- * The username to look up.
- * @return A description map intended for use by a server admin over JMX.
- */
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Get information about a server account.")
- @ManagedOperationParameters(@ManagedOperationParameter(name = "userName", description = "The username to look up."))
- public Map<String, String> getUserInfo(String userName) {
- User u = getById(userName);
- Map<String, String> info = new HashMap<>();
- info.put("name", u.getUsername());
- info.put("admin", u.isAdmin() ? "yes" : "no");
- info.put("enabled", u.isEnabled() ? "yes" : "no");
- info.put("localID", u.getLocalUsername());
- return info;
- }
-
- /**
- * Get a list of all the users in the database.
- *
- * @return A list of user details, <i>copied</i> out of the database.
- */
- @PerfLogged
- @WithinSingleTransaction
- public List<UserDetails> listUsers() {
- ArrayList<UserDetails> result = new ArrayList<>();
- for (String id : getUsers())
- result.add(detach(getById(id)));
- return result;
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Create a new user account; the account will be disabled and "
- + "non-administrative by default. Does not create any underlying system account.")
- @ManagedOperationParameters({
- @ManagedOperationParameter(name = "username", description = "The username to create."),
- @ManagedOperationParameter(name = "password", description = "The password to use."),
- @ManagedOperationParameter(name = "coupleLocalUsername", description = "Whether to set the local user name to the 'main' one.") })
- public void addUser(String username, String password,
- boolean coupleLocalUsername) {
- if (username.matches(".*[^a-zA-Z0-9].*"))
- throw new IllegalArgumentException(
- "bad user name; must be pure alphanumeric");
- if (getById(username) != null)
- throw new IllegalArgumentException("user name already exists");
- User u = new User();
- u.setDisabled(true);
- u.setAdmin(false);
- u.setUsername(username);
- installPassword(u, password);
- if (coupleLocalUsername)
- u.setLocalUsername(username);
- else
- u.setLocalUsername(defLocalUser);
- log.info("creating user for " + username);
- persist(u);
- epoch++;
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Set or clear whether this account is enabled. "
- + "Disabled accounts cannot be used to log in.")
- @ManagedOperationParameters({
- @ManagedOperationParameter(name = "username", description = "The username to adjust."),
- @ManagedOperationParameter(name = "enabled", description = "Whether to enable the account.") })
- public void setUserEnabled(String username, boolean enabled) {
- User u = getById(username);
- if (u != null) {
- u.setDisabled(!enabled);
- log.info((enabled ? "enabling" : "disabling") + " user " + username);
- epoch++;
- }
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Set or clear the mark on an account that indicates "
- + "that it has administrative privileges.")
- @ManagedOperationParameters({
- @ManagedOperationParameter(name = "username", description = "The username to adjust."),
- @ManagedOperationParameter(name = "admin", description = "Whether the account has admin privileges.") })
- public void setUserAdmin(String username, boolean admin) {
- User u = getById(username);
- if (u != null) {
- u.setAdmin(admin);
- log.info((admin ? "enabling" : "disabling") + " user " + username
- + " admin status");
- epoch++;
- }
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Change the password for an account.")
- @ManagedOperationParameters({
- @ManagedOperationParameter(name = "username", description = "The username to adjust."),
- @ManagedOperationParameter(name = "password", description = "The new password to use.") })
- public void setUserPassword(String username, String password) {
- User u = getById(username);
- if (u != null) {
- installPassword(u, password);
- log.info("changing password for user " + username);
- epoch++;
- }
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Change what local system account to use for a server account.")
- @ManagedOperationParameters({
- @ManagedOperationParameter(name = "username", description = "The username to adjust."),
- @ManagedOperationParameter(name = "password", description = "The new local user account use.") })
- public void setUserLocalUser(String username, String localUsername) {
- User u = getById(username);
- if (u != null) {
- u.setLocalUsername(localUsername);
- log.info("mapping user " + username + " to local account "
- + localUsername);
- epoch++;
- }
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- @ManagedOperation(description = "Delete a server account. The underlying "
- + "system account is not modified.")
- @ManagedOperationParameters(@ManagedOperationParameter(name = "username", description = "The username to delete."))
- public void deleteUser(String username) {
- delete(getById(username));
- log.info("deleting user " + username);
- epoch++;
- }
-
- @Override
- @PerfLogged
- @WithinSingleTransaction
- public UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException, DataAccessException {
- User u;
- if (base != null) {
- log.warn("bootstrap user store still installed!");
- BootstrapUserInfo ud = base.get(username);
- if (ud != null) {
- log.warn("retrieved production credentials for " + username
- + " from bootstrap store");
- u = ud.get(encoder);
- if (u != null)
- return u;
- }
- }
- try {
- u = detach(getById(username));
- } catch (NullPointerException npe) {
- throw new UsernameNotFoundException("who are you?");
- } catch (Exception ex) {
- throw new UsernameNotFoundException("who are you?", ex);
- }
- if (u != null)
- return u;
- throw new UsernameNotFoundException("who are you?");
- }
-
- int getEpoch() {
- return epoch;
- }
-
- public static class CachedUserStore implements UserDetailsService {
- private int epoch;
- private Map<String, UserDetails> cache = new HashMap<>();
- private UserStore realStore;
-
- @Required
- public void setRealStore(UserStore store) {
- this.realStore = store;
- }
-
- @Override
- @PerfLogged
- public UserDetails loadUserByUsername(String username) {
- int epoch = realStore.getEpoch();
- UserDetails details;
- synchronized (cache) {
- if (epoch != this.epoch) {
- cache.clear();
- this.epoch = epoch;
- details = null;
- } else
- details = cache.get(username);
- }
- if (details == null) {
- details = realStore.loadUserByUsername(username);
- synchronized (cache) {
- cache.put(username, details);
- }
- }
- return details;
- }
- }
-
- private static class BootstrapUserInfo {
- private String user;
- private String pass;
- private Collection<GrantedAuthority> auth;
-
- BootstrapUserInfo(String username, UserAttribute attr) {
- user = username;
- pass = attr.getPassword();
- auth = attr.getAuthorities();
- }
-
- User get(PasswordEncoder encoder) {
- User u = new User();
- boolean realUser = false;
- for (GrantedAuthority ga : auth) {
- String a = ga.getAuthority();
- if (a.startsWith(AUTHORITY_PREFIX))
- u.setLocalUsername(a.substring(AUTHORITY_PREFIX.length()));
- else if (a.equals(USER))
- realUser = true;
- else if (a.equals(ADMIN))
- u.setAdmin(true);
- }
- if (!realUser)
- return null;
- u.setUsername(user);
- u.setEncodedPassword(encoder.encode(pass));
- u.setDisabled(false);
- return u;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java b/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java
deleted file mode 100644
index a048da9..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.taverna.server.master.identity;
-
-import java.util.List;
-
-/**
- * The API that is exposed by the DAO that exposes user management.
- *
- * @author Donal Fellows
- * @see User
- */
-public interface UserStoreAPI {
- /**
- * List the currently-known account names.
- *
- * @return A list of users in the database. Note that this is a snapshot.
- */
- List<String> getUserNames();
-
- /**
- * Get a particular user's description.
- *
- * @param userName
- * The username to look up.
- * @return A <i>copy</i> of the user description.
- */
- User getUser(String userName);
-
- /**
- * Create a new user account; the account will be disabled and
- * non-administrative by default. Does not create any underlying system
- * account.
- *
- * @param username
- * The username to create.
- * @param password
- * The password to use.
- * @param coupleLocalUsername
- * Whether to set the local user name to the 'main' one.
- */
- void addUser(String username, String password, boolean coupleLocalUsername);
-
- /**
- * Set or clear whether this account is enabled. Disabled accounts cannot be
- * used to log in.
- *
- * @param username
- * The username to adjust.
- * @param enabled
- * Whether to enable the account.
- */
- void setUserEnabled(String username, boolean enabled);
-
- /**
- * Set or clear the mark on an account that indicates that it has
- * administrative privileges.
- *
- * @param username
- * The username to adjust.
- * @param admin
- * Whether the account has admin privileges.
- */
- void setUserAdmin(String username, boolean admin);
-
- /**
- * Change the password for an account.
- *
- * @param username
- * The username to adjust.
- * @param password
- * The new password to use.
- */
- void setUserPassword(String username, String password);
-
- /**
- * Change what local system account to use for a server account.
- *
- * @param username
- * The username to adjust.
- * @param localUsername
- * The new local user account use.
- */
- void setUserLocalUser(String username, String localUsername);
-
- /**
- * Delete a server account. The underlying system account is not modified.
- *
- * @param username
- * The username to delete.
- */
- void deleteUser(String username);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java b/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java
deleted file mode 100644
index 9219a60..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE.txt" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import static java.util.Collections.synchronizedMap;
-import static org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes;
-import static org.taverna.server.master.common.Roles.SELF;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.security.authentication.AuthenticationServiceException;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.web.authentication.WebAuthenticationDetails;
-import org.springframework.web.context.request.ServletRequestAttributes;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.interfaces.RunStore;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.UsernamePrincipal;
-import org.taverna.server.master.worker.RunDatabaseDAO;
-
-/**
- * A special authentication provider that allows a workflow to authenticate to
- * itself. This is used to allow the workflow to publish to its own interaction
- * feed.
- *
- * @author Donal Fellows
- */
-public class WorkflowInternalAuthProvider extends
- AbstractUserDetailsAuthenticationProvider {
- private Log log = LogFactory.getLog("Taverna.Server.UserDB");
- private static final boolean logDecisions = true;
- public static final String PREFIX = "wfrun_";
- private RunDatabaseDAO dao;
- private Map<String, String> cache;
-
- @Required
- public void setDao(RunDatabaseDAO dao) {
- this.dao = dao;
- }
-
- @Required
- @SuppressWarnings("serial")
- public void setCacheBound(final int bound) {
- cache = synchronizedMap(new LinkedHashMap<String, String>() {
- @Override
- protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
- return size() > bound;
- }
- });
- }
-
- public void setAuthorizedAddresses(String[] addresses) {
- authorizedAddresses = new HashSet<>(localAddresses);
- for (String s : addresses)
- authorizedAddresses.add(s);
- }
-
- @PostConstruct
- public void logConfig() {
- log.info("authorized addresses for automatic access: "
- + authorizedAddresses);
- }
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- private final Set<String> localAddresses = new HashSet<>();
- private Set<String> authorizedAddresses;
- {
- localAddresses.add("127.0.0.1"); // IPv4
- localAddresses.add("::1"); // IPv6
- try {
- InetAddress addr = InetAddress.getLocalHost();
- if (!addr.isLoopbackAddress())
- localAddresses.add(addr.getHostAddress());
- } catch (UnknownHostException e) {
- // Ignore the exception
- }
- authorizedAddresses = new HashSet<>(localAddresses);
- }
-
- /**
- * Check that the authentication request is actually valid for the given
- * user record.
- *
- * @param userRecord
- * as retrieved from the
- * {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)}
- * or <code>UserCache</code>
- * @param principal
- * the principal that is trying to authenticate (and that we're
- * trying to bind)
- * @param credentials
- * the credentials (e.g., password) presented by the principal
- *
- * @throws AuthenticationException
- * AuthenticationException if the credentials could not be
- * validated (generally a <code>BadCredentialsException</code>,
- * an <code>AuthenticationServiceException</code>)
- * @throws Exception
- * If something goes wrong. Will be logged and converted to a
- * generic AuthenticationException.
- */
- protected void additionalAuthenticationChecks(UserDetails userRecord,
- @Nonnull Object principal, @Nonnull Object credentials)
- throws Exception {
- @Nonnull
- HttpServletRequest req = ((ServletRequestAttributes) currentRequestAttributes())
- .getRequest();
-
- // Are we coming from a "local" address?
- if (!req.getLocalAddr().equals(req.getRemoteAddr())
- && !authorizedAddresses.contains(req.getRemoteAddr())) {
- if (logDecisions)
- log.info("attempt to use workflow magic token from untrusted address:"
- + " token="
- + userRecord.getUsername()
- + ", address="
- + req.getRemoteAddr());
- throw new BadCredentialsException("bad login token");
- }
-
- // Does the password match?
- if (!credentials.equals(userRecord.getPassword())) {
- if (logDecisions)
- log.info("workflow magic token is untrusted due to password mismatch:"
- + " wanted="
- + userRecord.getPassword()
- + ", got="
- + credentials);
- throw new BadCredentialsException("bad login token");
- }
-
- if (logDecisions)
- log.info("granted role " + SELF + " to user "
- + userRecord.getUsername());
- }
-
- /**
- * Retrieve the <code>UserDetails</code> from the relevant store, with the
- * option of throwing an <code>AuthenticationException</code> immediately if
- * the presented credentials are incorrect (this is especially useful if it
- * is necessary to bind to a resource as the user in order to obtain or
- * generate a <code>UserDetails</code>).
- *
- * @param username
- * The username to retrieve
- * @param details
- * The details from the authentication request.
- * @see #retrieveUser(String,UsernamePasswordAuthenticationToken)
- * @return the user information (never <code>null</code> - instead an
- * exception should the thrown)
- * @throws AuthenticationException
- * if the credentials could not be validated (generally a
- * <code>BadCredentialsException</code>, an
- * <code>AuthenticationServiceException</code> or
- * <code>UsernameNotFoundException</code>)
- * @throws Exception
- * If something goes wrong. It will be logged and converted into
- * a general AuthenticationException.
- */
- @Nonnull
- protected UserDetails retrieveUser(String username, Object details)
- throws Exception {
- if (details == null || !(details instanceof WebAuthenticationDetails))
- throw new UsernameNotFoundException("context unsupported");
- if (!username.startsWith(PREFIX))
- throw new UsernameNotFoundException(
- "unsupported username for this provider");
- if (logDecisions)
- log.info("request for auth for user " + username);
- String wfid = username.substring(PREFIX.length());
- String securityToken;
- try {
- securityToken = cache.get(wfid);
- if (securityToken == null) {
- securityToken = dao.getSecurityToken(wfid);
- if (securityToken == null)
- throw new UsernameNotFoundException("no such user");
- cache.put(wfid, securityToken);
- }
- } catch (NullPointerException npe) {
- throw new UsernameNotFoundException("no such user");
- }
- return new User(username, securityToken, true, true, true, true,
- Arrays.asList(new LiteralGrantedAuthority(SELF),
- new WorkflowSelfAuthority(wfid)));
- }
-
- @Override
- @PerfLogged
- protected final void additionalAuthenticationChecks(UserDetails userRecord,
- UsernamePasswordAuthenticationToken token) {
- try {
- additionalAuthenticationChecks(userRecord, token.getPrincipal(),
- token.getCredentials());
- } catch (AuthenticationException e) {
- throw e;
- } catch (Exception e) {
- log.warn("unexpected failure in authentication", e);
- throw new AuthenticationServiceException(
- "unexpected failure in authentication", e);
- }
- }
-
- @Override
- @Nonnull
- @PerfLogged
- protected final UserDetails retrieveUser(String username,
- UsernamePasswordAuthenticationToken token) {
- try {
- return retrieveUser(username, token.getDetails());
- } catch (AuthenticationException e) {
- throw e;
- } catch (Exception e) {
- log.warn("unexpected failure in authentication", e);
- throw new AuthenticationServiceException(
- "unexpected failure in authentication", e);
- }
- }
-
- @SuppressWarnings("serial")
- public static class WorkflowSelfAuthority extends LiteralGrantedAuthority {
- public WorkflowSelfAuthority(String wfid) {
- super(wfid);
- }
-
- public String getWorkflowID() {
- return getAuthority();
- }
-
- @Override
- public String toString() {
- return "WORKFLOW(" + getAuthority() + ")";
- }
- }
-
- public static class WorkflowSelfIDMapper implements LocalIdentityMapper {
- private Log log = LogFactory.getLog("Taverna.Server.UserDB");
- private RunStore runStore;
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- @Required
- public void setRunStore(RunStore runStore) {
- this.runStore = runStore;
- }
-
- private String getUsernameForSelfAccess(WorkflowSelfAuthority authority)
- throws UnknownRunException {
- return runStore.getRun(authority.getWorkflowID())
- .getSecurityContext().getOwner().getName();
- }
-
- @Override
- @PerfLogged
- public String getUsernameForPrincipal(UsernamePrincipal user) {
- Authentication auth = SecurityContextHolder.getContext()
- .getAuthentication();
- if (auth == null || !auth.isAuthenticated())
- return null;
- try {
- for (GrantedAuthority authority : auth.getAuthorities())
- if (authority instanceof WorkflowSelfAuthority)
- return getUsernameForSelfAccess((WorkflowSelfAuthority) authority);
- } catch (UnknownRunException e) {
- log.warn("workflow run disappeared during computation of workflow map identity");
- }
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java
deleted file mode 100644
index dd1500a..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Implementations of beans that map global user identities to local
- * usernames.
- */
-package org.taverna.server.master.identity;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java b/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java
deleted file mode 100644
index 99e1d99..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interaction;
-
-import static java.lang.management.ManagementFactory.getPlatformMBeanServer;
-import static java.util.Collections.reverse;
-import static javax.management.Query.attr;
-import static javax.management.Query.match;
-import static javax.management.Query.value;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.annotation.Nullable;
-import javax.annotation.PostConstruct;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.apache.abdera.Abdera;
-import org.apache.abdera.factory.Factory;
-import org.apache.abdera.i18n.iri.IRI;
-import org.apache.abdera.model.Document;
-import org.apache.abdera.model.Entry;
-import org.apache.abdera.model.Feed;
-import org.apache.abdera.parser.Parser;
-import org.apache.abdera.writer.Writer;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.TavernaServerSupport;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-import org.taverna.server.master.utils.FilenameUtils;
-
-/**
- * Bean that supports interaction feeds. This glues together the Abdera
- * serialization engine and the directory-based model used inside the server.
- *
- * @author Donal Fellows
- */
-public class InteractionFeedSupport {
- /**
- * The name of the resource within the run resource that is the run's
- * interaction feed resource.
- */
- public static final String FEED_URL_DIR = "interaction";
- /**
- * The name of the directory below the run working directory that will
- * contain the entries of the interaction feed.
- */
- public static final String FEED_DIR = "feed";
- /**
- * Should the contents of the entry be stripped when describing the overall
- * feed? This makes sense if (and only if) large entries are being pushed
- * through the feed.
- */
- private static final boolean STRIP_CONTENTS = false;
- /** Maximum size of an entry before truncation. */
- private static final long MAX_ENTRY_SIZE = 50 * 1024;
- /** Extension for entry files. */
- private static final String EXT = ".atom";
-
- private TavernaServerSupport support;
- private FilenameUtils utils;
- private Writer writer;
- private Parser parser;
- private Factory factory;
- private UriBuilderFactory uriBuilder;
-
- private AtomicInteger counter = new AtomicInteger();
-
- @Required
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Required
- public void setUtils(FilenameUtils utils) {
- this.utils = utils;
- }
-
- @Required
- public void setAbdera(Abdera abdera) {
- this.factory = abdera.getFactory();
- this.parser = abdera.getParser();
- this.writer = abdera.getWriterFactory().getWriter("prettyxml");
- }
-
- @Required
- // webapp
- public void setUriBuilder(UriBuilderFactory uriBuilder) {
- this.uriBuilder = uriBuilder;
- }
-
- private final Map<String, URL> endPoints = new HashMap<>();
-
- @PostConstruct
- void determinePorts() {
- try {
- MBeanServer mbs = getPlatformMBeanServer();
- for (ObjectName obj : mbs.queryNames(new ObjectName(
- "*:type=Connector,*"),
- match(attr("protocol"), value("HTTP/1.1")))) {
- String scheme = mbs.getAttribute(obj, "scheme").toString();
- String port = obj.getKeyProperty("port");
- endPoints.put(scheme, new URL(scheme + "://localhost:" + port));
- }
- getLog(getClass()).info(
- "installed feed port publication mapping for "
- + endPoints.keySet());
- } catch (Exception e) {
- getLog(getClass()).error(
- "failure in determining local port mapping", e);
- }
- }
-
- /**
- * @param run
- * The workflow run that defines which feed we are operating on.
- * @return The URI of the feed
- */
- public URI getFeedURI(TavernaRun run) {
- return uriBuilder.getRunUriBuilder(run).path(FEED_URL_DIR).build();
- }
-
- @Nullable
- public URL getLocalFeedBase(URI feedURI) {
- if (feedURI == null)
- return null;
- return endPoints.get(feedURI.getScheme());
- }
-
- /**
- * @param run
- * The workflow run that defines which feed we are operating on.
- * @param id
- * The ID of the entry.
- * @return The URI of the entry.
- */
- public URI getEntryURI(TavernaRun run, String id) {
- return uriBuilder.getRunUriBuilder(run)
- .path(FEED_URL_DIR + "/{entryID}").build(id);
- }
-
- private Entry getEntryFromFile(File f) throws FilesystemAccessException {
- long size = f.getSize();
- if (size > MAX_ENTRY_SIZE)
- throw new FilesystemAccessException("entry larger than 50kB");
- byte[] contents = f.getContents(0, (int) size);
- Document<Entry> doc = parser.parse(new ByteArrayInputStream(contents));
- return doc.getRoot();
- }
-
- private void putEntryInFile(Directory dir, String name, Entry contents)
- throws FilesystemAccessException, NoUpdateException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- writer.writeTo(contents, baos);
- } catch (IOException e) {
- throw new NoUpdateException("failed to serialize the ATOM entry", e);
- }
- File f = dir.makeEmptyFile(support.getPrincipal(), name);
- f.appendContents(baos.toByteArray());
- }
-
- private List<DirectoryEntry> listPossibleEntries(TavernaRun run)
- throws FilesystemAccessException, NoDirectoryEntryException {
- List<DirectoryEntry> entries = new ArrayList<>(utils.getDirectory(run,
- FEED_DIR).getContentsByDate());
- reverse(entries);
- return entries;
- }
-
- private String getRunURL(TavernaRun run) {
- return new IRI(uriBuilder.getRunUriBuilder(run).build()).toString();
- }
-
- /**
- * Get the interaction feed for a partciular run.
- *
- * @param run
- * The workflow run that defines which feed we are operating on.
- * @return The Abdera feed descriptor.
- * @throws FilesystemAccessException
- * If the feed directory can't be read for some reason.
- * @throws NoDirectoryEntryException
- * If the feed directory doesn't exist or an entry is
- * unexpectedly removed.
- */
- public Feed getRunFeed(TavernaRun run) throws FilesystemAccessException,
- NoDirectoryEntryException {
- URI feedURI = getFeedURI(run);
- Feed feed = factory.newFeed();
- feed.setTitle("Interactions for Taverna Run \"" + run.getName() + "\"");
- feed.addLink(new IRI(feedURI).toString(), "self");
- feed.addLink(getRunURL(run), "workflowrun");
- boolean fetchedDate = false;
- for (DirectoryEntry de : listPossibleEntries(run)) {
- if (!(de instanceof File))
- continue;
- try {
- Entry e = getEntryFromFile((File) de);
- if (STRIP_CONTENTS)
- e.setContentElement(null);
- feed.addEntry(e);
- if (fetchedDate)
- continue;
- Date last = e.getUpdated();
- if (last == null)
- last = e.getPublished();
- if (last == null)
- last = de.getModificationDate();
- feed.setUpdated(last);
- fetchedDate = true;
- } catch (FilesystemAccessException e) {
- // Can't do anything about it, so we'll just drop the entry.
- }
- }
- return feed;
- }
-
- /**
- * Gets the contents of a particular feed entry.
- *
- * @param run
- * The workflow run that defines which feed we are operating on.
- * @param entryID
- * The identifier (from the path) of the entry to read.
- * @return The description of the entry.
- * @throws FilesystemAccessException
- * If the entry can't be read or is too large.
- * @throws NoDirectoryEntryException
- * If the entry can't be found.
- */
- public Entry getRunFeedEntry(TavernaRun run, String entryID)
- throws FilesystemAccessException, NoDirectoryEntryException {
- File entryFile = utils.getFile(run, FEED_DIR + "/" + entryID + EXT);
- return getEntryFromFile(entryFile);
- }
-
- /**
- * Given a partial feed entry, store a complete feed entry in the filesystem
- * for a particular run. Note that this does not permit update of an
- * existing entry; the entry is always created new.
- *
- * @param run
- * The workflow run that defines which feed we are operating on.
- * @param entry
- * The partial entry to store
- * @return A link to the entry.
- * @throws FilesystemAccessException
- * If the entry can't be stored.
- * @throws NoDirectoryEntryException
- * If the run is improperly configured.
- * @throws NoUpdateException
- * If the user isn't allowed to do the write.
- * @throws MalformedURLException
- * If a generated URL is illegal (shouldn't happen).
- */
- public Entry addRunFeedEntry(TavernaRun run, Entry entry)
- throws FilesystemAccessException, NoDirectoryEntryException,
- NoUpdateException {
- support.permitUpdate(run);
- Date now = new Date();
- entry.newId();
- String localId = "entry_" + counter.incrementAndGet();
- IRI selfLink = new IRI(getEntryURI(run, localId));
- entry.addLink(selfLink.toString(), "self");
- entry.addLink(getRunURL(run), "workflowrun");
- entry.setUpdated(now);
- entry.setPublished(now);
- putEntryInFile(utils.getDirectory(run, FEED_DIR), localId + EXT, entry);
- return getEntryFromFile(utils.getFile(run, FEED_DIR + "/" + localId
- + EXT));
- }
-
- /**
- * Deletes an entry from a feed.
- *
- * @param run
- * The workflow run that defines which feed we are operating on.
- * @param entryID
- * The ID of the entry to delete.
- * @throws FilesystemAccessException
- * If the entry can't be deleted
- * @throws NoDirectoryEntryException
- * If the entry can't be found.
- * @throws NoUpdateException
- * If the current user is not permitted to modify the run's
- * characteristics.
- */
- public void removeRunFeedEntry(TavernaRun run, String entryID)
- throws FilesystemAccessException, NoDirectoryEntryException,
- NoUpdateException {
- support.permitUpdate(run);
- utils.getFile(run, FEED_DIR + "/" + entryID + EXT).destroy();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java
deleted file mode 100644
index 9efc30d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains the Atom feed implementation for interactions for a particular workflow run.
- * @author Donal Fellows
- */
-package org.taverna.server.master.interaction;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java
deleted file mode 100644
index 9a0a84e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.io.PipedInputStream;
-import java.security.Principal;
-import java.util.Collection;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-
-/**
- * Represents a directory that is the working directory of a workflow run, or a
- * sub-directory of it.
- *
- * @author Donal Fellows
- * @see File
- */
-public interface Directory extends DirectoryEntry {
- /**
- * @return A list of the contents of the directory.
- * @throws FilesystemAccessException
- * If things go wrong.
- */
- Collection<DirectoryEntry> getContents() throws FilesystemAccessException;
-
- /**
- * @return A list of the contents of the directory, in guaranteed date
- * order.
- * @throws FilesystemAccessException
- * If things go wrong.
- */
- Collection<DirectoryEntry> getContentsByDate()
- throws FilesystemAccessException;
-
- /**
- * @return The contents of the directory (and its sub-directories) as a zip.
- * @throws FilesystemAccessException
- * If things go wrong.
- */
- ZipStream getContentsAsZip() throws FilesystemAccessException;
-
- /**
- * Creates a sub-directory of this directory.
- *
- * @param actor
- * Who this is being created by.
- * @param name
- * The name of the sub-directory.
- * @return A handle to the newly-created directory.
- * @throws FilesystemAccessException
- * If the name is the same as some existing entry in the
- * directory, or if something else goes wrong during creation.
- */
- Directory makeSubdirectory(Principal actor, String name)
- throws FilesystemAccessException;
-
- /**
- * Creates an empty file in this directory.
- *
- * @param actor
- * Who this is being created by.
- * @param name
- * The name of the file to create.
- * @return A handle to the newly-created file.
- * @throws FilesystemAccessException
- * If the name is the same as some existing entry in the
- * directory, or if something else goes wrong during creation.
- */
- File makeEmptyFile(Principal actor, String name)
- throws FilesystemAccessException;
-
- /**
- * A simple pipe that produces the zipped contents of a directory.
- *
- * @author Donal Fellows
- */
- public static class ZipStream extends PipedInputStream {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java
deleted file mode 100644
index b098152..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.util.Date;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-
-/**
- * An entry in a {@link Directory} representing a file or sub-directory.
- *
- * @author Donal Fellows
- * @see Directory
- * @see File
- */
-public interface DirectoryEntry extends Comparable<DirectoryEntry> {
- /**
- * @return The "local" name of the entry. This will never be "<tt>..</tt>"
- * or contain the character "<tt>/</tt>".
- */
- public String getName();
-
- /**
- * @return The "full" name of the entry. This is computed relative to the
- * workflow run's working directory. It may contain the "<tt>/</tt>"
- * character.
- */
- public String getFullName();
-
- /**
- * @return The time that the entry was last modified.
- */
- public Date getModificationDate();
-
- /**
- * Destroy this directory entry, deleting the file or sub-directory. The
- * workflow run's working directory can never be manually destroyed.
- *
- * @throws FilesystemAccessException
- * If the destroy fails for some reason.
- */
- public void destroy() throws FilesystemAccessException;
- // TODO: Permissions (or decide not to do anything about them)
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java
deleted file mode 100644
index e4e6590..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-
-/**
- * Represents a file in the working directory of a workflow instance run, or in
- * some sub-directory of it.
- *
- * @author Donal Fellows
- * @see Directory
- */
-public interface File extends DirectoryEntry {
- /**
- * @param offset
- * Where in the file to start reading.
- * @param length
- * The length of file to read, or -1 to read to the end of the
- * file.
- * @return The literal byte contents of the section of the file, or null if
- * the section doesn't exist.
- * @throws FilesystemAccessException
- * If the read of the file goes wrong.
- */
- public byte[] getContents(int offset, int length)
- throws FilesystemAccessException;
-
- /**
- * Write the data to the file, totally replacing what was there before.
- *
- * @param data
- * The literal bytes that will form the new contents of the file.
- * @throws FilesystemAccessException
- * If the write to the file goes wrong.
- */
- public void setContents(byte[] data) throws FilesystemAccessException;
-
- /**
- * Append the data to the file.
- *
- * @param data
- * The literal bytes that will be added on to the end of the
- * file.
- * @throws FilesystemAccessException
- * If the write to the file goes wrong.
- */
- public void appendContents(byte[] data) throws FilesystemAccessException;
-
- /**
- * @return The length of the file, in bytes.
- * @throws FilesystemAccessException
- * If the read of the file size goes wrong.
- */
- public long getSize() throws FilesystemAccessException;
-
- /**
- * Asks for the argument file to be copied to this one.
- *
- * @param from
- * The source file.
- * @throws FilesystemAccessException
- * If anything goes wrong.
- */
- public void copy(File from) throws FilesystemAccessException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java
deleted file mode 100644
index 31cb7cb..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-
-/**
- * This represents the assignment of inputs to input ports of the workflow. Note
- * that the <tt>file</tt> and <tt>value</tt> properties are never set at the
- * same time.
- *
- * @author Donal Fellows
- */
-public interface Input {
- /**
- * @return The file currently assigned to this input port, or <tt>null</tt>
- * if no file is assigned.
- */
- @Nullable
- public String getFile();
-
- /**
- * @return The name of this input port. This may not be changed.
- */
- @Nonnull
- public String getName();
-
- /**
- * @return The value currently assigned to this input port, or <tt>null</tt>
- * if no value is assigned.
- */
- @Nullable
- public String getValue();
-
- /**
- * @return The delimiter for the input port, or <tt>null</tt> if the value
- * is not to be split.
- */
- @Nullable
- public String getDelimiter();
-
- /**
- * Sets the file to use for this input. This overrides the use of the
- * previous file and any set value.
- *
- * @param file
- * The filename to use. Must not start with a <tt>/</tt> or
- * contain any <tt>..</tt> segments. Will be interpreted relative
- * to the run's working directory.
- * @throws FilesystemAccessException
- * If the filename is invalid.
- * @throws BadStateChangeException
- * If the run isn't in the {@link Status#Initialized
- * Initialized} state.
- */
- public void setFile(String file) throws FilesystemAccessException,
- BadStateChangeException;
-
- /**
- * Sets the value to use for this input. This overrides the use of the
- * previous value and any set file.
- *
- * @param value
- * The value to use.
- * @throws BadStateChangeException
- * If the run isn't in the {@link Status#Initialized
- * Initialized} state.
- */
- public void setValue(String value) throws BadStateChangeException;
-
- /**
- * Sets (or clears) the delimiter for the input port.
- *
- * @param delimiter
- * The delimiter character, or <tt>null</tt> if the value is not
- * to be split.
- * @throws BadStateChangeException
- * If the run isn't in the {@link Status#Initialized
- * Initialized} state.
- */
- @Nullable
- public void setDelimiter(String delimiter) throws BadStateChangeException;
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java
deleted file mode 100644
index d7998bc..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-import org.taverna.server.master.exceptions.NoListenerException;
-
-/**
- * An event listener that can be attached to a {@link TavernaRun}.
- *
- * @author Donal Fellows
- */
-public interface Listener {
- /**
- * @return The name of the listener.
- */
- public String getName();
-
- /**
- * @return The type of the listener.
- */
- public String getType();
-
- /**
- * @return The configuration document for the listener.
- */
- public String getConfiguration();
-
- /**
- * @return The supported properties of the listener.
- */
- public String[] listProperties();
-
- /**
- * Get the value of a particular property, which should be listed in the
- * {@link #listProperties()} method.
- *
- * @param propName
- * The name of the property to read.
- * @return The value of the property.
- * @throws NoListenerException
- * If no property with that name exists.
- */
- public String getProperty(String propName) throws NoListenerException;
-
- /**
- * Set the value of a particular property, which should be listed in the
- * {@link #listProperties()} method.
- *
- * @param propName
- * The name of the property to write.
- * @param value
- * The value to set the property to.
- * @throws NoListenerException
- * If no property with that name exists.
- * @throws BadPropertyValueException
- * If the value of the property is bad (e.g., wrong syntax).
- */
- public void setProperty(String propName, String value)
- throws NoListenerException, BadPropertyValueException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java
deleted file mode 100644
index 37b104e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * This interface describes how to map from the identity understood by the
- * webapp to the identity understood by the local execution system.
- *
- * @author Donal Fellows
- */
-public interface LocalIdentityMapper {
- /**
- * Given a user's identity, get the local identity to use for executing
- * their workflows. Note that it is assumed that there will never be a
- * failure from this interface; it is <i>not</i> a security policy
- * decision or enforcement point.
- *
- * @param user
- * An identity token.
- * @return A user name, which must be defined in the context that workflows
- * will be running in.
- */
- public String getUsernameForPrincipal(UsernamePrincipal user);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java
deleted file mode 100644
index 37dbf2c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import javax.annotation.Nonnull;
-
-/**
- * The interface supported by all notification message dispatchers.
- * @author Donal Fellows
- */
-public interface MessageDispatcher {
- /**
- * @return Whether this message dispatcher is actually available (fully
- * configured, etc.)
- */
- boolean isAvailable();
-
- /**
- * @return The name of this dispatcher, which must match the protocol
- * supported by it (for a non-universal dispatcher) and the name of
- * the message generator used to produce the message.
- */
- String getName();
-
- /**
- * Dispatch a message to a recipient.
- *
- * @param originator
- * The workflow run that produced the message.
- * @param messageSubject
- * The subject of the message to send.
- * @param messageContent
- * The plain-text content of the message to send.
- * @param targetParameter
- * A description of where it is to go.
- * @throws Exception
- * If anything goes wrong.
- */
- void dispatch(@Nonnull TavernaRun originator,
- @Nonnull String messageSubject, @Nonnull String messageContent,
- @Nonnull String targetParameter) throws Exception;
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java
deleted file mode 100644
index f57fe71..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.net.URI;
-import java.util.List;
-
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Simple policy interface.
- *
- * @author Donal Fellows
- */
-public interface Policy {
- /**
- * @return The maximum number of runs that the system can support.
- */
- int getMaxRuns();
-
- /**
- * Get the limit on the number of runs for this user.
- *
- * @param user
- * Who to get the limit for
- * @return The maximum number of runs for this user, or <tt>null</tt> if no
- * per-user limit is imposed and only system-wide limits are to be
- * enforced.
- */
- Integer getMaxRuns(UsernamePrincipal user);
-
- /**
- * Test whether the user can create an instance of the given workflow.
- *
- * @param user
- * Who wants to do the creation.
- * @param workflow
- * The workflow they wish to instantiate.
- * @throws NoCreateException
- * If they may not instantiate it.
- */
- void permitCreate(UsernamePrincipal user, Workflow workflow)
- throws NoCreateException;
-
- /**
- * Test whether the user can destroy a workflow instance run or manipulate
- * its expiry date.
- *
- * @param user
- * Who wants to do the deletion.
- * @param run
- * What they want to delete.
- * @throws NoDestroyException
- * If they may not destroy it.
- */
- void permitDestroy(UsernamePrincipal user, TavernaRun run)
- throws NoDestroyException;
-
- /**
- * Return whether the user has access to a particular workflow run.
- * <b>Note</b> that this does not throw any exceptions!
- *
- * @param user
- * Who wants to read the workflow's state.
- * @param run
- * What do they want to read from.
- * @return Whether they can read it. Note that this check is always applied
- * before testing whether the workflow can be updated or deleted by
- * the user.
- */
- boolean permitAccess(UsernamePrincipal user, TavernaRun run);
-
- /**
- * Test whether the user can modify a workflow run (other than for its
- * expiry date).
- *
- * @param user
- * Who wants to do the modification.
- * @param run
- * What they want to modify.
- * @throws NoUpdateException
- * If they may not modify it.
- */
- void permitUpdate(UsernamePrincipal user, TavernaRun run)
- throws NoUpdateException;
-
- /**
- * Get the URIs of the workflows that the given user may execute.
- *
- * @param user
- * Who are we finding out on behalf of.
- * @return A list of workflow URIs that they may instantiate, or
- * <tt>null</tt> if any workflow may be submitted.
- */
- List<URI> listPermittedWorkflowURIs(UsernamePrincipal user);
-
- /**
- * @return The maximum number of {@linkplain Status#Operating operating}
- * runs that the system can support.
- */
- int getOperatingLimit();
-
- /**
- * Set the URIs of the workflows that the given user may execute.
- *
- * @param user
- * Who are we finding out on behalf of.
- * @param permitted
- * A list of workflow URIs that they may instantiate.
- */
- void setPermittedWorkflowURIs(UsernamePrincipal user, List<URI> permitted);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java
deleted file mode 100644
index b5e84c5..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.util.Map;
-
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Interface to the mechanism that looks after the mapping of names to runs.
- * Instances of this class may also be responsible for enforcing timely cleanup
- * of expired workflows.
- *
- * @author Donal Fellows.
- */
-public interface RunStore {
- /**
- * Obtain the workflow run for a given user and name.
- *
- * @param user
- * Who wants to do the lookup.
- * @param p
- * The general policy system context.
- * @param uuid
- * The handle for the run.
- * @return The workflow instance run.
- * @throws UnknownRunException
- * If the lookup fails (either because it does not exist or
- * because it is not permitted for the user by the policy).
- */
- TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
- throws UnknownRunException;
-
- /**
- * Obtain the named workflow run.
- *
- * @param uuid
- * The handle for the run.
- * @return The workflow instance run.
- * @throws UnknownRunException
- * If the lookup fails (either because it does not exist or
- * because it is not permitted for the user by the policy).
- */
- public TavernaRun getRun(String uuid) throws UnknownRunException;
-
- /**
- * List the runs that a particular user may access.
- *
- * @param user
- * Who wants to do the lookup, or <code>null</code> if it is
- * being done "by the system" when the full mapping should be
- * returned.
- * @param p
- * The general policy system context.
- * @return A mapping from run names to run instances.
- */
- Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p);
-
- /**
- * Adds a workflow instance run to the store. Note that this operation is
- * <i>not</i> expected to be security-checked; that is the callers'
- * responsibility.
- *
- * @param run
- * The run itself.
- * @return The name of the run.
- */
- String registerRun(TavernaRun run);
-
- /**
- * Removes a run from the store. Note that this operation is <i>not</i>
- * expected to be security-checked; that is the callers' responsibility.
- *
- * @param uuid
- * The name of the run.
- */
- void unregisterRun(String uuid);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java
deleted file mode 100644
index 902c4d0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.io.Serializable;
-
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * How to create instances of a security context.
- *
- * @author Donal Fellows
- */
-public interface SecurityContextFactory extends Serializable {
- /**
- * Creates a security context.
- *
- * @param run
- * Handle to remote run. Allows the security context to know how
- * to apply itself to the workflow run.
- * @param owner
- * The identity of the owner of the workflow run.
- * @return The security context.
- * @throws Exception
- * If anything goes wrong.
- */
- TavernaSecurityContext create(TavernaRun run, UsernamePrincipal owner)
- throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java
deleted file mode 100644
index 399164d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.io.Serializable;
-import java.util.Date;
-import java.util.List;
-
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-
-/**
- * The interface to a taverna workflow run, or "run" for short.
- *
- * @author Donal Fellows
- */
-public interface TavernaRun extends Serializable {
- /**
- * @return The identifier of the run.
- */
- String getId();
-
- /**
- * @return What was this run was create to execute.
- */
- Workflow getWorkflow();
-
- /**
- * @return The name of the run.
- */
- String getName();
-
- /**
- * @param name
- * The new name of the run. May be truncated.
- */
- void setName(String name);
-
- /**
- * @return The name of the Baclava file to use for all inputs, or
- * <tt>null</tt> if no Baclava file is set.
- */
- String getInputBaclavaFile();
-
- /**
- * Sets the Baclava file to use for all inputs. This overrides the use of
- * individual inputs.
- *
- * @param filename
- * The filename to use. Must not start with a <tt>/</tt> or
- * contain any <tt>..</tt> segments. Will be interpreted relative
- * to the run's working directory.
- * @throws FilesystemAccessException
- * If the filename is invalid.
- * @throws BadStateChangeException
- * If the workflow is not in the {@link Status#Initialized
- * Initialized} state.
- */
- void setInputBaclavaFile(String filename) throws FilesystemAccessException,
- BadStateChangeException;
-
- /**
- * @return The list of input assignments.
- */
- List<Input> getInputs();
-
- /**
- * Create an input assignment.
- *
- * @param name
- * The name of the port that this will be an input for.
- * @return The assignment reference.
- * @throws BadStateChangeException
- * If the workflow is not in the {@link Status#Initialized
- * Initialized} state.
- */
- Input makeInput(String name) throws BadStateChangeException;
-
- /**
- * @return The file (relative to the working directory) to write the outputs
- * of the run to as a Baclava document, or <tt>null</tt> if they are
- * to be written to non-Baclava files in a directory called
- * <tt>out</tt>.
- */
- String getOutputBaclavaFile();
-
- /**
- * Sets where the output of the run is to be written to. This will cause the
- * output to be generated as a Baclava document, rather than a collection of
- * individual non-Baclava files in the subdirectory of the working directory
- * called <tt>out</tt>.
- *
- * @param filename
- * Where to write the Baclava file (or <tt>null</tt> to cause the
- * output to be written to individual files); overwrites any
- * previous setting of this value.
- * @throws FilesystemAccessException
- * If the filename starts with a <tt>/</tt> or contains a
- * <tt>..</tt> segment.
- * @throws BadStateChangeException
- * If the workflow is not in the {@link Status#Initialized
- * Initialized} state.
- */
- void setOutputBaclavaFile(String filename)
- throws FilesystemAccessException, BadStateChangeException;
-
- /**
- * @return When this run will expire, becoming eligible for automated
- * deletion.
- */
- Date getExpiry();
-
- /**
- * Set when this run will expire.
- *
- * @param d
- * Expiry time. Deletion will happen some time after that.
- */
- void setExpiry(Date d);
-
- /**
- * @return The current status of the run.
- */
- Status getStatus();
-
- /**
- * Set the status of the run, which should cause it to move into the given
- * state. This may cause some significant changes.
- *
- * @param s
- * The state to try to change to.
- * @return <tt>null</tt>, or a string describing the incomplete state change
- * if the operation has internally timed out.
- * @throws BadStateChangeException
- * If the change to the given state is impossible.
- */
- String setStatus(Status s) throws BadStateChangeException;
-
- /**
- * @return Handle to the main working directory of the run.
- * @throws FilesystemAccessException
- */
- Directory getWorkingDirectory() throws FilesystemAccessException;
-
- /**
- * @return The list of listener instances attached to the run.
- */
- List<Listener> getListeners();
-
- /**
- * Add a listener to the run.
- *
- * @param listener
- * The listener to add.
- */
- void addListener(Listener listener);
-
- /**
- * @return The security context structure for this run.
- */
- TavernaSecurityContext getSecurityContext();
-
- /**
- * Kill off this run, removing all resources which it consumes.
- *
- * @throws NoDestroyException
- * If the destruction failed.
- */
- void destroy() throws NoDestroyException;
-
- /**
- * @return When this workflow run was created.
- */
- Date getCreationTimestamp();
-
- /**
- * @return When this workflow run was started, or <tt>null</tt> if it has
- * never been started.
- */
- Date getStartTimestamp();
-
- /**
- * @return When this workflow run was found to have finished, or
- * <tt>null</tt> if it has never finished (either still running or
- * never started).
- */
- Date getFinishTimestamp();
-
- /**
- * Test if this run is really there.
- *
- * <p>
- * <i>Implementation note:</i> Used to test communication fabrics, etc. so
- * implementations of this interface that do not delegate to another object
- * should do nothing.
- *
- * @throws UnknownRunException
- * If things fail.
- */
- void ping() throws UnknownRunException;
-
- /**
- * @return whether the run generates provenance data
- */
- boolean getGenerateProvenance();
-
- /**
- * @param generateProvenance
- * whether the run generates provenance data
- */
- void setGenerateProvenance(boolean generateProvenance);
-}
[16/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java
new file mode 100644
index 0000000..06202dc
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/StrippedDownAuthProvider.java
@@ -0,0 +1,278 @@
+package org.taverna.server.master.identity;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.PreDestroy;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.security.authentication.AccountExpiredException;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.CredentialsExpiredException;
+import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.authentication.LockedException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+
+/**
+ * A stripped down version of a
+ * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider
+ * DaoAuthenticationProvider}/
+ * {@link org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
+ * AbstractUserDetailsAuthenticationProvider} that avoids much of the overhead
+ * associated with that class.
+ */
+public class StrippedDownAuthProvider implements AuthenticationProvider {
+ /**
+ * The plaintext password used to perform
+ * {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when
+ * the user is not found to avoid SEC-2056.
+ */
+ private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
+
+ /**
+ * The password used to perform
+ * {@link PasswordEncoder#isPasswordValid(String, String, Object)} on when
+ * the user is not found to avoid SEC-2056. This is necessary, because some
+ * {@link PasswordEncoder} implementations will short circuit if the
+ * password is not in a valid format.
+ */
+ private String userNotFoundEncodedPassword;
+ private UserDetailsService userDetailsService;
+ private PasswordEncoder passwordEncoder;
+ private Map<String, AuthCacheEntry> authCache = new HashMap<>();
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private static class AuthCacheEntry {
+ private String creds;
+ private long timestamp;
+ private static final long VALIDITY = 1000 * 60 * 20;
+ AuthCacheEntry(String credentials) {
+ creds = credentials;
+ timestamp = System.currentTimeMillis();
+ }
+ boolean valid(String password) {
+ return creds.equals(password) && timestamp+VALIDITY > System.currentTimeMillis();
+ }
+ }
+
+ @PerfLogged
+ @Override
+ public Authentication authenticate(Authentication authentication)
+ throws AuthenticationException {
+
+ if (!(authentication instanceof UsernamePasswordAuthenticationToken))
+ throw new IllegalArgumentException(
+ "can only authenticate against username+password");
+ UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
+
+ // Determine username
+ String username = (auth.getPrincipal() == null) ? "NONE_PROVIDED"
+ : auth.getName();
+
+ UserDetails user;
+
+ try {
+ user = retrieveUser(username, auth);
+ if (user == null)
+ throw new IllegalStateException(
+ "retrieveUser returned null - a violation of the interface contract");
+ } catch (UsernameNotFoundException notFound) {
+ if (logger.isDebugEnabled())
+ logger.debug("User '" + username + "' not found", notFound);
+ throw new BadCredentialsException("Bad credentials");
+ }
+
+ // Pre-auth
+ if (!user.isAccountNonLocked())
+ throw new LockedException("User account is locked");
+ if (!user.isEnabled())
+ throw new DisabledException("User account is disabled");
+ if (!user.isAccountNonExpired())
+ throw new AccountExpiredException("User account has expired");
+ Object credentials = auth.getCredentials();
+ if (credentials == null) {
+ logger.debug("Authentication failed: no credentials provided");
+
+ throw new BadCredentialsException("Bad credentials");
+ }
+
+ String providedPassword = credentials.toString();
+ boolean matched = false;
+ synchronized (authCache) {
+ AuthCacheEntry pw = authCache.get(username);
+ if (pw != null && providedPassword != null) {
+ if (pw.valid(providedPassword))
+ matched = true;
+ else
+ authCache.remove(username);
+ }
+ }
+ // Auth
+ if (!matched) {
+ if (!passwordEncoder.matches(providedPassword, user.getPassword())) {
+ logger.debug("Authentication failed: password does not match stored value");
+
+ throw new BadCredentialsException("Bad credentials");
+ }
+ if (providedPassword != null)
+ synchronized (authCache) {
+ authCache.put(username, new AuthCacheEntry(providedPassword));
+ }
+ }
+
+ // Post-auth
+ if (!user.isCredentialsNonExpired())
+ throw new CredentialsExpiredException(
+ "User credentials have expired");
+
+ return createSuccessAuthentication(user, auth, user);
+ }
+
+ @PreDestroy
+ void clearCache() {
+ authCache.clear();
+ }
+
+ /**
+ * Creates a successful {@link Authentication} object.
+ * <p>
+ * Protected so subclasses can override.
+ * </p>
+ * <p>
+ * Subclasses will usually store the original credentials the user supplied
+ * (not salted or encoded passwords) in the returned
+ * <code>Authentication</code> object.
+ * </p>
+ *
+ * @param principal
+ * that should be the principal in the returned object (defined
+ * by the {@link #isForcePrincipalAsString()} method)
+ * @param authentication
+ * that was presented to the provider for validation
+ * @param user
+ * that was loaded by the implementation
+ *
+ * @return the successful authentication token
+ */
+ private Authentication createSuccessAuthentication(Object principal,
+ Authentication authentication, UserDetails user) {
+ /*
+ * Ensure we return the original credentials the user supplied, so
+ * subsequent attempts are successful even with encoded passwords. Also
+ * ensure we return the original getDetails(), so that future
+ * authentication events after cache expiry contain the details
+ */
+ UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
+ principal, authentication.getCredentials(),
+ user.getAuthorities());
+ result.setDetails(authentication.getDetails());
+
+ return result;
+ }
+
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return UsernamePasswordAuthenticationToken.class
+ .isAssignableFrom(authentication);
+ }
+
+ /**
+ * Allows subclasses to actually retrieve the <code>UserDetails</code> from
+ * an implementation-specific location, with the option of throwing an
+ * <code>AuthenticationException</code> immediately if the presented
+ * credentials are incorrect (this is especially useful if it is necessary
+ * to bind to a resource as the user in order to obtain or generate a
+ * <code>UserDetails</code>).
+ * <p>
+ * Subclasses are not required to perform any caching, as the
+ * <code>AbstractUserDetailsAuthenticationProvider</code> will by default
+ * cache the <code>UserDetails</code>. The caching of
+ * <code>UserDetails</code> does present additional complexity as this means
+ * subsequent requests that rely on the cache will need to still have their
+ * credentials validated, even if the correctness of credentials was assured
+ * by subclasses adopting a binding-based strategy in this method.
+ * Accordingly it is important that subclasses either disable caching (if
+ * they want to ensure that this method is the only method that is capable
+ * of authenticating a request, as no <code>UserDetails</code> will ever be
+ * cached) or ensure subclasses implement
+ * {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)}
+ * to compare the credentials of a cached <code>UserDetails</code> with
+ * subsequent authentication requests.
+ * </p>
+ * <p>
+ * Most of the time subclasses will not perform credentials inspection in
+ * this method, instead performing it in
+ * {@link #additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken)}
+ * so that code related to credentials validation need not be duplicated
+ * across two methods.
+ * </p>
+ *
+ * @param username
+ * The username to retrieve
+ * @param authentication
+ * The authentication request, which subclasses <em>may</em> need
+ * to perform a binding-based retrieval of the
+ * <code>UserDetails</code>
+ *
+ * @return the user information (never <code>null</code> - instead an
+ * exception should the thrown)
+ *
+ * @throws AuthenticationException
+ * if the credentials could not be validated (generally a
+ * <code>BadCredentialsException</code>, an
+ * <code>AuthenticationServiceException</code> or
+ * <code>UsernameNotFoundException</code>)
+ */
+ private UserDetails retrieveUser(String username,
+ UsernamePasswordAuthenticationToken authentication)
+ throws AuthenticationException {
+ try {
+ return userDetailsService.loadUserByUsername(username);
+ } catch (UsernameNotFoundException notFound) {
+ if (authentication.getCredentials() != null) {
+ String presentedPassword = authentication.getCredentials()
+ .toString();
+ passwordEncoder.matches(presentedPassword,
+ userNotFoundEncodedPassword);
+ }
+ throw notFound;
+ } catch (AuthenticationException e) {
+ throw e;
+ } catch (Exception repositoryProblem) {
+ throw new AuthenticationServiceException(
+ repositoryProblem.getMessage(), repositoryProblem);
+ }
+ }
+
+ /**
+ * Sets the PasswordEncoder instance to be used to encode and validate
+ * passwords.
+ */
+ @Required
+ public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
+ if (passwordEncoder == null)
+ throw new IllegalArgumentException("passwordEncoder cannot be null");
+
+ this.passwordEncoder = passwordEncoder;
+ this.userNotFoundEncodedPassword = passwordEncoder
+ .encode(USER_NOT_FOUND_PASSWORD);
+ }
+
+ @Required
+ public void setUserDetailsService(UserDetailsService userDetailsService) {
+ if (userDetailsService == null)
+ throw new IllegalStateException("A UserDetailsService must be set");
+ this.userDetailsService = userDetailsService;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/User.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/User.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/User.java
new file mode 100644
index 0000000..bdb6e40
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/User.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.identity;
+
+import static org.taverna.server.master.common.Roles.ADMIN;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.Query;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * The representation of a user in the database.
+ * <p>
+ * A user consists logically of a (non-ordered) tuple of items:
+ * <ul>
+ * <li>The {@linkplain #getUsername() user name},
+ * <li>The {@linkplain #getPassword() user's password} (salted, encoded),
+ * <li>Whether the user is {@linkplain #isEnabled() enabled} (i.e., able to log
+ * in),
+ * <li>Whether the user has {@linkplain #isAdmin() administrative privileges}, and
+ * <li>What {@linkplain #getLocalUsername() system (Unix) account} the user's
+ * workflows will run as; separation between different users that are mapped to
+ * the same system account is nothing like as strongly enforced.
+ * </ul>
+ *
+ * @author Donal Fellows
+ */
+@PersistenceCapable(schema = "USERS", table = "LIST")
+@Query(name = "users", language = "SQL", value = "SELECT id FROM USERS.LIST ORDER BY id", resultClass = String.class)
+@XmlRootElement
+@XmlType(name = "User", propOrder = {})
+@SuppressWarnings("serial")
+public class User implements UserDetails {
+ @XmlElement
+ @Persistent
+ private boolean disabled;
+ @XmlElement(name = "username", required = true)
+ @Persistent(primaryKey = "true")
+ private String id;
+ @XmlElement(name = "password", required = true)
+ @Persistent(column = "password")
+ private String encodedPassword;
+ @XmlElement
+ @Persistent
+ private boolean admin;
+ @XmlElement
+ @Persistent
+ private String localUsername;
+
+ @Override
+ public Collection<GrantedAuthority> getAuthorities() {
+ List<GrantedAuthority> auths = new ArrayList<>();
+ auths.add(new LiteralGrantedAuthority(USER));
+ if (admin)
+ auths.add(new LiteralGrantedAuthority(ADMIN));
+ if (localUsername != null)
+ auths.add(new LiteralGrantedAuthority(AUTHORITY_PREFIX
+ + localUsername));
+ return auths;
+ }
+
+ @Override
+ public String getPassword() {
+ return encodedPassword;
+ }
+
+ @Override
+ public String getUsername() {
+ return id;
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return !disabled;
+ }
+
+ void setDisabled(boolean disabled) {
+ this.disabled = disabled;
+ }
+
+ void setUsername(String username) {
+ this.id = username;
+ }
+
+ void setEncodedPassword(String password) {
+ this.encodedPassword = password;
+ }
+
+ void setAdmin(boolean admin) {
+ this.admin = admin;
+ }
+
+ public boolean isAdmin() {
+ return admin;
+ }
+
+ void setLocalUsername(String localUsername) {
+ this.localUsername = localUsername;
+ }
+
+ public String getLocalUsername() {
+ return localUsername;
+ }
+}
+
+@SuppressWarnings("serial")
+class LiteralGrantedAuthority implements GrantedAuthority {
+ private String auth;
+
+ LiteralGrantedAuthority(String auth) {
+ this.auth = auth;
+ }
+
+ @Override
+ public String getAuthority() {
+ return auth;
+ }
+
+ @Override
+ public String toString() {
+ return "AUTHORITY(" + auth + ")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java
new file mode 100644
index 0000000..054d932
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStore.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2011-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.identity;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+import static org.taverna.server.master.common.Roles.ADMIN;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.jdo.annotations.PersistenceAware;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedOperation;
+import org.springframework.jmx.export.annotation.ManagedOperationParameter;
+import org.springframework.jmx.export.annotation.ManagedOperationParameters;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.core.userdetails.memory.UserAttribute;
+import org.springframework.security.core.userdetails.memory.UserAttributeEditor;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.JDOSupport;
+
+/**
+ * The bean class that is responsible for managing the users in the database.
+ *
+ * @author Donal Fellows
+ */
+@PersistenceAware
+@ManagedResource(objectName = JMX_ROOT + "Users", description = "The user database.")
+public class UserStore extends JDOSupport<User> implements UserDetailsService,
+ UserStoreAPI {
+ /** The logger for the user store. */
+ private transient Log log = getLog("Taverna.Server.UserDB");
+
+ public UserStore() {
+ super(User.class);
+ }
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ private Map<String, BootstrapUserInfo> base = new HashMap<>();
+ private String defLocalUser;
+ private PasswordEncoder encoder;
+ private volatile int epoch;
+
+ /**
+ * Install the encoder that will be used to turn a plaintext password into
+ * something that it is safe to store in the database.
+ *
+ * @param encoder
+ * The password encoder bean to install.
+ */
+ public void setEncoder(PasswordEncoder encoder) {
+ this.encoder = encoder;
+ }
+
+ public void setBaselineUserProperties(Properties props) {
+ UserAttributeEditor parser = new UserAttributeEditor();
+
+ for (Object name : props.keySet()) {
+ String username = (String) name;
+ String value = props.getProperty(username);
+
+ // Convert value to a password, enabled setting, and list of granted
+ // authorities
+ parser.setAsText(value);
+
+ UserAttribute attr = (UserAttribute) parser.getValue();
+ if (attr != null && attr.isEnabled())
+ base.put(username, new BootstrapUserInfo(username, attr));
+ }
+ }
+
+ private void installPassword(User u, String password) {
+ u.setEncodedPassword(encoder.encode(password));
+ }
+
+ public void setDefaultLocalUser(String defLocalUser) {
+ this.defLocalUser = defLocalUser;
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<String> getUsers() {
+ return (List<String>) namedQuery("users").execute();
+ }
+
+ @WithinSingleTransaction
+ @PostConstruct
+ void initDB() {
+ if (base == null || base.isEmpty())
+ log.warn("no baseline user collection");
+ else if (!getUsers().isEmpty())
+ log.info("using existing users from database");
+ else
+ for (String username : base.keySet()) {
+ BootstrapUserInfo ud = base.get(username);
+ if (ud == null)
+ continue;
+ User u = ud.get(encoder);
+ if (u == null)
+ continue;
+ log.info("bootstrapping user " + username + " in the database");
+ persist(u);
+ }
+ base = null;
+ epoch++;
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedAttribute(description = "The list of server accounts known about.", currencyTimeLimit = 30)
+ public List<String> getUserNames() {
+ return getUsers();
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ public User getUser(String userName) {
+ return detach(getById(userName));
+ }
+
+ /**
+ * Get information about a server account.
+ *
+ * @param userName
+ * The username to look up.
+ * @return A description map intended for use by a server admin over JMX.
+ */
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Get information about a server account.")
+ @ManagedOperationParameters(@ManagedOperationParameter(name = "userName", description = "The username to look up."))
+ public Map<String, String> getUserInfo(String userName) {
+ User u = getById(userName);
+ Map<String, String> info = new HashMap<>();
+ info.put("name", u.getUsername());
+ info.put("admin", u.isAdmin() ? "yes" : "no");
+ info.put("enabled", u.isEnabled() ? "yes" : "no");
+ info.put("localID", u.getLocalUsername());
+ return info;
+ }
+
+ /**
+ * Get a list of all the users in the database.
+ *
+ * @return A list of user details, <i>copied</i> out of the database.
+ */
+ @PerfLogged
+ @WithinSingleTransaction
+ public List<UserDetails> listUsers() {
+ ArrayList<UserDetails> result = new ArrayList<>();
+ for (String id : getUsers())
+ result.add(detach(getById(id)));
+ return result;
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Create a new user account; the account will be disabled and "
+ + "non-administrative by default. Does not create any underlying system account.")
+ @ManagedOperationParameters({
+ @ManagedOperationParameter(name = "username", description = "The username to create."),
+ @ManagedOperationParameter(name = "password", description = "The password to use."),
+ @ManagedOperationParameter(name = "coupleLocalUsername", description = "Whether to set the local user name to the 'main' one.") })
+ public void addUser(String username, String password,
+ boolean coupleLocalUsername) {
+ if (username.matches(".*[^a-zA-Z0-9].*"))
+ throw new IllegalArgumentException(
+ "bad user name; must be pure alphanumeric");
+ if (getById(username) != null)
+ throw new IllegalArgumentException("user name already exists");
+ User u = new User();
+ u.setDisabled(true);
+ u.setAdmin(false);
+ u.setUsername(username);
+ installPassword(u, password);
+ if (coupleLocalUsername)
+ u.setLocalUsername(username);
+ else
+ u.setLocalUsername(defLocalUser);
+ log.info("creating user for " + username);
+ persist(u);
+ epoch++;
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Set or clear whether this account is enabled. "
+ + "Disabled accounts cannot be used to log in.")
+ @ManagedOperationParameters({
+ @ManagedOperationParameter(name = "username", description = "The username to adjust."),
+ @ManagedOperationParameter(name = "enabled", description = "Whether to enable the account.") })
+ public void setUserEnabled(String username, boolean enabled) {
+ User u = getById(username);
+ if (u != null) {
+ u.setDisabled(!enabled);
+ log.info((enabled ? "enabling" : "disabling") + " user " + username);
+ epoch++;
+ }
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Set or clear the mark on an account that indicates "
+ + "that it has administrative privileges.")
+ @ManagedOperationParameters({
+ @ManagedOperationParameter(name = "username", description = "The username to adjust."),
+ @ManagedOperationParameter(name = "admin", description = "Whether the account has admin privileges.") })
+ public void setUserAdmin(String username, boolean admin) {
+ User u = getById(username);
+ if (u != null) {
+ u.setAdmin(admin);
+ log.info((admin ? "enabling" : "disabling") + " user " + username
+ + " admin status");
+ epoch++;
+ }
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Change the password for an account.")
+ @ManagedOperationParameters({
+ @ManagedOperationParameter(name = "username", description = "The username to adjust."),
+ @ManagedOperationParameter(name = "password", description = "The new password to use.") })
+ public void setUserPassword(String username, String password) {
+ User u = getById(username);
+ if (u != null) {
+ installPassword(u, password);
+ log.info("changing password for user " + username);
+ epoch++;
+ }
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Change what local system account to use for a server account.")
+ @ManagedOperationParameters({
+ @ManagedOperationParameter(name = "username", description = "The username to adjust."),
+ @ManagedOperationParameter(name = "password", description = "The new local user account use.") })
+ public void setUserLocalUser(String username, String localUsername) {
+ User u = getById(username);
+ if (u != null) {
+ u.setLocalUsername(localUsername);
+ log.info("mapping user " + username + " to local account "
+ + localUsername);
+ epoch++;
+ }
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ @ManagedOperation(description = "Delete a server account. The underlying "
+ + "system account is not modified.")
+ @ManagedOperationParameters(@ManagedOperationParameter(name = "username", description = "The username to delete."))
+ public void deleteUser(String username) {
+ delete(getById(username));
+ log.info("deleting user " + username);
+ epoch++;
+ }
+
+ @Override
+ @PerfLogged
+ @WithinSingleTransaction
+ public UserDetails loadUserByUsername(String username)
+ throws UsernameNotFoundException, DataAccessException {
+ User u;
+ if (base != null) {
+ log.warn("bootstrap user store still installed!");
+ BootstrapUserInfo ud = base.get(username);
+ if (ud != null) {
+ log.warn("retrieved production credentials for " + username
+ + " from bootstrap store");
+ u = ud.get(encoder);
+ if (u != null)
+ return u;
+ }
+ }
+ try {
+ u = detach(getById(username));
+ } catch (NullPointerException npe) {
+ throw new UsernameNotFoundException("who are you?");
+ } catch (Exception ex) {
+ throw new UsernameNotFoundException("who are you?", ex);
+ }
+ if (u != null)
+ return u;
+ throw new UsernameNotFoundException("who are you?");
+ }
+
+ int getEpoch() {
+ return epoch;
+ }
+
+ public static class CachedUserStore implements UserDetailsService {
+ private int epoch;
+ private Map<String, UserDetails> cache = new HashMap<>();
+ private UserStore realStore;
+
+ @Required
+ public void setRealStore(UserStore store) {
+ this.realStore = store;
+ }
+
+ @Override
+ @PerfLogged
+ public UserDetails loadUserByUsername(String username) {
+ int epoch = realStore.getEpoch();
+ UserDetails details;
+ synchronized (cache) {
+ if (epoch != this.epoch) {
+ cache.clear();
+ this.epoch = epoch;
+ details = null;
+ } else
+ details = cache.get(username);
+ }
+ if (details == null) {
+ details = realStore.loadUserByUsername(username);
+ synchronized (cache) {
+ cache.put(username, details);
+ }
+ }
+ return details;
+ }
+ }
+
+ private static class BootstrapUserInfo {
+ private String user;
+ private String pass;
+ private Collection<GrantedAuthority> auth;
+
+ BootstrapUserInfo(String username, UserAttribute attr) {
+ user = username;
+ pass = attr.getPassword();
+ auth = attr.getAuthorities();
+ }
+
+ User get(PasswordEncoder encoder) {
+ User u = new User();
+ boolean realUser = false;
+ for (GrantedAuthority ga : auth) {
+ String a = ga.getAuthority();
+ if (a.startsWith(AUTHORITY_PREFIX))
+ u.setLocalUsername(a.substring(AUTHORITY_PREFIX.length()));
+ else if (a.equals(USER))
+ realUser = true;
+ else if (a.equals(ADMIN))
+ u.setAdmin(true);
+ }
+ if (!realUser)
+ return null;
+ u.setUsername(user);
+ u.setEncodedPassword(encoder.encode(pass));
+ u.setDisabled(false);
+ return u;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java
new file mode 100644
index 0000000..a048da9
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/UserStoreAPI.java
@@ -0,0 +1,91 @@
+package org.taverna.server.master.identity;
+
+import java.util.List;
+
+/**
+ * The API that is exposed by the DAO that exposes user management.
+ *
+ * @author Donal Fellows
+ * @see User
+ */
+public interface UserStoreAPI {
+ /**
+ * List the currently-known account names.
+ *
+ * @return A list of users in the database. Note that this is a snapshot.
+ */
+ List<String> getUserNames();
+
+ /**
+ * Get a particular user's description.
+ *
+ * @param userName
+ * The username to look up.
+ * @return A <i>copy</i> of the user description.
+ */
+ User getUser(String userName);
+
+ /**
+ * Create a new user account; the account will be disabled and
+ * non-administrative by default. Does not create any underlying system
+ * account.
+ *
+ * @param username
+ * The username to create.
+ * @param password
+ * The password to use.
+ * @param coupleLocalUsername
+ * Whether to set the local user name to the 'main' one.
+ */
+ void addUser(String username, String password, boolean coupleLocalUsername);
+
+ /**
+ * Set or clear whether this account is enabled. Disabled accounts cannot be
+ * used to log in.
+ *
+ * @param username
+ * The username to adjust.
+ * @param enabled
+ * Whether to enable the account.
+ */
+ void setUserEnabled(String username, boolean enabled);
+
+ /**
+ * Set or clear the mark on an account that indicates that it has
+ * administrative privileges.
+ *
+ * @param username
+ * The username to adjust.
+ * @param admin
+ * Whether the account has admin privileges.
+ */
+ void setUserAdmin(String username, boolean admin);
+
+ /**
+ * Change the password for an account.
+ *
+ * @param username
+ * The username to adjust.
+ * @param password
+ * The new password to use.
+ */
+ void setUserPassword(String username, String password);
+
+ /**
+ * Change what local system account to use for a server account.
+ *
+ * @param username
+ * The username to adjust.
+ * @param localUsername
+ * The new local user account use.
+ */
+ void setUserLocalUser(String username, String localUsername);
+
+ /**
+ * Delete a server account. The underlying system account is not modified.
+ *
+ * @param username
+ * The username to delete.
+ */
+ void deleteUser(String username);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java
new file mode 100644
index 0000000..9219a60
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/WorkflowInternalAuthProvider.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE.txt" for license terms.
+ */
+package org.taverna.server.master.identity;
+
+import static java.util.Collections.synchronizedMap;
+import static org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes;
+import static org.taverna.server.master.common.Roles.SELF;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.interfaces.RunStore;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.UsernamePrincipal;
+import org.taverna.server.master.worker.RunDatabaseDAO;
+
+/**
+ * A special authentication provider that allows a workflow to authenticate to
+ * itself. This is used to allow the workflow to publish to its own interaction
+ * feed.
+ *
+ * @author Donal Fellows
+ */
+public class WorkflowInternalAuthProvider extends
+ AbstractUserDetailsAuthenticationProvider {
+ private Log log = LogFactory.getLog("Taverna.Server.UserDB");
+ private static final boolean logDecisions = true;
+ public static final String PREFIX = "wfrun_";
+ private RunDatabaseDAO dao;
+ private Map<String, String> cache;
+
+ @Required
+ public void setDao(RunDatabaseDAO dao) {
+ this.dao = dao;
+ }
+
+ @Required
+ @SuppressWarnings("serial")
+ public void setCacheBound(final int bound) {
+ cache = synchronizedMap(new LinkedHashMap<String, String>() {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
+ return size() > bound;
+ }
+ });
+ }
+
+ public void setAuthorizedAddresses(String[] addresses) {
+ authorizedAddresses = new HashSet<>(localAddresses);
+ for (String s : addresses)
+ authorizedAddresses.add(s);
+ }
+
+ @PostConstruct
+ public void logConfig() {
+ log.info("authorized addresses for automatic access: "
+ + authorizedAddresses);
+ }
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ private final Set<String> localAddresses = new HashSet<>();
+ private Set<String> authorizedAddresses;
+ {
+ localAddresses.add("127.0.0.1"); // IPv4
+ localAddresses.add("::1"); // IPv6
+ try {
+ InetAddress addr = InetAddress.getLocalHost();
+ if (!addr.isLoopbackAddress())
+ localAddresses.add(addr.getHostAddress());
+ } catch (UnknownHostException e) {
+ // Ignore the exception
+ }
+ authorizedAddresses = new HashSet<>(localAddresses);
+ }
+
+ /**
+ * Check that the authentication request is actually valid for the given
+ * user record.
+ *
+ * @param userRecord
+ * as retrieved from the
+ * {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)}
+ * or <code>UserCache</code>
+ * @param principal
+ * the principal that is trying to authenticate (and that we're
+ * trying to bind)
+ * @param credentials
+ * the credentials (e.g., password) presented by the principal
+ *
+ * @throws AuthenticationException
+ * AuthenticationException if the credentials could not be
+ * validated (generally a <code>BadCredentialsException</code>,
+ * an <code>AuthenticationServiceException</code>)
+ * @throws Exception
+ * If something goes wrong. Will be logged and converted to a
+ * generic AuthenticationException.
+ */
+ protected void additionalAuthenticationChecks(UserDetails userRecord,
+ @Nonnull Object principal, @Nonnull Object credentials)
+ throws Exception {
+ @Nonnull
+ HttpServletRequest req = ((ServletRequestAttributes) currentRequestAttributes())
+ .getRequest();
+
+ // Are we coming from a "local" address?
+ if (!req.getLocalAddr().equals(req.getRemoteAddr())
+ && !authorizedAddresses.contains(req.getRemoteAddr())) {
+ if (logDecisions)
+ log.info("attempt to use workflow magic token from untrusted address:"
+ + " token="
+ + userRecord.getUsername()
+ + ", address="
+ + req.getRemoteAddr());
+ throw new BadCredentialsException("bad login token");
+ }
+
+ // Does the password match?
+ if (!credentials.equals(userRecord.getPassword())) {
+ if (logDecisions)
+ log.info("workflow magic token is untrusted due to password mismatch:"
+ + " wanted="
+ + userRecord.getPassword()
+ + ", got="
+ + credentials);
+ throw new BadCredentialsException("bad login token");
+ }
+
+ if (logDecisions)
+ log.info("granted role " + SELF + " to user "
+ + userRecord.getUsername());
+ }
+
+ /**
+ * Retrieve the <code>UserDetails</code> from the relevant store, with the
+ * option of throwing an <code>AuthenticationException</code> immediately if
+ * the presented credentials are incorrect (this is especially useful if it
+ * is necessary to bind to a resource as the user in order to obtain or
+ * generate a <code>UserDetails</code>).
+ *
+ * @param username
+ * The username to retrieve
+ * @param details
+ * The details from the authentication request.
+ * @see #retrieveUser(String,UsernamePasswordAuthenticationToken)
+ * @return the user information (never <code>null</code> - instead an
+ * exception should the thrown)
+ * @throws AuthenticationException
+ * if the credentials could not be validated (generally a
+ * <code>BadCredentialsException</code>, an
+ * <code>AuthenticationServiceException</code> or
+ * <code>UsernameNotFoundException</code>)
+ * @throws Exception
+ * If something goes wrong. It will be logged and converted into
+ * a general AuthenticationException.
+ */
+ @Nonnull
+ protected UserDetails retrieveUser(String username, Object details)
+ throws Exception {
+ if (details == null || !(details instanceof WebAuthenticationDetails))
+ throw new UsernameNotFoundException("context unsupported");
+ if (!username.startsWith(PREFIX))
+ throw new UsernameNotFoundException(
+ "unsupported username for this provider");
+ if (logDecisions)
+ log.info("request for auth for user " + username);
+ String wfid = username.substring(PREFIX.length());
+ String securityToken;
+ try {
+ securityToken = cache.get(wfid);
+ if (securityToken == null) {
+ securityToken = dao.getSecurityToken(wfid);
+ if (securityToken == null)
+ throw new UsernameNotFoundException("no such user");
+ cache.put(wfid, securityToken);
+ }
+ } catch (NullPointerException npe) {
+ throw new UsernameNotFoundException("no such user");
+ }
+ return new User(username, securityToken, true, true, true, true,
+ Arrays.asList(new LiteralGrantedAuthority(SELF),
+ new WorkflowSelfAuthority(wfid)));
+ }
+
+ @Override
+ @PerfLogged
+ protected final void additionalAuthenticationChecks(UserDetails userRecord,
+ UsernamePasswordAuthenticationToken token) {
+ try {
+ additionalAuthenticationChecks(userRecord, token.getPrincipal(),
+ token.getCredentials());
+ } catch (AuthenticationException e) {
+ throw e;
+ } catch (Exception e) {
+ log.warn("unexpected failure in authentication", e);
+ throw new AuthenticationServiceException(
+ "unexpected failure in authentication", e);
+ }
+ }
+
+ @Override
+ @Nonnull
+ @PerfLogged
+ protected final UserDetails retrieveUser(String username,
+ UsernamePasswordAuthenticationToken token) {
+ try {
+ return retrieveUser(username, token.getDetails());
+ } catch (AuthenticationException e) {
+ throw e;
+ } catch (Exception e) {
+ log.warn("unexpected failure in authentication", e);
+ throw new AuthenticationServiceException(
+ "unexpected failure in authentication", e);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static class WorkflowSelfAuthority extends LiteralGrantedAuthority {
+ public WorkflowSelfAuthority(String wfid) {
+ super(wfid);
+ }
+
+ public String getWorkflowID() {
+ return getAuthority();
+ }
+
+ @Override
+ public String toString() {
+ return "WORKFLOW(" + getAuthority() + ")";
+ }
+ }
+
+ public static class WorkflowSelfIDMapper implements LocalIdentityMapper {
+ private Log log = LogFactory.getLog("Taverna.Server.UserDB");
+ private RunStore runStore;
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ @Required
+ public void setRunStore(RunStore runStore) {
+ this.runStore = runStore;
+ }
+
+ private String getUsernameForSelfAccess(WorkflowSelfAuthority authority)
+ throws UnknownRunException {
+ return runStore.getRun(authority.getWorkflowID())
+ .getSecurityContext().getOwner().getName();
+ }
+
+ @Override
+ @PerfLogged
+ public String getUsernameForPrincipal(UsernamePrincipal user) {
+ Authentication auth = SecurityContextHolder.getContext()
+ .getAuthentication();
+ if (auth == null || !auth.isAuthenticated())
+ return null;
+ try {
+ for (GrantedAuthority authority : auth.getAuthorities())
+ if (authority instanceof WorkflowSelfAuthority)
+ return getUsernameForSelfAccess((WorkflowSelfAuthority) authority);
+ } catch (UnknownRunException e) {
+ log.warn("workflow run disappeared during computation of workflow map identity");
+ }
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java
new file mode 100644
index 0000000..dd1500a
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Implementations of beans that map global user identities to local
+ * usernames.
+ */
+package org.taverna.server.master.identity;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java
new file mode 100644
index 0000000..99e1d99
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/InteractionFeedSupport.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interaction;
+
+import static java.lang.management.ManagementFactory.getPlatformMBeanServer;
+import static java.util.Collections.reverse;
+import static javax.management.Query.attr;
+import static javax.management.Query.match;
+import static javax.management.Query.value;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.annotation.Nullable;
+import javax.annotation.PostConstruct;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.writer.Writer;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.TavernaServerSupport;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+import org.taverna.server.master.utils.FilenameUtils;
+
+/**
+ * Bean that supports interaction feeds. This glues together the Abdera
+ * serialization engine and the directory-based model used inside the server.
+ *
+ * @author Donal Fellows
+ */
+public class InteractionFeedSupport {
+ /**
+ * The name of the resource within the run resource that is the run's
+ * interaction feed resource.
+ */
+ public static final String FEED_URL_DIR = "interaction";
+ /**
+ * The name of the directory below the run working directory that will
+ * contain the entries of the interaction feed.
+ */
+ public static final String FEED_DIR = "feed";
+ /**
+ * Should the contents of the entry be stripped when describing the overall
+ * feed? This makes sense if (and only if) large entries are being pushed
+ * through the feed.
+ */
+ private static final boolean STRIP_CONTENTS = false;
+ /** Maximum size of an entry before truncation. */
+ private static final long MAX_ENTRY_SIZE = 50 * 1024;
+ /** Extension for entry files. */
+ private static final String EXT = ".atom";
+
+ private TavernaServerSupport support;
+ private FilenameUtils utils;
+ private Writer writer;
+ private Parser parser;
+ private Factory factory;
+ private UriBuilderFactory uriBuilder;
+
+ private AtomicInteger counter = new AtomicInteger();
+
+ @Required
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Required
+ public void setUtils(FilenameUtils utils) {
+ this.utils = utils;
+ }
+
+ @Required
+ public void setAbdera(Abdera abdera) {
+ this.factory = abdera.getFactory();
+ this.parser = abdera.getParser();
+ this.writer = abdera.getWriterFactory().getWriter("prettyxml");
+ }
+
+ @Required
+ // webapp
+ public void setUriBuilder(UriBuilderFactory uriBuilder) {
+ this.uriBuilder = uriBuilder;
+ }
+
+ private final Map<String, URL> endPoints = new HashMap<>();
+
+ @PostConstruct
+ void determinePorts() {
+ try {
+ MBeanServer mbs = getPlatformMBeanServer();
+ for (ObjectName obj : mbs.queryNames(new ObjectName(
+ "*:type=Connector,*"),
+ match(attr("protocol"), value("HTTP/1.1")))) {
+ String scheme = mbs.getAttribute(obj, "scheme").toString();
+ String port = obj.getKeyProperty("port");
+ endPoints.put(scheme, new URL(scheme + "://localhost:" + port));
+ }
+ getLog(getClass()).info(
+ "installed feed port publication mapping for "
+ + endPoints.keySet());
+ } catch (Exception e) {
+ getLog(getClass()).error(
+ "failure in determining local port mapping", e);
+ }
+ }
+
+ /**
+ * @param run
+ * The workflow run that defines which feed we are operating on.
+ * @return The URI of the feed
+ */
+ public URI getFeedURI(TavernaRun run) {
+ return uriBuilder.getRunUriBuilder(run).path(FEED_URL_DIR).build();
+ }
+
+ @Nullable
+ public URL getLocalFeedBase(URI feedURI) {
+ if (feedURI == null)
+ return null;
+ return endPoints.get(feedURI.getScheme());
+ }
+
+ /**
+ * @param run
+ * The workflow run that defines which feed we are operating on.
+ * @param id
+ * The ID of the entry.
+ * @return The URI of the entry.
+ */
+ public URI getEntryURI(TavernaRun run, String id) {
+ return uriBuilder.getRunUriBuilder(run)
+ .path(FEED_URL_DIR + "/{entryID}").build(id);
+ }
+
+ private Entry getEntryFromFile(File f) throws FilesystemAccessException {
+ long size = f.getSize();
+ if (size > MAX_ENTRY_SIZE)
+ throw new FilesystemAccessException("entry larger than 50kB");
+ byte[] contents = f.getContents(0, (int) size);
+ Document<Entry> doc = parser.parse(new ByteArrayInputStream(contents));
+ return doc.getRoot();
+ }
+
+ private void putEntryInFile(Directory dir, String name, Entry contents)
+ throws FilesystemAccessException, NoUpdateException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ writer.writeTo(contents, baos);
+ } catch (IOException e) {
+ throw new NoUpdateException("failed to serialize the ATOM entry", e);
+ }
+ File f = dir.makeEmptyFile(support.getPrincipal(), name);
+ f.appendContents(baos.toByteArray());
+ }
+
+ private List<DirectoryEntry> listPossibleEntries(TavernaRun run)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ List<DirectoryEntry> entries = new ArrayList<>(utils.getDirectory(run,
+ FEED_DIR).getContentsByDate());
+ reverse(entries);
+ return entries;
+ }
+
+ private String getRunURL(TavernaRun run) {
+ return new IRI(uriBuilder.getRunUriBuilder(run).build()).toString();
+ }
+
+ /**
+ * Get the interaction feed for a partciular run.
+ *
+ * @param run
+ * The workflow run that defines which feed we are operating on.
+ * @return The Abdera feed descriptor.
+ * @throws FilesystemAccessException
+ * If the feed directory can't be read for some reason.
+ * @throws NoDirectoryEntryException
+ * If the feed directory doesn't exist or an entry is
+ * unexpectedly removed.
+ */
+ public Feed getRunFeed(TavernaRun run) throws FilesystemAccessException,
+ NoDirectoryEntryException {
+ URI feedURI = getFeedURI(run);
+ Feed feed = factory.newFeed();
+ feed.setTitle("Interactions for Taverna Run \"" + run.getName() + "\"");
+ feed.addLink(new IRI(feedURI).toString(), "self");
+ feed.addLink(getRunURL(run), "workflowrun");
+ boolean fetchedDate = false;
+ for (DirectoryEntry de : listPossibleEntries(run)) {
+ if (!(de instanceof File))
+ continue;
+ try {
+ Entry e = getEntryFromFile((File) de);
+ if (STRIP_CONTENTS)
+ e.setContentElement(null);
+ feed.addEntry(e);
+ if (fetchedDate)
+ continue;
+ Date last = e.getUpdated();
+ if (last == null)
+ last = e.getPublished();
+ if (last == null)
+ last = de.getModificationDate();
+ feed.setUpdated(last);
+ fetchedDate = true;
+ } catch (FilesystemAccessException e) {
+ // Can't do anything about it, so we'll just drop the entry.
+ }
+ }
+ return feed;
+ }
+
+ /**
+ * Gets the contents of a particular feed entry.
+ *
+ * @param run
+ * The workflow run that defines which feed we are operating on.
+ * @param entryID
+ * The identifier (from the path) of the entry to read.
+ * @return The description of the entry.
+ * @throws FilesystemAccessException
+ * If the entry can't be read or is too large.
+ * @throws NoDirectoryEntryException
+ * If the entry can't be found.
+ */
+ public Entry getRunFeedEntry(TavernaRun run, String entryID)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ File entryFile = utils.getFile(run, FEED_DIR + "/" + entryID + EXT);
+ return getEntryFromFile(entryFile);
+ }
+
+ /**
+ * Given a partial feed entry, store a complete feed entry in the filesystem
+ * for a particular run. Note that this does not permit update of an
+ * existing entry; the entry is always created new.
+ *
+ * @param run
+ * The workflow run that defines which feed we are operating on.
+ * @param entry
+ * The partial entry to store
+ * @return A link to the entry.
+ * @throws FilesystemAccessException
+ * If the entry can't be stored.
+ * @throws NoDirectoryEntryException
+ * If the run is improperly configured.
+ * @throws NoUpdateException
+ * If the user isn't allowed to do the write.
+ * @throws MalformedURLException
+ * If a generated URL is illegal (shouldn't happen).
+ */
+ public Entry addRunFeedEntry(TavernaRun run, Entry entry)
+ throws FilesystemAccessException, NoDirectoryEntryException,
+ NoUpdateException {
+ support.permitUpdate(run);
+ Date now = new Date();
+ entry.newId();
+ String localId = "entry_" + counter.incrementAndGet();
+ IRI selfLink = new IRI(getEntryURI(run, localId));
+ entry.addLink(selfLink.toString(), "self");
+ entry.addLink(getRunURL(run), "workflowrun");
+ entry.setUpdated(now);
+ entry.setPublished(now);
+ putEntryInFile(utils.getDirectory(run, FEED_DIR), localId + EXT, entry);
+ return getEntryFromFile(utils.getFile(run, FEED_DIR + "/" + localId
+ + EXT));
+ }
+
+ /**
+ * Deletes an entry from a feed.
+ *
+ * @param run
+ * The workflow run that defines which feed we are operating on.
+ * @param entryID
+ * The ID of the entry to delete.
+ * @throws FilesystemAccessException
+ * If the entry can't be deleted
+ * @throws NoDirectoryEntryException
+ * If the entry can't be found.
+ * @throws NoUpdateException
+ * If the current user is not permitted to modify the run's
+ * characteristics.
+ */
+ public void removeRunFeedEntry(TavernaRun run, String entryID)
+ throws FilesystemAccessException, NoDirectoryEntryException,
+ NoUpdateException {
+ support.permitUpdate(run);
+ utils.getFile(run, FEED_DIR + "/" + entryID + EXT).destroy();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java
new file mode 100644
index 0000000..9efc30d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interaction/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains the Atom feed implementation for interactions for a particular workflow run.
+ * @author Donal Fellows
+ */
+package org.taverna.server.master.interaction;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java
new file mode 100644
index 0000000..9a0a84e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Directory.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.io.PipedInputStream;
+import java.security.Principal;
+import java.util.Collection;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+
+/**
+ * Represents a directory that is the working directory of a workflow run, or a
+ * sub-directory of it.
+ *
+ * @author Donal Fellows
+ * @see File
+ */
+public interface Directory extends DirectoryEntry {
+ /**
+ * @return A list of the contents of the directory.
+ * @throws FilesystemAccessException
+ * If things go wrong.
+ */
+ Collection<DirectoryEntry> getContents() throws FilesystemAccessException;
+
+ /**
+ * @return A list of the contents of the directory, in guaranteed date
+ * order.
+ * @throws FilesystemAccessException
+ * If things go wrong.
+ */
+ Collection<DirectoryEntry> getContentsByDate()
+ throws FilesystemAccessException;
+
+ /**
+ * @return The contents of the directory (and its sub-directories) as a zip.
+ * @throws FilesystemAccessException
+ * If things go wrong.
+ */
+ ZipStream getContentsAsZip() throws FilesystemAccessException;
+
+ /**
+ * Creates a sub-directory of this directory.
+ *
+ * @param actor
+ * Who this is being created by.
+ * @param name
+ * The name of the sub-directory.
+ * @return A handle to the newly-created directory.
+ * @throws FilesystemAccessException
+ * If the name is the same as some existing entry in the
+ * directory, or if something else goes wrong during creation.
+ */
+ Directory makeSubdirectory(Principal actor, String name)
+ throws FilesystemAccessException;
+
+ /**
+ * Creates an empty file in this directory.
+ *
+ * @param actor
+ * Who this is being created by.
+ * @param name
+ * The name of the file to create.
+ * @return A handle to the newly-created file.
+ * @throws FilesystemAccessException
+ * If the name is the same as some existing entry in the
+ * directory, or if something else goes wrong during creation.
+ */
+ File makeEmptyFile(Principal actor, String name)
+ throws FilesystemAccessException;
+
+ /**
+ * A simple pipe that produces the zipped contents of a directory.
+ *
+ * @author Donal Fellows
+ */
+ public static class ZipStream extends PipedInputStream {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java
new file mode 100644
index 0000000..b098152
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/DirectoryEntry.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.util.Date;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+
+/**
+ * An entry in a {@link Directory} representing a file or sub-directory.
+ *
+ * @author Donal Fellows
+ * @see Directory
+ * @see File
+ */
+public interface DirectoryEntry extends Comparable<DirectoryEntry> {
+ /**
+ * @return The "local" name of the entry. This will never be "<tt>..</tt>"
+ * or contain the character "<tt>/</tt>".
+ */
+ public String getName();
+
+ /**
+ * @return The "full" name of the entry. This is computed relative to the
+ * workflow run's working directory. It may contain the "<tt>/</tt>"
+ * character.
+ */
+ public String getFullName();
+
+ /**
+ * @return The time that the entry was last modified.
+ */
+ public Date getModificationDate();
+
+ /**
+ * Destroy this directory entry, deleting the file or sub-directory. The
+ * workflow run's working directory can never be manually destroyed.
+ *
+ * @throws FilesystemAccessException
+ * If the destroy fails for some reason.
+ */
+ public void destroy() throws FilesystemAccessException;
+ // TODO: Permissions (or decide not to do anything about them)
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java
new file mode 100644
index 0000000..e4e6590
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/File.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+
+/**
+ * Represents a file in the working directory of a workflow instance run, or in
+ * some sub-directory of it.
+ *
+ * @author Donal Fellows
+ * @see Directory
+ */
+public interface File extends DirectoryEntry {
+ /**
+ * @param offset
+ * Where in the file to start reading.
+ * @param length
+ * The length of file to read, or -1 to read to the end of the
+ * file.
+ * @return The literal byte contents of the section of the file, or null if
+ * the section doesn't exist.
+ * @throws FilesystemAccessException
+ * If the read of the file goes wrong.
+ */
+ public byte[] getContents(int offset, int length)
+ throws FilesystemAccessException;
+
+ /**
+ * Write the data to the file, totally replacing what was there before.
+ *
+ * @param data
+ * The literal bytes that will form the new contents of the file.
+ * @throws FilesystemAccessException
+ * If the write to the file goes wrong.
+ */
+ public void setContents(byte[] data) throws FilesystemAccessException;
+
+ /**
+ * Append the data to the file.
+ *
+ * @param data
+ * The literal bytes that will be added on to the end of the
+ * file.
+ * @throws FilesystemAccessException
+ * If the write to the file goes wrong.
+ */
+ public void appendContents(byte[] data) throws FilesystemAccessException;
+
+ /**
+ * @return The length of the file, in bytes.
+ * @throws FilesystemAccessException
+ * If the read of the file size goes wrong.
+ */
+ public long getSize() throws FilesystemAccessException;
+
+ /**
+ * Asks for the argument file to be copied to this one.
+ *
+ * @param from
+ * The source file.
+ * @throws FilesystemAccessException
+ * If anything goes wrong.
+ */
+ public void copy(File from) throws FilesystemAccessException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java
new file mode 100644
index 0000000..31cb7cb
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Input.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+
+/**
+ * This represents the assignment of inputs to input ports of the workflow. Note
+ * that the <tt>file</tt> and <tt>value</tt> properties are never set at the
+ * same time.
+ *
+ * @author Donal Fellows
+ */
+public interface Input {
+ /**
+ * @return The file currently assigned to this input port, or <tt>null</tt>
+ * if no file is assigned.
+ */
+ @Nullable
+ public String getFile();
+
+ /**
+ * @return The name of this input port. This may not be changed.
+ */
+ @Nonnull
+ public String getName();
+
+ /**
+ * @return The value currently assigned to this input port, or <tt>null</tt>
+ * if no value is assigned.
+ */
+ @Nullable
+ public String getValue();
+
+ /**
+ * @return The delimiter for the input port, or <tt>null</tt> if the value
+ * is not to be split.
+ */
+ @Nullable
+ public String getDelimiter();
+
+ /**
+ * Sets the file to use for this input. This overrides the use of the
+ * previous file and any set value.
+ *
+ * @param file
+ * The filename to use. Must not start with a <tt>/</tt> or
+ * contain any <tt>..</tt> segments. Will be interpreted relative
+ * to the run's working directory.
+ * @throws FilesystemAccessException
+ * If the filename is invalid.
+ * @throws BadStateChangeException
+ * If the run isn't in the {@link Status#Initialized
+ * Initialized} state.
+ */
+ public void setFile(String file) throws FilesystemAccessException,
+ BadStateChangeException;
+
+ /**
+ * Sets the value to use for this input. This overrides the use of the
+ * previous value and any set file.
+ *
+ * @param value
+ * The value to use.
+ * @throws BadStateChangeException
+ * If the run isn't in the {@link Status#Initialized
+ * Initialized} state.
+ */
+ public void setValue(String value) throws BadStateChangeException;
+
+ /**
+ * Sets (or clears) the delimiter for the input port.
+ *
+ * @param delimiter
+ * The delimiter character, or <tt>null</tt> if the value is not
+ * to be split.
+ * @throws BadStateChangeException
+ * If the run isn't in the {@link Status#Initialized
+ * Initialized} state.
+ */
+ @Nullable
+ public void setDelimiter(String delimiter) throws BadStateChangeException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java
new file mode 100644
index 0000000..d7998bc
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Listener.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+import org.taverna.server.master.exceptions.NoListenerException;
+
+/**
+ * An event listener that can be attached to a {@link TavernaRun}.
+ *
+ * @author Donal Fellows
+ */
+public interface Listener {
+ /**
+ * @return The name of the listener.
+ */
+ public String getName();
+
+ /**
+ * @return The type of the listener.
+ */
+ public String getType();
+
+ /**
+ * @return The configuration document for the listener.
+ */
+ public String getConfiguration();
+
+ /**
+ * @return The supported properties of the listener.
+ */
+ public String[] listProperties();
+
+ /**
+ * Get the value of a particular property, which should be listed in the
+ * {@link #listProperties()} method.
+ *
+ * @param propName
+ * The name of the property to read.
+ * @return The value of the property.
+ * @throws NoListenerException
+ * If no property with that name exists.
+ */
+ public String getProperty(String propName) throws NoListenerException;
+
+ /**
+ * Set the value of a particular property, which should be listed in the
+ * {@link #listProperties()} method.
+ *
+ * @param propName
+ * The name of the property to write.
+ * @param value
+ * The value to set the property to.
+ * @throws NoListenerException
+ * If no property with that name exists.
+ * @throws BadPropertyValueException
+ * If the value of the property is bad (e.g., wrong syntax).
+ */
+ public void setProperty(String propName, String value)
+ throws NoListenerException, BadPropertyValueException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java
new file mode 100644
index 0000000..37b104e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/LocalIdentityMapper.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * This interface describes how to map from the identity understood by the
+ * webapp to the identity understood by the local execution system.
+ *
+ * @author Donal Fellows
+ */
+public interface LocalIdentityMapper {
+ /**
+ * Given a user's identity, get the local identity to use for executing
+ * their workflows. Note that it is assumed that there will never be a
+ * failure from this interface; it is <i>not</i> a security policy
+ * decision or enforcement point.
+ *
+ * @param user
+ * An identity token.
+ * @return A user name, which must be defined in the context that workflows
+ * will be running in.
+ */
+ public String getUsernameForPrincipal(UsernamePrincipal user);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java
new file mode 100644
index 0000000..37dbf2c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/MessageDispatcher.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import javax.annotation.Nonnull;
+
+/**
+ * The interface supported by all notification message dispatchers.
+ * @author Donal Fellows
+ */
+public interface MessageDispatcher {
+ /**
+ * @return Whether this message dispatcher is actually available (fully
+ * configured, etc.)
+ */
+ boolean isAvailable();
+
+ /**
+ * @return The name of this dispatcher, which must match the protocol
+ * supported by it (for a non-universal dispatcher) and the name of
+ * the message generator used to produce the message.
+ */
+ String getName();
+
+ /**
+ * Dispatch a message to a recipient.
+ *
+ * @param originator
+ * The workflow run that produced the message.
+ * @param messageSubject
+ * The subject of the message to send.
+ * @param messageContent
+ * The plain-text content of the message to send.
+ * @param targetParameter
+ * A description of where it is to go.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ void dispatch(@Nonnull TavernaRun originator,
+ @Nonnull String messageSubject, @Nonnull String messageContent,
+ @Nonnull String targetParameter) throws Exception;
+}
\ 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/interfaces/Policy.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java
new file mode 100644
index 0000000..f57fe71
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/Policy.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.net.URI;
+import java.util.List;
+
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoDestroyException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Simple policy interface.
+ *
+ * @author Donal Fellows
+ */
+public interface Policy {
+ /**
+ * @return The maximum number of runs that the system can support.
+ */
+ int getMaxRuns();
+
+ /**
+ * Get the limit on the number of runs for this user.
+ *
+ * @param user
+ * Who to get the limit for
+ * @return The maximum number of runs for this user, or <tt>null</tt> if no
+ * per-user limit is imposed and only system-wide limits are to be
+ * enforced.
+ */
+ Integer getMaxRuns(UsernamePrincipal user);
+
+ /**
+ * Test whether the user can create an instance of the given workflow.
+ *
+ * @param user
+ * Who wants to do the creation.
+ * @param workflow
+ * The workflow they wish to instantiate.
+ * @throws NoCreateException
+ * If they may not instantiate it.
+ */
+ void permitCreate(UsernamePrincipal user, Workflow workflow)
+ throws NoCreateException;
+
+ /**
+ * Test whether the user can destroy a workflow instance run or manipulate
+ * its expiry date.
+ *
+ * @param user
+ * Who wants to do the deletion.
+ * @param run
+ * What they want to delete.
+ * @throws NoDestroyException
+ * If they may not destroy it.
+ */
+ void permitDestroy(UsernamePrincipal user, TavernaRun run)
+ throws NoDestroyException;
+
+ /**
+ * Return whether the user has access to a particular workflow run.
+ * <b>Note</b> that this does not throw any exceptions!
+ *
+ * @param user
+ * Who wants to read the workflow's state.
+ * @param run
+ * What do they want to read from.
+ * @return Whether they can read it. Note that this check is always applied
+ * before testing whether the workflow can be updated or deleted by
+ * the user.
+ */
+ boolean permitAccess(UsernamePrincipal user, TavernaRun run);
+
+ /**
+ * Test whether the user can modify a workflow run (other than for its
+ * expiry date).
+ *
+ * @param user
+ * Who wants to do the modification.
+ * @param run
+ * What they want to modify.
+ * @throws NoUpdateException
+ * If they may not modify it.
+ */
+ void permitUpdate(UsernamePrincipal user, TavernaRun run)
+ throws NoUpdateException;
+
+ /**
+ * Get the URIs of the workflows that the given user may execute.
+ *
+ * @param user
+ * Who are we finding out on behalf of.
+ * @return A list of workflow URIs that they may instantiate, or
+ * <tt>null</tt> if any workflow may be submitted.
+ */
+ List<URI> listPermittedWorkflowURIs(UsernamePrincipal user);
+
+ /**
+ * @return The maximum number of {@linkplain Status#Operating operating}
+ * runs that the system can support.
+ */
+ int getOperatingLimit();
+
+ /**
+ * Set the URIs of the workflows that the given user may execute.
+ *
+ * @param user
+ * Who are we finding out on behalf of.
+ * @param permitted
+ * A list of workflow URIs that they may instantiate.
+ */
+ void setPermittedWorkflowURIs(UsernamePrincipal user, List<URI> permitted);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java
new file mode 100644
index 0000000..b5e84c5
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/RunStore.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.util.Map;
+
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Interface to the mechanism that looks after the mapping of names to runs.
+ * Instances of this class may also be responsible for enforcing timely cleanup
+ * of expired workflows.
+ *
+ * @author Donal Fellows.
+ */
+public interface RunStore {
+ /**
+ * Obtain the workflow run for a given user and name.
+ *
+ * @param user
+ * Who wants to do the lookup.
+ * @param p
+ * The general policy system context.
+ * @param uuid
+ * The handle for the run.
+ * @return The workflow instance run.
+ * @throws UnknownRunException
+ * If the lookup fails (either because it does not exist or
+ * because it is not permitted for the user by the policy).
+ */
+ TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
+ throws UnknownRunException;
+
+ /**
+ * Obtain the named workflow run.
+ *
+ * @param uuid
+ * The handle for the run.
+ * @return The workflow instance run.
+ * @throws UnknownRunException
+ * If the lookup fails (either because it does not exist or
+ * because it is not permitted for the user by the policy).
+ */
+ public TavernaRun getRun(String uuid) throws UnknownRunException;
+
+ /**
+ * List the runs that a particular user may access.
+ *
+ * @param user
+ * Who wants to do the lookup, or <code>null</code> if it is
+ * being done "by the system" when the full mapping should be
+ * returned.
+ * @param p
+ * The general policy system context.
+ * @return A mapping from run names to run instances.
+ */
+ Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p);
+
+ /**
+ * Adds a workflow instance run to the store. Note that this operation is
+ * <i>not</i> expected to be security-checked; that is the callers'
+ * responsibility.
+ *
+ * @param run
+ * The run itself.
+ * @return The name of the run.
+ */
+ String registerRun(TavernaRun run);
+
+ /**
+ * Removes a run from the store. Note that this operation is <i>not</i>
+ * expected to be security-checked; that is the callers' responsibility.
+ *
+ * @param uuid
+ * The name of the run.
+ */
+ void unregisterRun(String uuid);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java
new file mode 100644
index 0000000..902c4d0
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/SecurityContextFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.io.Serializable;
+
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * How to create instances of a security context.
+ *
+ * @author Donal Fellows
+ */
+public interface SecurityContextFactory extends Serializable {
+ /**
+ * Creates a security context.
+ *
+ * @param run
+ * Handle to remote run. Allows the security context to know how
+ * to apply itself to the workflow run.
+ * @param owner
+ * The identity of the owner of the workflow run.
+ * @return The security context.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ TavernaSecurityContext create(TavernaRun run, UsernamePrincipal owner)
+ throws Exception;
+}
[30/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/jquery-1.8.0.min.js
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/jquery-1.8.0.min.js b/server-webapp/src/main/resources/static/jquery-1.8.0.min.js
deleted file mode 100644
index f121291..0000000
--- a/server-webapp/src/main/resources/static/jquery-1.8.0.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! jQuery v@1.8.0 jquery.com | jquery.org/license */
-(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(
a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="scri
pt"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bX(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bV.length;while(e--){b=bV[e]+c;if(b in a)return b}return d}function bY(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function bZ(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bY(c)&&(e[f]=p._data(c,"olddisplay",cb(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b$(a,b,c){
var d=bO.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function b_(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bU[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bU[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bU[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bU[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bU[e]+"Width"))||0));return f}function ca(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bP.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+b_(a,b,c||(f?"border":"content"),e)+"px"}function cb(a){if(bR[a])return bR[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createEle
ment)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cz(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cu;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cz(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cz(a,c,d,e,"*",g)),h}function cA(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c
)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cB(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cC(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"succe
ss",data:b}}function cK(){try{return new a.XMLHttpRequest}catch(b){}}function cL(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cT(){return setTimeout(function(){cM=b},0),cM=p.now()}function cU(a,b){p.each(b,function(b,c){var d=(cS[b]||[]).concat(cS["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cV(a,b,c){var d,e=0,f=0,g=cR.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cM||cT(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cM||cT(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.t
weens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cW(k,j.opts.specialEasing);for(;e<g;e++){d=cR[e].call(j,a,k,j.opts);if(d)return d}return cU(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cW(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cX(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bY(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||
"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cb(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cO.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cY(a,b,c,d,e){return new cY.prototype.init(a,b,c,d,e)}function cZ(a,b){var c,d={height:a},e=0;for(;e<4;e+=2-b)c=bU[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d
.width=a),d}function c_(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=r.test("Â ")?/^[\s\xA0]+|[\s\xA0]+$/g:/^\s+|\s+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:fu
nction(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.0",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return
d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)contin
ue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.p
rototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("In
valid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":a.toString().replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:functi
on(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||f.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if
(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete"||e.readyState!=="loading"&&e.addEventListener)setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;
h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){p.isFunction(c)&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callba
cks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return typeof a=="object"?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.n
otifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length||!d)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkO
n:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).c
loneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display
:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/^(?:\{.*\}|\[.*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQu
ery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||++p.uuid:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];
if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")===0&&(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,
c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.shift(),e=p._queueHooks(a,b),f=function(){p.dequeue(a,b)};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),delete e.stop,d.call(a,f,e)),!c.length&&e&&e.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue
:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)(d=p._data(g[h],a+"queueHooks"))&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.pro
p,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)~f.indexOf(" "+b[g]+" ")||(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>-1)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleCla
ss:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.va
l()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;
if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,""+d),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b
,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:
!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selec
tedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,argu
ments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(
".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join(
"\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[
m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,k,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=[].slice.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click")){g=p(this),g.context=this;for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){i={},k=[],g[0]=f;for(d=0;d<q;d++)l=o[d],m=l.selector,i[m]===b&&(i[m]=g.is(m)),i[m]&&k.push(l);k.length&&u.push({elem:f,matches:k})}}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){j=u[d],c.currentTarget=j.elem;for(e=0;e<j.matches.length&&!c.isImmediatePropagationStopped();e++){l=j.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=
l,h=((p.event.special[l.origType]||{}).handle||l.handler).apply(j.elem,r),h!==b&&(c.result=h,h===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&
&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{ready:{setup:p.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventList
ener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStop
ped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(t
his.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simul
ate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(t
his,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown m
ouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bd(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)Z(a,b[e],c,d)}function be(a,b,c,d,e,f){var g,h=$.setFilters[b.toLowerCase()];return h||Z.error(b),(a||!(g=e))&&bd(a||"*",d,g=[],e),g.length>0?h(g,c,f):[]}function bf(a,c,d,e,f){var g,h,i,j,k,l,m,n,p=0,q=f.length,s=L.POS,t=new RegExp("^"+s.source+"(?!"+r+")","i"),u=function(){var a=1,c=arguments.length-2;for(;a<c;a++)arguments[a]===b&&(g[a]=b)};for(;p<q;p++){s.exec(""),a=f[p],j=[],i=0,k=e;while(g=s.exec(a)){n=s.lastIndex=g.index+g[0].length;if(n>i){m=a.slice(i,g.index),i=n,l=[c],B.test(m)&&(k&&(l=k),k=e);if(h=H.test(m))m=m.slice(0,-5).replace(B,"$&*");g.length>1&&g[0]
.replace(t,u),k=be(m,g[1],g[2],l,k,h)}}k?(j=j.concat(k),(m=a.slice(i))&&m!==")"?B.test(m)?bd(m,j,d,e):Z(m,c,d,e?e.concat(k):k):o.apply(d,j)):Z(a,c,d,e)}return q===1?d:Z.uniqueSort(d)}function bg(a,b,c){var d,e,f,g=[],i=0,j=D.exec(a),k=!j.pop()&&!j.pop(),l=k&&a.match(C)||[""],m=$.preFilter,n=$.filter,o=!c&&b!==h;for(;(e=l[i])!=null&&k;i++){g.push(d=[]),o&&(e=" "+e);while(e){k=!1;if(j=B.exec(e))e=e.slice(j[0].length),k=d.push({part:j.pop().replace(A," "),captures:j});for(f in n)(j=L[f].exec(e))&&(!m[f]||(j=m[f](j,b,c)))&&(e=e.slice(j.shift().length),k=d.push({part:f,captures:j}));if(!k)break}}return k||Z.error(a),g}function bh(a,b,e){var f=b.dir,g=m++;return a||(a=function(a){return a===e}),b.first?function(b,c){while(b=b[f])if(b.nodeType===1)return a(b,c)&&b}:function(b,e){var h,i=g+"."+d,j=i+"."+c;while(b=b[f])if(b.nodeType===1){if((h=b[q])===j)return b.sizset;if(typeof h=="string"&&h.indexOf(i)===0){if(b.sizset)return b}else{b[q]=j;if(a(b,e))return b.sizset=!0,b;b.sizset=!1}}}}func
tion bi(a,b){return a?function(c,d){var e=b(c,d);return e&&a(e===!0?c:e,d)}:b}function bj(a,b,c){var d,e,f=0;for(;d=a[f];f++)$.relative[d.part]?e=bh(e,$.relative[d.part],b):(d.captures.push(b,c),e=bi(e,$.filter[d.part].apply(null,d.captures)));return e}function bk(a){return function(b,c){var d,e=0;for(;d=a[e];e++)if(d(b,c))return!0;return!1}}var c,d,e,f,g,h=a.document,i=h.documentElement,j="undefined",k=!1,l=!0,m=0,n=[].slice,o=[].push,q=("sizcache"+Math.random()).replace(".",""),r="[\\x20\\t\\r\\n\\f]",s="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",t=s.replace("w","w#"),u="([*^$|!~]?=)",v="\\["+r+"*("+s+")"+r+"*(?:"+u+r+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+t+")|)|)"+r+"*\\]",w=":("+s+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)",x=":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)",y=r+"*([\\x20\\t\\r\\n\\f>+~])"+r+"*",z="(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|"+v+"|"+w.replace(2,7)+"|[^\\\\(),])+",A=new RegExp("^"+r+"+|
((?:^|[^\\\\])(?:\\\\.)*)"+r+"+$","g"),B=new RegExp("^"+y),C=new RegExp(z+"?(?="+r+"*,|$)","g"),D=new RegExp("^(?:(?!,)(?:(?:^|,)"+r+"*"+z+")*?|"+r+"*(.*?))(\\)|$)"),E=new RegExp(z.slice(19,-6)+"\\x20\\t\\r\\n\\f>+~])+|"+y,"g"),F=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,G=/[\x20\t\r\n\f]*[+~]/,H=/:not\($/,I=/h\d/i,J=/input|select|textarea|button/i,K=/\\(?!\\)/g,L={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),NAME:new RegExp("^\\[name=['\"]?("+s+")['\"]?\\]"),TAG:new RegExp("^("+s.replace("[-","[-\\*")+")"),ATTR:new RegExp("^"+v),PSEUDO:new RegExp("^"+w),CHILD:new RegExp("^:(only|nth|last|first)-child(?:\\("+r+"*(even|odd|(([+-]|)(\\d*)n|)"+r+"*(?:([+-]|)"+r+"*(\\d+)|))"+r+"*\\)|)","i"),POS:new RegExp(x,"ig"),needsContext:new RegExp("^"+r+"*[>+~]|"+x,"i")},M={},N=[],O={},P=[],Q=function(a){return a.sizzleFilter=!0,a},R=function(a){return function(b){return b.nodeName.toLowerCase()==="input"&&b.type===a}},S=function(a){return function(b){var c=b.nodeName.toLowerCase();return
(c==="input"||c==="button")&&b.type===a}},T=function(a){var b=!1,c=h.createElement("div");try{b=a(c)}catch(d){}return c=null,b},U=T(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),V=T(function(a){a.id=q+0,a.innerHTML="<a name='"+q+"'></a><div name='"+q+"'></div>",i.insertBefore(a,i.firstChild);var b=h.getElementsByName&&h.getElementsByName(q).length===2+h.getElementsByName(q+0).length;return g=!h.getElementById(q),i.removeChild(a),b}),W=T(function(a){return a.appendChild(h.createComment("")),a.getElementsByTagName("*").length===0}),X=T(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==j&&a.firstChild.getAttribute("href")==="#"}),Y=T(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||a.getElementsByClassName("e").length===0?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length!=
=1)}),Z=function(a,b,c,d){c=c||[],b=b||h;var e,f,g,i,j=b.nodeType;if(j!==1&&j!==9)return[];if(!a||typeof a!="string")return c;g=ba(b);if(!g&&!d)if(e=F.exec(a))if(i=e[1]){if(j===9){f=b.getElementById(i);if(!f||!f.parentNode)return c;if(f.id===i)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(i))&&bb(b,f)&&f.id===i)return c.push(f),c}else{if(e[2])return o.apply(c,n.call(b.getElementsByTagName(a),0)),c;if((i=e[3])&&Y&&b.getElementsByClassName)return o.apply(c,n.call(b.getElementsByClassName(i),0)),c}return bm(a,b,c,d,g)},$=Z.selectors={cacheLength:50,match:L,order:["ID","TAG"],attrHandle:{},createPseudo:Q,find:{ID:g?function(a,b,c){if(typeof b.getElementById!==j&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==j&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==j&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:W?function(a,b){if(typeof b.getElementsByTagName!==j)retur
n b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(K,""),a[3]=(a[4]||a[5]||"").replace(K,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||Z.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&Z.error(a[0]),a},PSEUDO:function(a){var b,c=a[4];return L.CHILD.test(a[0])?null:(c&&(b=D.exec(c))&&b.pop()&&(a[0]=a[0].slice(0,b[0].length-c.length-1),c=b[0].slice(0,-1)),a.splice(2,3,c||a[3]),a)}},filter:{ID:g?function(a){return a=a.replace(K,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(K,""),function(b){var c=typeof b.getAttributeNode!==j
&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(K,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=M[a];return b||(b=M[a]=new RegExp("(^|"+r+")"+a+"("+r+"|$)"),N.push(a),N.length>$.cacheLength&&delete M[N.shift()]),function(a){return b.test(a.className||typeof a.getAttribute!==j&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return b?function(d){var e=Z.attr(d,a),f=e+"";if(e==null)return b==="!=";switch(b){case"=":return f===c;case"!=":return f!==c;case"^=":return c&&f.indexOf(c)===0;case"*=":return c&&f.indexOf(c)>-1;case"$=":return c&&f.substr(f.length-c.length)===c;case"~=":return(" "+f+" ").indexOf(c)>-1;case"|=":return f===c||f.substr(0,c.length+1)===c+"-"}}:function(b){return Z.attr(b,a)!=null}},CHILD:function(a,b,c,d){if(a==="nth"){var e=m++;return function(a){var b,f,g=0,h=a;if(c===1&&d===0)return!0;b=a.parentNode;if(b&&(b[q]!==e||!a.sizset)){for(
h=b.firstChild;h;h=h.nextSibling)if(h.nodeType===1){h.sizset=++g;if(h===a)break}b[q]=e}return f=a.sizset-d,c===0?f===0:f%c===0&&f/c>=0}}return function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b,c,d){var e=$.pseudos[a]||$.pseudos[a.toLowerCase()];return e||Z.error("unsupported pseudo: "+a),e.sizzleFilter?e(b,c,d):e}},pseudos:{not:Q(function(a,b,c){var d=bl(a.replace(A,"$1"),b,c);return function(a){return!d(a)}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!$.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.no
deType)===3||b===4)return!1;a=a.nextSibling}return!0},contains:Q(function(a){return function(b){return(b.textContent||b.innerText||bc(b)).indexOf(a)>-1}}),has:Q(function(a){return function(b){return Z(a,b).length>0}}),header:function(a){return I.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:R("radio"),checkbox:R("checkbox"),file:R("file"),password:R("password"),image:R("image"),submit:S("submit"),reset:S("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return J.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b,c){return c?a.slice(1):[a[0]]},last:function(a,b,c){var d=a.pop();return c?a:[d]},even:function(
a,b,c){var d=[],e=c?1:0,f=a.length;for(;e<f;e=e+2)d.push(a[e]);return d},odd:function(a,b,c){var d=[],e=c?0:1,f=a.length;for(;e<f;e=e+2)d.push(a[e]);return d},lt:function(a,b,c){return c?a.slice(+b):a.slice(0,+b)},gt:function(a,b,c){return c?a.slice(0,+b+1):a.slice(+b+1)},eq:function(a,b,c){var d=a.splice(+b,1);return c?a:d}}};$.setFilters.nth=$.setFilters.eq,$.filters=$.pseudos,X||($.attrHandle={href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}}),V&&($.order.push("NAME"),$.find.NAME=function(a,b){if(typeof b.getElementsByName!==j)return b.getElementsByName(a)}),Y&&($.order.splice(1,0,"CLASS"),$.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!==j&&!c)return b.getElementsByClassName(a)});try{n.call(i.childNodes,0)[0].nodeType}catch(_){n=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}var ba=Z.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},bb=Z.contains=i.compa
reDocumentPosition?function(a,b){return!!(a.compareDocumentPosition(b)&16)}:i.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc=Z.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=bc(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=bc(b);return c};Z.attr=function(a,b){var c,d=ba(a);return d||(b=b.toLowerCase()),$.attrHandle[b]?$.attrHandle[b](a):U||d?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},Z.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},[0,0].sort(function(){return l=0}),i.compareDocumentPosition?e=function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPos
ition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:(e=function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],g=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return f(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)g.unshift(j),j=j.parentNode;c=e.length,d=g.length;for(var l=0;l<c&&l<d;l++)if(e[l]!==g[l])return f(e[l],g[l]);return l===c?f(a,g[l],-1):f(e[l],b,1)},f=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),Z.uniqueSort=function(a){var b,c=1;if(e){k=l,a.sort(e);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1)}return a};var bl=Z.compile=function(a,b,c){var d,e,f,g=O[a];if(g&&g.context===b)return g;e=bg(a,b,c);for(f=0;d=e[f];f++)e[f]=bj(d,b,c);return g=O[a]=bk(e),g.context=b,g.runs=g.dirruns=0,P.push(a),P.length>$.cacheLength&&delete O[P.shift()],g};Z.matches=function(a,b){return Z(a,null,null,b)},Z.matchesSel
ector=function(a,b){return Z(b,null,null,[a]).length>0};var bm=function(a,b,e,f,g){a=a.replace(A,"$1");var h,i,j,k,l,m,p,q,r,s=a.match(C),t=a.match(E),u=b.nodeType;if(L.POS.test(a))return bf(a,b,e,f,s);if(f)h=n.call(f,0);else if(s&&s.length===1){if(t.length>1&&u===9&&!g&&(s=L.ID.exec(t[0]))){b=$.find.ID(s[1],b,g)[0];if(!b)return e;a=a.slice(t.shift().length)}q=(s=G.exec(t[0]))&&!s.index&&b.parentNode||b,r=t.pop(),m=r.split(":not")[0];for(j=0,k=$.order.length;j<k;j++){p=$.order[j];if(s=L[p].exec(m)){h=$.find[p]((s[1]||"").replace(K,""),q,g);if(h==null)continue;m===r&&(a=a.slice(0,a.length-r.length)+m.replace(L[p],""),a||o.apply(e,n.call(h,0)));break}}}if(a){i=bl(a,b,g),d=i.dirruns++,h==null&&(h=$.find.TAG("*",G.test(a)&&b.parentNode||b));for(j=0;l=h[j];j++)c=i.runs++,i(l,b)&&e.push(l)}return e};h.querySelectorAll&&function(){var a,b=bm,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[],f=[":active"],g=i.matchesSelector||i.mozMatchesSelector||i.webkitMatchesSelector||i.o
MatchesSelector||i.msMatchesSelector;T(function(a){a.innerHTML="<select><option selected></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+r+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),T(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+r+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=e.length&&new RegExp(e.join("|")),bm=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a)))if(d.nodeType===9)try{return o.apply(f,n.call(d.querySelectorAll(a),0)),f}catch(i){}else if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){var j=d.getAttribute("id"),k=j||q,l=G.test(a)&&d.parentNode||d;j?k=k.replace(c,"\\$&"):d.setAttribute("id",k);try{return o.apply(f,n.call(l.querySelectorAll(a.replace(C,"[id='"+k+"'] $&")),0)),f}catch(i){}finally{j||d.removeAttribute("id")}}return b
(a,d,f,g,h)},g&&(T(function(b){a=g.call(b,"div");try{g.call(b,"[test!='']:sizzle"),f.push($.match.PSEUDO)}catch(c){}}),f=new RegExp(f.join("|")),Z.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!ba(b)&&!f.test(c)&&(!e||!e.test(c)))try{var h=g.call(b,c);if(h||a||b.document&&b.document.nodeType!==11)return h}catch(i){}return Z(c,null,null,[b]).length>0})}(),Z.attr=p.attr,p.find=Z,p.expr=Z.selectors,p.expr[":"]=p.expr.pseudos,p.unique=Z.uniqueSort,p.text=Z.getText,p.isXMLDoc=Z.isXML,p.contains=Z.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice
(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.
merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.
map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new Reg
Exp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[
0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(
a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nod
eType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function()
{p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=(c[0]||c).ownerDocument||c[0]||c,typeof c.createDocumentFragment=="undefined"&&(c=e),a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p
.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return
d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=0,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(g=b===e&&bA;(h=a[s])!=null;s++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{g=g||bk(b),l=l||g.appendChild(b.createElement("div")),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(f=n.length-1;f>=0;--f)p.nodeName(n[f],"tbody")&&!n[f].childNodes.length&&n[f].parentNode.removeChild(n[f])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l=g.lastChild}h.nodeType?t.push(h):t=p.merge(t,h)}l&&(g.removeChild(l),h=l=g=null);if(!p.support.appendChecked)for(s=0;(h=t[s])!=null;s++)p.nodeName(h,"input")?bG(h):type
of h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(s=0;(h=t[s])!=null;s++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[s+1,0].concat(r)),s+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(ms
ie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^margin/,bO=new RegExp("^("+q+")(.*)$","i"),bP=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bQ=new RegExp("^([-+])=("+q+")","i"),bR={},bS={position:"absolute",visibility:"hidden",display:"block"},bT={letterSpacing:0,fontWeight:400,lineHeight:1},bU=["Top","Right","Bottom","Left"],bV=["Webkit","O","Moz","ms"],bW=p.fn.toggle;p.fn.extend({css:funct
ion(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return bZ(this,!0)},hide:function(){return bZ(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bW.apply(this,arguments):this.each(function(){(c?a:bY(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bX(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bQ.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&is
NaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bX(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bT&&(f=bT[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(a,b){var c,d,e,f,g=getComputedStyle(a,null),h=a.style;return g&&(c=g[b],c===""&&!p.contains(a.ownerDocument.documentElement,a)&&(c=p.style(a,b)),bP.test(c)&&bN.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=c,c=g.width,h.width=d,h.minWidth=e,h.maxWidth=f)),c}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bP.test(e)&&!bM.te
st(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0||bH(a,"display")!=="none"?ca(a,b,d):p.swap(a,bS,function(){return ca(a,b,d)})},set:function(a,c,d){return b$(a,c,d?b_(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarg
inRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bP.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bU[d]+b]=e[d]||e[d-2]||e[0];return f}},bN.test(a)||(p.cssHooks[a+b].set=b$)});var cc=/%20/g,cd=/\[\]$/,ce=/\r?\n/g,cf=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,cg=/^(?:select|t
extarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||cg.test(this.nodeName)||cf.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(ce,"\r\n")}}):{name:b.name,value:c.replace(ce,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ch(d,a[d],c,f);return e.join("&").replace(cc,"+")};var ci,cj,ck=/#.*$/,cl=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cm=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,cn=/^(?:GET|HEAD)$/
,co=/^\/\//,cp=/\?/,cq=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cr=/([?&])_=[^&]*/,cs=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,ct=p.fn.load,cu={},cv={},cw=["*/"]+["*"];try{ci=f.href}catch(cx){ci=e.createElement("a"),ci.href="",ci=ci.href}cj=cs.exec(ci.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&ct)return ct.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cq,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({ty
pe:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cA(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cA(a,b),a},ajaxSettings:{url:ci,isLocal:cm.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cw},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cy(cu),ajaxTransport:cy(cv),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cB(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHea
der("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cC(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=""+(c||y),k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cl.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return
c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(ck,"").replace(co,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=cs.exec(l.url.toLowerCase()),l.crossDomain=!(!i||i[1]==cj[1]&&i[2]==cj[2]&&(i[3]||(i[1]==="http:"?80:443))==(cj[3]||(cj[1]==="http:"?80:443)))),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cz(cu,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!cn.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cp.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cr,"$1_="+z);l.url=A+(A===
l.url?(cp.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cw+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cz(cv,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cD=[],cE=/\?/,cF=/(=)\?(?=&|$)|\?\?/,cG=p.now();p.ajaxSetup({j
sonp:"callback",jsonpCallback:function(){var a=cD.pop()||p.expando+"_"+cG++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cF.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cF.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cF,"$1"+f):m?c.data=i.replace(cF,"$1"+f):k&&(c.url+=(cE.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cD.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":fu
nction(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cH,cI=a.ActiveXObject?function(){for(var a in cH)cH[a](0,1)}:!1,cJ=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cK()||cL()}:cK,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){v
ar d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cI&&delete cH[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cJ,cI&&(cH||(cH={},p(a).unload(cI)),cH[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});
var cM,cN,cO=/^(?:toggle|show|hide)$/,cP=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cQ=/queueHooks$/,cR=[cX],cS={"*":[function(a,b){var c,d,e,f=this.createTween(a,b),g=cP.exec(b),h=f.cur(),i=+h||0,j=1;if(g){c=+g[2],d=g[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&i){i=p.css(f.elem,a,!0)||c||1;do e=j=j||".5",i=i/j,p.style(f.elem,a,i+d),j=f.cur()/h;while(j!==1&&j!==e)}f.unit=d,f.start=i,f.end=g[1]?i+(g[1]+1)*c:c}return f}]};p.Animation=p.extend(cV,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cS[c]=cS[c]||[],cS[c].unshift(b)},prefilter:function(a,b){b?cR.unshift(a):cR.push(a)}}),p.Tween=cY,cY.prototype={constructor:cY,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cY.propHooks[this.prop];return a&&a.get?a.get(this):cY.propHooks._default.get(this)},run:function(a){var b,c=cY.prop
Hooks[this.prop];return this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration),this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cY.propHooks._default.set(this),this}},cY.prototype.init.prototype=cY.prototype,cY.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cY.propHooks.scrollTop=cY.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,argum
ents):this.animate(cZ(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bY).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cV(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cQ.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:cZ("show"),slideUp:cZ("hide"),slideToggle:cZ("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.a
nimate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duratio
<TRUNCATED>
[03/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png
new file mode 100644
index 0000000..c664c51
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png
new file mode 100644
index 0000000..6aed97a
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png
new file mode 100644
index 0000000..43ba34e
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png
new file mode 100644
index 0000000..68306d1
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png b/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png
new file mode 100644
index 0000000..f567c28
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png b/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png
new file mode 100644
index 0000000..5c5494f
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png b/taverna-server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png
new file mode 100644
index 0000000..9a46d19
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png b/taverna-server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png
new file mode 100644
index 0000000..f811f30
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png b/taverna-server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png
new file mode 100644
index 0000000..755fe99
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png b/taverna-server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png
new file mode 100644
index 0000000..98705f9
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png b/taverna-server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png
new file mode 100644
index 0000000..3f67eca
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png b/taverna-server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png
new file mode 100644
index 0000000..de76ce2
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png b/taverna-server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png
new file mode 100644
index 0000000..42f8f99
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/version.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/version.properties b/taverna-server-webapp/src/main/resources/version.properties
new file mode 100644
index 0000000..7ddb7d3
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/version.properties
@@ -0,0 +1,5 @@
+# What is the version of the server? Bind this in automatically.
+tavernaserver.version=${project.version}
+tavernaserver.revision.describe=${git.commit.id.describe}
+tavernaserver.branch=${git.branch}
+tavernaserver.timestamp=${git.build.time}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/welcome.html
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/welcome.html b/taverna-server-webapp/src/main/resources/welcome.html
new file mode 100644
index 0000000..f80da4a
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/welcome.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>Taverna Server %{VERSION}</title>
+</head>
+<body>
+<h1>Taverna Server %{VERSION}</h1>
+<div style="text-align;center">
+ <p>
+ <i>Note that this is a pre-release version. Significant known
+ issues remain open and it is not guaranteed that the service API
+ will be stable.</i>
+ </p>
+</div>
+<p>For a full list of operations, see the <a
+ href="%{BASEURL}/services">service listing</a> generated by Apache
+CXF, which indicates where to access the WSDL and WADL descriptions of
+the T2Server interface.</p>
+<p>What follows below is a simple guide to using the server. It does
+<i>not</i> cover all the features; a much more extensive guide is available on
+<a href="http://www.mygrid.org.uk/dev/wiki/display/taverna/Taverna+Server+2.4"
+>the myGrid website</a>.</p>
+<h2>5 Minute Guide to Using the REST API</h2>
+<p>Taverna Server %{VERSION} supports both REST and SOAP APIs; you may use either API
+to access the service and any of the workflow runs hosted by the service. This
+simple guide just discusses the REST API.</p>
+<ol>
+ <li>
+ <p>The client starts by creating a workflow run. This is done by POSTing a
+ T2flow document to the service at the address <tt>%{BASEURL}/rest/runs</tt>
+ with the content type <tt>application/vnd.taverna.t2flow+xml</tt>.</p>
+ <p>The result of the POST is an <tt>HTTP 201 Created</tt> that gives the
+ location of the created run (in a <tt>Location</tt> header),
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b></tt> (where <tt><b>UUID</b></tt> is a
+ unique string that identifies the particular run; this is also the name of
+ the run that you would use in the SOAP interface). Note that the run is not
+ yet actually doing anything.</p>
+ </li>
+ <li>
+ <p>Next, you need to set up the inputs to the workflow ports. To set the
+ input port, <tt><b>FOO</b></tt>, to have the value <tt><b>BAR</b></tt>, you
+ would PUT a message like this to the URI
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/input/input/<b>FOO</b></tt>
+ </p>
+ <blockquote><pre><t2sr:runInput xmlns:t2sr="http://ns.taverna.org.uk/2010/xml/server/rest/">
+ <t2sr:value><b>BAR</b></t2sr:value>
+</t2sr:runInput></pre></blockquote>
+ </li>
+ <li>
+ <p>Now you can start the file running. This is done by using a PUT to set
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/status</tt> to the plain text value
+ <tt>Operating</tt>.</p>
+ </li>
+ <li>
+ <p>Now you need to poll, waiting for the workflow to finish. To discover the
+ state of a run, you can (at any time) do a GET on
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/status</tt>; when the workflow has
+ finished executing, this will return <tt>Finished</tt> instead of
+ <tt>Operating</tt> (or <tt>Initialized</tt>, the starting state).</p>
+ </li>
+ <li>
+ <p>Every workflow run has an expiry time, after which it will be destroyed
+ and all resources (i.e., local files) associated with it cleaned up. By
+ default in this release, this is 20 minutes after initial creation. To see
+ when a particular run is scheduled to be disposed of, do a GET on
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/expiry</tt>; you may set the time when
+ the run is disposed of by PUTting a new time to that same URI. Note that
+ this includes not just the time when the workflow is executing, but also
+ when the input files are being created beforehand and when the results are
+ being downloaded afterwards; you are advised to make your clients regularly
+ advance the expiry time while the run is in use.</p>
+ </li>
+ <li>
+ <p>The outputs from the workflow are files created in the <tt>out</tt>
+ subdirectory of the run's working directory. The contents of the
+ subdirectory can be read by doing a GET on
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/wd/out</tt> which will return an XML
+ document describing the contents of the directory, with links to each of the
+ files within it. Doing a GET on those links will retrieve the actual created
+ files (as uninterpreted binary data).</p>
+ <p>Thus, if a single output <tt><b>FOO.OUT</b></tt> was produced from the
+ workflow, it would be written to the file that can be retrieved from
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/wd/out/<b>FOO.OUT</b></tt> and the
+ result of the GET on <tt>%{BASEURL}/rest/runs/<b>UUID</b>/wd/out</tt> would
+ look something like this:</p>
+ <blockquote><pre><t2sr:directoryContents xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:t2sr="http://ns.taverna.org.uk/2010/xml/server/rest"
+ xmlns:t2s="http://ns.taverna.org.uk/2010/xml/server/">
+ <t2s:file xlink:href="%{BASEURL}/rest/runs/<b>UUID</b>/wd/out/<b>FOO.OUT</b>"
+ t2sr:name="<b>FOO.OUT</b>">out/<b>FOO.OUT</b></t2s:file>
+</t2sr:directoryContents></pre></blockquote>
+ </li>
+ <li>
+ <p>The standard output and standard error from the T2 Command Line Executor
+ subprocess can be read via properties of the special I/O listener. To do
+ that, do a GET on
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b>/listeners/io/properties/<b>stdout</b></tt>
+ (or <tt>.../<b>stderr</b></tt>). Once the subprocess has finished executing,
+ the I/O listener will provide a third property containing the exit code of
+ the subprocess, called <tt>exitcode</tt>.</p> <p>Note that the supported set
+ of listeners and properties will be subject to change in future versions of
+ the server, and should not be relied upon.</p>
+ </li>
+ <li>
+ <p>Once you have finished, destroy the run by doing a DELETE on
+ <tt>%{BASEURL}/rest/runs/<b>UUID</b></tt>. Once you have done that, none of
+ the resources associated with the run (including both input and output
+ files) will exist any more. If the run is still executing, this will also
+ cause it to be stopped.</p>
+ </li>
+</ol>
+<p>All operations described above have equivalents in the
+<a href="%{BASEURL}/soap?wsdl">SOAP service interface</a>.</p>
+
+<div>
+<hr>
+<p><small>Copyright © 2010–2014. The University of Manchester.</small></p>
+<p><small>Software Release ID: ${project.version} (commit: ${git.branch})</small></p>
+</div>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/META-INF/MANIFEST.MF b/taverna-server-webapp/src/main/webapp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger b/taverna-server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger
new file mode 100644
index 0000000..4fd9372
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger
@@ -0,0 +1 @@
+org.apache.cxf.common.logging.Log4jLogger
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/META-INF/persistence.xml b/taverna-server-webapp/src/main/webapp/META-INF/persistence.xml
new file mode 100644
index 0000000..afd640a
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/META-INF/persistence.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="1.0"
+ xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd ">
+ <persistence-unit name="TavernaServer">
+ <class>org.taverna.server.master.WebappState</class>
+ <class>org.taverna.server.master.identity.User</class>
+ <class>org.taverna.server.master.localworker.PersistedState</class>
+ <class>org.taverna.server.master.notification.atom.Event</class>
+ <class>org.taverna.server.master.usage.UsageRecord</class>
+ <class>org.taverna.server.master.worker.RunConnection</class>
+ <exclude-unlisted-classes>true</exclude-unlisted-classes>
+ </persistence-unit>
+</persistence>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/beans.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/beans.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..73990a7
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,518 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
+ default-lazy-init="false"
+ xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+ <bean id="webapp" class="org.taverna.server.master.TavernaServer">
+ <property name="policy" ref="worker.policy" />
+ <property name="runStore" ref="worker.rundb" />
+ <property name="fileUtils" ref="fileUtils" />
+ <property name="contentsDescriptorBuilder" ref="contentsDescriptorBuilder" />
+ <property name="notificationEngine" ref="notificationFabric" />
+ <property name="support" ref="webapp.support" />
+ <property name="eventSource" ref="dispatch.atom" />
+ <property name="interactionFeed" value="${taverna.interaction.feed_path}" />
+ <lookup-method name="makeRunInterface" bean="run.coreView.prototype" />
+ <lookup-method name="getPolicyDescription" bean="webapp.policyView" />
+ </bean>
+
+ <bean id="webapp.support" class="org.taverna.server.master.TavernaServerSupport">
+ <property name="policy" ref="worker.policy" />
+ <property name="listenerFactory" ref="localworker.factory" />
+ <property name="runFactory" ref="localworker.factory" />
+ <property name="fileUtils" ref="fileUtils" />
+ <property name="runStore" ref="worker.rundb" />
+ <property name="stateModel" ref="webapp.state" />
+ <property name="idMapper" ref="IdentityMapper" />
+ <property name="invocationCounter" ref="webapp.invocationCounter" />
+ <property name="webapp" ref="webapp" />
+ <property name="contentTypeMap">
+ <map key-type="java.lang.String" value-type="java.lang.String">
+ <description>Maps suffixes (post '.') to content types.</description>
+ <entry key="baclava" value="application/vnd.taverna.baclava+xml" />
+ <entry key="robundle.zip" value="application/vnd.wf4ever.robundle+zip" />
+ </map>
+ </property>
+ <property name="capabilitySource" ref="capabilities" />
+ </bean>
+
+ <bean id="capabilities" class="org.taverna.server.master.utils.CapabilityLister" />
+
+ <bean id="webapp.policyView" class="org.taverna.server.master.PolicyREST">
+ <property name="support" ref="webapp.support" />
+ <property name="policy" ref="worker.policy" />
+ <property name="listenerFactory" ref="localworker.factory" />
+ <property name="notificationEngine" ref="notificationFabric" />
+ </bean>
+
+ <bean id="contentsDescriptorBuilder" class="org.taverna.server.master.ContentsDescriptorBuilder">
+ <property name="uriBuilderFactory" ref="webapp" />
+ <property name="fileUtils" ref="fileUtils" />
+ </bean>
+
+ <bean id="webapp.state" class="org.taverna.server.master.ManagementState">
+ <description>The initial state of the webapp.</description>
+ <property name="logIncomingWorkflows" value="${default.logworkflows}" />
+ <property name="allowNewWorkflowRuns" value="${default.permitsubmit}" />
+ <property name="logOutgoingExceptions" value="${default.logexceptions}" />
+ <property name="persistenceManagerBuilder" ref="pmb" />
+ <property name="self" ref="webapp.state" />
+ </bean>
+
+ <bean id="webapp.invocationCounter" class="org.taverna.server.master.utils.InvocationCounter" />
+ <bean id="webapp.perfLogger" class="org.taverna.server.master.utils.CallTimeLogger">
+ <property name="threshold" value="${calltime.logthreshold:4000000}" />
+ </bean>
+
+ <bean id="run.coreView.prototype" scope="prototype"
+ class="org.taverna.server.master.RunREST">
+ <property name="support" ref="webapp.support" />
+ <property name="cdBuilder" ref="contentsDescriptorBuilder" />
+ <lookup-method name="makeSecurityInterface" bean="run.securityView.prototype" />
+ <lookup-method name="makeInputInterface" bean="run.inputView.prototype" />
+ <lookup-method name="makeListenersInterface" bean="run.listenersView.prototype" />
+ <lookup-method name="makeDirectoryInterface" bean="run.directoryView.prototype" />
+ <lookup-method name="makeInteractionFeed" bean="run.interactionFeed.prototype" />
+ </bean>
+
+ <bean id="run.directoryView.prototype" scope="prototype"
+ class="org.taverna.server.master.DirectoryREST">
+ <property name="support" ref="webapp.support" />
+ <property name="fileUtils" ref="fileUtils" />
+ </bean>
+
+ <bean id="run.listenersView.prototype" scope="prototype"
+ class="org.taverna.server.master.ListenersREST">
+ <property name="support" ref="webapp.support" />
+ <lookup-method name="makeListenerInterface" bean="run.singleListenerView.prototype" />
+ </bean>
+
+ <bean id="run.singleListenerView.prototype" scope="prototype"
+ class="org.taverna.server.master.SingleListenerREST">
+ <lookup-method name="makePropertyInterface" bean="run.propertyView.prototype" />
+ </bean>
+
+ <bean id="run.propertyView.prototype" scope="prototype"
+ class="org.taverna.server.master.ListenerPropertyREST">
+ <property name="support" ref="webapp.support" />
+ </bean>
+
+ <bean id="run.inputView.prototype" scope="prototype"
+ class="org.taverna.server.master.InputREST">
+ <property name="support" ref="webapp.support" />
+ <property name="cdBuilder" ref="contentsDescriptorBuilder" />
+ <property name="fileUtils" ref="fileUtils" />
+ </bean>
+
+ <bean id="run.securityView.prototype" scope="prototype"
+ class="org.taverna.server.master.RunSecurityREST">
+ <property name="support" ref="webapp.support" />
+ </bean>
+
+ <bean id="run.interactionFeed.prototype" scope="prototype"
+ class="org.taverna.server.master.InteractionFeed">
+ <property name="interactionFeedSupport" ref="interactionFeed" />
+ </bean>
+
+ <bean id="feed" class="org.taverna.server.master.notification.atom.AtomFeed">
+ <property name="eventSource" ref="dispatch.atom" />
+ <property name="support" ref="webapp.support" />
+ <property name="feedLanguage" value="${atom.language}" />
+ <property name="abdera" ref="abdera" />
+ </bean>
+
+ <bean id="admin" class="org.taverna.server.master.admin.AdminBean">
+ <property name="adminHtmlFile" value="/admin.html" />
+ <property name="counter" ref="webapp.invocationCounter" />
+ <property name="factory" ref="localworker.factory" />
+ <property name="localWorkerModel" ref="localworker.state" />
+ <property name="runDB" ref="worker.rundb" />
+ <property name="state" ref="webapp.state" />
+ <property name="usageRecords" ref="usageRecordSink" />
+ <property name="userStore" ref="userStore" />
+ </bean>
+
+ <bean id="IdentityMapper" class="org.taverna.server.master.identity.CompositeIDMapper">
+ <property name="identityMappers">
+ <list>
+ <bean id="AuthorityBased"
+ class="org.taverna.server.master.identity.AuthorityDerivedIDMapper">
+ <description>Derives the local user identity to use for execution
+ from the LOCALUSER_* Spring Security authority. Thus, if the user
+ has "LOCALUSER_foo", they will be executing as the local
+ user id "foo".</description>
+ </bean>
+ <bean id="SelfAccess"
+ class="org.taverna.server.master.identity.WorkflowInternalAuthProvider.WorkflowSelfIDMapper">
+ <description>Handles the case where a workflow is accessing itself for
+ the purpose of publishing interactions.</description>
+ <property name="runStore" ref="worker.rundb" />
+ </bean>
+ <bean id="Extracting" class="org.taverna.server.master.identity.NameIDMapper">
+ <description>An alternate mechanism for mapping users. This tries
+ to use an RE to extract the user name from the principal name.
+ </description>
+ <property name="regexp" value="${localusernameregexp}">
+ <description>An optional regexp to extract the local user name
+ from the principal's string description. The first capturing
+ group will be the result of the mapping operation.
+ </description>
+ </property>
+ </bean>
+ <bean id="Constant" class="org.taverna.server.master.identity.ConstantIDMapper">
+ <description>How to map web principals to local users. This one
+ maps everyone to the same user, "taverna".
+ </description>
+ <property name="constantId" value="${default.localusername}" />
+ </bean>
+ </list>
+ </property>
+ </bean>
+
+ <bean id="passwordEncoder"
+ class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
+ <bean class="org.taverna.server.master.identity.UserStore" id="userStore">
+ <property name="persistenceManagerBuilder" ref="pmb" />
+ <property name="baselineUserProperties">
+ <util:properties location="/WEB-INF/security/users.properties" />
+ </property>
+ <property name="defaultLocalUser" value="${default.localusername}" />
+ <property name="encoder" ref="passwordEncoder" />
+ </bean>
+
+ <!-- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
+ <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties">
+ <props> <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
+ <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> <property
+ name="annotatedClasses"> <list> </list> </property> </bean> -->
+ <bean id="pmb" class="org.taverna.server.master.utils.JDOSupport.PersistenceManagerBuilder">
+ <property name="persistenceManagerFactory">
+ <bean id="pmf" class="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"
+ destroy-method="close">
+ <property name="connectionFactory" ref="dataSource" />
+ <property name="nontransactionalRead" value="true" />
+ <property name="persistenceProperties">
+ <props>
+ <prop key="datanucleus.storeManagerType">rdbms</prop>
+ <prop key="datanucleus.autoCreateTables">true</prop>
+ <prop key="datanucleus.autoCreateTables">true</prop>
+ <prop key="datanucleus.validateTables">true</prop>
+ <prop key="datanucleus.autoCreateColumns">true</prop>
+ <prop key="datanucleus.autoCreateConstraints">true</prop>
+ <prop key="datanucleus.validateConstraints">true</prop>
+ <prop key="datanucleus.autoCreateSchema">true</prop>
+ <prop key="datanucleus.PersistenceUnitName">TavernaServer</prop>
+ <prop key="datanucleus.rdbms.datastoreAdapterClassName"
+ >org.taverna.server.master.utils.LoggingDerbyAdapter</prop>
+ </props>
+ </property>
+ </bean>
+ </property>
+ </bean>
+ <bean id="transactionAspect"
+ class="org.taverna.server.master.utils.JDOSupport.TransactionAspect" />
+
+ <bean id="systemPrereqs" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+ <description>http://stackoverflow.com/questions/3339736/set-system-property-with-spring-configuration-file</description>
+ <property name="targetObject" value="#{@systemProperties}" />
+ <property name="targetMethod" value="putAll" />
+ <property name="arguments">
+ <util:properties>
+ <prop key="derby.stream.error.field">org.taverna.server.master.utils.DerbyUtils.TO_LOG</prop>
+ <prop key="derby.stream.error.logSeverityLevel">30000</prop>
+ </util:properties>
+ </property>
+ </bean>
+ <!-- TODO: control the location of the database properly, or move to JNDI
+ TODO: review whether what we are doing now is correct! -->
+ <bean id="dataSource" class="org.taverna.server.master.utils.WebappAwareDataSource">
+ <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
+ <property name="url"
+ value="jdbc:derby:directory:%{WEBAPPROOT}tavernaserver;create=true" />
+ <!-- Needed for Derby... -->
+ <property name="shutdownUrl"
+ value="jdbc:derby:directory:%{WEBAPPROOT}tavernaserver;shutdown=true" />
+ <property name="username" value="taverna" />
+ <property name="password" value="" />
+ <property name="contextualizer" ref="contextualizer" />
+ </bean>
+
+ <bean id="contextualizer" class="org.taverna.server.master.utils.Contextualizer" />
+
+ <bean id="usageRecordSink" class="org.taverna.server.master.usage.UsageRecordRecorder">
+ <property name="state" ref="webapp.state" />
+ <property name="contextualizer" ref="contextualizer" />
+ <property name="persistenceManagerBuilder" ref="pmb" />
+ <property name="self" ref="usageRecordSink" />
+ <property name="disableDB" value="${usage.disableDB}" />
+ <property name="logFile" value="${usage.logFile}" />
+ </bean>
+
+ <context:property-placeholder
+ ignore-unresolvable="true" order="2" properties-ref="default-factory-properties" />
+ <util:properties id="default-factory-properties">
+ <prop key="backEndFactory">org.taverna.server.master.localworker.IdAwareForkRunFactory</prop>
+ </util:properties>
+
+ <!-- This bean configuration replaced with org.taverna.server.master.localworker.LocalWorkerFactory -->
+ <!-- <bean id="localworker.factory" scope="singleton" lazy-init="false"
+ class="${backEndFactory}"> <description> The simple policy manager and factory
+ for the baseline localworker case. </description> <property name="state"
+ ref="localworker.state" /> <property name="runDB" ref="worker.rundb"
+ /> -->
+ <!-- Handled by autowiring to make type-resilient. -->
+ <!-- <property name="idMapper" ref="IdentityMapper" /> -->
+ <!-- <property name="securityContextFactory" ref="worker.securityContext"
+ /> <property name="usageRecordSink" ref="usageRecordSink" /> <property name="URProcessorPool"
+ ref="URThreads" /> </bean> -->
+
+ <!-- <task:executor id="URThreads" pool-size="${pool.size}" /> -->
+
+ <bean id="worker.securityContext"
+ class="org.taverna.server.master.worker.SecurityContextFactory">
+ <property name="runDatabase" ref="worker.rundb" />
+ <property name="filenameConverter" ref="fileUtils" />
+ <property name="x500Utils" ref="x500Utils" />
+ <property name="httpRealm" value="${http.realmName}" />
+ <property name="uriSource" ref="webapp" />
+ <property name="certificateFetcher" ref="certificateChainFetcher" />
+ <property name="passwordIssuer" ref="passwordIssuer" />
+ </bean>
+
+ <bean id="passwordIssuer" class="org.taverna.server.master.worker.PasswordIssuer">
+ <!-- <property name="length" value="8" /> -->
+ </bean>
+
+ <bean id="certificateChainFetcher" class="org.taverna.server.master.utils.CertificateChainFetcher">
+ <property name="secure" value="${fetchCertificateChain}" />
+ </bean>
+
+ <bean id="localworker.state" class="org.taverna.server.master.localworker.LocalWorkerState"
+ scope="singleton" lazy-init="false">
+ <description>
+ The state of the simple factory for the identity-aware
+ local worker.
+ </description>
+ <property name="defaultLifetime" value="${default.lifetime}">
+ <description>How long the run lasts for by default, in seconds.
+ </description>
+ </property>
+ <property name="maxRuns" value="${default.runlimit}">
+ <description>The maximum simultaneous number of runs.</description>
+ </property>
+ <property name="operatingLimit" value="${default.operatinglimit}">
+ <description>
+ The maximum number of runs that are in the Operating state,
+ i.e., actually running with a process consuming resources.
+ </description>
+ </property>
+ <property name="extraArgs">
+ <description>Any extra arguments (memory control, etc.) to pass to
+ the spawned subprocesses.
+ </description>
+ <list>
+ </list>
+ </property>
+ <property name="waitSeconds" value="40">
+ <description>An upper bound (in seconds) on the time to wait for a
+ subprocess to start before failing it.
+ </description>
+ </property>
+ <property name="sleepMS" value="1000">
+ <description>The time to wait (in milliseconds) between polling for
+ the subprocess to complete its registration.
+ </description>
+ </property>
+ <property name="persistenceManagerBuilder" ref="pmb" />
+ <!-- <property name="javaBinary"> <description>The name of the java executable
+ used to run the server worker. Defaults to the executable used to run the
+ hosting environment.</description> </property> -->
+ <!-- <property name="serverWorkerJar"> <description>The full path to the
+ executable JAR file containing the implementation of the server worker.</description>
+ </property> -->
+ <!-- <property name="executeWorkflowScript"> <description>The full path
+ to the executeworkflow.sh in either the Taverna 2 Workbench distribution
+ or the Taverna 2 Command Line distribution.</description> </property> -->
+ <property name="self" ref="localworker.state" />
+ <property name="defaultExecuteWorkflowScript" value="${executeWorkflowScript:NONE}" />
+ </bean>
+
+ <bean id="worker.policy" class="org.taverna.server.master.worker.PolicyImpl">
+ <description>
+ The implementation of the access control policy supported
+ by the localworker run engine.
+ </description>
+ <property name="limits" ref="localworker.state" />
+ <property name="runDB" ref="worker.rundb" />
+ </bean>
+ <bean id="worker.rundb" class="org.taverna.server.master.worker.RunDatabase">
+ <property name="notifier" ref="worker.notifier" />
+ <property name="typeNotifiers">
+ <list>
+ <ref bean="cn.email" />
+ <ref bean="cn.sms" />
+ <ref bean="cn.twitter" />
+ <!-- <ref bean="cn.xmpp"/> -->
+ </list>
+ </property>
+ <property name="notificationEngine" ref="notificationFabric" />
+ <property name="dao" ref="worker.runDAO" />
+ </bean>
+ <bean id="cn.email"
+ class="org.taverna.server.master.worker.VelocityCompletionNotifier">
+ <property name="name" value="email" />
+ <property name="subject" value="Workflow run finished executing" />
+ <property name="velocityEngine" ref="velocity" />
+ <property name="uriBuilderFactory" ref="webapp" />
+ </bean>
+ <bean id="cn.sms"
+ class="org.taverna.server.master.worker.VelocityCompletionNotifier">
+ <property name="name" value="sms" />
+ <property name="subject" value="Run finished" />
+ <property name="velocityEngine" ref="velocity" />
+ <property name="uriBuilderFactory" ref="webapp" />
+ </bean>
+ <bean id="cn.twitter"
+ class="org.taverna.server.master.worker.VelocityCompletionNotifier">
+ <property name="name" value="twitter" />
+ <property name="subject" value="Run finished" />
+ <property name="velocityEngine" ref="velocity" />
+ <property name="uriBuilderFactory" ref="webapp" />
+ </bean>
+
+ <bean id="worker.runDAO" class="org.taverna.server.master.worker.RunDatabaseDAO">
+ <description>
+ The implementation of the catalog of workflow runs
+ supported by the localworker run engine.
+ </description>
+ <property name="persistenceManagerBuilder" ref="pmb" />
+ <property name="facade" ref="worker.rundb" />
+ </bean>
+ <task:scheduled-tasks scheduler="taskScheduler">
+ <task:scheduled ref="worker.rundb" method="cleanNow"
+ fixed-delay="${purge.interval}" />
+ <task:scheduled ref="worker.rundb" method="checkForFinishNow"
+ fixed-delay="${finish.interval}" />
+ <task:scheduled ref="dispatch.atom" method="deleteExpiredEvents"
+ fixed-delay="${atom.cleaninterval}" />
+ </task:scheduled-tasks>
+
+ <bean id="notificationFabric"
+ class="org.taverna.server.master.notification.NotificationEngine">
+ <property name="dispatchers">
+ <list>
+ <ref bean="dispatch.email" />
+ <ref bean="dispatch.twitter" />
+ <ref bean="dispatch.xmpp" />
+ <ref bean="dispatch.sms" />
+ </list>
+ </property>
+ <property name="universalDispatchers">
+ <list>
+ <ref bean="dispatch.atom" />
+ </list>
+ </property>
+ </bean>
+
+ <bean id="dispatch.email" class="org.taverna.server.master.notification.EmailDispatcher">
+ <property name="from" value="${email.from}" />
+ <property name="messageContentType" value="${email.type}" />
+ <property name="cooldownSeconds" value="${message.cooldown}" />
+ <property name="smtpHost" value="${email.host}" />
+ <property name="sender">
+ <bean class="org.springframework.mail.javamail.JavaMailSenderImpl"
+ id="javamail">
+ <property name="host" value="${email.host}" />
+ </bean>
+ </property>
+ </bean>
+ <bean id="dispatch.twitter"
+ class="org.taverna.server.master.notification.TwitterDispatcher">
+ <property name="cooldownSeconds" value="${message.cooldown}" />
+ <property name="accessToken" value="${twitter.oauth.accessToken}" />
+ <property name="accessSecret" value="${twitter.oauth.accessTokenSecret}" />
+ </bean>
+ <bean id="dispatch.xmpp" class="org.taverna.server.master.notification.JabberDispatcher">
+ <property name="resource" value="${xmpp.resource}" />
+ <property name="host" value="${xmpp.service}" />
+ <property name="username" value="${xmpp.user}" />
+ <property name="password" value="${xmpp.password}" />
+ </bean>
+ <bean id="dispatch.sms" class="org.taverna.server.master.notification.SMSDispatcher">
+ <property name="usernameField" value="${sms.userfield}" />
+ <property name="passwordField" value="${sms.passfield}" />
+ <property name="destinationField" value="${sms.destfield}" />
+ <property name="messageField" value="${sms.msgfield}" />
+ <property name="cooldownSeconds" value="${message.cooldown}" />
+ </bean>
+
+ <bean id="dispatch.atom" class="org.taverna.server.master.notification.atom.EventDAO">
+ <property name="expiryAgeDays" value="${atom.lifespan}" />
+ <property name="persistenceManagerBuilder" ref="pmb" />
+ <property name="uriBuilderFactory" ref="feed" />
+ <property name="self" ref="dispatch.atom" />
+ </bean>
+
+ <bean id="worker.notifier"
+ class="org.taverna.server.master.worker.SimpleFormattedCompletionNotifier">
+ <property name="subject" value="${message.termination.subject}" />
+ <property name="messageFormat" value="${message.termination.body}" />
+ <property name="name" value="fallback"/>
+ </bean>
+
+ <bean id="fileUtils" class="org.taverna.server.master.utils.FilenameUtils" />
+ <bean id="x500Utils" class="org.taverna.server.master.utils.X500Utils" />
+ <task:scheduler id="taskScheduler" pool-size="${pool.size}" />
+
+ <bean class="org.taverna.server.master.utils.JCECheck" id="JCECheck" />
+
+ <bean class="org.taverna.server.master.interaction.InteractionFeedSupport"
+ id="interactionFeed" scope="singleton">
+ <property name="abdera" ref="abdera" />
+ <property name="support" ref="webapp.support" />
+ <property name="uriBuilder" ref="webapp" />
+ <property name="utils" ref="fileUtils" />
+ </bean>
+ <bean class="org.taverna.server.master.rest.handler.FeedHandler" id="atomFeedHandler">
+ <property name="abdera" ref="abdera" />
+ </bean>
+ <bean class="org.taverna.server.master.rest.handler.EntryHandler" id="atomEntryHandler">
+ <property name="abdera" ref="abdera" />
+ </bean>
+
+ <bean id="authProvider" class="org.taverna.server.master.identity.StrippedDownAuthProvider">
+ <property name="passwordEncoder" ref="passwordEncoder" />
+ <property name="userDetailsService">
+ <bean class="org.taverna.server.master.identity.UserStore.CachedUserStore">
+ <property name="realStore" ref="userStore" />
+ </bean>
+ </property>
+ </bean>
+ <bean id="workflowInternalAuthProvder"
+ class="org.taverna.server.master.identity.WorkflowInternalAuthProvider">
+ <property name="dao" ref="worker.runDAO" />
+ <property name="cacheBound" value="${default.runlimit}" />
+ </bean>
+ <bean id="velocity" class="org.apache.velocity.app.VelocityEngine"
+ init-method="init" lazy-init="false">
+ <constructor-arg>
+ <props>
+ <prop key="input.encoding">UTF-8</prop>
+ <prop key="output.encoding">UTF-8</prop>
+ <prop key="runtime.log.logsystem.class">org.apache.velocity.runtime.log.Log4JLogChute</prop>
+ <prop key="runtime.log.logsystem.log4j.logger">org.taverna.server.master.worker.VelocityCompletionNotifier</prop>
+ <prop key="resource.loader">class</prop>
+ <prop key="class.resource.loader.description">Velocity Classpath Resource Loader</prop>
+ <prop key="class.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop>
+ </props>
+ </constructor-arg>
+ </bean>
+ <bean id="abdera" class="org.apache.abdera.Abdera"/>
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/insecure.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/insecure.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/insecure.xml
new file mode 100644
index 0000000..92c0b03
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/insecure.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2010-2012 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
+
+ <description>
+ The Taverna Server bean, plus supporting configuration.
+ THIS IS AN INSECURE CONFIGURATION!
+ </description>
+
+ <import resource="webappBeans.xml" />
+
+ <context:property-placeholder order="0" ignore-unresolvable="true"
+ properties-ref="security.override.properties" />
+ <util:properties id="security.override.properties">
+ <prop key="backEndFactory">org.taverna.server.master.localworker.ForkRunFactory</prop>
+ <prop key="fetchCertificateChain">false</prop>
+ <prop key="suppressRewriteEngine">true</prop>
+ <prop key="requiredChannel">any</prop>
+ </util:properties>
+
+ <!-- No JMX support; assume too unsafe. -->
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl b/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl
new file mode 100644
index 0000000..d706fed
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl
@@ -0,0 +1,15 @@
+Your workflow, $name, has #if( $prop_exitcode == 0)finished#{else}failed#{end}.
+
+It started execution at ${startTime}.
+It finished execution at ${finishTime}.
+
+For further information, go to $uriBuilder.build() before the run is
+automatically deleted (currently scheduled to happen at ${expiryTime}).
+
+#if( $prop_exitcode == 0)
+Exit code: $prop_exitcode
+Standard error:
+$prop_stderr
+#end
+
+(This message was automatically generated by Taverna Server ${serverVersion}.)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl b/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl
new file mode 100644
index 0000000..b595931
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl
@@ -0,0 +1 @@
+Taverna Server ${serverVersion}: Workflow "$name" from ${startTime} has #if( $prop_exitcode == 0)finished#{else}failed#{end}.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl b/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl
new file mode 100644
index 0000000..cd920a7
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl
@@ -0,0 +1 @@
+Your workflow, $name, has #if( $prop_exitcode == 0)finished#{else}failed#{end}. $uriBuilder.build() #TavernaServer ${serverVersion}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/partsecure.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/partsecure.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/partsecure.xml
new file mode 100644
index 0000000..2e27b81
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/partsecure.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2011-2012 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
+
+ <description>
+ The Taverna Server bean, plus supporting configuration.
+ THIS IS THE CONFIGURATION FOR SEMI-SECURE OPERATION ON WINDOWS.
+ </description>
+
+ <import resource="webappBeans.xml" />
+
+ <!-- This is all the same as the secure config *EXCEPT* for this override. -->
+ <context:property-placeholder order="0" ignore-unresolvable="true"
+ properties-ref="security.override.properties" />
+ <util:properties id="security.override.properties">
+ <prop key="backEndFactory">org.taverna.server.master.localworker.ForkRunFactory</prop>
+ <prop key="fetchCertificateChain">true</prop>
+ <prop key="suppressRewriteEngine">false</prop>
+ <prop key="requiredChannel">https</prop>
+ </util:properties>
+
+ <bean id="MBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
+ <property name="locateExistingServerIfPossible" value="true" />
+ </bean>
+ <context:mbean-export server="MBeanServer"
+ default-domain="${my.domain}" registration="ignoreExisting" />
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/providers.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/providers.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/providers.xml
new file mode 100644
index 0000000..43531ab
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/providers.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
+
+ <import resource="beans.xml" />
+
+ <bean id="ExceptionProvider.BadInputPortName" class="org.taverna.server.master.rest.handler.BadInputPortNameHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.BadPropertyValue" class="org.taverna.server.master.rest.handler.BadPropertyValueHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.BadStateChange" class="org.taverna.server.master.rest.handler.BadStateChangeHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.FilesystemAccess" class="org.taverna.server.master.rest.handler.FilesystemAccessHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.GeneralFailure" class="org.taverna.server.master.rest.handler.GeneralFailureHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.IllegalArgument" class="org.taverna.server.master.rest.handler.IllegalArgumentHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.ImplementationProblem"
+ class="org.taverna.server.master.rest.handler.ImplementationProblemHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.InvalidCredential" class="org.taverna.server.master.rest.handler.InvalidCredentialHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NoCreate" class="org.taverna.server.master.rest.handler.NoCreateHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.Overloaded" class="org.taverna.server.master.rest.handler.OverloadedHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NoCredential" class="org.taverna.server.master.rest.handler.NoCredentialHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NoDestroy" class="org.taverna.server.master.rest.handler.NoDestroyHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NoDirectoryEntry" class="org.taverna.server.master.rest.handler.NoDirectoryEntryHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NoListener" class="org.taverna.server.master.rest.handler.NoListenerHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NoUpdate" class="org.taverna.server.master.rest.handler.NoUpdateHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NotOwner" class="org.taverna.server.master.rest.handler.NotOwnerHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.UnknownRun" class="org.taverna.server.master.rest.handler.UnknownRunHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.JAXBException" class="org.taverna.server.master.rest.handler.JAXBExceptionHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.AccessDenied" class="org.taverna.server.master.rest.handler.AccessDeniedHandler">
+ <property name="managementModel" ref="webapp.state" />
+ </bean>
+ <bean id="ExceptionProvider.NegotiationFailed" class="org.taverna.server.master.rest.handler.NegotiationFailedHandler">
+ </bean>
+ <bean id="MessagingProvider.File" class="org.taverna.server.master.rest.handler.FileMessageHandler">
+ <property name="maxChunkSize" value="${default.messageSize}" />
+ </bean>
+ <bean id="MessagingProvider.FileConcatenation" class="org.taverna.server.master.rest.handler.FileConcatenationHandler">
+ <property name="maxChunkSize" value="${default.messageSize}" />
+ </bean>
+ <bean id="MessagingProvider.FileSegment" class="org.taverna.server.master.rest.handler.FileSegmentHandler">
+ <property name="maxChunkSize" value="${default.messageSize}" />
+ </bean>
+ <bean id="MessagingProvider.InputStream"
+ class="org.taverna.server.master.rest.handler.InputStreamMessageHandler">
+ </bean>
+ <bean id="MessagingProvider.T2flow" class="org.taverna.server.master.rest.handler.T2FlowDocumentHandler">
+ </bean>
+ <bean id="MessagingProvider.Permission" class="org.taverna.server.master.rest.handler.PermissionHandler">
+ </bean>
+
+ <bean id="Provider.RuntimeExceptionRemapping" class="org.taverna.server.master.utils.RuntimeExceptionWrapper" />
+ <bean id="MessagingProvider.ZipStream" class="org.taverna.server.master.rest.handler.ZipStreamHandler" />
+ <bean id="MessagingProvider.URIList" class="org.taverna.server.master.rest.handler.URIListHandler" />
+ <bean id="Interceptor.FlushThreadLocalCache"
+ class="org.taverna.server.master.utils.FlushThreadLocalCacheInterceptor"
+ lazy-init="false">
+ </bean>
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/secure.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/secure.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/secure.xml
new file mode 100644
index 0000000..cf08083
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/secure.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2010-2012 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
+
+ <description>
+ The Taverna Server bean, plus supporting configuration.
+ THIS IS THE CONFIGURATION FOR SECURE OPERATION.
+ </description>
+
+ <import resource="webappBeans.xml" />
+
+ <context:property-placeholder order="0" ignore-unresolvable="true"
+ properties-ref="security.override.properties" />
+ <util:properties id="security.override.properties">
+ <prop key="fetchCertificateChain">true</prop>
+ <prop key="suppressRewriteEngine">false</prop>
+ <prop key="requiredChannel">https</prop>
+ </util:properties>
+
+ <bean id="MBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
+ <property name="locateExistingServerIfPossible" value="true" />
+ </bean>
+ <context:mbean-export server="MBeanServer"
+ default-domain="${my.domain}" registration="ignoreExisting" />
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/security/users.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/security/users.properties b/taverna-server-webapp/src/main/webapp/WEB-INF/security/users.properties
new file mode 100644
index 0000000..03f8436
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/security/users.properties
@@ -0,0 +1,48 @@
+# This is a Java properties file that defines the default users supported by
+# Taverna Server. The keys are the user names, and the values are comma-
+# -separated lists of values: the first is the password (which must not have
+# any spaces or commas in) and the last is "enabled" or "disabled" to indicate
+# whether this user is actually allowed to log in or not. The values between
+# are the authorities associated with the user: these are either roles (which
+# describe a particular set of permissions for the user) or user mappings.
+#
+# The supported set of authorities are:
+#
+# ROLE_tavernauser - may use the standard Taverna Server interfaces
+#
+# ROLE_tavernasuperuser - may use the admin interfaces and see *all*
+# workflow runs irrespective of permissions
+#
+# LOCALUSER_* - map the server user to the given local system
+# account (i.e., the account name is in place of the
+# "*" in the authority); don't grant two of these
+# authorities at once, or confusion will reign
+#
+# Note that it is usually better to define accounts via the administrative
+# interface or through the JMX interface because those can then be modified
+# without restarting the server; anything in this file is fixed until the
+# next server restart. This file exists mainly to allow permissions for the
+# admin interface to be boot-strapped.
+
+# ---------------------------------------------------------------------
+
+# A normal user. Must have given role (ROLE_tavernauser) to use Taverna Server.
+# The user has password "taverna" and is enabled. The default mapping to user
+# accounts - using the user name - will be used.
+
+taverna: taverna,ROLE_tavernauser,enabled
+
+# Another normal user (username: "taverna_alt"). Will be mapped to the system
+# account called "taverna", but the user is currently disabled.
+
+taverna_alt: qwerty,ROLE_tavernauser,LOCALUSER_taverna,disabled
+
+# The default admin user, who has password "admin". You should change this!
+# Admin users also have ROLE_tavernasuperuser, which grants access to the
+# server's /admin pages and allows all workflow runs to be seen (if the
+# ROLE_tavernauser is also assigned, as below; one does not imply the other).
+# If you don't have any enabled admin users, you'll need to use JMX to do
+# management operations (JMX is only accessible from the local host and by
+# the overall container user or the system administrator).
+
+admin: admin,ROLE_tavernauser,ROLE_tavernasuperuser,LOCALUSER_taverna,enabled
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties b/taverna-server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties
new file mode 100644
index 0000000..9616a45
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties
@@ -0,0 +1,77 @@
+# Override the hostname, port and webapp; leave at 'NONE' if no override
+# desired. If set, set it to something like:
+# foo.example.com:8000/tav-serv
+default.webapp: NONE
+# User name to use if nothing else specified
+default.localusername: taverna
+# How to pick a user name out of a global identity
+localusernameregexp: ^TAVERNAUSER=(.*)$
+# General defaults
+default.logworkflows: false
+default.logexceptions: false
+default.permitsubmit: true
+default.lifetime: 1440
+default.runlimit: 100
+default.operatinglimit: 10
+default.messageSize: 65536
+#taverna.preferredUserUri: https://some.host:8443/tavernaserver/rest/
+http.realmName: tavernaserver
+
+rmi.localhostOnly: true
+helio.cis.enableTokenPassing: false
+log.security.details: false
+
+#executeWorkflowScript: /usr/taverna/executeworkflow.sh
+#secureForkPasswordFile: /usr/local/tomcat6.0/conf/sudopass.txt
+
+# Usage Record handling
+usage.logFile: none
+usage.disableDB: no
+
+# Delays used in the task executor
+purge.interval: 30000
+finish.interval: 10000
+
+# Static configuration of messaging
+
+### Email
+email.from: taverna.server@localhost
+email.type: text/plain
+#email.host: localhost
+
+### Jabber
+#xmpp.server: xmpp://some.host:5222
+xmpp.resource: TavernaServer
+#xmpp.user: taverna
+#xmpp.password: *******
+
+### Atom/RSS; lifespan in days, cleaninterval in milliseconds
+atom.language: en
+atom.lifespan: 7
+atom.cleaninterval: 3600000
+
+### SMS
+#sms.service: https://www.intellisoftware.co.uk/smsgateway/sendmsg.aspx
+sms.userfield: username
+sms.passfield: password
+sms.destfield: to
+sms.msgfield: text
+#sms.user: taverna
+#sms.pass: *******
+
+### Twitter
+#twitter.oauth.accessToken: ...
+#twitter.oauth.accessTokenSecret: ...
+
+### General; cooldown in seconds
+message.cooldown: 300
+message.termination.subject: Taverna workflow run finished
+message.termination.body: Your job with ID={0} has finished with exit code {1,number,integer}.
+
+# Thread pool sizing
+pool.size: 2
+
+taverna.interaction.host: none
+taverna.interaction.port: none
+taverna.interaction.webdav_path: none
+taverna.interaction.feed_path: none
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/web-nosec.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/web-nosec.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/web-nosec.xml
new file mode 100644
index 0000000..d6c6ee7
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/web-nosec.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<web-app id="TAVSERV-2.5.4">
+ <display-name>Taverna 2.5.4 Server</display-name>
+ <description>This is the front-end engine for Taverna 2.5.4 Server.</description>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/insecure.xml</param-value>
+ <description>Where Spring is to load its bean definitions from. DO NOT
+ CHANGE WITHOUT CONSULTING DOCUMENTATION.</description>
+ </context-param>
+ <context-param>
+ <param-name>log4jExposeWebAppRoot</param-name>
+ <param-value>false</param-value>
+ <description>
+ THIS IS STUPID! We have to do this so that Tomcat webapps do not
+ leak their configurations into each other via the log4j support
+ trying to be "smart".
+ http://javacolors.blogspot.co.uk/2010/08/tomcat-and-webxmls-webapprootkey.html
+ If you change this, good luck hunting down the weird crashes.
+ </description>
+ </context-param>
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <listener>
+ <listener-class>
+ org.springframework.web.context.request.RequestContextListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.springframework.web.util.Log4jConfigListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>CXFServlet</servlet-name>
+ <display-name>CXF Servlet</display-name>
+ <servlet-class>
+ org.apache.cxf.transport.servlet.CXFServlet
+ </servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>CXFServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <resource-ref>
+ <description>
+ Resource reference to a factory for javax.mail.Session
+ instances that may be used for sending electronic mail
+ messages, preconfigured to connect to the appropriate
+ SMTP server.
+ </description>
+ <res-ref-name>mail/Session</res-ref-name>
+ <res-type>javax.mail.Session</res-type>
+ <res-auth>Container</res-auth>
+ <res-sharing-scope>Shareable</res-sharing-scope>
+ </resource-ref>
+</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/web-partsec.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/web-partsec.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/web-partsec.xml
new file mode 100644
index 0000000..a2b545e
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/web-partsec.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<web-app id="TAVSERV-2.5.4">
+ <display-name>Taverna 2.5.4 Server</display-name>
+ <description>This is the front-end engine for Taverna 2.5.4 Server.</description>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/partsecure.xml</param-value>
+ <description>Where Spring is to load its bean definitions from. DO NOT
+ CHANGE WITHOUT CONSULTING DOCUMENTATION.</description>
+ </context-param>
+ <context-param>
+ <param-name>log4jExposeWebAppRoot</param-name>
+ <param-value>false</param-value>
+ <description>
+ THIS IS STUPID! We have to do this so that Tomcat webapps do not
+ leak their configurations into each other via the log4j support
+ trying to be "smart".
+ http://javacolors.blogspot.co.uk/2010/08/tomcat-and-webxmls-webapprootkey.html
+ If you change this, good luck hunting down the weird crashes.
+ </description>
+ </context-param>
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <listener>
+ <listener-class>
+ org.springframework.web.context.request.RequestContextListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.springframework.web.util.Log4jConfigListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>CXFServlet</servlet-name>
+ <display-name>CXF Servlet</display-name>
+ <servlet-class>
+ org.apache.cxf.transport.servlet.CXFServlet
+ </servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>CXFServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <resource-ref>
+ <description>
+ Resource reference to a factory for javax.mail.Session
+ instances that may be used for sending electronic mail
+ messages, preconfigured to connect to the appropriate
+ SMTP server.
+ </description>
+ <res-ref-name>mail/Session</res-ref-name>
+ <res-type>javax.mail.Session</res-type>
+ <res-auth>Container</res-auth>
+ <res-sharing-scope>Shareable</res-sharing-scope>
+ </resource-ref>
+</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/web-sec.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/web-sec.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/web-sec.xml
new file mode 100644
index 0000000..9a5395a
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/web-sec.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<web-app id="TAVSERV-2.5.4">
+ <display-name>Taverna 2.5.4 Server</display-name>
+ <description>This is the front-end engine for Taverna 2.5.4 Server.</description>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/secure.xml</param-value>
+ <description>Where Spring is to load its bean definitions from. DO NOT
+ CHANGE WITHOUT CONSULTING DOCUMENTATION.</description>
+ </context-param>
+ <context-param>
+ <param-name>log4jExposeWebAppRoot</param-name>
+ <param-value>false</param-value>
+ <description>
+ THIS IS STUPID! We have to do this so that Tomcat webapps do not
+ leak their configurations into each other via the log4j support
+ trying to be "smart".
+ http://javacolors.blogspot.co.uk/2010/08/tomcat-and-webxmls-webapprootkey.html
+ If you change this, good luck hunting down the weird crashes.
+ </description>
+ </context-param>
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+ <listener>
+ <listener-class>
+ org.springframework.web.context.request.RequestContextListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.springframework.web.util.Log4jConfigListener
+ </listener-class>
+ </listener>
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>CXFServlet</servlet-name>
+ <display-name>CXF Servlet</display-name>
+ <servlet-class>
+ org.apache.cxf.transport.servlet.CXFServlet
+ </servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>CXFServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <resource-ref>
+ <description>
+ Resource reference to a factory for javax.mail.Session
+ instances that may be used for sending electronic mail
+ messages, preconfigured to connect to the appropriate
+ SMTP server.
+ </description>
+ <res-ref-name>mail/Session</res-ref-name>
+ <res-type>javax.mail.Session</res-type>
+ <res-auth>Container</res-auth>
+ <res-sharing-scope>Shareable</res-sharing-scope>
+ </resource-ref>
+</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/webapp/WEB-INF/webappBeans.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/webapp/WEB-INF/webappBeans.xml b/taverna-server-webapp/src/main/webapp/WEB-INF/webappBeans.xml
new file mode 100644
index 0000000..22e74b3
--- /dev/null
+++ b/taverna-server-webapp/src/main/webapp/WEB-INF/webappBeans.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2010-2012 The University of Manchester See the file "LICENSE"
+ for license terms. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+ xmlns:jaxws="http://cxf.apache.org/jaxws"
+ xmlns:cxf="http://cxf.apache.org/core"
+ xmlns:security="http://www.springframework.org/schema/security"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
+ http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
+ http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
+ http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
+ http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
+
+ <description>
+ The Taverna Server bean, plus supporting configuration.
+ </description>
+
+ <import resource="classpath:META-INF/cxf/cxf.xml" />
+ <import resource="providers.xml" />
+
+ <context:annotation-config />
+ <context:component-scan base-package="org.taverna.server" />
+ <bean id="servletContextPropertyConfigurer"
+ class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
+ <property name="ignoreUnresolvablePlaceholders" value="true" />
+ <property name="localOverride" value="true" />
+ <property name="order" value="0" />
+ <property name="location" value="/WEB-INF/tavernaserver.properties" />
+ </bean>
+
+ <jaxws:server id="master_SOAP"
+ serviceClass="org.taverna.server.master.TavernaServer" address="/soap">
+ <jaxws:serviceBean>
+ <ref bean="webapp" />
+ </jaxws:serviceBean>
+ <jaxws:properties>
+ <entry key="mtom-enabled" value="true" />
+ </jaxws:properties>
+ <!-- <jaxws:dataBinding><ref bean="addStylesheet"/></jaxws:dataBinding> -->
+ </jaxws:server>
+
+ <jaxrs:server id="root_REST" address="/">
+ <jaxrs:serviceBeans>
+ <ref bean="root_facade" />
+ </jaxrs:serviceBeans>
+ <jaxrs:properties>
+ <entry key="org.apache.cxf.endpoint.private" value="true" />
+ </jaxrs:properties>
+ </jaxrs:server>
+
+ <jaxrs:server id="master_REST" address="/rest"
+ staticSubresourceResolution="true">
+ <jaxrs:serviceBeans>
+ <ref bean="webapp" />
+ </jaxrs:serviceBeans>
+ <jaxrs:features>
+ <!-- <cxf:logging /> --><!-- NOISY! -->
+ </jaxrs:features>
+ <jaxrs:providers>
+ <ref bean="ExceptionProvider.AccessDenied" />
+ <ref bean="ExceptionProvider.BadInputPortName" />
+ <ref bean="ExceptionProvider.BadPropertyValue" />
+ <ref bean="ExceptionProvider.BadStateChange" />
+ <ref bean="ExceptionProvider.FilesystemAccess" />
+ <ref bean="ExceptionProvider.GeneralFailure" />
+ <ref bean="ExceptionProvider.IllegalArgument" />
+ <ref bean="ExceptionProvider.ImplementationProblem" />
+ <ref bean="ExceptionProvider.InvalidCredential" />
+ <ref bean="ExceptionProvider.JAXBException" />
+ <ref bean="ExceptionProvider.NegotiationFailed" />
+ <ref bean="ExceptionProvider.NoCreate" />
+ <ref bean="ExceptionProvider.NoCredential" />
+ <ref bean="ExceptionProvider.NoDestroy" />
+ <ref bean="ExceptionProvider.NoDirectoryEntry" />
+ <ref bean="ExceptionProvider.NoListener" />
+ <ref bean="ExceptionProvider.NoUpdate" />
+ <ref bean="ExceptionProvider.NotOwner" />
+ <ref bean="ExceptionProvider.Overloaded" />
+ <ref bean="ExceptionProvider.UnknownRun" />
+ <ref bean="MessagingProvider.File" />
+ <ref bean="MessagingProvider.FileConcatenation" />
+ <ref bean="MessagingProvider.FileSegment" />
+ <ref bean="MessagingProvider.InputStream" />
+ <ref bean="MessagingProvider.T2flow" />
+ <ref bean="MessagingProvider.Permission" />
+ <ref bean="MessagingProvider.URIList" />
+ <ref bean="MessagingProvider.ZipStream" />
+ <ref bean="jsonProvider" />
+ <ref bean="atomEntryHandler" />
+ <ref bean="atomFeedHandler" />
+ <bean class="org.apache.cxf.jaxrs.model.wadl.WadlGenerator">
+ <property name="addResourceAndMethodIds" value="true"/>
+ </bean>
+ </jaxrs:providers>
+ <jaxrs:outInterceptors>
+ <ref bean="Interceptor.FlushThreadLocalCache" />
+ </jaxrs:outInterceptors>
+ </jaxrs:server>
+
+ <jaxrs:server id="AtomFeed" address="/feed">
+ <jaxrs:serviceBeans>
+ <ref bean="feed" />
+ </jaxrs:serviceBeans>
+ <jaxrs:properties>
+ <entry key="org.apache.cxf.endpoint.private" value="true" />
+ </jaxrs:properties>
+ <jaxrs:providers>
+ <ref bean="atomEntryHandler" />
+ <ref bean="atomFeedHandler" />
+ </jaxrs:providers>
+ </jaxrs:server>
+
+ <jaxrs:server id="AdministrationInterface" address="/admin"
+ staticSubresourceResolution="true">
+ <jaxrs:serviceBeans>
+ <ref bean="admin" />
+ </jaxrs:serviceBeans>
+ <jaxrs:providers>
+ <ref bean="jsonProvider" />
+ </jaxrs:providers>
+ </jaxrs:server>
+
+ <bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
+ <property name="ignoreNamespaces" value="true" />
+ <property name="namespaceMap" ref="jsonNamespaceMap" />
+ </bean>
+ <util:map id="jsonNamespaceMap" key-type="java.lang.String"
+ value-type="java.lang.String">
+ <entry key="http://www.w3.org/1999/xlink" value="" />
+ <entry key="http://www.w3.org/2000/09/xmldsig#" value="" />
+ <entry key="http://schema.ogf.org/urf/2003/09/urf" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/xml/server/" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/xml/server/rest/" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/xml/server/soap/" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/xml/server/feed/" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/xml/server/admin/" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/port/" value="" />
+ <entry key="http://ns.taverna.org.uk/2010/run/" value="" />
+ </util:map>
+
+ <bean id="root_facade" class="org.taverna.server.master.facade.Facade">
+ <property name="file" value="/welcome.html" />
+ <property name="contextualizer" ref="contextualizer" />
+ </bean>
+
+ <bean class="org.taverna.server.master.common.Uri.Rewriter"
+ autowire="byType" id="URI-Rewriter-Thunk">
+ <property name="suppressSecurity" value="${suppressRewriteEngine}" />
+ <property name="rewriteTarget" value="${default.webapp}" />
+ </bean>
+ <security:authentication-manager>
+ <security:authentication-provider ref="workflowInternalAuthProvder" />
+ <security:authentication-provider ref="authProvider" />
+ </security:authentication-manager>
+
+ <bean id="WSDLHeadOptionsInterceptor"
+ class="org.taverna.server.master.utils.WSDLHeadOptionsInterceptor" />
+ <cxf:bus>
+ <cxf:inInterceptors>
+ <ref bean="WSDLHeadOptionsInterceptor" />
+ </cxf:inInterceptors>
+ </cxf:bus>
+
+ <aop:aspectj-autoproxy proxy-target-class="true" />
+ <security:global-method-security
+ jsr250-annotations="enabled" />
+
+ <security:http realm="${http.realmName}" create-session="never"
+ use-expressions="true">
+ <security:http-basic />
+ <security:intercept-url pattern="/"
+ requires-channel="any" access="permitAll" />
+ <security:intercept-url pattern="/rest"
+ requires-channel="${requiredChannel}" access="permitAll" />
+ <security:intercept-url pattern="/rest/"
+ requires-channel="${requiredChannel}" access="permitAll" />
+ <security:intercept-url pattern="/rest/policy"
+ requires-channel="${requiredChannel}" access="permitAll" />
+ <security:intercept-url pattern="/rest/policy/"
+ requires-channel="${requiredChannel}" access="permitAll" />
+ <security:intercept-url pattern="/services/**"
+ requires-channel="${requiredChannel}" access="permitAll" />
+ <security:intercept-url pattern="/soap/**" method="GET"
+ requires-channel="${requiredChannel}" access="permitAll" />
+ <security:intercept-url pattern="/soap/**" method="POST"
+ requires-channel="${requiredChannel}"
+ access="hasRole('ROLE_tavernauser')" />
+ <security:intercept-url pattern="/admin"
+ requires-channel="${requiredChannel}"
+ access="hasRole('ROLE_tavernasuperuser')" />
+ <security:intercept-url pattern="/admin/**"
+ requires-channel="${requiredChannel}"
+ access="hasRole('ROLE_tavernasuperuser')" />
+ <security:intercept-url pattern="/rest/**"
+ requires-channel="${requiredChannel}"
+ access="hasAnyRole('ROLE_tavernauser','ROLE_tavernaworkflow')" />
+ <security:intercept-url pattern="/feed"
+ requires-channel="${requiredChannel}"
+ access="hasRole('ROLE_tavernauser')" />
+ <security:intercept-url pattern="/feed/**"
+ requires-channel="${requiredChannel}"
+ access="hasRole('ROLE_tavernauser')" />
+ </security:http>
+</beans>
[24/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-client/pom.xml b/taverna-server-client/pom.xml
new file mode 100644
index 0000000..d16b07a
--- /dev/null
+++ b/taverna-server-client/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-client</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Taverna Server Client OSGi Module</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jvnet.ws.wadl</groupId>
+ <artifactId>wadl-core</artifactId>
+ <version>1.1.6</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.8</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tika</groupId>
+ <artifactId>tika-core</artifactId>
+ <version>1.5</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-usagerecord</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>uk.org.taverna.server.client</Export-Package>
+ <Private-Package>uk.org.taverna.server.client.*</Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.ws.wadl</groupId>
+ <artifactId>wadl-client-plugin</artifactId>
+ <version>1.1.6</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <packageName>org.taverna.server.client.wadl</packageName>
+ <includes>*.wadl</includes>
+ <customClassNames>
+ <property>
+ <name>http://example.com/taverna/rest</name>
+ <value>TavernaServer</value>
+ </property>
+ </customClassNames>
+ </configuration>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.jvnet.ws.wadl
+ </groupId>
+ <artifactId>
+ wadl-client-plugin
+ </artifactId>
+ <versionRange>
+ [1.1.6,)
+ </versionRange>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java
new file mode 100644
index 0000000..263034c
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Connected.java
@@ -0,0 +1,20 @@
+package uk.org.taverna.server.client;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+abstract class Connected {
+ void checkError(ClientResponse response) throws ClientException,
+ ServerException {
+ ClientResponse.Status s = response.getClientResponseStatus();
+ if (s.getStatusCode() == 401)
+ throw new TavernaServer.AuthorizationException("not authorized",
+ null);
+ if (s.getStatusCode() >= 500)
+ throw new TavernaServer.ServerException(s.getReasonPhrase(), null);
+ if (s.getStatusCode() >= 400)
+ throw new TavernaServer.ClientException(s.getReasonPhrase(), null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
new file mode 100644
index 0000000..267707d
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
@@ -0,0 +1,39 @@
+package uk.org.taverna.server.client;
+
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd.Path2;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public abstract class DirEntry extends Connected {
+ final Path2 handle;
+ final String path;
+ final Run run;
+
+ protected DirEntry(Run run, String path) {
+ this.run = run;
+ this.path = path.replaceFirst("/+$", "");
+ this.handle = run.run.wd().path2(this.path);
+ }
+
+ public void delete() throws ClientException, ServerException {
+ checkError(handle.deleteAsXml(ClientResponse.class));
+ }
+
+ String path(ClientResponse response) throws ClientException, ServerException {
+ checkError(response);
+ String[] bits = response.getLocation().getPath().split("/");
+ return concat(bits[bits.length - 1]);
+ }
+
+ String localName() {
+ String[] bits = path.split("/");
+ return bits[bits.length - 1];
+ }
+
+ String concat(String name) {
+ return path + "/" + name.split("/", 2)[0];
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java
new file mode 100644
index 0000000..38dc394
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Directory.java
@@ -0,0 +1,94 @@
+package uk.org.taverna.server.client;
+
+import static java.io.File.createTempFile;
+import static javax.ws.rs.client.Entity.entity;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipFile;
+
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+import uk.org.taverna.server.client.generic.DirectoryEntry;
+import uk.org.taverna.server.client.generic.DirectoryReference;
+import uk.org.taverna.server.client.generic.FileReference;
+import uk.org.taverna.server.client.rest.DirectoryContents;
+import uk.org.taverna.server.client.rest.MakeDirectory;
+import uk.org.taverna.server.client.rest.UploadFile;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public class Directory extends DirEntry {
+ private final Wd wd;
+
+ Directory(Run run) {
+ super(run, "");
+ this.wd = run.run.wd();
+ }
+
+ Directory(Run run, String path) {
+ super(run, path);
+ this.wd = run.run.wd();
+ }
+
+ public List<DirEntry> list() {
+ List<DirEntry> result = new ArrayList<>();
+ for (DirectoryEntry de : wd.path3(path)
+ .getAsXml(DirectoryContents.class).getDirOrFile())
+ if (de instanceof DirectoryReference)
+ result.add(new Directory(run, de.getValue()));
+ else if (de instanceof FileReference)
+ result.add(new File(run, de.getValue()));
+ return result;
+ }
+
+ public File createFile(String name, byte[] content) throws ClientException,
+ ServerException {
+ UploadFile uf = new UploadFile();
+ uf.setName(name);
+ uf.setValue(content);
+ return new File(run, path(wd.path(path).putAsXml(uf,
+ ClientResponse.class)));
+ }
+
+ public File createFile(String name, java.io.File content)
+ throws ClientException, ServerException {
+ return new File(run, path(wd.path(concat(name)).putOctetStreamAsXml(
+ entity(content, APPLICATION_OCTET_STREAM_TYPE),
+ ClientResponse.class)));
+ }
+
+ public File createFile(String name, URI source) throws ClientException,
+ ServerException {
+ return new File(run, path(wd.path(concat(name)).postTextUriListAsXml(
+ source.toString(), ClientResponse.class)));
+ }
+
+ public Directory createDirectory(String name) throws ClientException,
+ ServerException {
+ MakeDirectory mkdir = new MakeDirectory();
+ mkdir.setName(name);
+ return new Directory(run, path(wd.path(path).putAsXml(mkdir,
+ ClientResponse.class)));
+ }
+
+ public byte[] getZippedContents() {
+ return wd.path3(path).getAsZip(byte[].class);
+ }
+
+ public ZipFile getZip() throws IOException {
+ byte[] contents = getZippedContents();
+ java.io.File tmp = createTempFile(localName(), ".zip");
+ try (OutputStream os = new FileOutputStream(tmp)) {
+ os.write(contents);
+ }
+ return new ZipFile(tmp);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java
new file mode 100644
index 0000000..0287afb
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/File.java
@@ -0,0 +1,95 @@
+package uk.org.taverna.server.client;
+
+import static java.io.File.createTempFile;
+import static javax.ws.rs.client.Entity.entity;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
+import static org.apache.commons.io.IOUtils.copy;
+import static org.apache.tika.mime.MimeTypes.getDefaultMimeTypes;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
+import org.apache.tika.mime.MimeTypeException;
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+
+public class File extends DirEntry {
+ private final Wd wd;
+
+ File(Run run, String path) {
+ super(run, path);
+ wd = run.run.wd();
+ }
+
+ public InputStream getAsStream() {
+ return wd.path3(path).getAsOctetStream(InputStream.class);
+ }
+
+ public byte[] get() {
+ return wd.path3(path).getAsOctetStream(byte[].class);
+ }
+
+ public String get(Charset encoding) {
+ return new String(wd.path3(path).getAsOctetStream(byte[].class),
+ encoding);
+ }
+
+ public java.io.File getAsFile() throws ClientHandlerException,
+ UniformInterfaceException, IOException, MimeTypeException,
+ ClientException, ServerException {
+ ClientResponse cr = wd.path3(path).getAsOctetStream(
+ ClientResponse.class);
+ checkError(cr);
+ String[] bits = localName().split("[.]");
+ String ext = getDefaultMimeTypes().forName(
+ cr.getHeaders().getFirst("Content-Type")).getExtension();
+ if (ext == null)
+ ext = bits[bits.length - 1];
+ java.io.File tmp = createTempFile(bits[0], ext);
+ try (OutputStream os = new FileOutputStream(tmp);
+ InputStream is = cr.getEntity(InputStream.class)) {
+ copy(is, os);
+ }
+ return tmp;
+ }
+
+ public void setContents(byte[] newContents) throws ClientException,
+ ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(newContents,
+ ClientResponse.class));
+ }
+
+ public void setContents(String newContents) throws ClientException,
+ ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(newContents,
+ ClientResponse.class));
+ }
+
+ public void setContents(String newContents, Charset encoding)
+ throws ClientException, ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(
+ newContents.getBytes(encoding), ClientResponse.class));
+ }
+
+ public void setContents(InputStream newContents) throws ClientException,
+ ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(newContents,
+ ClientResponse.class));
+ }
+
+ public void setContents(java.io.File newContents) throws IOException,
+ ClientException, ServerException {
+ checkError(wd.path(path).putOctetStreamAsXml(
+ entity(newContents, APPLICATION_OCTET_STREAM_TYPE),
+ ClientResponse.class));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java
new file mode 100644
index 0000000..0e6542f
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Property.java
@@ -0,0 +1,18 @@
+package uk.org.taverna.server.client;
+
+public enum Property {
+ STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
+ "readyToNotify"), EMAIL("notificationAddress"), USAGE(
+ "usageRecord");
+
+ private String s;
+
+ private Property(String s) {
+ this.s = s;
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java
new file mode 100644
index 0000000..5c6875e
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Run.java
@@ -0,0 +1,215 @@
+package uk.org.taverna.server.client;
+
+import static org.joda.time.format.ISODateTimeFormat.dateTime;
+import static org.joda.time.format.ISODateTimeFormat.dateTimeParser;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.io.IOUtils;
+import org.joda.time.DateTime;
+import org.ogf.usage.JobUsageRecord;
+import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName;
+import org.w3c.dom.Element;
+
+import uk.org.taverna.server.client.TavernaServer.ClientException;
+import uk.org.taverna.server.client.TavernaServer.ServerException;
+import uk.org.taverna.server.client.generic.KeyPairCredential;
+import uk.org.taverna.server.client.generic.PasswordCredential;
+import uk.org.taverna.server.client.generic.port.InputPort;
+import uk.org.taverna.server.client.generic.port.OutputPort;
+import uk.org.taverna.server.client.rest.InputDescription;
+import uk.org.taverna.server.client.rest.InputDescription.Value;
+
+import com.sun.jersey.api.client.ClientResponse;
+
+public class Run extends Connected {
+ RunsRunName run;
+
+ Run(TavernaServer server, String value) {
+ run = server.root.runsRunName(value);
+ }
+
+ public String getName() {
+ return run.name().getAsTextPlain(ClientResponse.class)
+ .getEntity(String.class);
+ }
+
+ public void setName(String name) {
+ run.name().putTextPlain(name, String.class);
+ }
+
+ public Date getExpiry() {
+ return dateTimeParser().parseDateTime(
+ run.expiry().getAsTextPlain(String.class)).toDate();
+ }
+
+ public void setExpiry(Date expiryTimestamp) {
+ run.expiry().putTextPlain(
+ dateTime().print(new DateTime(expiryTimestamp)), String.class);
+ }
+
+ public Date getCreate() {
+ String timestamp = run.createTime().getAsTextPlain(String.class);
+ if (timestamp == null || timestamp.trim().isEmpty())
+ return null;
+ return dateTimeParser().parseDateTime(timestamp).toDate();
+ }
+
+ public Date getStart() {
+ String timestamp = run.startTime().getAsTextPlain(String.class);
+ if (timestamp == null || timestamp.trim().isEmpty())
+ return null;
+ return dateTimeParser().parseDateTime(timestamp).toDate();
+ }
+
+ public Date getFinish() {
+ String timestamp = run.finishTime().getAsTextPlain(String.class);
+ if (timestamp == null || timestamp.trim().isEmpty())
+ return null;
+ return dateTimeParser().parseDateTime(timestamp).toDate();
+ }
+
+ public Status getStatus() {
+ return Status.valueOf(run.status().getAsTextPlain(String.class));
+ }
+
+ public void setStatus(Status status) {
+ run.status().putTextPlain(status, String.class);
+ }
+
+ public void start() {
+ setStatus(Status.Operating);
+ }
+
+ public void kill() {
+ setStatus(Status.Finished);
+ }
+
+ public boolean isRunning() {
+ return getStatus() == Status.Operating;
+ }
+
+ public String getStandardOutput() {
+ return run.stdout().getAsTextPlain(String.class);
+ }
+
+ public String getStandardError() {
+ return run.stderr().getAsTextPlain(String.class);
+ }
+
+ public String getLog() {
+ return run.log().getAsTextPlain(String.class);
+ }
+
+ public Integer getExitCode() {
+ String code = run.listeners().name("io")
+ .propertiesPropertyName("exitCode")
+ .getAsTextPlain(String.class);
+ if (code == null || code.trim().isEmpty())
+ return null;
+ return Integer.parseInt(code);
+ }
+
+ public String getProperty(Property prop) {
+ return run.listeners().name("io")
+ .propertiesPropertyName(prop.toString())
+ .getAsTextPlain(String.class);
+ }
+
+ public void setGenerateRunBundle(boolean generateRunBundle) {
+ run.generateProvenance().putTextPlain(generateRunBundle, String.class);
+ }
+
+ public byte[] getRunBundle() {
+ return run.runBundle().getAsVndWf4everRobundleZip(byte[].class);
+ }
+
+ public List<InputPort> getInputs() {
+ return run.input().expected().getAsInputDescriptionXml().getInput();
+ }
+
+ public List<OutputPort> getOutputs() {
+ return run.output().getAsOutputDescriptionXml().getOutput();
+ }
+
+ public void setInput(String name, String value) {
+ Value v = new Value();
+ v.setValue(value);
+ InputDescription idesc = new InputDescription();
+ idesc.setValue(v);
+ run.input().inputName(name).putXmlAsInputDescription(idesc);
+ }
+
+ public void setInput(String name, String value, char listSeparator) {
+ Value v = new Value();
+ v.setValue(value);
+ InputDescription idesc = new InputDescription();
+ idesc.setValue(v);
+ idesc.setListDelimiter(new String(new char[] { listSeparator }));
+ run.input().inputName(name).putXmlAsInputDescription(idesc);
+ }
+
+ public byte[] getWorkflow() {
+ return run.workflow().getAsVndTavernaT2flowXml(byte[].class);
+ }
+
+ // TODO Consider better ways to do this
+ public Element getInteractionFeed() {
+ return run.interaction().getAsAtomXml(Element.class);
+ }
+
+ public Element getInteractionEntry(String id) {
+ return run.interaction().id(id).getAsAtomXml(Element.class);
+ }
+
+ public JobUsageRecord getUsageRecord() throws JAXBException {
+ return JobUsageRecord.unmarshal(run.usage().getAsXml(Element.class));
+ }
+
+ public Directory getWorkingDirectory() {
+ return new Directory(this);
+ }
+
+ public String getOwner() {
+ return run.security().owner().getAsTextPlain(String.class);
+ }
+
+ // TODO permissions
+
+ public void grantPasswordCredential(URI contextService, String username,
+ String password) throws ClientException, ServerException {
+ PasswordCredential pc = new PasswordCredential();
+ pc.setServiceURI(contextService.toString());
+ pc.setUsername(username);
+ pc.setPassword(password);
+ checkError(run.security().credentials()
+ .postXmlAsOctetStream(pc, ClientResponse.class));
+ }
+
+ public void grantKeyCredential(URI contextService, java.io.File source,
+ String unlockPassword, String aliasEntry) throws IOException,
+ ClientException, ServerException {
+ KeyPairCredential kpc = new KeyPairCredential();
+ kpc.setServiceURI(contextService.toString());
+ try (InputStream in = new FileInputStream(source)) {
+ byte[] buffer = new byte[(int) source.length()];
+ IOUtils.read(in, buffer);
+ kpc.setCredentialBytes(buffer);
+ }
+ if (source.getName().endsWith(".p12"))
+ kpc.setFileType("PKCS12");
+ else
+ kpc.setFileType("JKS");
+ kpc.setCredentialName(aliasEntry);
+ kpc.setUnlockPassword(unlockPassword);
+ checkError(run.security().credentials()
+ .postXmlAsOctetStream(kpc, ClientResponse.class));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java
new file mode 100644
index 0000000..9c375ad
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/Status.java
@@ -0,0 +1,36 @@
+package uk.org.taverna.server.client;
+
+/**
+ * States of a workflow run. They are {@link #Initialized Initialized},
+ * {@link #Operating Operating}, {@link #Stopped Stopped}, and
+ * {@link #Finished Finished}. Conceptually, there is also a
+ * <tt>Destroyed</tt> state, but the workflow run does not exist (and hence
+ * can't have its state queried or set) in that case.
+ *
+ * @author Donal Fellows
+ */
+public enum Status {
+ /**
+ * The workflow run has been created, but is not yet running. The run
+ * will need to be manually moved to {@link #Operating Operating} when
+ * ready.
+ */
+ Initialized,
+ /**
+ * The workflow run is going, reading input, generating output, etc.
+ * Will eventually either move automatically to {@link #Finished
+ * Finished} or can be moved manually to {@link #Stopped Stopped} (where
+ * supported).
+ */
+ Operating,
+ /**
+ * The workflow run is paused, and will need to be moved back to
+ * {@link #Operating Operating} manually.
+ */
+ Stopped,
+ /**
+ * The workflow run has ceased; data files will continue to exist until
+ * the run is destroyed (which may be manual or automatic).
+ */
+ Finished
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
new file mode 100644
index 0000000..7c0dcdd
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
@@ -0,0 +1,128 @@
+package uk.org.taverna.server.client;
+
+import static java.nio.file.Files.readAllBytes;
+import static org.taverna.server.client.wadl.TavernaServer.createClient;
+import static org.taverna.server.client.wadl.TavernaServer.root;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.taverna.server.client.wadl.TavernaServer.Root;
+
+import uk.org.taverna.server.client.generic.Capability;
+import uk.org.taverna.server.client.generic.TavernaRun;
+import uk.org.taverna.server.client.generic.VersionedElement;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+
+public class TavernaServer extends Connected {
+ final Root root;
+ private final URI location;
+ private final boolean authenticated;
+
+ TavernaServer(URI serviceRoot) {
+ root = root(createClient(), location = serviceRoot);
+ authenticated = false;
+ }
+
+ TavernaServer(URI serviceRoot, String username, String password) {
+ Client client = createClient();
+ client.addFilter(new HTTPBasicAuthFilter(username, password));
+ authenticated = true;
+ root = root(client, location = serviceRoot);
+ }
+
+ TavernaServer(TavernaServer service, String username, String password) {
+ Client client = createClient();
+ client.addFilter(new HTTPBasicAuthFilter(username, password));
+ authenticated = true;
+ root = root(client, location = service.location);
+ getServerVersionInfo();
+ }
+
+ public TavernaServer upgradeToAuth(String username, String password) {
+ if (authenticated)
+ throw new IllegalStateException("may only upgrade an unauthenticated connection");
+ return new TavernaServer(this, username, password);
+ }
+
+ public List<Capability> getCapabilities() {
+ return root.policy().capabilities().getAsCapabilitiesXml()
+ .getCapability();
+ }
+
+ public int getRunLimit() {
+ return root.policy().runLimit().getAsTextPlain(Integer.class);
+ }
+
+ public int getOperatingLimit() {
+ return root.policy().operatingLimit().getAsTextPlain(Integer.class);
+ }
+
+ public List<String> getPermittedWorkflows() {
+ return root.policy().permittedWorkflows().getAsPermittedWorkflowsXml()
+ .getWorkflow();
+ }
+
+ public List<Run> getExistingRuns() {
+ List<Run> runs = new ArrayList<>();
+ for (TavernaRun run : root.runs().getAsRunListXml().getRun())
+ runs.add(new Run(this, run.getValue()));
+ return runs;
+ }
+
+ public VersionedElement getServerVersionInfo() {
+ return root.getAsServerDescriptionXml();
+ }
+
+ private Run response2run(ClientResponse response) throws ClientException, ServerException {
+ checkError(response);
+ if (response.getClientResponseStatus().getStatusCode() == 201) {
+ String[] path = response.getLocation().getPath().split("/");
+ return new Run(this, path[path.length - 1]);
+ }
+ return null;
+ }
+
+ public Run createWorkflowRun(byte[] t2flowBytes) throws ClientException, ServerException {
+ return response2run(root.runs().postVndTavernaT2flowXmlAsOctetStream(
+ t2flowBytes, ClientResponse.class));
+ }
+
+ public Run createWorkflowRun(File t2flowFile) throws IOException, ClientException, ServerException {
+ return createWorkflowRun(readAllBytes(t2flowFile.toPath()));
+ }
+
+ public Run createWorkflowRun(URI t2flowUri) throws ClientException, ServerException {
+ return response2run(root.runs().postTextUriListAsOctetStream(
+ t2flowUri.toString(), ClientResponse.class));
+ }
+
+
+ public static class ClientException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ ClientException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+ public static class AuthorizationException extends ClientException {
+ private static final long serialVersionUID = 1L;
+
+ AuthorizationException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+ static class ServerException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ ServerException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
new file mode 100644
index 0000000..b00b075
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
@@ -0,0 +1,23 @@
+package uk.org.taverna.server.client;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TavernaServerConnectionFactory {
+ private Map<URI, TavernaServer> cache = new HashMap<>();
+
+ public synchronized TavernaServer connectNoAuth(URI uri) {
+ TavernaServer conn = cache.get(uri);
+ if (conn == null)
+ cache.put(uri, conn = new TavernaServer(uri));
+ return conn;
+ }
+
+ public TavernaServer connectAuth(URI uri, String username, String password) {
+ TavernaServer conn = new TavernaServer(uri, username, password);
+ // Force a check of the credentials by getting the server version
+ conn.getServerVersionInfo();
+ return conn;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java b/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java
new file mode 100644
index 0000000..59e809d
--- /dev/null
+++ b/taverna-server-client/src/main/java/uk/org/taverna/server/client/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Implementation of a basic client for Taverna Server.
+ * @author Donal Fellows
+ */
+package uk.org.taverna.server.client;
\ No newline at end of file
[05/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css b/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css
new file mode 100644
index 0000000..8b8afac
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css
@@ -0,0 +1,563 @@
+/*!
+ * jQuery UI CSS Framework 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+
+
+/*!
+ * jQuery UI CSS Framework 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=segoe%20ui,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=3px&bgColorHeader=f9f9f9&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=cccccc&fcHeader=e69700&iconColorHeader=5fa5e3&bgColorContent=eeeeee&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=0a82eb&bgColorDefault=1484e6&bgTextureDefault=08_diagonals_thick.png&bgImgOpacityDefault=22&borderColorDefault=ffffff&fcDefault=ffffff&iconColorDefault=fcdd4a&bgColorHover=2293f7&bgTextureHover=08_diagonals_thick.png&bgImgOpacityHover=26&borderColorHover=2293f7&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=e69700&bgTextureActive=08_diagonals_thick.png&bgImgOpacityActive=20&borderColorActive=e69700&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=c5ddfc&bgTextureHighlight=07_diagonals_small.png&bgImgOpacityHighlight=25&borderCol
orHighlight=ffffff&fcHighlight=333333&iconColorHighlight=0b54d5&bgColorError=e69700&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=20&borderColorError=e69700&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=e6b900&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=e69700&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=20&thicknessShadow=0px&offsetTopShadow=6px&offsetLeftShadow=6px&cornerRadiusShadow=3px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: segoe ui, Arial, sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: segoe ui, Arial, sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #eeeeee url(ui-bg_inset-hard_100_eeeeee_1x100.png) 50% bottom repeat-x; color: #222222; }
+.ui-widget-content a { color: #222222; }
+.ui-widget-header { border: 1px solid #cccccc; background: #f9f9f9 url(ui-bg_highlight-soft_100_f9f9f9_1x100.png) 50% 50% repeat-x; color: #e69700; font-weight: bold; }
+.ui-widget-header a { color: #e69700; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #ffffff; background: #1484e6 url(ui-bg_diagonals-thick_22_1484e6_40x40.png) 50% 50% repeat; font-weight: bold; color: #ffffff; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #2293f7; background: #2293f7 url(ui-bg_diagonals-thick_26_2293f7_40x40.png) 50% 50% repeat; font-weight: bold; color: #ffffff; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #e69700; background: #e69700 url(ui-bg_diagonals-thick_20_e69700_40x40.png) 50% 50% repeat; font-weight: bold; color: #ffffff; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #ffffff; background: #c5ddfc url(ui-bg_diagonals-small_25_c5ddfc_40x40.png) 50% 50% repeat; color: #333333; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #333333; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #e69700; background: #e69700 url(ui-bg_diagonals-thick_20_e69700_40x40.png) 50% 50% repeat; color: #ffffff; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_0a82eb_256x240.png); }
+.ui-widget-content .ui-icon {background-image: url(ui-icons_0a82eb_256x240.png); }
+.ui-widget-header .ui-icon {background-image: url(ui-icons_5fa5e3_256x240.png); }
+.ui-state-default .ui-icon { background-image: url(ui-icons_fcdd4a_256x240.png); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
+.ui-state-active .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
+.ui-state-highlight .ui-icon {background-image: url(ui-icons_0b54d5_256x240.png); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -khtml-border-top-left-radius: 3px; border-top-left-radius: 3px; }
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; -khtml-border-top-right-radius: 3px; border-top-right-radius: 3px; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; -khtml-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; -khtml-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #e6b900 url(ui-bg_flat_0_e6b900_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: 6px 0 0 6px; padding: 0px; background: #e69700 url(ui-bg_flat_0_e69700_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 3px; -khtml-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; }/*!
+ * jQuery UI Resizable 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
+ * jQuery UI Selectable 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
+/*!
+ * jQuery UI Accordion 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+/* IE/Win - Fix animation bug - #4615 */
+.ui-accordion { width: 100%; }
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }
+/*!
+ * jQuery UI Autocomplete 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete { position: absolute; cursor: default; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/*
+ * jQuery UI Menu 1.8.23
+ *
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+ float: left;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+/*!
+ * jQuery UI Button 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+/*!
+ * jQuery UI Dialog 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/*!
+ * jQuery UI Slider 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
+ * jQuery UI Tabs 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*!
+ * jQuery UI Datepicker 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}/*!
+ * jQuery UI Progressbar 1.8.23
+ *
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
[14/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java
new file mode 100644
index 0000000..61640bf
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+
+package org.taverna.server.master.notification;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jivesoftware.smack.Chat;
+import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.MessageListener;
+import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.packet.Message;
+import org.taverna.server.master.interfaces.MessageDispatcher;
+import org.taverna.server.master.interfaces.TavernaRun;
+
+/**
+ * Send notifications by Jabber/XMPP.
+ *
+ * @author Donal Fellows
+ */
+public class JabberDispatcher implements MessageDispatcher {
+ @Override
+ public String getName() {
+ return "xmpp";
+ }
+
+ private Log log = LogFactory.getLog("Taverna.Server.Notification");
+ private XMPPConnection conn;
+ private String resource = "TavernaServer";
+ private String host = "";
+ private String user = "";
+ private String pass = "";
+
+ /**
+ * @param resource
+ * The XMPP resource to use when connecting the server. This
+ * defaults to "<tt>TavernaServer</tt>".
+ */
+ public void setResource(String resource) {
+ this.resource = resource;
+ }
+
+ /**
+ * @param service
+ * The XMPP service URL.
+ */
+ public void setHost(String service) {
+ if (service == null || service.trim().isEmpty()
+ || service.trim().startsWith("$"))
+ this.host = "";
+ else
+ this.host = service.trim();
+ }
+
+ /**
+ * @param user
+ * The user identity to use with the XMPP service.
+ */
+ public void setUsername(String user) {
+ if (user == null || user.trim().isEmpty()
+ || user.trim().startsWith("$"))
+ this.user = "";
+ else
+ this.user = user.trim();
+ }
+
+ /**
+ * @param pass
+ * The password to use with the XMPP service.
+ */
+ public void setPassword(String pass) {
+ if (pass == null || pass.trim().isEmpty()
+ || pass.trim().startsWith("$"))
+ this.pass = "";
+ else
+ this.pass = pass.trim();
+ }
+
+ @PostConstruct
+ void setup() {
+ try {
+ if (host.isEmpty() || user.isEmpty() || pass.isEmpty()) {
+ log.info("disabling XMPP support; incomplete configuration");
+ conn = null;
+ return;
+ }
+ ConnectionConfiguration cfg = new ConnectionConfiguration(host);
+ cfg.setSendPresence(false);
+ XMPPConnection c = new XMPPConnection(cfg);
+ c.connect();
+ c.login(user, pass, resource);
+ conn = c;
+ log.info("connected to XMPP service <" + host + "> as user <"
+ + user + ">");
+ } catch (Exception e) {
+ log.info("failed to connect to XMPP server", e);
+ }
+ }
+
+ @PreDestroy
+ public void close() {
+ if (conn != null)
+ conn.disconnect();
+ conn = null;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return conn != null;
+ }
+
+ @Override
+ public void dispatch(TavernaRun ignored, String messageSubject,
+ String messageContent, String targetParameter) throws Exception {
+ Chat chat = conn.getChatManager().createChat(targetParameter,
+ new DroppingListener());
+ Message m = new Message();
+ m.addBody(null, messageContent);
+ m.setSubject(messageSubject);
+ chat.sendMessage(m);
+ }
+
+ static class DroppingListener implements MessageListener {
+ private Log log = LogFactory
+ .getLog("Taverna.Server.Notification.Jabber");
+
+ @Override
+ public void processMessage(Chat chat, Message message) {
+ if (log.isDebugEnabled())
+ log.debug("unexpectedly received XMPP message from <"
+ + message.getFrom() + ">; ignoring");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java
new file mode 100644
index 0000000..bc0f60d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.interfaces.MessageDispatcher;
+import org.taverna.server.master.interfaces.TavernaRun;
+
+/**
+ * A common object for handling dispatch of event-driven messages.
+ *
+ * @author Donal Fellows
+ */
+public class NotificationEngine {
+ private Log log = LogFactory.getLog("Taverna.Server.Notification");
+ private Map<String, MessageDispatcher> dispatchers;
+ private List<MessageDispatcher> universalDispatchers;
+
+ /**
+ * @param dispatchers
+ * The various dispatchers we want to install.
+ */
+ @Required
+ public void setDispatchers(List<MessageDispatcher> dispatchers) {
+ this.dispatchers = new HashMap<>();
+ for (MessageDispatcher d : dispatchers)
+ this.dispatchers.put(d.getName(), d);
+ }
+
+ /**
+ * @param dispatcherList
+ * A list of dispatch objects to always dispatch to.
+ */
+ @Required
+ public void setUniversalDispatchers(List<MessageDispatcher> dispatcherList) {
+ this.universalDispatchers = dispatcherList;
+ }
+
+ private void dispatchToChosenTarget(TavernaRun originator, String scheme,
+ String target, Message message) throws Exception {
+ try {
+ MessageDispatcher d = dispatchers.get(scheme);
+ if (d != null && d.isAvailable())
+ d.dispatch(originator, message.getTitle(scheme),
+ message.getContent(scheme), target);
+ else
+ log.warn("no such notification dispatcher for " + scheme);
+ } catch (URISyntaxException e) {
+ // See if *someone* will handle the message
+ Exception e2 = null;
+ for (MessageDispatcher d : dispatchers.values())
+ try {
+ if (d.isAvailable()) {
+ d.dispatch(originator, message.getTitle(d.getName()),
+ message.getContent(d.getName()), scheme + ":"
+ + target);
+ return;
+ }
+ } catch (Exception ex) {
+ if (log.isDebugEnabled())
+ log.debug("failed in pseudo-directed dispatch of "
+ + scheme + ":" + target, ex);
+ e2 = ex;
+ }
+ if (e2 != null)
+ throw e2;
+ }
+ }
+
+ private void dispatchUniversally(TavernaRun originator, Message message)
+ throws Exception {
+ for (MessageDispatcher d : universalDispatchers)
+ try {
+ if (d.isAvailable())
+ d.dispatch(originator, message.getTitle(d.getName()),
+ message.getContent(d.getName()), null);
+ } catch (Exception e) {
+ log.warn("problem in universal dispatcher", e);
+ }
+ }
+
+ /**
+ * Dispatch a message over the notification fabric.
+ *
+ * @param originator
+ * What workflow run was the source of this message?
+ * @param destination
+ * Where the message should get delivered to. The correct format
+ * of this is either as a URI of some form (where the scheme
+ * determines the dispatcher) or as an invalid URI in which case
+ * it is just tried against the possibilities to see if any
+ * succeeds.
+ * @param subject
+ * The subject line of the message.
+ * @param message
+ * The plain text body of the message.
+ * @throws Exception
+ * If anything goes wrong with the dispatch process.
+ */
+ public void dispatchMessage(TavernaRun originator, String destination,
+ Message message) throws Exception {
+ if (destination != null && !destination.trim().isEmpty()) {
+ try {
+ URI toURI = new URI(destination.trim());
+ dispatchToChosenTarget(originator, toURI.getScheme(),
+ toURI.getSchemeSpecificPart(), message);
+ } catch (URISyntaxException e) {
+ // Ignore
+ }
+ }
+ dispatchUniversally(originator, message);
+ }
+
+ /**
+ * @return The message dispatchers that are actually available (i.e., not
+ * disabled by configuration somewhere).
+ */
+ public List<String> listAvailableDispatchers() {
+ ArrayList<String> result = new ArrayList<>();
+ for (Map.Entry<String, MessageDispatcher> entry : dispatchers
+ .entrySet()) {
+ if (entry.getValue().isAvailable())
+ result.add(entry.getKey());
+ }
+ return result;
+ }
+
+ public interface Message {
+ String getContent(String type);
+
+ String getTitle(String type);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java
new file mode 100644
index 0000000..c8d7ef6
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.joda.time.DateTime;
+import org.taverna.server.master.interfaces.MessageDispatcher;
+import org.taverna.server.master.interfaces.TavernaRun;
+
+/**
+ * Rate-limiting support. Some message fabrics simply should not be used to send
+ * a lot of messages.
+ *
+ * @author Donal Fellows
+ */
+public abstract class RateLimitedDispatcher implements MessageDispatcher {
+ /** Pre-configured logger. */
+ protected Log log = LogFactory.getLog("Taverna.Server.Notification");
+ private int cooldownSeconds;
+ private Map<String, DateTime> lastSend = new HashMap<>();
+
+ String valid(String value, String def) {
+ if (value == null || value.trim().isEmpty()
+ || value.trim().startsWith("${"))
+ return def;
+ else
+ return value.trim();
+ }
+
+ /**
+ * Set how long must elapse between updates to the status of any particular
+ * user. Calls before that time are just silently dropped.
+ *
+ * @param cooldownSeconds
+ * Time to elapse, in seconds.
+ */
+ public void setCooldownSeconds(int cooldownSeconds) {
+ this.cooldownSeconds = cooldownSeconds;
+ }
+
+ /**
+ * Test whether the rate limiter allows the given user to send a message.
+ *
+ * @param who
+ * Who wants to send the message?
+ * @return <tt>true</tt> iff they are permitted.
+ */
+ protected boolean isSendAllowed(String who) {
+ DateTime now = new DateTime();
+ synchronized (lastSend) {
+ DateTime last = lastSend.get(who);
+ if (last != null) {
+ if (!now.isAfter(last.plusSeconds(cooldownSeconds)))
+ return false;
+ }
+ lastSend.put(who, now);
+ }
+ return true;
+ }
+
+ @Override
+ public void dispatch(TavernaRun ignored, String messageSubject,
+ String messageContent, String target) throws Exception {
+ if (isSendAllowed(target))
+ dispatch(messageSubject, messageContent, target);
+ }
+
+ /**
+ * Dispatch a message to a recipient that doesn't care what produced it.
+ *
+ * @param messageSubject
+ * The subject of the message to send.
+ * @param messageContent
+ * The plain-text content of the message to send.
+ * @param target
+ * A description of where it is to go.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ public abstract void dispatch(String messageSubject, String messageContent,
+ String target) throws Exception;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java
new file mode 100644
index 0000000..5553141
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification;
+
+import static org.taverna.server.master.defaults.Default.SMS_GATEWAY_URL;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Dispatch termination messages via SMS.
+ *
+ * @author Donal Fellows
+ */
+public class SMSDispatcher extends RateLimitedDispatcher {
+ @Override
+ public String getName() {
+ return "sms";
+ }
+
+ private CloseableHttpClient client;
+ private URI service;
+ private String user = "", pass = "";
+ private String usernameField = "username", passwordField = "password",
+ destinationField = "to", messageField = "text";
+
+ /**
+ * @param usernameField
+ * The name of the field that conveys the sending username; this
+ * is the <i>server</i>'s identity.
+ */
+ @Required
+ public void setUsernameField(String usernameField) {
+ this.usernameField = usernameField;
+ }
+
+ /**
+ * @param passwordField
+ * The field holding the password to authenticate the server to
+ * the SMS gateway.
+ */
+ @Required
+ public void setPasswordField(String passwordField) {
+ this.passwordField = passwordField;
+ }
+
+ /**
+ * @param destinationField
+ * The field holding the number to send the SMS to.
+ */
+ @Required
+ public void setDestinationField(String destinationField) {
+ this.destinationField = destinationField;
+ }
+
+ /**
+ * @param messageField
+ * The field holding the plain-text message to send.
+ */
+ @Required
+ public void setMessageField(String messageField) {
+ this.messageField = messageField;
+ }
+
+ public void setService(String serviceURL) {
+ String s = valid(serviceURL, "");
+ if (s.isEmpty()) {
+ log.warn("did not get sms.service from servlet config; using default ("
+ + SMS_GATEWAY_URL + ")");
+ s = SMS_GATEWAY_URL;
+ }
+ try {
+ service = new URI(s);
+ } catch (URISyntaxException e) {
+ service = null;
+ }
+ }
+
+ public void setUser(String user) {
+ this.user = valid(user, "");
+ }
+
+ public void setPassword(String pass) {
+ this.pass = valid(pass, "");
+ }
+
+ @PostConstruct
+ void init() {
+ client = HttpClientBuilder.create().build();
+ }
+
+ @PreDestroy
+ void close() throws IOException {
+ try {
+ if (client != null)
+ client.close();
+ } finally {
+ client = null;
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return service != null && !user.isEmpty() && !pass.isEmpty();
+ }
+
+ @Override
+ public void dispatch(String messageSubject, String messageContent,
+ String targetParameter) throws Exception {
+ // Sanity check
+ if (!targetParameter.matches("[^0-9]+"))
+ throw new Exception("invalid phone number");
+
+ if (!isSendAllowed("anyone"))
+ return;
+
+ // Build the message to send
+ List<NameValuePair> params = new ArrayList<>();
+ params.add(new BasicNameValuePair(usernameField, user));
+ params.add(new BasicNameValuePair(passwordField, pass));
+ params.add(new BasicNameValuePair(destinationField, targetParameter));
+ params.add(new BasicNameValuePair(messageField, messageContent));
+
+ // Send the message
+ HttpPost post = new HttpPost(service);
+ post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
+ HttpResponse response = client.execute(post);
+
+ // Log the response
+ HttpEntity entity = response.getEntity();
+ if (entity != null)
+ try (BufferedReader e = new BufferedReader(new InputStreamReader(
+ entity.getContent()))) {
+ log.info(e.readLine());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java
new file mode 100644
index 0000000..8ee4815
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification;
+
+import java.util.Properties;
+
+import twitter4j.Twitter;
+import twitter4j.TwitterFactory;
+import twitter4j.conf.Configuration;
+import twitter4j.conf.PropertyConfiguration;
+import twitter4j.auth.AuthorizationFactory;
+
+/**
+ * Super simple-minded twitter dispatcher. You need to tell it your consumer key
+ * and secret as part of the connection parameters, for example via a dispatcher
+ * URN of "<tt>twitter:fred:bloggs</tt>" where <tt>fred</tt> is the key and
+ * <tt>bloggs</tt> is the secret.
+ *
+ * @author Donal Fellows
+ */
+public class TwitterDispatcher extends RateLimitedDispatcher {
+ @Override
+ public String getName() {
+ return "twitter";
+ }
+
+ public static final int MAX_MESSAGE_LENGTH = 140;
+ public static final char ELLIPSIS = '\u2026';
+
+ private String token = "";
+ private String secret = "";
+
+ public void setAccessToken(String token) {
+ this.token = valid(token, "");
+ }
+
+ public void setAccessSecret(String secret) {
+ this.secret = valid(secret, "");
+ }
+
+ private Properties getConfig() throws NotConfiguredException {
+ if (token.isEmpty() || secret.isEmpty())
+ throw new NotConfiguredException();
+ Properties p = new Properties();
+ p.setProperty(ACCESS_TOKEN_PROP, token);
+ p.setProperty(ACCESS_SECRET_PROP, secret);
+ return p;
+ }
+
+ public static final String ACCESS_TOKEN_PROP = "oauth.accessToken";
+ public static final String ACCESS_SECRET_PROP = "oauth.accessTokenSecret";
+
+ private Twitter getTwitter(String key, String secret) throws Exception {
+ if (key.isEmpty() || secret.isEmpty())
+ throw new NoCredentialsException();
+
+ Properties p = getConfig();
+ p.setProperty("oauth.consumerKey", key);
+ p.setProperty("oauth.consumerSecret", secret);
+
+ Configuration config = new PropertyConfiguration(p);
+ TwitterFactory factory = new TwitterFactory(config);
+ Twitter t = factory.getInstance(AuthorizationFactory
+ .getInstance(config));
+ // Verify that we can connect!
+ t.getOAuthAccessToken();
+ return t;
+ }
+
+ // TODO: Get secret from credential manager
+ @Override
+ public void dispatch(String messageSubject, String messageContent,
+ String targetParameter) throws Exception {
+ // messageSubject ignored
+ String[] target = targetParameter.split(":", 2);
+ if (target == null || target.length != 2)
+ throw new Exception("missing consumer key or secret");
+ String who = target[0];
+ if (!isSendAllowed(who))
+ return;
+ Twitter twitter = getTwitter(who, target[1]);
+
+ if (messageContent.length() > MAX_MESSAGE_LENGTH)
+ messageContent = messageContent
+ .substring(0, MAX_MESSAGE_LENGTH - 1) + ELLIPSIS;
+ twitter.updateStatus(messageContent);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ try {
+ // Try to create the configuration and push it through as far as
+ // confirming that we can build an access object (even if it isn't
+ // bound to a user)
+ new TwitterFactory(new PropertyConfiguration(getConfig()))
+ .getInstance();
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Indicates that the dispatcher has not been configured with service
+ * credentials.
+ *
+ * @author Donal Fellows
+ */
+ @SuppressWarnings("serial")
+ public static class NotConfiguredException extends Exception {
+ NotConfiguredException() {
+ super("not configured with xAuth key and secret; "
+ + "dispatch not possible");
+ }
+ }
+
+ /**
+ * Indicates that the user did not supply their credentials.
+ *
+ * @author Donal Fellows
+ */
+ @SuppressWarnings("serial")
+ public static class NoCredentialsException extends Exception {
+ NoCredentialsException() {
+ super("no consumer key and secret present; "
+ + "dispatch not possible");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java
new file mode 100644
index 0000000..e5beaeb
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification.atom;
+
+import static java.lang.String.format;
+import static java.util.UUID.randomUUID;
+import static javax.ws.rs.core.UriBuilder.fromUri;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.common.Uri.secure;
+
+import java.net.URI;
+import java.util.Date;
+
+import javax.annotation.security.RolesAllowed;
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.web.context.ServletContextAware;
+import org.taverna.server.master.TavernaServerSupport;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+import org.taverna.server.master.rest.TavernaServerREST.EventFeed;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * Simple REST handler that allows an Atom feed to be served up of events
+ * generated by workflow runs.
+ *
+ * @author Donal Fellows
+ */
+public class AtomFeed implements EventFeed, UriBuilderFactory,
+ ServletContextAware {
+ /**
+ * The name of a parameter that states what address we should claim that the
+ * feed's internally-generated URIs are relative to. If not set, a default
+ * will be guessed.
+ */
+ public static final String PREFERRED_URI_PARAM = "taverna.preferredUserUri";
+ private EventDAO eventSource;
+ private TavernaServerSupport support;
+ private URI baseURI;
+ private Abdera abdera;
+ private String feedLanguage = "en";
+ private String uuid = randomUUID().toString();
+
+ @Required
+ public void setEventSource(EventDAO eventSource) {
+ this.eventSource = eventSource;
+ }
+
+ @Required
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ public void setFeedLanguage(String language) {
+ this.feedLanguage = language;
+ }
+
+ public String getFeedLanguage() {
+ return feedLanguage;
+ }
+
+ @Required
+ public void setAbdera(Abdera abdera) {
+ this.abdera = abdera;
+ }
+
+ @Override
+ @CallCounted
+ @RolesAllowed(USER)
+ public Feed getFeed(UriInfo ui) {
+ Feed feed = abdera.getFactory().newFeed();
+ feed.setTitle("events relating to workflow runs").setLanguage(
+ feedLanguage);
+ String user = support.getPrincipal().toString()
+ .replaceAll("[^A-Za-z0-9]+", "");
+ feed.setId(format("urn:taverna-server:%s:%s", uuid, user));
+ org.joda.time.DateTime modification = null;
+ for (Event e : eventSource.getEvents(support.getPrincipal())) {
+ if (modification == null || e.getPublished().isAfter(modification))
+ modification = e.getPublished();
+ feed.addEntry(e.getEntry(abdera, feedLanguage));
+ }
+ if (modification == null)
+ feed.setUpdated(new Date());
+ else
+ feed.setUpdated(modification.toDate());
+ feed.addLink(ui.getAbsolutePath().toASCIIString(), "self");
+ return feed;
+ }
+
+ @Override
+ @CallCounted
+ @RolesAllowed(USER)
+ public Entry getEvent(String id) {
+ return eventSource.getEvent(support.getPrincipal(), id).getEntry(
+ abdera, feedLanguage);
+ }
+
+ @Override
+ public UriBuilder getRunUriBuilder(TavernaRun run) {
+ return secure(fromUri(getBaseUriBuilder().path("runs/{uuid}").build(
+ run.getId())));
+ }
+
+ @Override
+ public UriBuilder getBaseUriBuilder() {
+ return secure(fromUri(baseURI));
+ }
+
+ @Override
+ public String resolve(String uri) {
+ if (uri == null)
+ return null;
+ return secure(baseURI, uri).toString();
+ }
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ String base = servletContext.getInitParameter(PREFERRED_URI_PARAM);
+ if (base == null)
+ base = servletContext.getContextPath() + "/rest";
+ baseURI = URI.create(base);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java
new file mode 100644
index 0000000..825029d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification.atom;
+
+import static java.util.UUID.randomUUID;
+
+import java.io.Serializable;
+import java.net.URI;
+import java.util.Date;
+
+import javax.jdo.annotations.Column;
+import javax.jdo.annotations.Index;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.Queries;
+import javax.jdo.annotations.Query;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Entry;
+import org.joda.time.DateTime;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Parent class of all events that may appear on the feed for a workflow run.
+ *
+ * @author Donal Fellows
+ */
+@SuppressWarnings("serial")
+@PersistenceCapable(schema = "ATOM", table = "EVENTS")
+@Queries({
+ @Query(name = "eventsForUser", language = "SQL", value = "SELECT id FROM ATOM.EVENTS WHERE owner = ? ORDER BY published DESC", resultClass = String.class),
+ @Query(name = "eventForUserAndId", language = "SQL", value = "SELECT id FROM ATOM.EVENTS WHERE owner = ? AND id = ?", resultClass = String.class),
+ @Query(name = "eventsFromBefore", language = "SQL", value = "SELECT id FROM ATOM.EVENTS where published < ?", resultClass = String.class) })
+public class Event implements Serializable {
+ @Persistent(primaryKey = "true")
+ @Column(length = 48)
+ private String id;
+ @Persistent
+ private String owner;
+ @Persistent
+ @Index
+ private Date published;
+ @Persistent
+ private String message;
+ @Persistent
+ private String title;
+ @Persistent
+ private String link;
+
+ Event() {
+ }
+
+ /**
+ * Initialise the identity of this event and the point at which it was
+ * published.
+ *
+ * @param idPrefix
+ * A prefix for the identity of this event.
+ * @param owner
+ * Who is the owner of this event.
+ */
+ Event(String idPrefix, URI workflowLink, UsernamePrincipal owner,
+ String title, String message) {
+ id = idPrefix + "." + randomUUID().toString();
+ published = new Date();
+ this.owner = owner.getName();
+ this.title = title;
+ this.message = message;
+ this.link = workflowLink.toASCIIString();
+ }
+
+ public final String getId() {
+ return id;
+ }
+
+ public final String getOwner() {
+ return owner;
+ }
+
+ public final DateTime getPublished() {
+ return new DateTime(published);
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getLink() {
+ return link;
+ }
+
+ public Entry getEntry(Abdera abdera, String language) {
+ Entry entry = abdera.getFactory().newEntry();
+ entry.setId(id);
+ entry.setPublished(published);
+ entry.addAuthor(owner).setLanguage(language);
+ entry.setUpdated(published);
+ entry.setTitle(title).setLanguage(language);
+ entry.addLink(link, "related").setTitle("workflow run");
+ entry.setContent(message).setLanguage(language);
+ return entry;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java
new file mode 100644
index 0000000..56f25ff
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification.atom;
+
+import static java.lang.Thread.interrupted;
+import static java.lang.Thread.sleep;
+import static java.util.Arrays.asList;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import javax.annotation.Nonnull;
+import javax.annotation.PreDestroy;
+import javax.jdo.annotations.PersistenceAware;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.joda.time.DateTime;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.interfaces.MessageDispatcher;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+import org.taverna.server.master.utils.JDOSupport;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * The database interface that supports the event feed.
+ *
+ * @author Donal Fellows
+ */
+@PersistenceAware
+public class EventDAO extends JDOSupport<Event> implements MessageDispatcher {
+ public EventDAO() {
+ super(Event.class);
+ }
+
+ @Override
+ public String getName() {
+ return "atom";
+ }
+
+ private Log log = LogFactory.getLog("Taverna.Server.Atom");
+ private UriBuilderFactory ubf;
+ private int expiryAgeDays;
+
+ @Required
+ public void setExpiryAgeDays(int expiryAgeDays) {
+ this.expiryAgeDays = expiryAgeDays;
+ }
+
+ @Required
+ public void setUriBuilderFactory(UriBuilderFactory ubf) {
+ this.ubf = ubf;
+ }
+
+ /**
+ * Get the given user's list of events.
+ *
+ * @param user
+ * The identity of the user to get the events for.
+ * @return A copy of the list of events currently known about.
+ */
+ @Nonnull
+ @WithinSingleTransaction
+ public List<Event> getEvents(@Nonnull UsernamePrincipal user) {
+ @SuppressWarnings("unchecked")
+ List<String> ids = (List<String>) namedQuery("eventsForUser").execute(
+ user.getName());
+ if (log.isDebugEnabled())
+ log.debug("found " + ids.size() + " events for user " + user);
+
+ List<Event> result = new ArrayList<>();
+ for (String id : ids) {
+ Event event = getById(id);
+ result.add(detach(event));
+ }
+ return result;
+ }
+
+ /**
+ * Get a particular event.
+ *
+ * @param user
+ * The identity of the user to get the event for.
+ * @param id
+ * The handle of the event to look up.
+ * @return A copy of the event.
+ */
+ @Nonnull
+ @WithinSingleTransaction
+ public Event getEvent(@Nonnull UsernamePrincipal user, @Nonnull String id) {
+ @SuppressWarnings("unchecked")
+ List<String> ids = (List<String>) namedQuery("eventForUserAndId")
+ .execute(user.getName(), id);
+ if (log.isDebugEnabled())
+ log.debug("found " + ids.size() + " events for user " + user
+ + " with id = " + id);
+
+ if (ids.size() != 1)
+ throw new IllegalArgumentException("no such id");
+ return detach(getById(ids.get(0)));
+ }
+
+ /**
+ * Delete a particular event.
+ *
+ * @param id
+ * The identifier of the event to delete.
+ */
+ @WithinSingleTransaction
+ public void deleteEventById(@Nonnull String id) {
+ delete(getById(id));
+ }
+
+ /**
+ * Delete all events that have expired.
+ */
+ @WithinSingleTransaction
+ public void deleteExpiredEvents() {
+ Date death = new DateTime().plusDays(-expiryAgeDays).toDate();
+ death = new Timestamp(death.getTime()); // UGLY SQL HACK
+
+ @SuppressWarnings("unchecked")
+ List<String> ids = (List<String>) namedQuery("eventsFromBefore")
+ .execute(death);
+ if (log.isDebugEnabled() && !ids.isEmpty())
+ log.debug("found " + ids.size()
+ + " events to be squelched (older than " + death + ")");
+
+ for (String id : ids)
+ delete(getById(id));
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ private BlockingQueue<Event> insertQueue = new ArrayBlockingQueue<>(16);
+
+ @Override
+ public void dispatch(TavernaRun originator, String messageSubject,
+ String messageContent, String targetParameter) throws Exception {
+ insertQueue.put(new Event("finish", ubf.getRunUriBuilder(originator)
+ .build(), originator.getSecurityContext().getOwner(),
+ messageSubject, messageContent));
+ }
+
+ public void started(TavernaRun originator, String messageSubject,
+ String messageContent) throws InterruptedException {
+ insertQueue.put(new Event("start", ubf.getRunUriBuilder(originator)
+ .build(), originator.getSecurityContext().getOwner(),
+ messageSubject, messageContent));
+ }
+
+ private Thread eventDaemon;
+ private boolean shuttingDown = false;
+
+ @Required
+ public void setSelf(final EventDAO dao) {
+ eventDaemon = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ while (!shuttingDown && !interrupted()) {
+ transferEvents(dao, new ArrayList<Event>(
+ asList(insertQueue.take())));
+ sleep(5000);
+ }
+ } catch (InterruptedException e) {
+ } finally {
+ transferEvents(dao, new ArrayList<Event>());
+ }
+ }
+ }, "ATOM event daemon");
+ eventDaemon.setContextClassLoader(null);
+ eventDaemon.setDaemon(true);
+ eventDaemon.start();
+ }
+
+ private void transferEvents(EventDAO dao, List<Event> e) {
+ insertQueue.drainTo(e);
+ dao.storeEvents(e);
+ }
+
+ @PreDestroy
+ void stopDaemon() {
+ shuttingDown = true;
+ if (eventDaemon != null)
+ eventDaemon.interrupt();
+ }
+
+ @WithinSingleTransaction
+ protected void storeEvents(List<Event> events) {
+ for (Event e : events)
+ persist(e);
+ log.info("stored " + events.size() + " notification events");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java
new file mode 100644
index 0000000..9cc592d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains the Atom feed implementation within Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = FEED, 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) })
+package org.taverna.server.master.notification.atom;
+
+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.XLINK;
+
+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/notification/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java
new file mode 100644
index 0000000..979066a
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * The notification fabric and implementations of notification dispatchers
+ * that support subscription.
+ */
+package org.taverna.server.master.notification;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/package-info.java
new file mode 100644
index 0000000..17bfd03
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/package-info.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * The core of the implementation of Taverna Server, including the
+ * implementations of the SOAP and REST interfaces.
+ */
+package org.taverna.server.master;
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java
new file mode 100644
index 0000000..b0819a5
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_ATOM_XML;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+
+/**
+ * Miscellaneous content type constants.
+ *
+ * @author Donal Fellows
+ */
+interface ContentTypes {
+ static final String URI_LIST = "text/uri-list";
+ static final String ZIP = "application/zip";
+ static final String TEXT = TEXT_PLAIN;
+ static final String XML = APPLICATION_XML;
+ static final String JSON = APPLICATION_JSON;
+ static final String BYTES = APPLICATION_OCTET_STREAM;
+ static final String ATOM = APPLICATION_ATOM_XML;
+ static final String ROBUNDLE = "application/vnd.wf4ever.robundle+zip";
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java
new file mode 100644
index 0000000..e01d1c4
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.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.rest;
+
+import static org.taverna.server.master.common.Uri.secure;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.common.DirEntryReference;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+
+/**
+ * The result of a RESTful operation to list the contents of a directory. Done
+ * with JAXB.
+ *
+ * @author Donal Fellows
+ */
+@XmlRootElement
+@XmlType(name = "DirectoryContents")
+@XmlSeeAlso(MakeOrUpdateDirEntry.class)
+public class DirectoryContents {
+ /**
+ * The contents of the directory.
+ */
+ @XmlElementRef
+ public List<DirEntryReference> contents;
+
+ /**
+ * Make an empty directory description. Required for JAXB.
+ */
+ public DirectoryContents() {
+ contents = new ArrayList<>();
+ }
+
+ /**
+ * Make a directory description.
+ *
+ * @param ui
+ * The factory for URIs.
+ * @param collection
+ * The real directory contents that we are to describe.
+ */
+ public DirectoryContents(UriInfo ui, Collection<DirectoryEntry> collection) {
+ contents = new ArrayList<>();
+ UriBuilder ub = secure(ui).path("{filename}");
+ for (DirectoryEntry e : collection)
+ contents.add(DirEntryReference.newInstance(ub, e));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java
new file mode 100644
index 0000000..74269c1
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static javax.ws.rs.core.Response.ok;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.File;
+
+/**
+ * Representation of a segment of a file to be read by JAX-RS.
+ *
+ * @author Donal Fellows
+ */
+public class FileSegment {
+ /** The file to read a segment of. */
+ public final File file;
+ /** The offset of the first byte of the segment to read. */
+ public Integer from;
+ /** The offset of the first byte after the segment to read. */
+ public Integer to;
+
+ /**
+ * Parse the HTTP Range header and determine what exact range of the file to
+ * read.
+ *
+ * @param f
+ * The file this refers to
+ * @param range
+ * The content of the Range header.
+ * @throws FilesystemAccessException
+ * If we can't determine the length of the file (shouldn't
+ * happen).
+ */
+ public FileSegment(File f, String range) throws FilesystemAccessException {
+ file = f;
+ Matcher m = Pattern.compile("^\\s*bytes=(\\d*)-(\\d*)\\s*$").matcher(
+ range);
+ if (m.matches()) {
+ if (!m.group(1).isEmpty())
+ from = Integer.valueOf(m.group(1));
+ if (!m.group(2).isEmpty())
+ to = Integer.valueOf(m.group(2)) + 1;
+ int size = (int) f.getSize();
+ if (from == null) {
+ from = size - to;
+ to = size;
+ } else if (to == null)
+ to = size;
+ else if (to > size)
+ to = size;
+ }
+ }
+
+ /**
+ * Convert to a response, as per RFC 2616.
+ *
+ * @param type
+ * The expected type of the data.
+ * @return A JAX-RS response.
+ */
+ public Response toResponse(MediaType type) {
+ if (from == null && to == null)
+ return ok(file).type(type).build();
+ if (from >= to)
+ return ok("Requested range not satisfiable").status(416).build();
+ return ok(this).status(206).type(type).build();
+ }
+}
\ 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/InteractionFeedREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java
new file mode 100644
index 0000000..b9b4718
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static org.taverna.server.master.rest.ContentTypes.ATOM;
+
+import java.net.MalformedURLException;
+
+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.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+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.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+
+/**
+ * A very stripped down ATOM feed for the interaction service.
+ *
+ * @author Donal Fellows
+ */
+public interface InteractionFeedREST {
+ /**
+ * Get the feed document for this ATOM feed.
+ *
+ * @return The feed.
+ * @throws FilesystemAccessException
+ * If we can't read from the feed directory.
+ * @throws NoDirectoryEntryException
+ * If something changes things under our feet.
+ */
+ @GET
+ @Path("/")
+ @Produces(ATOM)
+ @Description("Get the feed document for this ATOM feed.")
+ Feed getFeed() throws FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Adds an entry to this ATOM feed.
+ *
+ * @param entry
+ * The entry to create.
+ * @return A redirect to the created entry.
+ * @throws MalformedURLException
+ * If we have problems generating the URI of the entry.
+ * @throws FilesystemAccessException
+ * If we can't create the feed entry file.
+ * @throws NoDirectoryEntryException
+ * If things get changed under our feet.
+ * @throws NoUpdateException
+ * If we don't have permission to change things relating to this
+ * run.
+ */
+ @POST
+ @Path("/")
+ @Consumes(ATOM)
+ @Produces(ATOM)
+ @Description("Adds an entry to this ATOM feed.")
+ Response addEntry(Entry entry) throws MalformedURLException,
+ FilesystemAccessException, NoDirectoryEntryException,
+ NoUpdateException;
+
+ /** Handles the OPTIONS request. */
+ @OPTIONS
+ @Path("/")
+ @Description("Describes what HTTP operations are supported on the feed.")
+ Response feedOptions();
+
+ /**
+ * Gets the content of an entry in this ATOM feed.
+ *
+ * @param id
+ * The ID of the entry to fetch.
+ * @return The entry contents.
+ * @throws FilesystemAccessException
+ * If we have problems reading the entry.
+ * @throws NoDirectoryEntryException
+ * If we can't find the entry to read.
+ */
+ @GET
+ @Path("{id}")
+ @Produces(ATOM)
+ @Description("Get the entry with a particular ID within this ATOM feed.")
+ Entry getEntry(@PathParam("id") String id)
+ throws FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Delete an entry from this ATOM feed.
+ *
+ * @param id
+ * The ID of the entry to delete.
+ * @return A simple message. Not very important!
+ * @throws FilesystemAccessException
+ * If we have problems deleting the entry.
+ * @throws NoDirectoryEntryException
+ * If we can't find the entry to delete.
+ * @throws NoUpdateException
+ * If we don't have permission to alter things relating to this
+ * run.
+ */
+ @DELETE
+ @Path("{id}")
+ @Produces("text/plain")
+ @Description("Deletes an entry from this ATOM feed.")
+ String deleteEntry(@PathParam("id") String id)
+ throws FilesystemAccessException, NoDirectoryEntryException,
+ NoUpdateException;
+
+ /** Handles the OPTIONS request. */
+ @OPTIONS
+ @Path("{id}")
+ @Description("Describes what HTTP operations are supported on an entry.")
+ Response entryOptions(@PathParam("{id}") String id);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java
new file mode 100644
index 0000000..7a072be
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * Description of what sort of event listener to create and attach to a workflow
+ * run. Bound via JAXB.
+ *
+ * @author Donal Fellows
+ */
+@XmlRootElement(name = "listenerDefinition")
+@XmlType(name="ListenerDefinition")
+public class ListenerDefinition {
+ /**
+ * The type of event listener to create.
+ */
+ @XmlAttribute
+ public String type;
+ /**
+ * How the event listener should be configured.
+ */
+ @XmlValue
+ public String configuration;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java
new file mode 100644
index 0000000..0138f88
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * The input to the REST interface for making directories and files, and
+ * uploading file contents. Done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+@XmlRootElement(name = "filesystemOperation")
+@XmlType(name = "FilesystemCreationOperation")
+@XmlSeeAlso( { MakeOrUpdateDirEntry.MakeDirectory.class,
+ MakeOrUpdateDirEntry.SetFileContents.class })
+public abstract class MakeOrUpdateDirEntry {
+ /**
+ * The name of the file or directory that the operation applies to.
+ */
+ @XmlAttribute
+ public String name;
+ /**
+ * The contents of the file to upload.
+ */
+ @XmlValue
+ public byte[] contents;
+
+ /**
+ * Create a directory, described with JAXB. Should leave the
+ * {@link MakeOrUpdateDirEntry#contents contents} field empty.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "mkdir")
+ @XmlType(name = "MakeDirectory")
+ public static class MakeDirectory extends MakeOrUpdateDirEntry {
+ }
+
+ /**
+ * Create a file or set its contents, described with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "upload")
+ @XmlType(name = "UploadFile")
+ public static class SetFileContents extends MakeOrUpdateDirEntry {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java
new file mode 100644
index 0000000..ea2f776
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest;
+
+import static java.util.Collections.unmodifiableList;
+import static javax.ws.rs.core.MediaType.WILDCARD;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.rest.ContentTypes.BYTES;
+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.ContentTypes.ZIP;
+
+import java.io.InputStream;
+import java.net.URI;
+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.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.HttpHeaders;
+import javax.ws.rs.core.PathSegment;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.Variant;
+
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.File;
+
+/**
+ * Representation of how a workflow run's working directory tree looks.
+ *
+ * @author Donal Fellows
+ */
+@RolesAllowed(USER)
+@Produces({ XML, JSON })
+@Consumes({ XML, JSON })
+@Description("Representation of how a workflow run's working directory tree looks.")
+public interface TavernaServerDirectoryREST {
+ /**
+ * Get the working directory of the workflow run.
+ *
+ * @param ui
+ * About how this method was called.
+ * @return A description of the working directory.
+ * @throws FilesystemAccessException
+ */
+ @GET
+ @Path("/")
+ @Description("Describes the working directory of the workflow run.")
+ @Nonnull
+ DirectoryContents getDescription(@Nonnull @Context UriInfo ui)
+ throws FilesystemAccessException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("{path:.*}")
+ @Description("Produces the description of the files/directories' baclava operations.")
+ Response options(@PathParam("path") List<PathSegment> path);
+
+ /**
+ * Gets a description of the named entity in or beneath the working
+ * directory of the workflow run, which may be either a {@link Directory} or
+ * a {@link File}.
+ *
+ * @param path
+ * The path to the thing to describe.
+ * @param ui
+ * About how this method was called.
+ * @param headers
+ * About what the caller was looking for.
+ * @return An HTTP response containing a description of the named thing.
+ * @throws NoDirectoryEntryException
+ * If the name of the file or directory can't be looked up.
+ * @throws FilesystemAccessException
+ * If something went wrong during the filesystem operation.
+ * @throws NegotiationFailedException
+ * If the content type being downloaded isn't one that this
+ * method can support.
+ */
+ @GET
+ @Path("{path:.+}")
+ @Produces({ XML, JSON, BYTES, ZIP, WILDCARD })
+ @Description("Gives a description of the named entity in or beneath the "
+ + "working directory of the workflow run (either a Directory or File).")
+ @Nonnull
+ Response getDirectoryOrFileContents(
+ @Nonnull @PathParam("path") List<PathSegment> path,
+ @Nonnull @Context UriInfo ui, @Nonnull @Context HttpHeaders headers)
+ throws NoDirectoryEntryException, FilesystemAccessException,
+ NegotiationFailedException;
+
+ /**
+ * Creates a directory in the filesystem beneath the working directory of
+ * the workflow run, or creates or updates a file's contents, where that
+ * file is in or below the working directory of a workflow run.
+ *
+ * @param parent
+ * The directory to create the directory in.
+ * @param operation
+ * What to call the directory to create.
+ * @param ui
+ * About how this method was called.
+ * @return An HTTP response indicating where the directory was actually made
+ * or what file was created/updated.
+ * @throws NoDirectoryEntryException
+ * If the name of the containing directory can't be looked up.
+ * @throws NoUpdateException
+ * If the user is not permitted to update the run.
+ * @throws FilesystemAccessException
+ * If something went wrong during the filesystem operation.
+ */
+ @POST
+ @Path("{path:.*}")
+ @Description("Creates a directory in the filesystem beneath the working "
+ + "directory of the workflow run, or creates or updates a file's "
+ + "contents, where that file is in or below the working directory "
+ + "of a workflow run.")
+ @Nonnull
+ Response makeDirectoryOrUpdateFile(
+ @Nonnull @PathParam("path") List<PathSegment> parent,
+ @Nonnull MakeOrUpdateDirEntry operation,
+ @Nonnull @Context UriInfo ui) throws NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Creates or updates a file in a particular location beneath the working
+ * directory of the workflow run.
+ *
+ * @param file
+ * The path to the file to create or update.
+ * @param referenceList
+ * Location to get the file's contents from. Must be
+ * <i>publicly</i> readable.
+ * @param ui
+ * About how this method was called.
+ * @return An HTTP response indicating what file was created/updated.
+ * @throws NoDirectoryEntryException
+ * If the name of the containing directory can't be looked up.
+ * @throws NoUpdateException
+ * If the user is not permitted to update the run.
+ * @throws FilesystemAccessException
+ * If something went wrong during the filesystem operation.
+ */
+ @POST
+ @Path("{path:(.*)}")
+ @Consumes(URI_LIST)
+ @Description("Creates or updates a file in a particular location beneath the "
+ + "working directory of the workflow run with the contents of a "
+ + "publicly readable URL.")
+ @Nonnull
+ Response setFileContentsFromURL(@PathParam("path") List<PathSegment> file,
+ List<URI> referenceList, @Context UriInfo ui)
+ throws NoDirectoryEntryException, NoUpdateException,
+ FilesystemAccessException;
+
+ /**
+ * Creates or updates a file in a particular location beneath the working
+ * directory of the workflow run.
+ *
+ * @param file
+ * The path to the file to create or update.
+ * @param contents
+ * Stream of bytes to set the file's contents to.
+ * @param ui
+ * About how this method was called.
+ * @return An HTTP response indicating what file was created/updated.
+ * @throws NoDirectoryEntryException
+ * If the name of the containing directory can't be looked up.
+ * @throws NoUpdateException
+ * If the user is not permitted to update the run.
+ * @throws FilesystemAccessException
+ * If something went wrong during the filesystem operation.
+ */
+ @PUT
+ @Path("{path:(.*)}")
+ @Consumes({ BYTES, WILDCARD })
+ @Description("Creates or updates a file in a particular location beneath the "
+ + "working directory of the workflow run.")
+ @Nonnull
+ Response setFileContents(@PathParam("path") List<PathSegment> file,
+ InputStream contents, @Context UriInfo ui)
+ throws NoDirectoryEntryException, NoUpdateException,
+ FilesystemAccessException;
+
+ /**
+ * Deletes a file or directory that is in or below the working directory of
+ * a workflow run.
+ *
+ * @param path
+ * The path to the file or directory.
+ * @return An HTTP response to the method.
+ * @throws NoUpdateException
+ * If the user is not permitted to update the run.
+ * @throws FilesystemAccessException
+ * If something went wrong during the filesystem operation.
+ * @throws NoDirectoryEntryException
+ * If the name of the file or directory can't be looked up.
+ */
+ @DELETE
+ @Path("{path:.*}")
+ @Description("Deletes a file or directory that is in or below the working "
+ + "directory of a workflow run.")
+ @Nonnull
+ Response destroyDirectoryEntry(@PathParam("path") List<PathSegment> path)
+ throws NoUpdateException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Exception thrown to indicate a failure by the client to provide an
+ * acceptable content type.
+ *
+ * @author Donal Fellows
+ */
+ @SuppressWarnings("serial")
+ public static class NegotiationFailedException extends Exception {
+ public List<Variant> accepted;
+
+ public NegotiationFailedException(String msg, List<Variant> accepted) {
+ super(msg);
+ this.accepted = unmodifiableList(accepted);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java
new file mode 100644
index 0000000..faed19d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java
@@ -0,0 +1,355 @@
+/*
+ * 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.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.TavernaServerInputREST.PathNames.BACLAVA;
+import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.EXPECTED;
+import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.ONE_INPUT;
+
+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.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.PathSegment;
+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.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+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.BadInputPortNameException;
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Input;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.port_description.InputDescription;
+
+/**
+ * This represents how a Taverna Server workflow run's inputs looks to a RESTful
+ * API.
+ *
+ * @author Donal Fellows.
+ */
+@RolesAllowed(USER)
+@Description("This represents how a Taverna Server workflow run's inputs "
+ + "looks to a RESTful API.")
+public interface TavernaServerInputREST {
+ /**
+ * @return A description of the various URIs to inputs associated with a
+ * workflow run.
+ */
+ @GET
+ @Path("/")
+ @Produces({ XML, JSON })
+ @Description("Describe the sub-URIs of this resource.")
+ @Nonnull
+ InputsDescriptor get();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path("/")
+ @Description("Produces the description of one run's inputs' operations.")
+ Response options();
+
+ /**
+ * @return A description of the various URIs to inputs associated with a
+ * workflow run.
+ */
+ @GET
+ @Path(EXPECTED)
+ @Produces({ XML, JSON })
+ @Description("Describe the expected inputs of this workflow run.")
+ @Nonnull
+ InputDescription getExpected();
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(EXPECTED)
+ @Description("Produces the description of the expected inputs' operations.")
+ Response expectedOptions();
+
+ /**
+ * @return The Baclava file that will supply all the inputs to the workflow
+ * run, or empty to indicate that no such file is specified.
+ */
+ @GET
+ @Path(BACLAVA)
+ @Produces(TEXT)
+ @Description("Gives the Baclava file describing the inputs, or empty if "
+ + "individual files are used.")
+ @Nonnull
+ String getBaclavaFile();
+
+ /**
+ * Set the Baclava file that will supply all the inputs to the workflow run.
+ *
+ * @param filename
+ * The filename to set.
+ * @return The name of the Baclava file that was actually set.
+ * @throws NoUpdateException
+ * If the user can't update the run.
+ * @throws BadStateChangeException
+ * If the run is not Initialized.
+ * @throws FilesystemAccessException
+ * If the filename starts with a <tt>/</tt> or if it contains a
+ * <tt>..</tt> segment.
+ */
+ @PUT
+ @Path(BACLAVA)
+ @Consumes(TEXT)
+ @Produces(TEXT)
+ @Description("Sets the Baclava file describing the inputs.")
+ @Nonnull
+ String setBaclavaFile(@Nonnull String filename) throws NoUpdateException,
+ BadStateChangeException, FilesystemAccessException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(BACLAVA)
+ @Description("Produces the description of the inputs' baclava operations.")
+ Response baclavaOptions();
+
+ /**
+ * Get what input is set for the specific input.
+ *
+ * @param name
+ * The input to set.
+ * @param uriInfo
+ * About the URI used to access this resource.
+ * @return A description of the input.
+ * @throws BadInputPortNameException
+ * If no input with that name exists.
+ */
+ @GET
+ @Path(ONE_INPUT)
+ @Produces({ XML, JSON })
+ @Description("Gives a description of what is used to supply a particular "
+ + "input.")
+ @Nonnull
+ InDesc getInput(@Nonnull @PathParam("name") String name,
+ @Context UriInfo uriInfo) throws BadInputPortNameException;
+
+ /**
+ * Set what an input uses to provide data into the workflow run.
+ *
+ * @param name
+ * The name of the input.
+ * @param inputDescriptor
+ * A description of the input
+ * @param uriInfo
+ * About the URI used to access this resource.
+ * @return A description of the input.
+ * @throws NoUpdateException
+ * If the user can't update the run.
+ * @throws BadStateChangeException
+ * If the run is not Initialized.
+ * @throws FilesystemAccessException
+ * If a filename is being set and the filename starts with a
+ * <tt>/</tt> or if it contains a <tt>..</tt> segment.
+ * @throws BadInputPortNameException
+ * If no input with that name exists.
+ * @throws BadPropertyValueException
+ * If some bad misconfiguration has happened.
+ */
+ @PUT
+ @Path(ONE_INPUT)
+ @Consumes({ XML, JSON })
+ @Produces({ XML, JSON })
+ @Description("Sets the source for a particular input port.")
+ @Nonnull
+ InDesc setInput(@Nonnull @PathParam("name") String name,
+ @Nonnull InDesc inputDescriptor, @Context UriInfo uriInfo) throws NoUpdateException,
+ BadStateChangeException, FilesystemAccessException,
+ BadPropertyValueException, BadInputPortNameException;
+
+ /** Get an outline of the operations supported. */
+ @OPTIONS
+ @Path(ONE_INPUT)
+ @Description("Produces the description of the one input's operations.")
+ Response inputOptions(@PathParam("name") String name);
+
+ interface PathNames {
+ final String EXPECTED = "expected";
+ final String BACLAVA = "baclava";
+ final String ONE_INPUT = "input/{name}";
+ }
+
+ /**
+ * A description of the structure of inputs to a Taverna workflow run, done
+ * with JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "runInputs")
+ @XmlType(name = "TavernaRunInputs")
+ public static class InputsDescriptor extends VersionedElement {
+ /**
+ * Where to find a description of the expected inputs to this workflow
+ * run.
+ */
+ public Uri expected;
+ /**
+ * Where to find the overall Baclava document filename (if set).
+ */
+ public Uri baclava;
+ /**
+ * Where to find the details of inputs to particular ports (if set).
+ */
+ public List<Uri> input;
+
+ /**
+ * Make a blank description of the inputs.
+ */
+ public InputsDescriptor() {
+ }
+
+ /**
+ * Make the description of the inputs.
+ *
+ * @param ui
+ * Information about the URIs to generate.
+ * @param run
+ * The run whose inputs are to be described.
+ */
+ public InputsDescriptor(UriInfo ui, TavernaRun run) {
+ super(true);
+ expected = new Uri(ui, EXPECTED);
+ baclava = new Uri(ui, BACLAVA);
+ input = new ArrayList<>();
+ for (Input i : run.getInputs())
+ input.add(new Uri(ui, ONE_INPUT, i.getName()));
+ }
+ }
+
+ /**
+ * The Details of a particular input port's value assignment, done with
+ * JAXB.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "runInput")
+ @XmlType(name = "InputDescription")
+ public static class InDesc extends VersionedElement {
+ /** Make a blank description of an input port. */
+ public InDesc() {
+ }
+
+ /**
+ * Make a description of the given input port.
+ *
+ * @param inputPort
+ */
+ public InDesc(Input inputPort, UriInfo ui) {
+ super(true);
+ name = inputPort.getName();
+ if (inputPort.getFile() != null) {
+ assignment = new InDesc.File();
+ assignment.contents = inputPort.getFile();
+ } else {
+ assignment = new InDesc.Value();
+ assignment.contents = inputPort.getValue();
+ }
+ // .../runs/{id}/input/input/{name} ->
+ // .../runs/{id}/input/expected#{name}
+ UriBuilder ub = ui.getBaseUriBuilder();
+ List<PathSegment> segments = ui.getPathSegments();
+ for (PathSegment s : segments.subList(0, segments.size() - 2))
+ ub.segment(s.getPath());
+ ub.fragment(name);
+ descriptorRef = new Uri(ub).ref;
+ }
+
+ /** The name of the port. */
+ @XmlAttribute(required = false)
+ public String name;
+ /** Where the port is described. Ignored in user input. */
+ @XmlAttribute(required = false)
+ @XmlSchemaType(name = "anyURI")
+ public URI descriptorRef;
+ /** The character to use to split the input into a list. */
+ @XmlAttribute(name = "listDelimiter", required = false)
+ public String delimiter;
+
+ /**
+ * Either a filename or a literal string, used to provide input to a
+ * workflow port.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "InputContents")
+ public static abstract class AbstractContents {
+ /**
+ * The contents of the description of the input port. Meaning not
+ * defined.
+ */
+ @XmlValue
+ public String contents;
+ };
+
+ /**
+ * The name of a file that provides input to the port. The
+ * {@link AbstractContents#contents contents} field is a filename.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "")
+ public static class File extends AbstractContents {
+ }
+
+ /**
+ * The literal input to the port. The {@link AbstractContents#contents
+ * contents} field is a literal input value.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "")
+ public static class Value extends AbstractContents {
+ }
+
+ /**
+ * A reference to a file elsewhere <i>on this server</i>. The
+ * {@link AbstractContents#contents contents} field is a URL to the file
+ * (using the RESTful notation).
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "")
+ public static class Reference extends AbstractContents {
+ }
+
+ /**
+ * The assignment of input values to the port.
+ */
+ @XmlElements({ @XmlElement(name = "file", type = File.class),
+ @XmlElement(name = "reference", type = Reference.class),
+ @XmlElement(name = "value", type = Value.class) })
+ public AbstractContents assignment;
+ }
+}
[29/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css b/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css
deleted file mode 100644
index 8b8afac..0000000
--- a/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.css
+++ /dev/null
@@ -1,563 +0,0 @@
-/*!
- * jQuery UI CSS Framework 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- */
-
-/* Layout helpers
-----------------------------------*/
-.ui-helper-hidden { display: none; }
-.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
-.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
-.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
-.ui-helper-clearfix:after { clear: both; }
-.ui-helper-clearfix { zoom: 1; }
-.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
-
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-disabled { cursor: default !important; }
-
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Overlays */
-.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
-
-
-/*!
- * jQuery UI CSS Framework 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- *
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=segoe%20ui,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=3px&bgColorHeader=f9f9f9&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=100&borderColorHeader=cccccc&fcHeader=e69700&iconColorHeader=5fa5e3&bgColorContent=eeeeee&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=0a82eb&bgColorDefault=1484e6&bgTextureDefault=08_diagonals_thick.png&bgImgOpacityDefault=22&borderColorDefault=ffffff&fcDefault=ffffff&iconColorDefault=fcdd4a&bgColorHover=2293f7&bgTextureHover=08_diagonals_thick.png&bgImgOpacityHover=26&borderColorHover=2293f7&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=e69700&bgTextureActive=08_diagonals_thick.png&bgImgOpacityActive=20&borderColorActive=e69700&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=c5ddfc&bgTextureHighlight=07_diagonals_small.png&bgImgOpacityHighlight=25&borderCol
orHighlight=ffffff&fcHighlight=333333&iconColorHighlight=0b54d5&bgColorError=e69700&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=20&borderColorError=e69700&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=e6b900&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=e69700&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=20&thicknessShadow=0px&offsetTopShadow=6px&offsetLeftShadow=6px&cornerRadiusShadow=3px
- */
-
-
-/* Component containers
-----------------------------------*/
-.ui-widget { font-family: segoe ui, Arial, sans-serif; font-size: 1.1em; }
-.ui-widget .ui-widget { font-size: 1em; }
-.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: segoe ui, Arial, sans-serif; font-size: 1em; }
-.ui-widget-content { border: 1px solid #aaaaaa; background: #eeeeee url(ui-bg_inset-hard_100_eeeeee_1x100.png) 50% bottom repeat-x; color: #222222; }
-.ui-widget-content a { color: #222222; }
-.ui-widget-header { border: 1px solid #cccccc; background: #f9f9f9 url(ui-bg_highlight-soft_100_f9f9f9_1x100.png) 50% 50% repeat-x; color: #e69700; font-weight: bold; }
-.ui-widget-header a { color: #e69700; }
-
-/* Interaction states
-----------------------------------*/
-.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #ffffff; background: #1484e6 url(ui-bg_diagonals-thick_22_1484e6_40x40.png) 50% 50% repeat; font-weight: bold; color: #ffffff; }
-.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; }
-.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #2293f7; background: #2293f7 url(ui-bg_diagonals-thick_26_2293f7_40x40.png) 50% 50% repeat; font-weight: bold; color: #ffffff; }
-.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
-.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #e69700; background: #e69700 url(ui-bg_diagonals-thick_20_e69700_40x40.png) 50% 50% repeat; font-weight: bold; color: #ffffff; }
-.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
-.ui-widget :active { outline: none; }
-
-/* Interaction Cues
-----------------------------------*/
-.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #ffffff; background: #c5ddfc url(ui-bg_diagonals-small_25_c5ddfc_40x40.png) 50% 50% repeat; color: #333333; }
-.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #333333; }
-.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #e69700; background: #e69700 url(ui-bg_diagonals-thick_20_e69700_40x40.png) 50% 50% repeat; color: #ffffff; }
-.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
-.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
-.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
-.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
-.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
-
-/* Icons
-----------------------------------*/
-
-/* states and images */
-.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_0a82eb_256x240.png); }
-.ui-widget-content .ui-icon {background-image: url(ui-icons_0a82eb_256x240.png); }
-.ui-widget-header .ui-icon {background-image: url(ui-icons_5fa5e3_256x240.png); }
-.ui-state-default .ui-icon { background-image: url(ui-icons_fcdd4a_256x240.png); }
-.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
-.ui-state-active .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
-.ui-state-highlight .ui-icon {background-image: url(ui-icons_0b54d5_256x240.png); }
-.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(ui-icons_ffffff_256x240.png); }
-
-/* positioning */
-.ui-icon-carat-1-n { background-position: 0 0; }
-.ui-icon-carat-1-ne { background-position: -16px 0; }
-.ui-icon-carat-1-e { background-position: -32px 0; }
-.ui-icon-carat-1-se { background-position: -48px 0; }
-.ui-icon-carat-1-s { background-position: -64px 0; }
-.ui-icon-carat-1-sw { background-position: -80px 0; }
-.ui-icon-carat-1-w { background-position: -96px 0; }
-.ui-icon-carat-1-nw { background-position: -112px 0; }
-.ui-icon-carat-2-n-s { background-position: -128px 0; }
-.ui-icon-carat-2-e-w { background-position: -144px 0; }
-.ui-icon-triangle-1-n { background-position: 0 -16px; }
-.ui-icon-triangle-1-ne { background-position: -16px -16px; }
-.ui-icon-triangle-1-e { background-position: -32px -16px; }
-.ui-icon-triangle-1-se { background-position: -48px -16px; }
-.ui-icon-triangle-1-s { background-position: -64px -16px; }
-.ui-icon-triangle-1-sw { background-position: -80px -16px; }
-.ui-icon-triangle-1-w { background-position: -96px -16px; }
-.ui-icon-triangle-1-nw { background-position: -112px -16px; }
-.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
-.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
-.ui-icon-arrow-1-n { background-position: 0 -32px; }
-.ui-icon-arrow-1-ne { background-position: -16px -32px; }
-.ui-icon-arrow-1-e { background-position: -32px -32px; }
-.ui-icon-arrow-1-se { background-position: -48px -32px; }
-.ui-icon-arrow-1-s { background-position: -64px -32px; }
-.ui-icon-arrow-1-sw { background-position: -80px -32px; }
-.ui-icon-arrow-1-w { background-position: -96px -32px; }
-.ui-icon-arrow-1-nw { background-position: -112px -32px; }
-.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
-.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
-.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
-.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
-.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
-.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
-.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
-.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
-.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
-.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
-.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
-.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
-.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
-.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
-.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
-.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
-.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
-.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
-.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
-.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
-.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
-.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
-.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
-.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
-.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
-.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
-.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
-.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
-.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
-.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
-.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
-.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
-.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
-.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
-.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
-.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
-.ui-icon-arrow-4 { background-position: 0 -80px; }
-.ui-icon-arrow-4-diag { background-position: -16px -80px; }
-.ui-icon-extlink { background-position: -32px -80px; }
-.ui-icon-newwin { background-position: -48px -80px; }
-.ui-icon-refresh { background-position: -64px -80px; }
-.ui-icon-shuffle { background-position: -80px -80px; }
-.ui-icon-transfer-e-w { background-position: -96px -80px; }
-.ui-icon-transferthick-e-w { background-position: -112px -80px; }
-.ui-icon-folder-collapsed { background-position: 0 -96px; }
-.ui-icon-folder-open { background-position: -16px -96px; }
-.ui-icon-document { background-position: -32px -96px; }
-.ui-icon-document-b { background-position: -48px -96px; }
-.ui-icon-note { background-position: -64px -96px; }
-.ui-icon-mail-closed { background-position: -80px -96px; }
-.ui-icon-mail-open { background-position: -96px -96px; }
-.ui-icon-suitcase { background-position: -112px -96px; }
-.ui-icon-comment { background-position: -128px -96px; }
-.ui-icon-person { background-position: -144px -96px; }
-.ui-icon-print { background-position: -160px -96px; }
-.ui-icon-trash { background-position: -176px -96px; }
-.ui-icon-locked { background-position: -192px -96px; }
-.ui-icon-unlocked { background-position: -208px -96px; }
-.ui-icon-bookmark { background-position: -224px -96px; }
-.ui-icon-tag { background-position: -240px -96px; }
-.ui-icon-home { background-position: 0 -112px; }
-.ui-icon-flag { background-position: -16px -112px; }
-.ui-icon-calendar { background-position: -32px -112px; }
-.ui-icon-cart { background-position: -48px -112px; }
-.ui-icon-pencil { background-position: -64px -112px; }
-.ui-icon-clock { background-position: -80px -112px; }
-.ui-icon-disk { background-position: -96px -112px; }
-.ui-icon-calculator { background-position: -112px -112px; }
-.ui-icon-zoomin { background-position: -128px -112px; }
-.ui-icon-zoomout { background-position: -144px -112px; }
-.ui-icon-search { background-position: -160px -112px; }
-.ui-icon-wrench { background-position: -176px -112px; }
-.ui-icon-gear { background-position: -192px -112px; }
-.ui-icon-heart { background-position: -208px -112px; }
-.ui-icon-star { background-position: -224px -112px; }
-.ui-icon-link { background-position: -240px -112px; }
-.ui-icon-cancel { background-position: 0 -128px; }
-.ui-icon-plus { background-position: -16px -128px; }
-.ui-icon-plusthick { background-position: -32px -128px; }
-.ui-icon-minus { background-position: -48px -128px; }
-.ui-icon-minusthick { background-position: -64px -128px; }
-.ui-icon-close { background-position: -80px -128px; }
-.ui-icon-closethick { background-position: -96px -128px; }
-.ui-icon-key { background-position: -112px -128px; }
-.ui-icon-lightbulb { background-position: -128px -128px; }
-.ui-icon-scissors { background-position: -144px -128px; }
-.ui-icon-clipboard { background-position: -160px -128px; }
-.ui-icon-copy { background-position: -176px -128px; }
-.ui-icon-contact { background-position: -192px -128px; }
-.ui-icon-image { background-position: -208px -128px; }
-.ui-icon-video { background-position: -224px -128px; }
-.ui-icon-script { background-position: -240px -128px; }
-.ui-icon-alert { background-position: 0 -144px; }
-.ui-icon-info { background-position: -16px -144px; }
-.ui-icon-notice { background-position: -32px -144px; }
-.ui-icon-help { background-position: -48px -144px; }
-.ui-icon-check { background-position: -64px -144px; }
-.ui-icon-bullet { background-position: -80px -144px; }
-.ui-icon-radio-off { background-position: -96px -144px; }
-.ui-icon-radio-on { background-position: -112px -144px; }
-.ui-icon-pin-w { background-position: -128px -144px; }
-.ui-icon-pin-s { background-position: -144px -144px; }
-.ui-icon-play { background-position: 0 -160px; }
-.ui-icon-pause { background-position: -16px -160px; }
-.ui-icon-seek-next { background-position: -32px -160px; }
-.ui-icon-seek-prev { background-position: -48px -160px; }
-.ui-icon-seek-end { background-position: -64px -160px; }
-.ui-icon-seek-start { background-position: -80px -160px; }
-/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
-.ui-icon-seek-first { background-position: -80px -160px; }
-.ui-icon-stop { background-position: -96px -160px; }
-.ui-icon-eject { background-position: -112px -160px; }
-.ui-icon-volume-off { background-position: -128px -160px; }
-.ui-icon-volume-on { background-position: -144px -160px; }
-.ui-icon-power { background-position: 0 -176px; }
-.ui-icon-signal-diag { background-position: -16px -176px; }
-.ui-icon-signal { background-position: -32px -176px; }
-.ui-icon-battery-0 { background-position: -48px -176px; }
-.ui-icon-battery-1 { background-position: -64px -176px; }
-.ui-icon-battery-2 { background-position: -80px -176px; }
-.ui-icon-battery-3 { background-position: -96px -176px; }
-.ui-icon-circle-plus { background-position: 0 -192px; }
-.ui-icon-circle-minus { background-position: -16px -192px; }
-.ui-icon-circle-close { background-position: -32px -192px; }
-.ui-icon-circle-triangle-e { background-position: -48px -192px; }
-.ui-icon-circle-triangle-s { background-position: -64px -192px; }
-.ui-icon-circle-triangle-w { background-position: -80px -192px; }
-.ui-icon-circle-triangle-n { background-position: -96px -192px; }
-.ui-icon-circle-arrow-e { background-position: -112px -192px; }
-.ui-icon-circle-arrow-s { background-position: -128px -192px; }
-.ui-icon-circle-arrow-w { background-position: -144px -192px; }
-.ui-icon-circle-arrow-n { background-position: -160px -192px; }
-.ui-icon-circle-zoomin { background-position: -176px -192px; }
-.ui-icon-circle-zoomout { background-position: -192px -192px; }
-.ui-icon-circle-check { background-position: -208px -192px; }
-.ui-icon-circlesmall-plus { background-position: 0 -208px; }
-.ui-icon-circlesmall-minus { background-position: -16px -208px; }
-.ui-icon-circlesmall-close { background-position: -32px -208px; }
-.ui-icon-squaresmall-plus { background-position: -48px -208px; }
-.ui-icon-squaresmall-minus { background-position: -64px -208px; }
-.ui-icon-squaresmall-close { background-position: -80px -208px; }
-.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
-.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
-.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
-.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
-.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
-.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
-
-
-/* Misc visuals
-----------------------------------*/
-
-/* Corner radius */
-.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; -khtml-border-top-left-radius: 3px; border-top-left-radius: 3px; }
-.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; -khtml-border-top-right-radius: 3px; border-top-right-radius: 3px; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 3px; -webkit-border-bottom-left-radius: 3px; -khtml-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 3px; -webkit-border-bottom-right-radius: 3px; -khtml-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; }
-
-/* Overlays */
-.ui-widget-overlay { background: #e6b900 url(ui-bg_flat_0_e6b900_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
-.ui-widget-shadow { margin: 6px 0 0 6px; padding: 0px; background: #e69700 url(ui-bg_flat_0_e69700_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 3px; -khtml-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; }/*!
- * jQuery UI Resizable 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Resizable#theming
- */
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
-.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
-.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
-.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
-.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
-.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
-.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
-.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
-.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
-.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
- * jQuery UI Selectable 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Selectable#theming
- */
-.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
-/*!
- * jQuery UI Accordion 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Accordion#theming
- */
-/* IE/Win - Fix animation bug - #4615 */
-.ui-accordion { width: 100%; }
-.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
-.ui-accordion .ui-accordion-li-fix { display: inline; }
-.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
-.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
-.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
-.ui-accordion .ui-accordion-content-active { display: block; }
-/*!
- * jQuery UI Autocomplete 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Autocomplete#theming
- */
-.ui-autocomplete { position: absolute; cursor: default; }
-
-/* workarounds */
-* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
-
-/*
- * jQuery UI Menu 1.8.23
- *
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Menu#theming
- */
-.ui-menu {
- list-style:none;
- padding: 2px;
- margin: 0;
- display:block;
- float: left;
-}
-.ui-menu .ui-menu {
- margin-top: -3px;
-}
-.ui-menu .ui-menu-item {
- margin:0;
- padding: 0;
- zoom: 1;
- float: left;
- clear: left;
- width: 100%;
-}
-.ui-menu .ui-menu-item a {
- text-decoration:none;
- display:block;
- padding:.2em .4em;
- line-height:1.5;
- zoom:1;
-}
-.ui-menu .ui-menu-item a.ui-state-hover,
-.ui-menu .ui-menu-item a.ui-state-active {
- font-weight: normal;
- margin: -1px;
-}
-/*!
- * jQuery UI Button 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Button#theming
- */
-.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
-.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
-button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
-.ui-button-icons-only { width: 3.4em; }
-button.ui-button-icons-only { width: 3.7em; }
-
-/*button text element */
-.ui-button .ui-button-text { display: block; line-height: 1.4; }
-.ui-button-text-only .ui-button-text { padding: .4em 1em; }
-.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
-.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
-.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
-.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
-/* no icon support for input elements, provide padding by default */
-input.ui-button { padding: .4em 1em; }
-
-/*button icon element(s) */
-.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
-.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
-.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
-.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-
-/*button sets*/
-.ui-buttonset { margin-right: 7px; }
-.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
-
-/* workarounds */
-button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
-/*!
- * jQuery UI Dialog 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Dialog#theming
- */
-.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
-.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
-.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
-.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
-.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
-.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
-.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
-.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
-.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
-.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
-.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
-.ui-draggable .ui-dialog-titlebar { cursor: move; }
-/*!
- * jQuery UI Slider 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Slider#theming
- */
-.ui-slider { position: relative; text-align: left; }
-.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
-.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
-
-.ui-slider-horizontal { height: .8em; }
-.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
-.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
-.ui-slider-horizontal .ui-slider-range-min { left: 0; }
-.ui-slider-horizontal .ui-slider-range-max { right: 0; }
-
-.ui-slider-vertical { width: .8em; height: 100px; }
-.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
-.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
-.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
-.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
- * jQuery UI Tabs 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Tabs#theming
- */
-.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
-.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
-.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
-.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
-.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
-.ui-tabs .ui-tabs-hide { display: none !important; }
-/*!
- * jQuery UI Datepicker 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Datepicker#theming
- */
-.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
-.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
-.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
-.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
-.ui-datepicker .ui-datepicker-prev { left:2px; }
-.ui-datepicker .ui-datepicker-next { right:2px; }
-.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
-.ui-datepicker .ui-datepicker-next-hover { right:1px; }
-.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
-.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
-.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
-.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
-.ui-datepicker select.ui-datepicker-month,
-.ui-datepicker select.ui-datepicker-year { width: 49%;}
-.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
-.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
-.ui-datepicker td { border: 0; padding: 1px; }
-.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
-.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
-.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
-.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
-
-/* with multiple calendars */
-.ui-datepicker.ui-datepicker-multi { width:auto; }
-.ui-datepicker-multi .ui-datepicker-group { float:left; }
-.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
-.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
-.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
-.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
-.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
-.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
-.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
-
-/* RTL support */
-.ui-datepicker-rtl { direction: rtl; }
-.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
-.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
-.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group { float:right; }
-.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
-
-/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
-.ui-datepicker-cover {
- position: absolute; /*must have*/
- z-index: -1; /*must have*/
- filter: mask(); /*must have*/
- top: -4px; /*must have*/
- left: -4px; /*must have*/
- width: 200px; /*must have*/
- height: 200px; /*must have*/
-}/*!
- * jQuery UI Progressbar 1.8.23
- *
- * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Progressbar#theming
- */
-.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
-.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
[17/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java
new file mode 100644
index 0000000..69c3622
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE.txt" 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.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * Description of the profiles that can apply to a workflow.
+ *
+ * @author Donal K. Fellows
+ */
+@XmlRootElement(name = "profiles")
+@XmlType(name = "ProfileList")
+public class ProfileList {
+ public List<ProfileList.Info> profile = new ArrayList<ProfileList.Info>();
+
+ /**
+ * Description of a single workflow profile.
+ *
+ * @author Donal Fellows
+ */
+ @XmlRootElement(name = "profile")
+ @XmlType(name = "Profile")
+ public static class Info {
+ @XmlValue
+ public String name;
+ /**
+ * Whether this is the main profile.
+ */
+ @XmlAttribute(name = "isMain")
+ public Boolean main;
+ }
+}
\ 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/Roles.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java
new file mode 100644
index 0000000..8079b1c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.common;
+
+/**
+ * The roles defined in this webapp.
+ *
+ * @author Donal Fellows
+ */
+public interface Roles {
+ /** The role of a normal user. */
+ static final String USER = "ROLE_tavernauser";
+ /**
+ * The role of an administrator. Administrators <i>should</i> have the
+ * normal user role as well.
+ */
+ static final String ADMIN = "ROLE_tavernasuperuser";
+ /**
+ * The role of a workflow accessing itself. Do not give users this role.
+ */
+ static final String SELF = "ROLE_tavernaworkflow";
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java
new file mode 100644
index 0000000..3486bf7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java
@@ -0,0 +1,67 @@
+/*
+ * 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.SERVER;
+import static org.taverna.server.master.common.Namespaces.XLINK;
+import static org.taverna.server.master.common.VersionedElement.VERSION;
+
+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;
+
+/**
+ * A reference to a single workflow run, described using JAXB.
+ *
+ * @author Donal Fellows
+ * @see org.taverna.server.master.interfaces.TavernaRun TavernaRun
+ */
+@XmlRootElement
+@XmlType(name = "TavernaRun")
+@XmlSeeAlso( { Workflow.class, DirEntryReference.class })
+public class RunReference {
+ /**
+ * Where to get information about the run. For REST.
+ */
+ @XmlAttribute(name = "href", namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI link;
+ /** What version of server produced this element? */
+ @XmlAttribute(namespace = SERVER)
+ public String serverVersion;
+ /**
+ * The name of the run. For SOAP.
+ */
+ @XmlValue
+ public String name;
+
+ /**
+ * Make a blank run reference.
+ */
+ public RunReference() {
+ }
+
+ /**
+ * Make a reference to the given workflow run.
+ *
+ * @param name
+ * The name of the run.
+ * @param ub
+ * A factory for URIs, or <tt>null</tt> if none is to be made.
+ */
+ public RunReference(String name, UriBuilder ub) {
+ this.serverVersion = VERSION;
+ this.name = name;
+ if (ub != null)
+ this.link = ub.build(name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java
new file mode 100644
index 0000000..8e360dc
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 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.XmlType;
+
+/**
+ * States of a workflow run. They are {@link #Initialized Initialized},
+ * {@link #Operating Operating}, {@link #Stopped Stopped}, and {@link #Finished
+ * Finished}. Conceptually, there is also a <tt>Destroyed</tt> state, but the
+ * workflow run does not exist (and hence can't have its state queried or set)
+ * in that case.
+ *
+ * @author Donal Fellows
+ */
+@XmlEnum
+@XmlType(name = "Status")
+public enum Status {
+ /**
+ * The workflow run has been created, but is not yet running. The run will
+ * need to be manually moved to {@link #Operating Operating} when ready.
+ */
+ Initialized,
+ /**
+ * The workflow run is going, reading input, generating output, etc. Will
+ * eventually either move automatically to {@link #Finished Finished} or can
+ * be moved manually to {@link #Stopped Stopped} (where supported).
+ */
+ Operating,
+ /**
+ * The workflow run is paused, and will need to be moved back to
+ * {@link #Operating Operating} manually.
+ */
+ Stopped,
+ /**
+ * The workflow run has ceased; data files will continue to exist until the
+ * run is destroyed (which may be manual or automatic).
+ */
+ Finished
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java
new file mode 100644
index 0000000..6d77aa7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java
@@ -0,0 +1,79 @@
+/*
+ * 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.security.cert.Certificate;
+import java.util.Collection;
+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.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * A description of a trusted identity or identities. This description is
+ * characterised by a file visible to the workflow run that contains one or more
+ * certificates.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "TrustDescriptor")
+@XmlRootElement(name = "trustedIdentity")
+@SuppressWarnings("serial")
+public final class Trust 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 file containing the certificate(s). This is resolved with respect to
+ * the workflow run working directory.
+ */
+ @XmlElement
+ public String certificateFile;
+ /**
+ * The type of certificate file. Defaults to <tt>X.509</tt> if unspecified.
+ */
+ @XmlElement
+ public String fileType;
+ /**
+ * The encoded serialized keystore containing the certificate(s).
+ */
+ @XmlElement
+ public byte[] certificateBytes;
+ /**
+ * The names of the server(s) identified by this trust.
+ */
+ @XmlElement
+ public List<String> serverName;
+ /**
+ * The collection of certificates loaded from the specified file. This is
+ * always <tt>null</tt> before validation.
+ */
+ public transient Collection<? extends Certificate> loadedCertificates;
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || !(o instanceof Trust))
+ return false;
+ return id.equals(((Trust) o).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/Uri.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java
new file mode 100644
index 0000000..d6d057c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.common;
+
+import static javax.ws.rs.core.UriBuilder.fromUri;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.common.Namespaces.XLINK;
+
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Map;
+
+import javax.annotation.PreDestroy;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriBuilderException;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.web.PortMapper;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A class that makes it simpler to work with an element with a {@link URI} in
+ * an <tt>href</tt> attribute. Done with JAXB.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "Location")
+public class Uri {
+ static Log log = getLog("Taverna.Server.UriRewriter");
+ private static final String SECURE_SCHEME = "https";
+ /**
+ * This type is characterised by an attribute that is the reference to some
+ * other element.
+ */
+ @XmlAttribute(name = "href", namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI ref;
+
+ /** Make a reference that points nowhere. */
+ public Uri() {
+ }
+
+ /**
+ * Make a reference to the given location.
+ *
+ * @param ref
+ * Where to point to.
+ */
+ public Uri(@Nonnull URI ref) {
+ this.ref = secure(ref);
+ }
+
+ /**
+ * Make a reference from the factory with the given parameters.
+ *
+ * @param ub
+ * The configured factory.
+ * @param strings
+ * The parameters to the factory.
+ */
+ public Uri(@Nonnull UriBuilder ub, String... strings) {
+ ref = secure(ub).build((Object[]) strings);
+ }
+
+ /**
+ * Make a reference from the factory with the given parameters.
+ *
+ * @param ui
+ * The factory factory.
+ * @param path
+ * The path to configure the factory with.
+ * @param strings
+ * The parameters to the factory.
+ */
+ public Uri(@Nonnull UriInfo ui, @Nonnull String path, String... strings) {
+ this(ui, true, path, strings);
+ }
+
+ /**
+ * Make a reference from the factory with the given parameters.
+ *
+ * @param ui
+ * The factory factory.
+ * @param secure
+ * Whether the URI should be required to use HTTPS.
+ * @param path
+ * The path to configure the factory with.
+ * @param strings
+ * The parameters to the factory.
+ */
+ public Uri(@Nonnull UriInfo ui, boolean secure, @Nonnull String path,
+ String... strings) {
+ UriBuilder ub = ui.getAbsolutePathBuilder();
+ if (secure) {
+ ub = secure(ub);
+ }
+ ref = ub.path(path).build((Object[]) strings);
+ }
+
+ public static UriBuilder secure(UriBuilder ub) {
+ return Rewriter.getInstance().getSecuredUriBuilder(ub);
+ }
+
+ public static UriBuilder secure(UriInfo ui) {
+ return secure(ui.getAbsolutePathBuilder());
+ }
+
+ public static URI secure(URI uri) {
+ URI newURI = secure(fromUri(uri)).build();
+ if (log.isDebugEnabled())
+ log.debug("rewrote " + uri + " to " + newURI);
+ return newURI;
+ }
+
+ public static URI secure(URI base, String uri) {
+ URI newURI = secure(fromUri(base.resolve(uri))).build();
+ if (log.isDebugEnabled())
+ log.debug("rewrote " + uri + " to " + newURI);
+ return newURI;
+ }
+
+ /**
+ * A bean that allows configuration of how to rewrite generated URIs to be
+ * secure.
+ *
+ * @author Donal Fellows
+ */
+ public static class Rewriter {
+ private static Rewriter instance;
+ private PortMapper portMapper;
+ private boolean suppress;
+ private String rewriteRE = "://[^/]+/[^/]+";
+ private String rewriteTarget;
+
+ static Rewriter getInstance() {
+ if (instance == null)
+ new Rewriter();
+ return instance;
+ }
+
+ @Autowired
+ public void setPortMapper(PortMapper portMapper) {
+ this.portMapper = portMapper;
+ }
+
+ /**
+ * Whether to suppress rewriting of URIs to be secure.
+ *
+ * @param suppressSecurity
+ * True if no rewriting should be done.
+ */
+ public void setSuppressSecurity(boolean suppressSecurity) {
+ suppress = suppressSecurity;
+ }
+
+ public void setRewriteRegexp(String rewriteRegexp) {
+ this.rewriteRE = rewriteRegexp;
+ }
+
+ /**
+ * What to rewrite the host, port and web-app name to be.
+ *
+ * @param rewriteTarget
+ * What to rewrite to, or "<tt>NONE</tt>" for no rewrite.
+ */
+ public void setRewriteTarget(String rewriteTarget) {
+ if (rewriteTarget.isEmpty())
+ this.rewriteTarget = null;
+ else if (rewriteTarget.equals("NONE"))
+ this.rewriteTarget = null;
+ else if (rewriteTarget.startsWith("${"))
+ this.rewriteTarget = null;
+ else
+ this.rewriteTarget = "://" + rewriteTarget;
+ }
+
+ private Integer lookupHttpsPort(URI uri) {
+ if (portMapper != null)
+ return portMapper.lookupHttpsPort(uri.getPort());
+ return null;
+ }
+
+ public Rewriter() {
+ instance = this;
+ }
+
+ @PreDestroy
+ public void done() {
+ instance = null;
+ Uri.log = null;
+ }
+
+ @Nonnull
+ URI rewrite(@Nonnull String url) {
+ if (rewriteTarget != null)
+ url = url.replaceFirst(rewriteRE, rewriteTarget);
+ return URI.create(url);
+ }
+
+ @Nonnull
+ public UriBuilder getSecuredUriBuilder(@Nonnull UriBuilder uribuilder) {
+ if (suppress)
+ return uribuilder.clone();
+ UriBuilder ub = new RewritingUriBuilder(uribuilder);
+ Integer secPort = null;
+ try {
+ secPort = lookupHttpsPort(ub.build());
+ } catch (Exception e) {
+ /*
+ * Do not log this; we know why it happens and don't actually
+ * care to do anything about it. All it does is fill up the log
+ * with pointless scariness!
+ */
+
+ // log.debug("failed to extract current URI port", e);
+ }
+ if (secPort == null || secPort.intValue() == -1)
+ return ub.scheme(SECURE_SCHEME);
+ return ub.scheme(SECURE_SCHEME).port(secPort);
+ }
+
+ /**
+ * {@link UriBuilder} that applies a rewrite rule to the URIs produced
+ * by the wrapped builder.
+ *
+ * @author Donal Fellows
+ */
+ class RewritingUriBuilder extends UriBuilder {
+ private UriBuilder wrapped;
+
+ RewritingUriBuilder(UriBuilder builder) {
+ wrapped = builder.clone();
+ }
+
+ private URI rewrite(URI uri) {
+ return Rewriter.this.rewrite(uri.toString());
+ }
+
+ @Override
+ public UriBuilder clone() {
+ return new RewritingUriBuilder(wrapped);
+ }
+
+ @Override
+ public URI buildFromMap(Map<String, ?> values)
+ throws IllegalArgumentException, UriBuilderException {
+ return rewrite(wrapped.buildFromMap(values));
+ }
+
+ @Override
+ public URI buildFromEncodedMap(Map<String, ? extends Object> values)
+ throws IllegalArgumentException, UriBuilderException {
+ return rewrite(wrapped.buildFromEncodedMap(values));
+ }
+
+ @Override
+ public URI build(Object... values) throws IllegalArgumentException,
+ UriBuilderException {
+ return rewrite(wrapped.build(values));
+ }
+
+ @Override
+ public URI build(Object[] values, boolean encodeSlashInPath)
+ throws IllegalArgumentException, UriBuilderException {
+ return rewrite(wrapped.build(values, encodeSlashInPath));
+ }
+
+ @Override
+ public URI buildFromEncoded(Object... values)
+ throws IllegalArgumentException, UriBuilderException {
+ return rewrite(wrapped.buildFromEncoded(values));
+ }
+
+ @Override
+ public URI buildFromMap(Map<String, ?> values,
+ boolean encodeSlashInPath) throws IllegalArgumentException,
+ UriBuilderException {
+ return rewrite(wrapped.buildFromEncoded(values,
+ encodeSlashInPath));
+ }
+
+ @Override
+ public UriBuilder uri(URI uri) throws IllegalArgumentException {
+ wrapped.uri(uri);
+ return this;
+ }
+
+ @Override
+ public UriBuilder uri(String uriTemplate)
+ throws IllegalArgumentException {
+ wrapped.uri(uriTemplate);
+ return this;
+ }
+
+ @Override
+ public String toTemplate() {
+ return wrapped.toTemplate();
+ }
+
+ @Override
+ public UriBuilder scheme(String scheme)
+ throws IllegalArgumentException {
+ wrapped.scheme(scheme);
+ return this;
+ }
+
+ @Override
+ public UriBuilder schemeSpecificPart(String ssp)
+ throws IllegalArgumentException {
+ wrapped.schemeSpecificPart(ssp);
+ return this;
+ }
+
+ @Override
+ public UriBuilder userInfo(String ui) {
+ wrapped.userInfo(ui);
+ return this;
+ }
+
+ @Override
+ public UriBuilder host(String host) throws IllegalArgumentException {
+ wrapped.host(host);
+ return this;
+ }
+
+ @Override
+ public UriBuilder port(int port) throws IllegalArgumentException {
+ wrapped.port(port);
+ return this;
+ }
+
+ @Override
+ public UriBuilder replacePath(String path) {
+ wrapped.replacePath(path);
+ return this;
+ }
+
+ @Override
+ public UriBuilder path(String path) throws IllegalArgumentException {
+ wrapped.path(path);
+ return this;
+ }
+
+ @Override
+ public UriBuilder path(
+ @java.lang.SuppressWarnings("rawtypes") Class resource)
+ throws IllegalArgumentException {
+ wrapped.path(resource);
+ return this;
+ }
+
+ @Override
+ public UriBuilder path(
+ @java.lang.SuppressWarnings("rawtypes") Class resource,
+ String method) throws IllegalArgumentException {
+ wrapped.path(resource, method);
+ return this;
+ }
+
+ @Override
+ public UriBuilder path(Method method)
+ throws IllegalArgumentException {
+ wrapped.path(method);
+ return this;
+ }
+
+ @Override
+ public UriBuilder segment(String... segments)
+ throws IllegalArgumentException {
+ wrapped.segment(segments);
+ return this;
+ }
+
+ @Override
+ public UriBuilder replaceMatrix(String matrix)
+ throws IllegalArgumentException {
+ wrapped.replaceMatrix(matrix);
+ return this;
+ }
+
+ @Override
+ public UriBuilder matrixParam(String name, Object... values)
+ throws IllegalArgumentException {
+ wrapped.matrixParam(name, values);
+ return this;
+ }
+
+ @Override
+ public UriBuilder replaceMatrixParam(String name, Object... values)
+ throws IllegalArgumentException {
+ wrapped.replaceMatrixParam(name, values);
+ return this;
+ }
+
+ @Override
+ public UriBuilder replaceQuery(String query)
+ throws IllegalArgumentException {
+ wrapped.replaceQuery(query);
+ return this;
+ }
+
+ @Override
+ public UriBuilder queryParam(String name, Object... values)
+ throws IllegalArgumentException {
+ wrapped.queryParam(name, values);
+ return this;
+ }
+
+ @Override
+ public UriBuilder replaceQueryParam(String name, Object... values)
+ throws IllegalArgumentException {
+ wrapped.replaceQueryParam(name, values);
+ return this;
+ }
+
+ @Override
+ public UriBuilder fragment(String fragment) {
+ wrapped.fragment(fragment);
+ return this;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java
new file mode 100644
index 0000000..6eddf2d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.common;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.common.Namespaces.SERVER;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * The type of an element that declares the version of the server that produced
+ * it.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "VersionedElement", namespace = SERVER)
+public abstract class VersionedElement {
+ /** What version of server produced this element? */
+ @XmlAttribute(namespace = SERVER)
+ public String serverVersion;
+ /** What revision of server produced this element? Derived from SCM commit. */
+ @XmlAttribute(namespace = SERVER)
+ public String serverRevision;
+ /** When was the server built? */
+ @XmlAttribute(namespace = SERVER)
+ public String serverBuildTimestamp;
+ public static final String VERSION, REVISION, TIMESTAMP;
+ static {
+ Log log = getLog("Taverna.Server.Webapp");
+ Properties p = new Properties();
+ try {
+ try (InputStream is = VersionedElement.class
+ .getResourceAsStream("/version.properties")) {
+ p.load(is);
+ }
+ } catch (IOException e) {
+ log.warn("failed to read /version.properties", e);
+ }
+ VERSION = p.getProperty("tavernaserver.version", "unknownVersion");
+ REVISION = String.format("%s (tag: %s)",
+ p.getProperty("tavernaserver.branch", "unknownRevision"),
+ p.getProperty("tavernaserver.revision.describe", "unknownTag"));
+ TIMESTAMP = p
+ .getProperty("tavernaserver.timestamp", "unknownTimestamp");
+ }
+
+ public VersionedElement() {
+ }
+
+ protected VersionedElement(boolean ignored) {
+ serverVersion = VERSION;
+ serverRevision = REVISION;
+ serverBuildTimestamp = TIMESTAMP;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java
new file mode 100644
index 0000000..ba6a68c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.common;
+
+import static javax.xml.bind.Marshaller.JAXB_ENCODING;
+import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT;
+import static javax.xml.bind.annotation.XmlAccessType.NONE;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.rest.handler.Scufl2DocumentHandler.SCUFL2;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_NS;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_ROOTNAME;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.URL;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.taverna.server.master.rest.handler.Scufl2DocumentHandler;
+import org.taverna.server.master.rest.handler.T2FlowDocumentHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import uk.org.taverna.scufl2.api.common.NamedSet;
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+import uk.org.taverna.scufl2.api.io.ReaderException;
+import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
+import uk.org.taverna.scufl2.api.io.WriterException;
+import uk.org.taverna.scufl2.api.profiles.Profile;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Encapsulation of a T2flow or Scufl2 document.
+ *
+ * @author Donal K. Fellows
+ */
+@XmlRootElement(name = "workflow")
+@XmlType(name = "Workflow")
+@XmlAccessorType(NONE)
+public class Workflow implements Serializable, Externalizable {
+ /** Literal document, if present. */
+ @XmlAnyElement(lax = true)
+ private Element content;
+ /** SCUFL2 bundle, if present. */
+ @XmlTransient
+ private WorkflowBundle bundle;
+ /** Which came first, the bundle or the t2flow document. */
+ @XmlTransient
+ private boolean isBundleFirst;
+
+ private static Marshaller marshaller;
+ private static Unmarshaller unmarshaller;
+ private final static String ENCODING = "UTF-8";
+ private final static WorkflowBundleIO io;
+ static {
+ try {
+ JAXBContext context = JAXBContext.newInstance(Workflow.class);
+ marshaller = context.createMarshaller();
+ unmarshaller = context.createUnmarshaller();
+ marshaller.setProperty(JAXB_ENCODING, ENCODING);
+ marshaller.setProperty(JAXB_FORMATTED_OUTPUT, false);
+ } catch (JAXBException e) {
+ getLog("Taverna.Server.Webapp").fatal(
+ "failed to build JAXB context for working with "
+ + Workflow.class, e);
+ }
+ io = new WorkflowBundleIO();
+ }
+
+ public enum ContentType {
+ T2FLOW(T2FlowDocumentHandler.T2FLOW), SCUFL2(
+ Scufl2DocumentHandler.SCUFL2);
+ private String type;
+
+ ContentType(String type) {
+ this.type = type;
+ }
+
+ public String getContentType() {
+ return type;
+ }
+ }
+
+ public Workflow() {
+ }
+
+ public Workflow(Element element) {
+ this.content = element;
+ this.isBundleFirst = false;
+ }
+
+ public Workflow(WorkflowBundle bundle) {
+ this.bundle = bundle;
+ this.isBundleFirst = true;
+ }
+
+ public Workflow(URL url) throws ReaderException, IOException {
+ this(io.readBundle(url, null));
+ }
+
+ /**
+ * What content type would this workflow "prefer" to be?
+ */
+ public ContentType getPreferredContentType() {
+ if (isBundleFirst)
+ return ContentType.SCUFL2;
+ else
+ return ContentType.T2FLOW;
+ }
+
+ /**
+ * Retrieves the workflow as a SCUFL2 document, converting it if necessary.
+ *
+ * @return The SCUFL2 document.
+ * @throws IOException
+ * If anything goes wrong.
+ */
+ public WorkflowBundle getScufl2Workflow() throws IOException {
+ try {
+ if (bundle == null)
+ bundle = io.readBundle(new ByteArrayInputStream(getAsT2Flow()),
+ T2FLOW);
+ return bundle;
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IOException("problem when converting to SCUFL2", e);
+ }
+ }
+
+ /**
+ * Get the bytes of the serialized SCUFL2 workflow.
+ *
+ * @return Array of bytes.
+ * @throws IOException
+ * If serialization fails.
+ * @throws WriterException
+ * If conversion fails.
+ */
+ public byte[] getScufl2Bytes() throws IOException, WriterException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ io.writeBundle(getScufl2Workflow(), baos, SCUFL2);
+ return baos.toByteArray();
+ }
+
+ /**
+ * Retrieves the workflow as a T2Flow document, converting it if necessary.
+ *
+ * @return The T2Flow document.
+ * @throws IOException
+ * If anything goes wrong.
+ */
+ public Element getT2flowWorkflow() throws IOException {
+ try {
+ if (content != null)
+ return content;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ io.writeBundle(bundle, baos, T2FLOW);
+ Document doc;
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory
+ .newInstance();
+ dbf.setNamespaceAware(true);
+ doc = dbf.newDocumentBuilder().parse(
+ new ByteArrayInputStream(baos.toByteArray()));
+ } catch (SAXException e) {
+ throw new IOException("failed to convert to DOM tree", e);
+ }
+ Element e = doc.getDocumentElement();
+ if (e.getNamespaceURI().equals(T2FLOW_NS)
+ && e.getNodeName().equals(T2FLOW_ROOTNAME))
+ return content = e;
+ throw new IOException(
+ "unexpected element when converting to T2Flow: {"
+ + e.getNamespaceURI() + "}" + e.getNodeName());
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IOException("problem when converting to SCUFL2", e);
+ }
+ }
+
+ /**
+ * @return The name of the main workflow profile, or <tt>null</tt> if there
+ * is none.
+ */
+ public String getMainProfileName() {
+ try {
+ return getScufl2Workflow().getMainProfile().getName();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * @return The set of profiles supported over this workflow.
+ */
+ public NamedSet<Profile> getProfiles() {
+ try {
+ return getScufl2Workflow().getProfiles();
+ } catch (IOException e) {
+ return new NamedSet<Profile>();
+ }
+ }
+
+ /**
+ * Convert from marshalled form.
+ *
+ * @throws JAXBException
+ * If the conversion fails.
+ */
+ public static Workflow unmarshal(String representation)
+ throws JAXBException {
+ StringReader sr = new StringReader(representation);
+ return (Workflow) unmarshaller.unmarshal(sr);
+ }
+
+ /**
+ * Convert to marshalled form.
+ */
+ public String marshal() throws JAXBException {
+ StringWriter sw = new StringWriter();
+ marshaller.marshal(this, sw);
+ return sw.toString();
+ }
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException {
+ try {
+ ByteArrayInputStream bytes = readbytes(in);
+ if (bytes != null)
+ try (Reader r = new InputStreamReader(bytes, ENCODING)) {
+ content = ((Workflow) unmarshaller.unmarshal(r)).content;
+ }
+ bytes = readbytes(in);
+ if (bytes != null)
+ bundle = io.readBundle(bytes, SCUFL2);
+ isBundleFirst = in.readBoolean();
+ return;
+ } catch (JAXBException e) {
+ throw new IOException("failed to unmarshal", e);
+ } catch (ClassCastException e) {
+ throw new IOException("bizarre result of unmarshalling", e);
+ } catch (ReaderException e) {
+ throw new IOException("failed to unmarshal", e);
+ }
+ }
+
+ private byte[] getAsT2Flow() throws IOException, JAXBException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ OutputStreamWriter w = new OutputStreamWriter(baos, ENCODING);
+ marshaller.marshal(this, w);
+ w.close();
+ return baos.toByteArray();
+ }
+
+ private byte[] getAsScufl2() throws IOException, WriterException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ io.writeBundle(bundle, baos, SCUFL2);
+ baos.close();
+ return baos.toByteArray();
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {
+ try {
+ writebytes(out, (content != null) ? getAsT2Flow() : null);
+ } catch (JAXBException e) {
+ throw new IOException("failed to marshal t2flow", e);
+ }
+ try {
+ writebytes(out, (bundle != null) ? getAsScufl2() : null);
+ } catch (WriterException e) {
+ throw new IOException("failed to marshal scufl2", e);
+ }
+ out.writeBoolean(isBundleFirst);
+ }
+
+ private ByteArrayInputStream readbytes(ObjectInput in) throws IOException {
+ int len = in.readInt();
+ if (len > 0) {
+ byte[] bytes = new byte[len];
+ in.readFully(bytes);
+ return new ByteArrayInputStream(bytes);
+ }
+ return null;
+ }
+
+ private void writebytes(ObjectOutput out, byte[] data) throws IOException {
+ out.writeInt(data == null ? 0 : data.length);
+ if (data != null && data.length > 0)
+ out.write(data);
+ }
+
+ /**
+ * Make up for the lack of an integrated XPath engine.
+ *
+ * @param name
+ * The element names to look up from the root of the contained
+ * document.
+ * @return The looked up element, or <tt>null</tt> if it doesn't exist.
+ */
+ private Element getEl(String... name) {
+ Element el = content;
+ boolean skip = true;
+ for (String n : name) {
+ if (skip) {
+ skip = false;
+ continue;
+ }
+ if (el == null)
+ return null;
+ NodeList nl = el.getElementsByTagNameNS(T2FLOW_NS, n);
+ if (nl.getLength() == 0)
+ return null;
+ Node node = nl.item(0);
+ if (node instanceof Element)
+ el = (Element) node;
+ else
+ return null;
+ }
+ return el;
+ }
+
+ /**
+ * @return The content of the embedded
+ * <tt><workflow><dataflow><name></tt> element.
+ */
+ @XmlTransient
+ public String getName() {
+ return getEl("workflow", "dataflow", "name").getTextContent();
+ }
+
+ /**
+ * @return The embedded <tt><workflow></tt> element.
+ */
+ @XmlTransient
+ public Element getWorkflowRoot() {
+ return getEl("workflow");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java
new file mode 100644
index 0000000..fd040de
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains the common XML elements used throughout Taverna Server's various interfaces.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER, 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) })
+package org.taverna.server.master.common;
+
+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.XLINK;
+
+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/common/version/Version.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java
new file mode 100644
index 0000000..e9c58a9
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.common.version;
+
+import static org.taverna.server.master.common.version.Constants.PATCH;
+import static org.taverna.server.master.common.version.Constants.VERSION;
+
+/**
+ * Common location for describing the version of the server.
+ *
+ * @author Donal Fellows
+ */
+public interface Version {
+ public static final String JAVA = VERSION + Constants.releaseChar + PATCH;
+ public static final String HTML = VERSION + Constants.releaseHEnt + PATCH;
+ public static final String XML = VERSION + Constants.releaseXEnt + PATCH;
+}
+
+/**
+ * The pieces of a version string.
+ *
+ * @author Donal Fellows
+ */
+interface Constants {
+ static final String MAJOR = "2";
+ static final String MINOR = "5";
+ static final String PATCH = "4";
+
+ static final char alphaChar = '\u03b1';
+ static final char betaChar = '\u03b2';
+ static final char releaseChar = '.';
+ static final String alphaHEnt = "α";
+ static final String betaHEnt = "β";
+ static final String releaseHEnt = ".";
+ static final String alphaXEnt = "α";
+ static final String betaXEnt = "β";
+ static final String releaseXEnt = ".";
+
+ static final String VERSION = MAJOR + "." + MINOR;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java
new file mode 100644
index 0000000..c2a2bc9
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.defaults;
+
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.localworker.LocalWorkerState;
+
+/**
+ * This defines a collection of default values, collecting them from various
+ * parts of the server.
+ *
+ * @author Donal Fellows
+ */
+public interface Default {
+ /** The default value of the <tt>prefix</tt> property. */
+ static final String AUTHORITY_PREFIX = "LOCALUSER_";
+
+ /**
+ * The name of the resource that is the implementation of the subprocess
+ * that this class will fork off.
+ */
+ static final String SERVER_WORKER_IMPLEMENTATION_JAR = "util/server.worker.jar";
+
+ /**
+ * The name of the resource that is the implementation of the subprocess
+ * that manages secure forking.
+ */
+ static final String SECURE_FORK_IMPLEMENTATION_JAR = "util/secure.fork.jar";
+
+ /**
+ * The name of the resource that is the implementation of the subprocess
+ * that acts as the RMI registry.
+ */
+ static final String REGISTRY_JAR = "util/rmi.daemon.jar";
+
+ /** Initial lifetime of runs, in minutes. */
+ static final int RUN_LIFE_MINUTES = 20;
+
+ /**
+ * Maximum number of runs to exist at once. Note that this includes when
+ * they are just existing for the purposes of file transfer (
+ * {@link Status#Initialized}/{@link Status#Finished} states).
+ */
+ static final int RUN_COUNT_MAX = 5;
+
+ /**
+ * Prefix to use for RMI names.
+ */
+ static final String RMI_PREFIX = "ForkRunFactory.";
+
+ /** Default value for {@link LocalWorkerState#passwordFile}. */
+ static final String PASSWORD_FILE = null;
+
+ /**
+ * The extra arguments to pass to the subprocess.
+ */
+ static final String[] EXTRA_ARGUMENTS = new String[0];
+
+ /**
+ * How long to wait for subprocess startup, in seconds.
+ */
+ static final int SUBPROCESS_START_WAIT = 40;
+
+ /**
+ * Polling interval to use during startup, in milliseconds.
+ */
+ static final int SUBPROCESS_START_POLL_SLEEP = 1000;
+
+ /**
+ * Maximum number of {@link Status#Operating} runs at any time.
+ */
+ static final int RUN_OPERATING_LIMIT = 10;
+
+ /**
+ * What fields of a certificate we look at when understanding who it is
+ * talking about, in the order that we look.
+ */
+ static final String[] CERTIFICATE_FIELD_NAMES = { "CN", "COMMONNAME",
+ "COMMON NAME", "COMMON_NAME", "OU", "ORGANIZATIONALUNITNAME",
+ "ORGANIZATIONAL UNIT NAME", "O", "ORGANIZATIONNAME",
+ "ORGANIZATION NAME" };
+
+ /** The type of certificates that are processed if we don't say otherwise. */
+ static final String CERTIFICATE_TYPE = "X.509";
+
+ /** Max size of credential file, in kiB. */
+ static final int CREDENTIAL_FILE_SIZE_LIMIT = 20;
+
+ /**
+ * The notification message format to use if none is configured.
+ */
+ public static final String NOTIFY_MESSAGE_FORMAT = "Your job with ID={0} has finished with exit code {1,number,integer}.";
+
+ /** The address of the SMS gateway service used. */
+ public static final String SMS_GATEWAY_URL = "https://www.intellisoftware.co.uk/smsgateway/sendmsg.aspx";
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java
new file mode 100644
index 0000000..239b260
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * This package contains information about the various default values supported by the server.
+ * @author Donal Fellows
+ */
+package org.taverna.server.master.defaults;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java
new file mode 100644
index 0000000..0b6247e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Indicates that the port name was not recognized.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "BadInputPortNameFault")
+@SuppressWarnings("serial")
+public class BadInputPortNameException extends Exception {
+ public BadInputPortNameException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java
new file mode 100644
index 0000000..303b19b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Indicates a bad property value.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "BadPropertyValueFault")
+public class BadPropertyValueException extends NoListenerException {
+ private static final long serialVersionUID = -8459491388504556875L;
+
+ public BadPropertyValueException(String msg) {
+ super(msg);
+ }
+
+ public BadPropertyValueException(String msg, Throwable e) {
+ super(msg, e);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java
new file mode 100644
index 0000000..4b843e2
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception that is thrown to indicate that the state change requested for a
+ * run is impossible.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NoUpdateFault")
+public class BadStateChangeException extends NoUpdateException {
+ private static final long serialVersionUID = -4490826388447601775L;
+
+ public BadStateChangeException() {
+ super("cannot do that state change");
+ }
+
+ public BadStateChangeException(Throwable t) {
+ super("cannot do that state change", t);
+ }
+
+ public BadStateChangeException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+ public BadStateChangeException(String message) {
+ super(message);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java
new file mode 100644
index 0000000..0b6cf07
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import java.rmi.RemoteException;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * An exception that happened when the underlying filesystem was accessed.
+ * @author Donal Fellows
+ */
+@WebFault(name = "FilesystemAccessFault")
+public class FilesystemAccessException extends Exception {
+ private static final long serialVersionUID = 8715937300989820318L;
+
+ public FilesystemAccessException(String msg) {
+ super(msg);
+ }
+
+ public FilesystemAccessException(String string, Throwable cause) {
+ super(string, getRealCause(cause));
+ }
+
+ private static Throwable getRealCause(Throwable t) {
+ if (t instanceof RemoteException) {
+ RemoteException remote = (RemoteException) t;
+ if (remote.detail != null)
+ return remote.detail;
+ }
+ if (t.getCause() != null)
+ return t.getCause();
+ return t;
+ }
+}
\ 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/exceptions/GeneralFailureException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java
new file mode 100644
index 0000000..11d47c7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Some sort of exception that occurred which we can't map any other way. This
+ * is generally indicative of a problem server-side.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "GeneralFailureFault", targetNamespace = SERVER_SOAP)
+@SuppressWarnings("serial")
+public class GeneralFailureException extends RuntimeException {
+ public GeneralFailureException(Throwable cause) {
+ super(cause.getMessage(), cause);
+ }
+
+ public GeneralFailureException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java
new file mode 100644
index 0000000..67ba551
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+/**
+ * An exception that is thrown to indicate that a credential-descriptor or
+ * trust-descriptor supplied as part of a credential or trust management
+ * operation is invalid.
+ *
+ * @author Donal Fellows
+ *
+ */
+@SuppressWarnings("serial")
+public class InvalidCredentialException extends Exception {
+ private static final String MSG = "that credential is invalid";
+
+ public InvalidCredentialException() {
+ super(MSG);
+ }
+
+ public InvalidCredentialException(String reason) {
+ super(MSG + ": " + reason);
+ }
+
+ public InvalidCredentialException(String reason, Throwable cause) {
+ this(reason);
+ initCause(cause);
+ }
+
+ public InvalidCredentialException(Throwable cause) {
+ this(cause.getMessage(), cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java
new file mode 100644
index 0000000..e2ddf4c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+
+/**
+ * Exception that is thrown to indicate that the user is not permitted to
+ * create something.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NoCreateFault")
+public class NoCreateException extends NoUpdateException {
+ private static final long serialVersionUID = 270413810410167235L;
+
+ public NoCreateException() {
+ super("not permitted to create");
+ }
+
+ public NoCreateException(String string) {
+ super(string);
+ }
+
+ public NoCreateException(String string, Throwable e) {
+ super(string, e);
+ }
+}
\ 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/exceptions/NoCredentialException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java
new file mode 100644
index 0000000..7077fc4
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+/**
+ * Exception that indicates the absence of an expected credential.
+ *
+ * @author Donal Fellows
+ */
+@SuppressWarnings("serial")
+public class NoCredentialException extends Exception {
+ public NoCredentialException() {
+ super("no such credential");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java
new file mode 100644
index 0000000..d7b0d29
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+
+/**
+ * Exception that is thrown to indicate that the user is not permitted to
+ * destroy something.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NoDestroyFault")
+public class NoDestroyException extends NoUpdateException {
+ private static final long serialVersionUID = 6207448533265237933L;
+
+ public NoDestroyException() {
+ super("not permitted to destroy");
+ }
+}
\ 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/exceptions/NoDirectoryEntryException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java
new file mode 100644
index 0000000..0d6ca63
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Indicates that the file or directory name was not recognized.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NoDirectoryEntryFault")
+@SuppressWarnings("serial")
+public class NoDirectoryEntryException extends Exception {
+ public NoDirectoryEntryException(String msg) {
+ super(msg);
+ }
+ public NoDirectoryEntryException(String msg,Exception cause) {
+ super(msg, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java
new file mode 100644
index 0000000..f4b8e81
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception thrown to indicate that no listener by that name exists, or that
+ * some other problem with listeners has occurred.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NoListenerFault")
+@XmlSeeAlso(BadPropertyValueException.class)
+public class NoListenerException extends Exception {
+ private static final long serialVersionUID = -2550897312787546547L;
+
+ public NoListenerException() {
+ super("no such listener");
+ }
+
+ public NoListenerException(String msg) {
+ super(msg);
+ }
+
+ public NoListenerException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
\ 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/exceptions/NoUpdateException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java
new file mode 100644
index 0000000..c49d111
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.bind.annotation.XmlSeeAlso;
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception that is thrown to indicate that the user is not permitted to update
+ * something.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NoUpdateFault")
+@XmlSeeAlso( { NoCreateException.class, NoDestroyException.class, BadStateChangeException.class })
+public class NoUpdateException extends Exception {
+ private static final long serialVersionUID = 4230987102653846379L;
+
+ public NoUpdateException() {
+ super("not permitted to update");
+ }
+
+ public NoUpdateException(String msg) {
+ super(msg);
+ }
+
+ public NoUpdateException(String string, Throwable e) {
+ super(string, e);
+ }
+}
\ 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/exceptions/NotOwnerException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java
new file mode 100644
index 0000000..6e1f792
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * An exception thrown when an operation is attempted which only the owner is
+ * permitted to do. Notably, permissions may <i>only</i> be manipulated by the
+ * owner.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "NotOwnerFault")
+@SuppressWarnings("serial")
+public class NotOwnerException extends Exception {
+ public NotOwnerException() {
+ super("not permitted; not the owner");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java
new file mode 100644
index 0000000..dda371e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception that is thrown to indicate that the state change requested for a
+ * run is currently impossible due to excessive server load.
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "OverloadedFault")
+public class OverloadedException extends BadStateChangeException {
+ private static final long serialVersionUID = 490826388447601776L;
+
+ public OverloadedException() {
+ super("server too busy; try later please");
+ }
+
+ public OverloadedException(Throwable t) {
+ super("server too busy; try later please", t);
+ }
+
+ public OverloadedException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+ public OverloadedException(String message) {
+ super(message);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java
new file mode 100644
index 0000000..4632d4a
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.exceptions;
+
+import javax.xml.ws.WebFault;
+
+/**
+ * Exception thrown to indicate that the handle of the run is unknown (or
+ * unacceptable to the current user).
+ *
+ * @author Donal Fellows
+ */
+@WebFault(name = "UnknownRunFault")
+public class UnknownRunException extends Exception {
+ private static final long serialVersionUID = -3028749401786242841L;
+
+ public UnknownRunException() {
+ super("unknown run UUID");
+ }
+
+ public UnknownRunException(Throwable t) {
+ super("implementation problems", t);
+ }
+}
\ 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/exceptions/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java
new file mode 100644
index 0000000..29ccacd
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains the exceptions/faults thrown by Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER, 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) })
+package org.taverna.server.master.exceptions;
+
+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.XLINK;
+
+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/facade/Facade.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java
new file mode 100644
index 0000000..0015754
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.facade;
+
+import static javax.ws.rs.core.MediaType.TEXT_HTML_TYPE;
+import static javax.ws.rs.core.Response.ok;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.ws.rs.GET;
+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.UriInfo;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.utils.Contextualizer;
+
+/**
+ * This is a simple class that is used to serve up a file (with a simple
+ * substitution applied) as the root of the T2Server webapp.
+ *
+ * @author Donal Fellows
+ */
+@Path("/")
+public class Facade {
+ private Log log = LogFactory.getLog("Taverna.Server.Utils");
+ private String welcome;
+ private Contextualizer contextualizer;
+
+ /**
+ * Set what resource file to use as the template for the response.
+ *
+ * @param file
+ * The file from which to load the data (presumed HTML) to serve
+ * up as the root content.
+ * @throws IOException
+ * If the file doesn't exist.
+ */
+ public void setFile(String file) throws IOException {
+ URL full = Facade.class.getResource(file);
+ log.info("setting " + full + " as source of root page");
+ this.welcome = IOUtils.toString(full);
+ }
+
+ @Required
+ public void setContextualizer(Contextualizer contextualizer) {
+ this.contextualizer = contextualizer;
+ }
+
+ /**
+ * Serve up some HTML as the root of the service.
+ *
+ * @param ui
+ * A reference to how we were accessed by the service.
+ * @return The response, containing the HTML.
+ */
+ @GET
+ @Path("{dummy:.*}")
+ @Produces("text/html")
+ public Response get(@Context UriInfo ui) {
+ return ok(contextualizer.contextualize(ui, welcome), TEXT_HTML_TYPE)
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java
new file mode 100644
index 0000000..73c884f
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Simple facade used at the top level of the Taverna Server in order to
+ * provide an entry splash page.
+ */
+package org.taverna.server.master.facade;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java
new file mode 100644
index 0000000..954b6f1
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.factories;
+
+/**
+ * Interface to run factories for the purpose of configuration.
+ *
+ * @author Donal Fellows
+ */
+public interface ConfigurableRunFactory extends RunFactory {
+ /** Where is the registry? Getter */
+ String getRegistryHost();
+
+ /** Where is the registry? Setter */
+ void setRegistryHost(String host);
+
+ /** Where is the registry? Getter */
+ int getRegistryPort();
+
+ /** Where is the registry? Setter */
+ void setRegistryPort(int port);
+
+ /** How much can be done at once? Getter */
+ int getMaxRuns();
+
+ /** How much can be done at once? Setter */
+ void setMaxRuns(int maxRuns);
+
+ /** How long will things live? Getter */
+ int getDefaultLifetime();
+
+ /** How long will things live? Setter */
+ void setDefaultLifetime(int defaultLifetime);
+
+ /** How often do we probe for info? Getter */
+ int getSleepTime();
+
+ /** How often do we probe for info? Setter */
+ void setSleepTime(int sleepTime);
+
+ /** How long do we allow for actions? Getter */
+ int getWaitSeconds();
+
+ /** How long do we allow for actions? Setter */
+ void setWaitSeconds(int seconds);
+
+ /** How do we start the workflow engine? Getter */
+ String getExecuteWorkflowScript();
+
+ /** How do we start the workflow engine? Setter */
+ void setExecuteWorkflowScript(String executeWorkflowScript);
+
+ /** How do we start the file system access process? Getter */
+ String getServerWorkerJar();
+
+ /** How do we start the file system access process? Setter */
+ void setServerWorkerJar(String serverWorkerJar);
+
+ /**
+ * How do we start the file system access process? Extra arguments to pass.
+ * Getter
+ */
+ String[] getExtraArguments();
+
+ /**
+ * How do we start the file system access process? Extra arguments to pass.
+ * Setter
+ */
+ void setExtraArguments(String[] firstArguments);
+
+ /** Where is Java? Getter */
+ String getJavaBinary();
+
+ /** Where is Java? Setter */
+ void setJavaBinary(String javaBinary);
+
+ /** Where do we get passwords from? Getter */
+ String getPasswordFile();
+
+ /** Where do we get passwords from? Setter */
+ void setPasswordFile(String newValue);
+
+ /** How do we switch users? Getter */
+ String getServerForkerJar();
+
+ /** How do we switch users? Setter */
+ void setServerForkerJar(String newValue);
+
+ /** How many runs have there been? */
+ int getTotalRuns();
+
+ /** How long did the last subprocess startup take? */
+ int getLastStartupCheckCount();
+
+ /** What are the current runs? */
+ String[] getCurrentRunNames();
+
+ /** What is the RMI ID of the factory process? */
+ String getFactoryProcessName();
+
+ /** What was the last observed exit code? */
+ Integer getLastExitCode();
+
+ /** What factory process to use for a particular user? */
+ String[] getFactoryProcessMapping();
+
+ /** How many runs can be operating at once? Setter */
+ void setOperatingLimit(int operatingLimit);
+
+ /** How many runs can be operating at once? Getter */
+ int getOperatingLimit();
+
+ /**
+ * How many runs are actually operating?
+ *
+ * @throws Exception
+ * if anything goes wrong
+ */
+ int getOperatingCount() throws Exception;
+
+ /** How do we start the RMI registry process? Getter */
+ String getRmiRegistryJar();
+
+ /** How do we start the RMI registry process? Setter */
+ void setRmiRegistryJar(String rmiRegistryJar);
+
+ boolean getGenerateProvenance();
+
+ void setGenerateProvenance(boolean generateProvenance);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java
new file mode 100644
index 0000000..ecc13cd
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.factories;
+
+import java.util.List;
+
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+
+/**
+ * How to make event listeners of various types that are attached to a workflow
+ * instance.
+ *
+ * @author Donal Fellows
+ */
+public interface ListenerFactory {
+ /**
+ * Make an event listener.
+ *
+ * @param run
+ * The workflow instance to attach the event listener to.
+ * @param listenerType
+ * The type of event listener to create. Must be one of the
+ * strings returned by {@link #getSupportedListenerTypes()}.
+ * @param configuration
+ * A configuration document to pass to the listener.
+ * @return The event listener that was created.
+ * @throws NoListenerException
+ * If the <b>listenerType</b> is unrecognized or the
+ * <b>configuration</b> is bad in some way.
+ */
+ public Listener makeListener(TavernaRun run, String listenerType,
+ String configuration) throws NoListenerException;
+
+ /**
+ * What types of listener are supported? Note that we assume that the list
+ * of types is the same for all users and all workflow instances.
+ *
+ * @return A list of supported listener types.
+ */
+ public List<String> getSupportedListenerTypes();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java
new file mode 100644
index 0000000..eeacad7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.factories;
+
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * How to construct a Taverna Server Workflow Run.
+ *
+ * @author Donal Fellows
+ */
+public interface RunFactory {
+ /**
+ * Make a Taverna Server workflow run that is bound to a particular user
+ * (the "creator") and able to run a particular workflow.
+ *
+ * @param creator
+ * The user creating the workflow instance.
+ * @param workflow
+ * The workflow to instantiate
+ * @return An object representing the run.
+ * @throws NoCreateException
+ * On failure.
+ */
+ TavernaRun create(UsernamePrincipal creator, Workflow workflow)
+ throws NoCreateException;
+
+ /**
+ * Check whether the factory is permitting runs to actually start operating.
+ *
+ * @return Whether a run should start.
+ */
+ boolean isAllowingRunsToStart();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java
new file mode 100644
index 0000000..39b9ac6
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * These interfaces define the principal way for the <i>factories</i> of
+ * worker classes to be invoked.
+ */
+package org.taverna.server.master.factories;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java
new file mode 100644
index 0000000..63402ef
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.identity;
+
+import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Extracts the local user id from the set of Spring Security authorities
+ * granted to the current user. This is done by scanning the set of authorities
+ * to see if any of them start with the substring listed in the <tt>prefix</tt>
+ * property; the username is the rest of the authority string in that case.
+ *
+ * @author Donal Fellows
+ */
+public class AuthorityDerivedIDMapper implements LocalIdentityMapper {
+ private String prefix = AUTHORITY_PREFIX;
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ public String getUsernameForPrincipal(UsernamePrincipal user) {
+ Authentication auth = SecurityContextHolder.getContext()
+ .getAuthentication();
+ if (auth == null || !auth.isAuthenticated())
+ return null;
+ for (GrantedAuthority authority : auth.getAuthorities()) {
+ String token = authority.getAuthority();
+ if (token == null)
+ continue;
+ if (token.startsWith(prefix))
+ return token.substring(prefix.length());
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java
new file mode 100644
index 0000000..b5fcd5a
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.identity;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * An identity mapper that composes the results from other mappers, using the
+ * identity mappers in order until one can provide a non-<tt>null</tt> answer.
+ *
+ * @author Donal Fellows.
+ */
+public class CompositeIDMapper implements LocalIdentityMapper,
+ ApplicationContextAware {
+ private Log log = getLog("Taverna.Server.IdentityMapper");
+ private List<LocalIdentityMapper> mappers;
+ private ApplicationContext context;
+
+ /**
+ * @param mappers
+ * The list of mappers to delegate to. Order is significant.
+ */
+ public void setIdentityMappers(List<LocalIdentityMapper> mappers) {
+ this.mappers = mappers;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ context = applicationContext;
+ }
+
+ @Override
+ public String getUsernameForPrincipal(UsernamePrincipal user) {
+ if (mappers == null)
+ return null;
+ for (LocalIdentityMapper m : mappers) {
+ String u = m.getUsernameForPrincipal(user);
+ if (u == null)
+ continue;
+ for (Entry<String, ? extends LocalIdentityMapper> entry : context
+ .getBeansOfType(m.getClass()).entrySet())
+ if (m == entry.getValue()) {
+ log.info("used " + entry.getKey() + " LIM to map " + user
+ + " to " + u);
+ break;
+ }
+ return u;
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java
new file mode 100644
index 0000000..e81f926
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.identity;
+
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * A trivial principal to user mapper that always uses the same ID.
+ * @author Donal Fellows
+ */
+public class ConstantIDMapper implements LocalIdentityMapper {
+ private String id;
+
+ /**
+ * Sets what local user ID all users should be mapped to.
+ *
+ * @param id
+ * The local user ID.
+ */
+ public void setConstantId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String getUsernameForPrincipal(UsernamePrincipal user) {
+ return id;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java
new file mode 100644
index 0000000..42a3874
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.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.identity;
+
+import static java.util.regex.Pattern.compile;
+
+import java.security.Principal;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * A trivial identity mapper that just uses the name out of the
+ * {@link Principal}, or uses a regular expression to extract it from the string
+ * representation of the principal.
+ *
+ * @author Donal Fellows
+ */
+public class NameIDMapper implements LocalIdentityMapper {
+ private Pattern pat;
+
+ /**
+ * @param regexp
+ * The regular expression to use. The first capturing group
+ * within the RE will be the result of the extraction.
+ * @throws PatternSyntaxException
+ * If the pattern is invalid.
+ */
+ public void setRegexp(String regexp) throws PatternSyntaxException {
+ pat = compile(regexp);
+ }
+
+ @Override
+ public String getUsernameForPrincipal(UsernamePrincipal user) {
+ if (pat != null) {
+ Matcher m = pat.matcher(user.toString());
+ if (m.find() && m.groupCount() > 0) {
+ return m.group(1);
+ }
+ return null;
+ }
+ return user.getName();
+ }
+}
[42/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java b/server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java
deleted file mode 100644
index 184c7b5..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/admin/Admin.java
+++ /dev/null
@@ -1,1100 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java b/server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java
deleted file mode 100644
index b83d88f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/admin/AdminBean.java
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java
deleted file mode 100644
index 930fd75..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/admin/package-info.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java b/server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java
deleted file mode 100644
index 1a89b8d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/ContentTypes.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java
deleted file mode 100644
index 8fa5c78..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/DirectoryBean.java
+++ /dev/null
@@ -1,16 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java
deleted file mode 100644
index 5ace6a3..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/FeedBean.java
+++ /dev/null
@@ -1,13 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java
deleted file mode 100644
index eecea44..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/InputBean.java
+++ /dev/null
@@ -1,21 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java
deleted file mode 100644
index 5c480d4..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/ListenerPropertyBean.java
+++ /dev/null
@@ -1,15 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java
deleted file mode 100644
index c02bf62..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/ListenersBean.java
+++ /dev/null
@@ -1,13 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java b/server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java
deleted file mode 100644
index 6bc6058..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/ManagementModel.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java
deleted file mode 100644
index 9f80a12..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/OneListenerBean.java
+++ /dev/null
@@ -1,14 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java
deleted file mode 100644
index 4903ea9..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/RunBean.java
+++ /dev/null
@@ -1,17 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java
deleted file mode 100644
index 04fbd6e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/SecurityBean.java
+++ /dev/null
@@ -1,14 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java b/server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java
deleted file mode 100644
index c632657..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/SupportAware.java
+++ /dev/null
@@ -1,21 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java b/server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java
deleted file mode 100644
index 5a14fb6..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/TavernaServerBean.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/api/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/api/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/api/package-info.java
deleted file mode 100644
index fe76a09..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/api/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * 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/server-webapp/src/main/java/org/taverna/server/master/common/Capability.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Capability.java b/server-webapp/src/main/java/org/taverna/server/master/common/Capability.java
deleted file mode 100644
index 034d489..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Capability.java
+++ /dev/null
@@ -1,22 +0,0 @@
-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/server-webapp/src/main/java/org/taverna/server/master/common/Credential.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Credential.java b/server-webapp/src/main/java/org/taverna/server/master/common/Credential.java
deleted file mode 100644
index 5c16e79..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Credential.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java b/server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java
deleted file mode 100644
index 318ae4f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/DirEntryReference.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java b/server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java
deleted file mode 100644
index bb98d6d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/InputDescription.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java b/server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java
deleted file mode 100644
index 1311272..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Namespaces.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/common/Permission.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Permission.java b/server-webapp/src/main/java/org/taverna/server/master/common/Permission.java
deleted file mode 100644
index 258bfd0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Permission.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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
[15/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java
new file mode 100644
index 0000000..399164d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaRun.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDestroyException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+
+/**
+ * The interface to a taverna workflow run, or "run" for short.
+ *
+ * @author Donal Fellows
+ */
+public interface TavernaRun extends Serializable {
+ /**
+ * @return The identifier of the run.
+ */
+ String getId();
+
+ /**
+ * @return What was this run was create to execute.
+ */
+ Workflow getWorkflow();
+
+ /**
+ * @return The name of the run.
+ */
+ String getName();
+
+ /**
+ * @param name
+ * The new name of the run. May be truncated.
+ */
+ void setName(String name);
+
+ /**
+ * @return The name of the Baclava file to use for all inputs, or
+ * <tt>null</tt> if no Baclava file is set.
+ */
+ String getInputBaclavaFile();
+
+ /**
+ * Sets the Baclava file to use for all inputs. This overrides the use of
+ * individual inputs.
+ *
+ * @param filename
+ * The filename to use. Must not start with a <tt>/</tt> or
+ * contain any <tt>..</tt> segments. Will be interpreted relative
+ * to the run's working directory.
+ * @throws FilesystemAccessException
+ * If the filename is invalid.
+ * @throws BadStateChangeException
+ * If the workflow is not in the {@link Status#Initialized
+ * Initialized} state.
+ */
+ void setInputBaclavaFile(String filename) throws FilesystemAccessException,
+ BadStateChangeException;
+
+ /**
+ * @return The list of input assignments.
+ */
+ List<Input> getInputs();
+
+ /**
+ * Create an input assignment.
+ *
+ * @param name
+ * The name of the port that this will be an input for.
+ * @return The assignment reference.
+ * @throws BadStateChangeException
+ * If the workflow is not in the {@link Status#Initialized
+ * Initialized} state.
+ */
+ Input makeInput(String name) throws BadStateChangeException;
+
+ /**
+ * @return The file (relative to the working directory) to write the outputs
+ * of the run to as a Baclava document, or <tt>null</tt> if they are
+ * to be written to non-Baclava files in a directory called
+ * <tt>out</tt>.
+ */
+ String getOutputBaclavaFile();
+
+ /**
+ * Sets where the output of the run is to be written to. This will cause the
+ * output to be generated as a Baclava document, rather than a collection of
+ * individual non-Baclava files in the subdirectory of the working directory
+ * called <tt>out</tt>.
+ *
+ * @param filename
+ * Where to write the Baclava file (or <tt>null</tt> to cause the
+ * output to be written to individual files); overwrites any
+ * previous setting of this value.
+ * @throws FilesystemAccessException
+ * If the filename starts with a <tt>/</tt> or contains a
+ * <tt>..</tt> segment.
+ * @throws BadStateChangeException
+ * If the workflow is not in the {@link Status#Initialized
+ * Initialized} state.
+ */
+ void setOutputBaclavaFile(String filename)
+ throws FilesystemAccessException, BadStateChangeException;
+
+ /**
+ * @return When this run will expire, becoming eligible for automated
+ * deletion.
+ */
+ Date getExpiry();
+
+ /**
+ * Set when this run will expire.
+ *
+ * @param d
+ * Expiry time. Deletion will happen some time after that.
+ */
+ void setExpiry(Date d);
+
+ /**
+ * @return The current status of the run.
+ */
+ Status getStatus();
+
+ /**
+ * Set the status of the run, which should cause it to move into the given
+ * state. This may cause some significant changes.
+ *
+ * @param s
+ * The state to try to change to.
+ * @return <tt>null</tt>, or a string describing the incomplete state change
+ * if the operation has internally timed out.
+ * @throws BadStateChangeException
+ * If the change to the given state is impossible.
+ */
+ String setStatus(Status s) throws BadStateChangeException;
+
+ /**
+ * @return Handle to the main working directory of the run.
+ * @throws FilesystemAccessException
+ */
+ Directory getWorkingDirectory() throws FilesystemAccessException;
+
+ /**
+ * @return The list of listener instances attached to the run.
+ */
+ List<Listener> getListeners();
+
+ /**
+ * Add a listener to the run.
+ *
+ * @param listener
+ * The listener to add.
+ */
+ void addListener(Listener listener);
+
+ /**
+ * @return The security context structure for this run.
+ */
+ TavernaSecurityContext getSecurityContext();
+
+ /**
+ * Kill off this run, removing all resources which it consumes.
+ *
+ * @throws NoDestroyException
+ * If the destruction failed.
+ */
+ void destroy() throws NoDestroyException;
+
+ /**
+ * @return When this workflow run was created.
+ */
+ Date getCreationTimestamp();
+
+ /**
+ * @return When this workflow run was started, or <tt>null</tt> if it has
+ * never been started.
+ */
+ Date getStartTimestamp();
+
+ /**
+ * @return When this workflow run was found to have finished, or
+ * <tt>null</tt> if it has never finished (either still running or
+ * never started).
+ */
+ Date getFinishTimestamp();
+
+ /**
+ * Test if this run is really there.
+ *
+ * <p>
+ * <i>Implementation note:</i> Used to test communication fabrics, etc. so
+ * implementations of this interface that do not delegate to another object
+ * should do nothing.
+ *
+ * @throws UnknownRunException
+ * If things fail.
+ */
+ void ping() throws UnknownRunException;
+
+ /**
+ * @return whether the run generates provenance data
+ */
+ boolean getGenerateProvenance();
+
+ /**
+ * @param generateProvenance
+ * whether the run generates provenance data
+ */
+ void setGenerateProvenance(boolean generateProvenance);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java
new file mode 100644
index 0000000..b227bfa
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.util.Set;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.xml.ws.handler.MessageContext;
+
+import org.springframework.security.core.context.SecurityContext;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Security context for a workflow run.
+ *
+ * @author Donal Fellows
+ */
+public interface TavernaSecurityContext {
+ /**
+ * @return Who owns the security context.
+ */
+ UsernamePrincipal getOwner();
+
+ /**
+ * Describe the names of the users (as extracted from their
+ * {@link Principal} objects) that may destroy the run or manipulate its
+ * lifetime.
+ *
+ * @return The names of the users who may use destroy operations. Read-only.
+ */
+ Set<String> getPermittedDestroyers();
+
+ /**
+ * Sets the collection of names of users (as extracted from their
+ * {@link Principal} objects) that may destroy the run or manipulate its
+ * lifetime.
+ *
+ * @param destroyers
+ * The names of the users who may use destroy operations.
+ */
+ void setPermittedDestroyers(Set<String> destroyers);
+
+ /**
+ * Describe the names of the users (as extracted from their
+ * {@link Principal} objects) that may update the run (including writing to
+ * files).
+ *
+ * @return The names of the users who may use update operations. Read-only.
+ */
+ Set<String> getPermittedUpdaters();
+
+ /**
+ * Sets the collection of names of users (as extracted from their
+ * {@link Principal} objects) that may update the run (including writing to
+ * its files).
+ *
+ * @param updaters
+ * The names of the users who may use update operations.
+ */
+ void setPermittedUpdaters(Set<String> updaters);
+
+ /**
+ * Describe the names of the users (as extracted from their
+ * {@link Principal} objects) that may read from the run (including its
+ * files).
+ *
+ * @return The names of the users who may use read operations. Read-only.
+ */
+ Set<String> getPermittedReaders();
+
+ /**
+ * Sets the collection of names of users (as extracted from their
+ * {@link Principal} objects) that may read from the run (including its
+ * files).
+ *
+ * @param readers
+ * The names of the users who may use read operations.
+ */
+ void setPermittedReaders(Set<String> readers);
+
+ /**
+ * @return The credentials owned by the user. Never <tt>null</tt>.
+ */
+ Credential[] getCredentials();
+
+ /**
+ * Add a credential to the owned set or replaces the old version with the
+ * new one.
+ *
+ * @param toAdd
+ * The credential to add.
+ */
+ void addCredential(Credential toAdd);
+
+ /**
+ * Remove a credential from the owned set. It's not a failure to remove
+ * something that isn't in the set.
+ *
+ * @param toDelete
+ * The credential to remove.
+ */
+ void deleteCredential(Credential toDelete);
+
+ /**
+ * Tests if the credential is valid. This includes testing whether the
+ * underlying credential file exists and can be unlocked by the password in
+ * the {@link Credential} object.
+ *
+ * @param c
+ * The credential object to validate.
+ * @throws InvalidCredentialException
+ * If it is invalid.
+ */
+ void validateCredential(Credential c) throws InvalidCredentialException;
+
+ /**
+ * @return The identities trusted by the user. Never <tt>null</tt>.
+ */
+ Trust[] getTrusted();
+
+ /**
+ * Add an identity to the trusted set.
+ *
+ * @param toAdd
+ * The identity to add.
+ */
+ void addTrusted(Trust toAdd);
+
+ /**
+ * Remove an identity from the trusted set. It's not a failure to remove
+ * something that isn't in the set.
+ *
+ * @param toDelete
+ * The identity to remove.
+ */
+ void deleteTrusted(Trust toDelete);
+
+ /**
+ * Tests if the trusted identity descriptor is valid. This includes checking
+ * whether the underlying trusted identity file exists.
+ *
+ * @param t
+ * The trusted identity descriptor to check.
+ * @throws InvalidCredentialException
+ * If it is invalid.
+ */
+ void validateTrusted(Trust t) throws InvalidCredentialException;
+
+ /**
+ * Establish the security context from how the owning workflow run was
+ * created. In particular, this gives an opportunity for boot-strapping
+ * things with any delegateable credentials.
+ *
+ * @param securityContext
+ * The security context associated with the request that caused
+ * the workflow to be created.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ void initializeSecurityFromContext(SecurityContext securityContext)
+ throws Exception;
+
+ /**
+ * Establish the security context from how the owning workflow run was
+ * created. In particular, this gives an opportunity for boot-strapping
+ * things with any delegateable credentials.
+ *
+ * @param context
+ * The full information about the request that caused the
+ * workflow to be created.
+ */
+ void initializeSecurityFromSOAPContext(MessageContext context);
+
+ /**
+ * Establish the security context from how the owning workflow run was
+ * created. In particular, this gives an opportunity for boot-strapping
+ * things with any delegateable credentials.
+ *
+ * @param headers
+ * The full information about the request that caused the
+ * workflow to be created.
+ */
+ void initializeSecurityFromRESTContext(HttpHeaders headers);
+
+ /**
+ * Transfer the security context to the remote system.
+ *
+ * @throws IOException
+ * If the communication fails.
+ * @throws GeneralSecurityException
+ * If the assembly of the context fails.
+ * @throws ImplementationException
+ * If the local worker has problems with creating the realized
+ * security context.
+ */
+ void conveySecurity() throws GeneralSecurityException, IOException,
+ ImplementationException;
+
+ /**
+ * @return The factory that created this security context.
+ */
+ SecurityContextFactory getFactory();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java
new file mode 100644
index 0000000..e5cd02c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.interfaces;
+
+import java.net.URI;
+
+import javax.ws.rs.core.UriBuilder;
+
+/**
+ * How to manufacture URIs to workflow runs.
+ *
+ * @author Donal Fellows
+ */
+public interface UriBuilderFactory {
+ /**
+ * Given a run, get a factory for RESTful URIs to resources associated
+ * with it.
+ *
+ * @param run
+ * The run in question.
+ * @return The {@link URI} factory.
+ */
+ UriBuilder getRunUriBuilder(TavernaRun run);
+
+ /**
+ * @return a URI factory that is preconfigured to point to the base of
+ * the webapp.
+ */
+ UriBuilder getBaseUriBuilder();
+
+ /**
+ * Resolves a URI with respect to the base URI of the factory.
+ *
+ * @param uri
+ * The URI to resolve, or <tt>null</tt>.
+ * @return The resolved URI, or <tt>null</tt> if <b>uri</b> is
+ * <tt>null</tt>.
+ */
+ String resolve(String uri);
+}
\ 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/interfaces/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java
new file mode 100644
index 0000000..cfbbe79
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Interfaces to the main worker classes that provide the magical power
+ * that drives the webapp front-end.
+ */
+package org.taverna.server.master.interfaces;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java
new file mode 100644
index 0000000..fc7f881
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.localworker;
+
+import static java.lang.System.getSecurityManager;
+import static java.lang.System.setProperty;
+import static java.lang.System.setSecurityManager;
+import static java.rmi.registry.LocateRegistry.createRegistry;
+import static java.rmi.registry.LocateRegistry.getRegistry;
+import static java.rmi.registry.Registry.REGISTRY_PORT;
+import static java.util.UUID.randomUUID;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.DIR;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.URI;
+import java.net.URL;
+import java.rmi.MarshalledObject;
+import java.rmi.RMISecurityManager;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.Resource;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.taverna.server.localworker.remote.RemoteRunFactory;
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.factories.ListenerFactory;
+import org.taverna.server.master.factories.RunFactory;
+import org.taverna.server.master.interaction.InteractionFeedSupport;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.SecurityContextFactory;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+import org.taverna.server.master.notification.atom.EventDAO;
+import org.taverna.server.master.usage.UsageRecordRecorder;
+import org.taverna.server.master.utils.UsernamePrincipal;
+import org.taverna.server.master.worker.FactoryBean;
+import org.taverna.server.master.worker.RemoteRunDelegate;
+import org.taverna.server.master.worker.RunFactoryConfiguration;
+
+import uk.org.taverna.scufl2.api.io.WriterException;
+
+/**
+ * Bridge to remote runs via RMI.
+ *
+ * @author Donal Fellows
+ */
+@ManagedResource(objectName = JMX_ROOT + "Factory", description = "The factory for runs")
+public abstract class AbstractRemoteRunFactory extends RunFactoryConfiguration
+ implements ListenerFactory, RunFactory, FactoryBean {
+ /**
+ * Whether to apply stronger limitations than normal to RMI. It is
+ * recommended that this be true!
+ */
+ @Value("${rmi.localhostOnly}")
+ private boolean rmiLocalhostOnly;
+ /** The interaction host name. */
+ private String interhost;
+ /** The interaction port number. */
+ private String interport;
+ private Process registryProcess;
+ /**
+ * The interaction WebDAV location. Will be resolved before being passed to
+ * the back-end.
+ */
+ private String interwebdav;
+ /**
+ * The interaction ATOM feed location. Will be resolved before being passed
+ * to the back-end.
+ */
+ private String interfeed;
+ /** Used for doing URI resolution. */
+ @Resource(name = "webapp")
+ private UriBuilderFactory baseurifactory;
+ @Autowired
+ private InteractionFeedSupport interactionFeedSupport;
+
+ @Value("${taverna.interaction.host}")
+ void setInteractionHost(String host) {
+ if (host != null && host.equals("none"))
+ host = null;
+ interhost = host;
+ }
+
+ @Value("${taverna.interaction.port}")
+ void setInteractionPort(String port) {
+ if (port != null && port.equals("none"))
+ port = null;
+ interport = port;
+ }
+
+ @Value("${taverna.interaction.webdav_path}")
+ void setInteractionWebdav(String webdav) {
+ if (webdav != null && webdav.equals("none"))
+ webdav = null;
+ interwebdav = webdav;
+ }
+
+ @Value("${taverna.interaction.feed_path}")
+ void setInteractionFeed(String feed) {
+ if (feed != null && feed.equals("none"))
+ feed = null;
+ interfeed = feed;
+ }
+
+ @Override
+ protected void reinitRegistry() {
+ registry = null;
+ if (registryProcess != null) {
+ registryProcess.destroy();
+ registryProcess = null;
+ }
+ }
+
+ protected void initInteractionDetails(RemoteRunFactory factory)
+ throws RemoteException {
+ if (interhost != null) {
+ String feed = baseurifactory.resolve(interfeed);
+ String webdav = baseurifactory.resolve(interwebdav);
+ factory.setInteractionServiceDetails(interhost, interport, webdav,
+ feed);
+ }
+ }
+
+ protected static final Process launchSubprocess(ProcessBuilder b)
+ throws IOException {
+ Thread t = Thread.currentThread();
+ ClassLoader ccl = t.getContextClassLoader();
+ try {
+ t.setContextClassLoader(null);
+ return b.start();
+ } finally {
+ t.setContextClassLoader(ccl);
+ }
+ }
+
+ /** Get a handle to a new instance of the RMI registry. */
+ private Registry makeRegistry(int port) throws RemoteException {
+ ProcessBuilder p = new ProcessBuilder(getJavaBinary());
+ p.command().add("-jar");
+ p.command().add(getRmiRegistryJar());
+ p.command().add(Integer.toString(port));
+ p.command().add(Boolean.toString(rmiLocalhostOnly));
+ try {
+ Process proc = launchSubprocess(p);
+ Thread.sleep(getSleepTime());
+ try {
+ if (proc.exitValue() == 0)
+ return null;
+ String error = IOUtils.toString(proc.getErrorStream());
+ throw new RemoteException(error);
+ } catch (IllegalThreadStateException ise) {
+ // Still running!
+ }
+ try (ObjectInputStream ois = new ObjectInputStream(
+ proc.getInputStream())) {
+ @SuppressWarnings("unchecked")
+ Registry r = ((MarshalledObject<Registry>) ois.readObject())
+ .get();
+ registryProcess = proc;
+ return r;
+ }
+ } catch (RemoteException e) {
+ throw e;
+ } catch (ClassNotFoundException e) {
+ throw new RemoteException("unexpected registry type", e);
+ } catch (IOException e) {
+ throw new RemoteException("unexpected IO problem with registry", e);
+ } catch (InterruptedException e) {
+ throw new RemoteException("unexpected interrupt");
+ }
+ }
+
+ /**
+ * @return A handle to the current RMI registry.
+ */
+ protected Registry getTheRegistry() {
+ try {
+ if (registry != null) {
+ registry.list();
+ return registry;
+ }
+ } catch (RemoteException e) {
+ log.warn("non-functioning existing registry handle", e);
+ registry = null;
+ }
+ try {
+ registry = getRegistry(getRegistryHost(), getRegistryPort());
+ registry.list();
+ return registry;
+ } catch (RemoteException e) {
+ log.warn("Failed to get working RMI registry handle.");
+ registry = null;
+ log.warn("Will build new registry, "
+ + "but service restart ability is at risk.");
+ try {
+ registry = makeRegistry(getRegistryPort());
+ registry.list();
+ return registry;
+ } catch (RemoteException e2) {
+ log.error(
+ "failed to create local working RMI registry on port "
+ + getRegistryPort(), e2);
+ log.info("original connection exception", e);
+ }
+ }
+ try {
+ registry = getRegistry(getRegistryHost(), REGISTRY_PORT);
+ registry.list();
+ return registry;
+ } catch (RemoteException e) {
+ log.warn("Failed to get working RMI registry handle on backup port.");
+ try {
+ registry = makeRegistry(REGISTRY_PORT);
+ registry.list();
+ return registry;
+ } catch (RemoteException e2) {
+ log.fatal(
+ "totally failed to get registry handle, even on fallback!",
+ e2);
+ log.info("original connection exception", e);
+ registry = null;
+ throw new RuntimeException("No RMI Registry Available");
+ }
+ }
+ }
+
+ private Registry registry;
+ /**
+ * The name of the resource that describes the default security policy to
+ * install.
+ */
+ public static final String SECURITY_POLICY_FILE = "security.policy";
+ private SecurityContextFactory securityFactory;
+ UsageRecordRecorder usageRecordSink;
+ private EventDAO masterEventFeed;
+
+ @Autowired(required = true)
+ void setSecurityContextFactory(SecurityContextFactory factory) {
+ this.securityFactory = factory;
+ }
+
+ @Autowired(required = true)
+ void setMasterEventFeed(EventDAO masterEventFeed) {
+ this.masterEventFeed = masterEventFeed;
+ }
+
+ @Autowired(required = true)
+ void setUsageRecordSink(UsageRecordRecorder usageRecordSink) {
+ this.usageRecordSink = usageRecordSink;
+ }
+
+ /**
+ * Configures the Java security model. Not currently used, as it is
+ * viciously difficult to get right!
+ */
+ @SuppressWarnings("unused")
+ private static void installSecurityManager() {
+ if (getSecurityManager() == null) {
+ setProperty("java.security.policy", AbstractRemoteRunFactory.class
+ .getClassLoader().getResource(SECURITY_POLICY_FILE)
+ .toExternalForm());
+ setSecurityManager(new RMISecurityManager());
+ }
+ }
+
+ // static {
+ // installSecurityManager();
+ // }
+
+ /**
+ * Set up the run expiry management engine.
+ *
+ * @throws JAXBException
+ */
+ public AbstractRemoteRunFactory() throws JAXBException {
+ try {
+ registry = LocateRegistry.getRegistry();
+ registry.list();
+ } catch (RemoteException e) {
+ log.warn("Failed to get working RMI registry handle.");
+ log.warn("Will build new registry, but service restart ability is at risk.");
+ try {
+ registry = createRegistry(REGISTRY_PORT);
+ registry.list();
+ } catch (RemoteException e2) {
+ log.error("failed to create working RMI registry", e2);
+ log.info("original connection exception", e);
+ }
+ }
+ }
+
+ @Override
+ public List<String> getSupportedListenerTypes() {
+ try {
+ RemoteRunDelegate rrd = runDB.pickArbitraryRun();
+ if (rrd != null)
+ return rrd.getListenerTypes();
+ log.warn("no remote runs; no listener types");
+ } catch (Exception e) {
+ log.warn("failed to get list of listener types", e);
+ }
+ return new ArrayList<>();
+ }
+
+ @Override
+ public Listener makeListener(TavernaRun run, String listenerType,
+ String configuration) throws NoListenerException {
+ if (run instanceof RemoteRunDelegate)
+ return ((RemoteRunDelegate) run).makeListener(listenerType,
+ configuration);
+ throw new NoListenerException("unexpected run type: " + run.getClass());
+ }
+
+ @Override
+ public TavernaRun create(UsernamePrincipal creator, Workflow workflow)
+ throws NoCreateException {
+ try {
+ Date now = new Date();
+ UUID id = randomUUID();
+ RemoteSingleRun rsr = getRealRun(creator, workflow, id);
+ RemoteRunDelegate run = new RemoteRunDelegate(now, workflow, rsr,
+ state.getDefaultLifetime(), runDB, id,
+ state.getGenerateProvenance(), this);
+ run.setSecurityContext(securityFactory.create(run, creator));
+ @Nonnull
+ URI feed = interactionFeedSupport.getFeedURI(run);
+ @Nonnull
+ URL feedUrl = feed.toURL();
+ @Nonnull
+ URL webdavUrl = baseurifactory.getRunUriBuilder(run)
+ .path(DIR + "/interactions").build().toURL();
+ @Nullable
+ URL pub = interactionFeedSupport.getLocalFeedBase(feed);
+ rsr.setInteractionServiceDetails(feedUrl, webdavUrl, pub);
+ return run;
+ } catch (NoCreateException e) {
+ log.warn("failed to build run instance", e);
+ throw e;
+ } catch (Exception e) {
+ log.warn("failed to build run instance", e);
+ throw new NoCreateException("failed to build run instance", e);
+ }
+ }
+
+ /**
+ * Gets the RMI connector for a new run.
+ *
+ * @param creator
+ * Who is creating the workflow run.
+ * @param workflow
+ * What workflow are they instantiating.
+ * @param id
+ * The identity token for the run, newly minted.
+ * @return The remote interface to the run.
+ * @throws Exception
+ * Just about anything can go wrong...
+ */
+ protected abstract RemoteSingleRun getRealRun(UsernamePrincipal creator,
+ Workflow workflow, UUID id) throws Exception;
+
+ /**
+ * How to convert a wrapped workflow into XML.
+ *
+ * @param workflow
+ * The wrapped workflow.
+ * @return The XML version of the document.
+ * @throws JAXBException
+ * If serialization fails.
+ */
+ protected byte[] serializeWorkflow(Workflow workflow) throws JAXBException {
+ try {
+ return workflow.getScufl2Bytes();
+ } catch (IOException e) {
+ throw new JAXBException("problem converting to scufl2", e);
+ } catch (WriterException e) {
+ throw new JAXBException("problem converting to scufl2", e);
+ }
+ }
+
+ private void acceptUsageRecord(String usageRecord) {
+ if (usageRecordSink != null)
+ usageRecordSink.storeUsageRecord(usageRecord);
+ runDB.checkForFinishNow();
+ }
+
+ /**
+ * Make a Remote object that can act as a consumer for usage records.
+ *
+ * @param creator
+ *
+ * @return The receiver, or <tt>null</tt> if the construction fails.
+ */
+ protected UsageRecordReceiver makeURReciver(UsernamePrincipal creator) {
+ try {
+ @SuppressWarnings("serial")
+ class URReceiver extends UnicastRemoteObject implements
+ UsageRecordReceiver {
+ public URReceiver() throws RemoteException {
+ super();
+ }
+
+ @Override
+ public void acceptUsageRecord(String usageRecord) {
+ AbstractRemoteRunFactory.this.acceptUsageRecord(usageRecord);
+ }
+ }
+ return new URReceiver();
+ } catch (RemoteException e) {
+ log.warn("failed to build usage record receiver", e);
+ return null;
+ }
+ }
+
+ @Override
+ public EventDAO getMasterEventFeed() {
+ return masterEventFeed;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java
new file mode 100644
index 0000000..b67e121
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.localworker;
+
+import static java.lang.System.getProperty;
+import static java.lang.Thread.sleep;
+import static java.util.Arrays.asList;
+import static java.util.Calendar.SECOND;
+import static java.util.UUID.randomUUID;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+
+import java.io.File;
+import java.rmi.ConnectException;
+import java.rmi.ConnectIOException;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.util.Calendar;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.xml.bind.JAXBException;
+
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.taverna.server.localworker.remote.RemoteRunFactory;
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.factories.ConfigurableRunFactory;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * A simple factory for workflow runs that forks runs from a subprocess.
+ *
+ * @author Donal Fellows
+ */
+@ManagedResource(objectName = JMX_ROOT + "RunFactory", description = "The factory for simple singleton forked run.")
+public class ForkRunFactory extends AbstractRemoteRunFactory implements
+ ConfigurableRunFactory {
+ private int lastStartupCheckCount;
+ private Integer lastExitCode;
+ private RemoteRunFactory factory;
+ private Process factoryProcess;
+ private String factoryProcessName;
+
+ /**
+ * Create a factory for remote runs that works by forking off a subprocess.
+ *
+ * @throws JAXBException
+ * Shouldn't happen.
+ */
+ public ForkRunFactory() throws JAXBException {
+ }
+
+ @PostConstruct
+ protected void initRegistry() {
+ log.info("waiting for availability of default RMI registry");
+ getTheRegistry();
+ }
+
+ @Override
+ protected void reinitFactory() {
+ boolean makeFactory = factory != null;
+ killFactory();
+ try {
+ if (makeFactory)
+ initFactory();
+ } catch (Exception e) {
+ log.fatal("failed to make connection to remote run factory", e);
+ }
+ }
+
+ private RemoteRunFactory getFactory() throws RemoteException {
+ try {
+ initFactory();
+ } catch (RemoteException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RemoteException("problem constructing factory", e);
+ }
+ return factory;
+ }
+
+ /**
+ * @return How many checks were done for the worker process the last time a
+ * spawn was tried.
+ */
+ @ManagedAttribute(description = "How many checks were done for the worker process the last time a spawn was tried.", currencyTimeLimit = 60)
+ @Override
+ public int getLastStartupCheckCount() {
+ return lastStartupCheckCount;
+ }
+
+ /**
+ * @return What was the exit code from the last time the factory subprocess
+ * was killed?
+ */
+ @ManagedAttribute(description = "What was the exit code from the last time the factory subprocess was killed?")
+ @Override
+ public Integer getLastExitCode() {
+ return lastExitCode;
+ }
+
+ /**
+ * @return What the factory subprocess's main RMI interface is registered
+ * as.
+ */
+ @ManagedAttribute(description = "What the factory subprocess's main RMI interface is registered as.", currencyTimeLimit = 60)
+ @Override
+ public String getFactoryProcessName() {
+ return factoryProcessName;
+ }
+
+ /**
+ * Makes the subprocess that manufactures runs.
+ *
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ public void initFactory() throws Exception {
+ if (factory != null)
+ return;
+ // Generate the arguments to use when spawning the subprocess
+ factoryProcessName = state.getFactoryProcessNamePrefix() + randomUUID();
+ ProcessBuilder p = new ProcessBuilder(getJavaBinary());
+ p.command().add("-jar");
+ p.command().add(getServerWorkerJar());
+ if (getExecuteWorkflowScript() == null)
+ log.fatal("no execute workflow script");
+ p.command().add(getExecuteWorkflowScript());
+ p.command().addAll(asList(getExtraArguments()));
+ p.command().add(factoryProcessName);
+ p.redirectErrorStream(true);
+ p.directory(new File(getProperty("javax.servlet.context.tempdir",
+ getProperty("java.io.tmpdir"))));
+
+ // Spawn the subprocess
+ log.info("about to create subprocess: " + p.command());
+
+ factoryProcess = launchSubprocess(p);
+ outlog = new StreamLogger("FactoryStdout", factoryProcess.getInputStream()) {
+ @Override
+ protected void write(String msg) {
+ log.info(msg);
+ }
+ };
+ errlog = new StreamLogger("FactoryStderr", factoryProcess.getErrorStream()) {
+ @Override
+ protected void write(String msg) {
+ log.info(msg);
+ }
+ };
+
+ // Wait for the subprocess to register itself in the RMI registry
+ Calendar deadline = Calendar.getInstance();
+ deadline.add(SECOND, state.getWaitSeconds());
+ Exception lastException = null;
+ lastStartupCheckCount = 0;
+ while (deadline.after(Calendar.getInstance())) {
+ try {
+ sleep(state.getSleepMS());
+ lastStartupCheckCount++;
+ factory = getRemoteFactoryHandle(factoryProcessName);
+ initInteractionDetails(factory);
+ return;
+ } catch (InterruptedException ie) {
+ continue;
+ } catch (NotBoundException nbe) {
+ lastException = nbe;
+ log.info("resource \"" + factoryProcessName
+ + "\" not yet registered...");
+ continue;
+ } catch (RemoteException re) {
+ // Unpack a remote exception if we can
+ lastException = re;
+ try {
+ if (re.getCause() != null)
+ lastException = (Exception) re.getCause();
+ } catch (Throwable t) {
+ // Ignore!
+ }
+ } catch (RuntimeException e) {
+ lastException = e;
+ }
+ }
+ if (lastException == null)
+ lastException = new InterruptedException();
+ throw lastException;
+ }
+
+ private StreamLogger outlog, errlog;
+
+ private void stopLoggers() {
+ if (outlog != null)
+ outlog.stop();
+ outlog = null;
+ if (errlog != null)
+ errlog.stop();
+ errlog = null;
+ }
+
+ private RemoteRunFactory getRemoteFactoryHandle(String name)
+ throws RemoteException, NotBoundException {
+ log.info("about to look up resource called " + name);
+ try {
+ // Validate registry connection first
+ getTheRegistry().list();
+ } catch (ConnectException | ConnectIOException e) {
+ log.warn("connection problems with registry", e);
+ }
+ RemoteRunFactory rrf = (RemoteRunFactory) getTheRegistry().lookup(name);
+ log.info("successfully connected to factory subprocess "
+ + factoryProcessName);
+ return rrf;
+ }
+
+ /**
+ * Destroys the subprocess that manufactures runs.
+ */
+ @PreDestroy
+ public void killFactory() {
+ if (factory != null) {
+ log.info("requesting shutdown of " + factoryProcessName);
+ try {
+ factory.shutdown();
+ sleep(700);
+ } catch (RemoteException e) {
+ log.warn(factoryProcessName + " failed to shut down nicely", e);
+ } catch (InterruptedException e) {
+ if (log.isDebugEnabled())
+ log.debug("interrupted during wait after asking "
+ + factoryProcessName + " to shut down", e);
+ } finally {
+ factory = null;
+ }
+ }
+
+ if (factoryProcess != null) {
+ int code = -1;
+ try {
+ lastExitCode = code = factoryProcess.exitValue();
+ log.info(factoryProcessName + " already dead?");
+ } catch (RuntimeException e) {
+ log.info("trying to force death of " + factoryProcessName);
+ try {
+ factoryProcess.destroy();
+ sleep(350); // takes a little time, even normally
+ lastExitCode = code = factoryProcess.exitValue();
+ } catch (Exception e2) {
+ code = -1;
+ }
+ } finally {
+ factoryProcess = null;
+ stopLoggers();
+ }
+ if (code > 128) {
+ log.info(factoryProcessName + " died with signal="
+ + (code - 128));
+ } else if (code >= 0) {
+ log.info(factoryProcessName + " process killed: code=" + code);
+ } else {
+ log.warn(factoryProcessName + " not yet dead");
+ }
+ }
+ }
+
+ /**
+ * The real core of the run builder, factored out from its reliability
+ * support.
+ *
+ * @param creator
+ * Who created this workflow?
+ * @param wf
+ * The serialized workflow.
+ * @return The remote handle of the workflow run.
+ * @throws RemoteException
+ * If anything fails (communications error, etc.)
+ */
+ private RemoteSingleRun getRealRun(@Nonnull UsernamePrincipal creator,
+ @Nonnull byte[] wf, UUID id) throws RemoteException {
+ @Nonnull
+ String globaluser = "Unknown Person";
+ if (creator != null)
+ globaluser = creator.getName();
+ RemoteSingleRun rsr = getFactory().make(wf, globaluser,
+ makeURReciver(creator), id);
+ incrementRunCount();
+ return rsr;
+ }
+
+ @Override
+ protected RemoteSingleRun getRealRun(UsernamePrincipal creator,
+ Workflow workflow, UUID id) throws Exception {
+ @Nonnull
+ byte[] wf = serializeWorkflow(workflow);
+ for (int i = 0; i < 3; i++) {
+ initFactory();
+ try {
+ return getRealRun(creator, wf, id);
+ } catch (ConnectException | ConnectIOException e) {
+ // factory was lost; try to recreate
+ }
+ killFactory();
+ }
+ throw new NoCreateException("total failure to connect to factory "
+ + factoryProcessName + "despite attempting restart");
+ }
+
+ @Override
+ public String[] getFactoryProcessMapping() {
+ return new String[0];
+ }
+
+ @Override
+ protected int operatingCount() throws Exception {
+ return getFactory().countOperatingRuns();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java
new file mode 100644
index 0000000..e449373
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.localworker;
+
+import static java.lang.System.getProperty;
+import static java.lang.Thread.sleep;
+import static java.util.Arrays.asList;
+import static java.util.Calendar.SECOND;
+import static java.util.UUID.randomUUID;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+import static org.taverna.server.master.localworker.AbstractRemoteRunFactory.launchSubprocess;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.rmi.ConnectException;
+import java.rmi.ConnectIOException;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.annotation.Nonnull;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.annotation.Order;
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.taverna.server.localworker.remote.RemoteRunFactory;
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.factories.ConfigurableRunFactory;
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * A simple factory for workflow runs that forks runs from a subprocess.
+ *
+ * @author Donal Fellows
+ */
+@ManagedResource(objectName = JMX_ROOT + "RunFactory", description = "The factory for a user-specific forked run.")
+public class IdAwareForkRunFactory extends AbstractRemoteRunFactory implements
+ ConfigurableRunFactory {
+ private MetaFactory forker;
+ private Map<String, RemoteRunFactory> factory;
+ private Map<String, String> factoryProcessName;
+
+ /**
+ * Create a factory for remote runs that works by forking off a subprocess.
+ *
+ * @throws JAXBException
+ * Shouldn't happen.
+ */
+ public IdAwareForkRunFactory() throws JAXBException {
+ factory = new HashMap<>();
+ factoryProcessName = new HashMap<>();
+ }
+
+ @Override
+ protected void reinitFactory() {
+ boolean makeForker = forker != null;
+ try {
+ killForker();
+ } catch (Exception e) {
+ log.warn("exception when killing secure-fork process", e);
+ }
+ try {
+ if (makeForker)
+ initMetaFactory();
+ } catch (Exception e) {
+ log.fatal("failed to make secure-fork process", e);
+ }
+ }
+
+ /**
+ * @return How many checks were done for the worker process the last time a
+ * spawn was tried.
+ */
+ @Override
+ @ManagedAttribute(description = "How many checks were done for the worker process the last time a spawn was tried.", currencyTimeLimit = 60)
+ public int getLastStartupCheckCount() {
+ return forker == null ? 0 : forker.lastStartupCheckCount();
+ }
+
+ /**
+ * @return What was the exit code from the last time the factory subprocess
+ * was killed?
+ */
+ @Override
+ @ManagedAttribute(description = "What was the exit code from the last time the factory subprocess was killed?")
+ public Integer getLastExitCode() {
+ return forker == null ? null : forker.lastExitCode();
+ }
+
+ /**
+ * @return The mapping of user names to RMI factory IDs.
+ */
+ @Override
+ @ManagedAttribute(description = "The mapping of user names to RMI factory IDs.", currencyTimeLimit = 60)
+ public String[] getFactoryProcessMapping() {
+ ArrayList<String> result = new ArrayList<>();
+ ArrayList<String> keys = new ArrayList<>(factoryProcessName.keySet());
+ String[] ks = keys.toArray(new String[keys.size()]);
+ Arrays.sort(ks);
+ for (String k : ks) {
+ result.add(k);
+ result.add(factoryProcessName.get(k));
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * How construction of factories is actually done.
+ *
+ * @author Donal Fellows
+ */
+ public interface MetaFactory {
+ /**
+ * Make a factory for the given user.
+ *
+ * @param username
+ * Who to make it for.
+ * @return Handle of the factory.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ RemoteRunFactory make(String username) throws Exception;
+
+ /**
+ * Shut down the meta-factory. It is not defined whether factories
+ * created by it are also shut down at the same time.
+ *
+ * @throws IOException
+ * If something goes wrong when communicating with the
+ * meta-factory.
+ * @throws InterruptedException
+ * If something stops us waiting for the shut down to
+ * happen.
+ */
+ void close() throws IOException, InterruptedException;
+
+ int lastStartupCheckCount();
+
+ Integer lastExitCode();
+ }
+
+ void registerFactory(String username, String fpn, RemoteRunFactory f) {
+ factoryProcessName.put(username, fpn);
+ factory.put(username, f);
+ }
+
+ /**
+ * Makes the connection to the meta-factory that makes factories.
+ *
+ * @throws IOException
+ * If the connection fails.
+ */
+ @PostConstruct
+ void initMetaFactory() throws IOException {
+ log.info("waiting for availability of default RMI registry");
+ getTheRegistry();
+ log.info("constructing secure fork subprocess");
+ forker = new SecureFork(this, state, log);
+ }
+
+ private void killForker() throws IOException, InterruptedException {
+ try {
+ if (forker != null)
+ forker.close();
+ } finally {
+ forker = null;
+ }
+ }
+
+ /**
+ * Makes the subprocess that manufactures runs.
+ *
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ private void initFactory(String username) throws Exception {
+ if (factory.containsKey(username))
+ return;
+ if (forker == null)
+ initMetaFactory();
+ forker.make(username);
+ }
+
+ /**
+ * Destroys the subprocess that manufactures runs.
+ */
+ @PreDestroy
+ public void killFactories() {
+ if (!factory.isEmpty()) {
+ Iterator<String> keys = factory.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ log.info("requesting shutdown of "
+ + factoryProcessName.get(key));
+ try {
+ factory.get(key).shutdown();
+ } catch (RemoteException e) {
+ log.warn(factoryProcessName.get(key)
+ + " failed to shut down nicely", e);
+ } finally {
+ keys.remove();
+ factoryProcessName.remove(key);
+ }
+ }
+ try {
+ sleep(700);
+ } catch (InterruptedException e) {
+ if (log.isDebugEnabled())
+ log.debug("interrupted during wait after "
+ + "asking factories to shut down", e);
+ }
+ }
+
+ try {
+ killForker();
+ } catch (Exception e) {
+ if (log.isDebugEnabled())
+ log.debug("exception in shutdown of secure-fork process", e);
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ killFactories();
+ super.finalize();
+ }
+
+ @Autowired
+ public void setIdMapper(LocalIdentityMapper mapper) {
+ this.mapper = mapper;
+ }
+
+ private LocalIdentityMapper mapper;
+
+ /**
+ * The real core of the run builder, factored out from its reliability
+ * support.
+ *
+ * @param creator
+ * Who created this workflow?
+ * @param username
+ * What user account is this workflow to be executed in?
+ * @param wf
+ * The serialized workflow.
+ * @return The remote handle of the workflow run.
+ * @throws RemoteException
+ * If anything fails (communications error, etc.)
+ */
+ private RemoteSingleRun getRealRun(@Nonnull UsernamePrincipal creator,
+ @Nonnull String username, @Nonnull byte[] wf, UUID id)
+ throws RemoteException {
+ String globaluser = "Unknown Person";
+ if (creator != null)
+ globaluser = creator.getName();
+ RemoteSingleRun rsr = factory.get(username).make(wf, globaluser,
+ makeURReciver(creator), id);
+ incrementRunCount();
+ return rsr;
+ }
+
+ @Override
+ protected RemoteSingleRun getRealRun(UsernamePrincipal creator,
+ Workflow workflow, UUID id) throws Exception {
+ byte[] wf = serializeWorkflow(workflow);
+ String username = mapper == null ? null : mapper
+ .getUsernameForPrincipal(creator);
+ if (username == null)
+ throw new Exception("cannot determine who to run workflow as; "
+ + "local identity mapper returned null");
+ for (int i = 0; i < 3; i++) {
+ if (!factory.containsKey(username))
+ initFactory(username);
+ try {
+ return getRealRun(creator, username, wf, id);
+ } catch (ConnectException | ConnectIOException e) {
+ // factory was lost; try to recreate
+ }
+ factory.remove(username);
+ }
+ throw new NoCreateException("total failure to connect to factory "
+ + factoryProcessName + "despite attempting restart");
+ }
+
+ @Value("${secureForkPasswordFile}")
+ @Order(20)
+ public void setPasswordSource(String passwordSource) {
+ if (passwordSource == null || passwordSource.isEmpty()
+ || passwordSource.startsWith("${"))
+ state.setDefaultPasswordFile(null);
+ else
+ state.setDefaultPasswordFile(passwordSource);
+ if (state.getPasswordFile() == null)
+ log.info("assuming password-free forking enabled");
+ else
+ log.info("configured secureForkPasswordFile from context as "
+ + state.getPasswordFile());
+ }
+
+ @Override
+ public String getFactoryProcessName() {
+ return "<PROPERTY-NOT-SUPPORTED>";
+ }
+
+ @Override
+ protected int operatingCount() throws Exception {
+ int total = 0;
+ for (RemoteRunFactory rrf : factory.values())
+ total += rrf.countOperatingRuns();
+ return total;
+ }
+}
+
+/**
+ * The connector that handles the secure fork process itself.
+ *
+ * @author Donal Fellows
+ */
+class SecureFork implements IdAwareForkRunFactory.MetaFactory {
+ private IdAwareForkRunFactory main;
+ private Process process;
+ private PrintWriter channel;
+ private int lastStartupCheckCount;
+ private Integer lastExitCode;
+ private Log log;
+ private LocalWorkerState state;
+ private StreamLogger out, err;
+
+ /**
+ * Construct the command to run the meta-factory process.
+ *
+ * @param args
+ * The live list of arguments to pass.
+ */
+ public void initFactoryArgs(List<String> args) {
+ args.add(main.getJavaBinary());
+ String pwf = main.getPasswordFile();
+ if (pwf != null) {
+ args.add("-Dpassword.file=" + pwf);
+ }
+ args.add("-jar");
+ args.add(main.getServerForkerJar());
+ args.add(main.getJavaBinary());
+ args.add("-jar");
+ args.add(main.getServerWorkerJar());
+ if (main.getExecuteWorkflowScript() == null)
+ log.fatal("no execute workflow script");
+ args.add(main.getExecuteWorkflowScript());
+ args.addAll(asList(main.getExtraArguments()));
+ }
+
+ SecureFork(IdAwareForkRunFactory main, LocalWorkerState state, Log log)
+ throws IOException {
+ this.main = main;
+ this.log = log;
+ this.state = state;
+ ProcessBuilder p = new ProcessBuilder();
+ initFactoryArgs(p.command());
+ p.redirectErrorStream(true);
+ p.directory(new File(getProperty("javax.servlet.context.tempdir",
+ getProperty("java.io.tmpdir"))));
+
+ // Spawn the subprocess
+ log.info("about to create subprocess: " + p.command());
+ log.info("subprocess directory: " + p.directory());
+ process = launchSubprocess(p);
+ channel = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
+ process.getOutputStream())), true);
+ // Log the responses
+ out = new StreamLogger("ForkedStdout", process.getInputStream()) {
+ @Override
+ protected void write(String msg) {
+ log.info(msg);
+ }
+ };
+ err = new StreamLogger("ForkedStderr", process.getErrorStream()) {
+ @Override
+ protected void write(String msg) {
+ log.info(msg);
+ }
+ };
+ }
+
+ @Override
+ public void close() throws IOException, InterruptedException {
+ try {
+ if (process != null) {
+ log.info("about to close down subprocess");
+ channel.close();
+ int code = -1;
+ try {
+ try {
+ code = process.exitValue();
+ log.info("secure-fork process already dead?");
+ } catch (IllegalThreadStateException e) {
+ try {
+ code = process.waitFor();
+ } catch (InterruptedException e1) {
+ log.info("interrupted waiting for natural death of secure-fork process?!");
+ process.destroy();
+ code = process.waitFor();
+ }
+ }
+ } finally {
+ lastExitCode = code;
+ if (code > 128) {
+ log.info("secure-fork process died with signal="
+ + (code - 128));
+ } else if (code >= 0) {
+ log.info("secure-fork process killed: code=" + code);
+ } else {
+ log.warn("secure-fork process not yet dead");
+ }
+ }
+ }
+ } finally {
+ process = null;
+ channel = null;
+ out.stop();
+ err.stop();
+ }
+ }
+
+ protected void make(String username, String fpn) {
+ log.info("about to request subprocess creation for " + username
+ + " producing ID " + fpn);
+ channel.println(username + " " + fpn);
+ }
+
+ @Override
+ public RemoteRunFactory make(String username) throws Exception {
+ try {
+ main.getTheRegistry().list(); // Validate registry connection first
+ } catch (ConnectException | ConnectIOException e) {
+ log.warn("connection problems with registry", e);
+ } catch (RemoteException e) {
+ if (e.getCause() != null && e.getCause() instanceof Exception) {
+ throw (Exception) e.getCause();
+ }
+ log.warn("connection problems with registry", e);
+ }
+
+ String fpn = state.getFactoryProcessNamePrefix() + randomUUID();
+ make(username, fpn);
+
+ // Wait for the subprocess to register itself in the RMI registry
+ Calendar deadline = Calendar.getInstance();
+ deadline.add(SECOND, state.getWaitSeconds());
+ Exception lastException = null;
+ lastStartupCheckCount = 0;
+ while (deadline.after(Calendar.getInstance())) {
+ try {
+ sleep(state.getSleepMS());
+ lastStartupCheckCount++;
+ log.info("about to look up resource called " + fpn);
+ RemoteRunFactory f = (RemoteRunFactory) main.getTheRegistry()
+ .lookup(fpn);
+ log.info("successfully connected to factory subprocess " + fpn);
+ main.initInteractionDetails(f);
+ main.registerFactory(username, fpn, f);
+ return f;
+ } catch (InterruptedException ie) {
+ continue;
+ } catch (NotBoundException nbe) {
+ lastException = nbe;
+ log.info("resource \"" + fpn + "\" not yet registered...");
+ continue;
+ } catch (RemoteException re) {
+ // Unpack a remote exception if we can
+ lastException = re;
+ try {
+ if (re.getCause() != null)
+ lastException = (Exception) re.getCause();
+ } catch (Throwable t) {
+ // Ignore!
+ }
+ } catch (Exception e) {
+ lastException = e;
+ }
+ }
+ if (lastException == null)
+ lastException = new InterruptedException();
+ throw lastException;
+ }
+
+ @Override
+ public Integer lastExitCode() {
+ return lastExitCode;
+ }
+
+ @Override
+ public int lastStartupCheckCount() {
+ return lastStartupCheckCount;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java
new file mode 100644
index 0000000..f890204
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.localworker;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Provider of the configuration of the "localworker.factory" bean, which is
+ * sufficiently complex to be too hard to manufacture directly from the XML
+ * configuration.
+ *
+ * @author Donal Fellows
+ */
+@Configuration
+public class LocalWorkerFactory {
+ @Bean(name = "localworker.factory")
+ AbstractRemoteRunFactory getLocalworkerFactory(
+ @Value("${backEndFactory}") String mode) throws Exception {
+ if (mode == null || mode.isEmpty() || mode.startsWith("${"))
+ throw new Exception("no value for ${backEndFactory}");
+ Class<?> c = Class.forName(mode);
+ if (AbstractRemoteRunFactory.class.isAssignableFrom(c))
+ return (AbstractRemoteRunFactory) c.newInstance();
+ throw new Exception("unknown remote run factory: " + mode);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java
new file mode 100644
index 0000000..9f0f39b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.localworker;
+
+import static java.io.File.separator;
+import static java.lang.System.getProperty;
+import static java.rmi.registry.Registry.REGISTRY_PORT;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static org.taverna.server.master.defaults.Default.EXTRA_ARGUMENTS;
+import static org.taverna.server.master.defaults.Default.PASSWORD_FILE;
+import static org.taverna.server.master.defaults.Default.REGISTRY_JAR;
+import static org.taverna.server.master.defaults.Default.RMI_PREFIX;
+import static org.taverna.server.master.defaults.Default.RUN_LIFE_MINUTES;
+import static org.taverna.server.master.defaults.Default.RUN_OPERATING_LIMIT;
+import static org.taverna.server.master.defaults.Default.SECURE_FORK_IMPLEMENTATION_JAR;
+import static org.taverna.server.master.defaults.Default.SERVER_WORKER_IMPLEMENTATION_JAR;
+import static org.taverna.server.master.defaults.Default.SUBPROCESS_START_POLL_SLEEP;
+import static org.taverna.server.master.defaults.Default.SUBPROCESS_START_WAIT;
+import static org.taverna.server.master.localworker.PersistedState.KEY;
+import static org.taverna.server.master.localworker.PersistedState.makeInstance;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.URI;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.jdo.annotations.PersistenceAware;
+
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.defaults.Default;
+import org.taverna.server.master.utils.JDOSupport;
+import org.taverna.server.master.worker.WorkerModel;
+
+/**
+ * The persistent state of a local worker factory.
+ *
+ * @author Donal Fellows
+ */
+@PersistenceAware
+public class LocalWorkerState extends JDOSupport<PersistedState> implements
+ WorkerModel {
+ public LocalWorkerState() {
+ super(PersistedState.class);
+ }
+
+ private LocalWorkerState self;
+
+ @Required
+ public void setSelf(LocalWorkerState self) {
+ this.self = self;
+ }
+
+ /** Initial lifetime of runs, in minutes. */
+ int defaultLifetime;
+ /**
+ * Maximum number of runs to exist at once. Note that this includes when
+ * they are just existing for the purposes of file transfer (
+ * {@link Status#Initialized}/{@link Status#Finished} states).
+ */
+ int maxRuns;
+ /**
+ * Prefix to use for RMI names.
+ */
+ String factoryProcessNamePrefix;
+ /**
+ * Full path name of the script used to start running a workflow; normally
+ * expected to be "<i>somewhere/</i><tt>executeWorkflow.sh</tt>".
+ */
+ String executeWorkflowScript;
+ /** Default value for {@link #executeWorkflowScript}. */
+ private transient String defaultExecuteWorkflowScript;
+ /**
+ * Full path name of the file containing the password used to launch workers
+ * as other users. The file is normally expected to contain a single line,
+ * the password, and to be thoroughly locked down so only the user running
+ * the server (e.g., "<tt>tomcat</tt>") can read it; it will probably reside
+ * in either the user's home directory or in a system configuration
+ * directory.
+ */
+ String passwordFile;
+ /** Default value for {@link #passwordFile}. */
+ private transient String defaultPasswordFile = PASSWORD_FILE;
+ /**
+ * The extra arguments to pass to the subprocess.
+ */
+ String[] extraArgs;
+ /**
+ * How long to wait for subprocess startup, in seconds.
+ */
+ int waitSeconds;
+ /**
+ * Polling interval to use during startup, in milliseconds.
+ */
+ int sleepMS;
+ /**
+ * Full path name to the worker process's implementation JAR.
+ */
+ String serverWorkerJar;
+ private static final String DEFAULT_WORKER_JAR = LocalWorkerState.class
+ .getClassLoader().getResource(SERVER_WORKER_IMPLEMENTATION_JAR)
+ .getFile();
+ /**
+ * Full path name to the Java binary to use to run the subprocess.
+ */
+ String javaBinary;
+ private static final String DEFAULT_JAVA_BINARY = getProperty("java.home")
+ + separator + "bin" + separator + "java";
+ /**
+ * Full path name to the secure fork process's implementation JAR.
+ */
+ String serverForkerJar;
+ private static final String DEFAULT_FORKER_JAR = LocalWorkerState.class
+ .getClassLoader().getResource(SECURE_FORK_IMPLEMENTATION_JAR)
+ .getFile();
+
+ String registryHost;
+ int registryPort;
+
+ int operatingLimit;
+
+ URI[] permittedWorkflows;
+ private String registryJar;
+ private static final String DEFAULT_REGISTRY_JAR = LocalWorkerState.class
+ .getClassLoader().getResource(REGISTRY_JAR).getFile();
+
+ @Override
+ public void setDefaultLifetime(int defaultLifetime) {
+ this.defaultLifetime = defaultLifetime;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public int getDefaultLifetime() {
+ return defaultLifetime < 1 ? RUN_LIFE_MINUTES : defaultLifetime;
+ }
+
+ @Override
+ public void setMaxRuns(int maxRuns) {
+ this.maxRuns = maxRuns;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public int getMaxRuns() {
+ return maxRuns < 1 ? Default.RUN_COUNT_MAX : maxRuns;
+ }
+
+ @Override
+ public int getOperatingLimit() {
+ return operatingLimit < 1 ? RUN_OPERATING_LIMIT : operatingLimit;
+ }
+
+ @Override
+ public void setOperatingLimit(int operatingLimit) {
+ this.operatingLimit = operatingLimit;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public void setFactoryProcessNamePrefix(String factoryProcessNamePrefix) {
+ this.factoryProcessNamePrefix = factoryProcessNamePrefix;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getFactoryProcessNamePrefix() {
+ return factoryProcessNamePrefix == null ? RMI_PREFIX
+ : factoryProcessNamePrefix;
+ }
+
+ @Override
+ public void setExecuteWorkflowScript(String executeWorkflowScript) {
+ this.executeWorkflowScript = executeWorkflowScript;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getExecuteWorkflowScript() {
+ return executeWorkflowScript == null ? defaultExecuteWorkflowScript
+ : executeWorkflowScript;
+ }
+
+ private static String guessWorkflowScript() {
+ File utilDir = new File(DEFAULT_WORKER_JAR).getParentFile();
+ File[] dirs = utilDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("taverna-commandline-");
+ }
+ });
+ assert dirs.length > 0;
+ return new File(dirs[0], "executeworkflow.sh").toString();
+ }
+
+ /**
+ * Set what executeworkflow script to use by default. This is the value that
+ * is used if not overridden by the administration interface.
+ *
+ * @param defaultScript
+ * Full path to the script to use.
+ */
+ public void setDefaultExecuteWorkflowScript(String defaultScript) {
+ if (defaultScript.startsWith("${") || defaultScript.equals("NONE")) {
+ this.defaultExecuteWorkflowScript = guessWorkflowScript();
+ return;
+ }
+ this.defaultExecuteWorkflowScript = defaultScript;
+ }
+
+ String getDefaultExecuteWorkflowScript() {
+ return defaultExecuteWorkflowScript;
+ }
+
+ @Override
+ public void setExtraArgs(String[] extraArgs) {
+ this.extraArgs = extraArgs.clone();
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String[] getExtraArgs() {
+ return extraArgs == null ? EXTRA_ARGUMENTS : extraArgs.clone();
+ }
+
+ @Override
+ public void setWaitSeconds(int waitSeconds) {
+ this.waitSeconds = waitSeconds;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public int getWaitSeconds() {
+ return waitSeconds < 1 ? SUBPROCESS_START_WAIT : waitSeconds;
+ }
+
+ @Override
+ public void setSleepMS(int sleepMS) {
+ this.sleepMS = sleepMS;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public int getSleepMS() {
+ return sleepMS < 1 ? SUBPROCESS_START_POLL_SLEEP : sleepMS;
+ }
+
+ @Override
+ public void setServerWorkerJar(String serverWorkerJar) {
+ this.serverWorkerJar = serverWorkerJar;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getServerWorkerJar() {
+ return serverWorkerJar == null ? DEFAULT_WORKER_JAR : serverWorkerJar;
+ }
+
+ @Override
+ public void setServerForkerJar(String serverForkerJar) {
+ this.serverForkerJar = serverForkerJar;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getServerForkerJar() {
+ return serverForkerJar == null ? DEFAULT_FORKER_JAR : serverForkerJar;
+ }
+
+ @Override
+ public void setJavaBinary(String javaBinary) {
+ this.javaBinary = javaBinary;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getJavaBinary() {
+ return javaBinary == null ? DEFAULT_JAVA_BINARY : javaBinary;
+ }
+
+ @Override
+ public void setPasswordFile(String passwordFile) {
+ this.passwordFile = passwordFile;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getPasswordFile() {
+ return passwordFile == null ? defaultPasswordFile : passwordFile;
+ }
+
+ void setDefaultPasswordFile(String defaultPasswordFile) {
+ this.defaultPasswordFile = defaultPasswordFile;
+ }
+
+ @Override
+ public void setRegistryHost(String registryHost) {
+ this.registryHost = (registryHost == null ? "" : registryHost);
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public String getRegistryHost() {
+ return (registryHost == null || registryHost.isEmpty()) ? null
+ : registryHost;
+ }
+
+ @Override
+ public void setRegistryPort(int registryPort) {
+ this.registryPort = ((registryPort < 1 || registryPort > 65534) ? REGISTRY_PORT
+ : registryPort);
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public int getRegistryPort() {
+ return registryPort == 0 ? REGISTRY_PORT : registryPort;
+ }
+
+ @Override
+ public String getRegistryJar() {
+ return registryJar == null ? DEFAULT_REGISTRY_JAR : registryJar;
+ }
+
+ @Override
+ public void setRegistryJar(String rmiRegistryJar) {
+ this.registryJar = (rmiRegistryJar == null || rmiRegistryJar.isEmpty()) ? null
+ : rmiRegistryJar;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public List<URI> getPermittedWorkflowURIs() {
+ if (permittedWorkflows == null || permittedWorkflows.length == 0)
+ return emptyList();
+ return unmodifiableList(asList(permittedWorkflows));
+ }
+
+ @Override
+ public void setPermittedWorkflowURIs(List<URI> permittedWorkflows) {
+ if (permittedWorkflows == null || permittedWorkflows.isEmpty())
+ this.permittedWorkflows = new URI[0];
+ else
+ this.permittedWorkflows = permittedWorkflows
+ .toArray(new URI[permittedWorkflows.size()]);
+ if (loadedState)
+ self.store();
+ }
+
+ public static final boolean DEFAULT_GENERATE_PROVENANCE = false;
+ private Boolean generateProvenance;
+
+ @Override
+ public boolean getGenerateProvenance() {
+ Boolean g = generateProvenance;
+ return g == null ? DEFAULT_GENERATE_PROVENANCE : (boolean) g;
+ }
+
+ @Override
+ public void setGenerateProvenance(boolean generate) {
+ this.generateProvenance = generate;
+ if (loadedState)
+ self.store();
+ }
+
+ // --------------------------------------------------------------
+
+ private boolean loadedState;
+
+ @PostConstruct
+ @WithinSingleTransaction
+ public void load() {
+ if (loadedState || !isPersistent())
+ return;
+ WorkerModel state = getById(KEY);
+ if (state == null) {
+ store();
+ return;
+ }
+
+ defaultLifetime = state.getDefaultLifetime();
+ executeWorkflowScript = state.getExecuteWorkflowScript();
+ extraArgs = state.getExtraArgs();
+ factoryProcessNamePrefix = state.getFactoryProcessNamePrefix();
+ javaBinary = state.getJavaBinary();
+ maxRuns = state.getMaxRuns();
+ serverWorkerJar = state.getServerWorkerJar();
+ serverForkerJar = state.getServerForkerJar();
+ passwordFile = state.getPasswordFile();
+ sleepMS = state.getSleepMS();
+ waitSeconds = state.getWaitSeconds();
+ registryHost = state.getRegistryHost();
+ registryPort = state.getRegistryPort();
+ operatingLimit = state.getOperatingLimit();
+ List<URI> pwu = state.getPermittedWorkflowURIs();
+ permittedWorkflows = (URI[]) pwu.toArray(new URI[pwu.size()]);
+ registryJar = state.getRegistryJar();
+ generateProvenance = state.getGenerateProvenance();
+
+ loadedState = true;
+ }
+
+ @WithinSingleTransaction
+ public void store() {
+ if (!isPersistent())
+ return;
+ WorkerModel state = getById(KEY);
+ if (state == null)
+ state = persist(makeInstance());
+
+ state.setDefaultLifetime(defaultLifetime);
+ state.setExecuteWorkflowScript(executeWorkflowScript);
+ state.setExtraArgs(extraArgs);
+ state.setFactoryProcessNamePrefix(factoryProcessNamePrefix);
+ state.setJavaBinary(javaBinary);
+ state.setMaxRuns(maxRuns);
+ state.setServerWorkerJar(serverWorkerJar);
+ state.setServerForkerJar(serverForkerJar);
+ state.setPasswordFile(passwordFile);
+ state.setSleepMS(sleepMS);
+ state.setWaitSeconds(waitSeconds);
+ state.setRegistryHost(registryHost);
+ state.setRegistryPort(registryPort);
+ state.setOperatingLimit(operatingLimit);
+ if (permittedWorkflows != null)
+ state.setPermittedWorkflowURIs(asList(permittedWorkflows));
+ state.setRegistryJar(registryJar);
+ if (generateProvenance != null)
+ state.setGenerateProvenance(generateProvenance);
+
+ loadedState = true;
+ }
+}
\ 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/localworker/PersistedState.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java
new file mode 100644
index 0000000..83d6bda
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.localworker;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jdo.annotations.Join;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+
+import org.taverna.server.master.worker.WorkerModel;
+
+/**
+ * The actual database connector for persisted local worker state.
+ *
+ * @author Donal Fellows
+ */
+/*
+ * WARNING! If you change the name of this class, update persistence.xml as
+ * well!
+ */
+@PersistenceCapable(table = PersistedState.TABLE)
+class PersistedState implements WorkerModel {
+ static final String TABLE = "LOCALWORKERSTATE__PERSISTEDSTATE";
+
+ static PersistedState makeInstance() {
+ PersistedState o = new PersistedState();
+ o.ID = KEY;
+ return o;
+ }
+
+ @PrimaryKey(column = "ID")
+ protected int ID;
+
+ static final int KEY = 32;
+
+ @Persistent
+ private int defaultLifetime;
+ @Persistent
+ private int maxRuns;
+ @Persistent
+ private String factoryProcessNamePrefix;
+ @Persistent
+ private String executeWorkflowScript;
+ @Persistent(serialized = "true")
+ private String[] extraArgs;
+ @Persistent
+ private int waitSeconds;
+ @Persistent
+ private int sleepMS;
+ @Persistent
+ private String serverWorkerJar;
+ @Persistent
+ private String serverForkerJar;
+ @Persistent
+ private String registryJar;
+ @Persistent
+ private String passwordFile;
+ @Persistent
+ private String javaBinary;
+ @Persistent
+ private int registryPort;
+ @Persistent
+ private String registryHost;
+ @Persistent
+ private int operatingLimit;
+ @Persistent(defaultFetchGroup = "true")
+ @Join(table = TABLE + "_PERMWFURI", column = "ID")
+ private String[] permittedWorkflows;
+ @Persistent
+ private int generateProvenance;
+
+ @Override
+ public void setDefaultLifetime(int defaultLifetime) {
+ this.defaultLifetime = defaultLifetime;
+ }
+
+ @Override
+ public int getDefaultLifetime() {
+ return defaultLifetime;
+ }
+
+ @Override
+ public void setMaxRuns(int maxRuns) {
+ this.maxRuns = maxRuns;
+ }
+
+ @Override
+ public int getMaxRuns() {
+ return maxRuns;
+ }
+
+ @Override
+ public void setFactoryProcessNamePrefix(String factoryProcessNamePrefix) {
+ this.factoryProcessNamePrefix = factoryProcessNamePrefix;
+ }
+
+ @Override
+ public String getFactoryProcessNamePrefix() {
+ return factoryProcessNamePrefix;
+ }
+
+ @Override
+ public void setExecuteWorkflowScript(String executeWorkflowScript) {
+ this.executeWorkflowScript = executeWorkflowScript;
+ }
+
+ @Override
+ public String getExecuteWorkflowScript() {
+ return executeWorkflowScript;
+ }
+
+ @Override
+ public void setExtraArgs(String[] extraArgs) {
+ this.extraArgs = extraArgs;
+ }
+
+ @Override
+ public String[] getExtraArgs() {
+ return extraArgs;
+ }
+
+ @Override
+ public void setWaitSeconds(int waitSeconds) {
+ this.waitSeconds = waitSeconds;
+ }
+
+ @Override
+ public int getWaitSeconds() {
+ return waitSeconds;
+ }
+
+ @Override
+ public void setSleepMS(int sleepMS) {
+ this.sleepMS = sleepMS;
+ }
+
+ @Override
+ public int getSleepMS() {
+ return sleepMS;
+ }
+
+ @Override
+ public void setServerWorkerJar(String serverWorkerJar) {
+ this.serverWorkerJar = serverWorkerJar;
+ }
+
+ @Override
+ public String getServerWorkerJar() {
+ return serverWorkerJar;
+ }
+
+ @Override
+ public void setJavaBinary(String javaBinary) {
+ this.javaBinary = javaBinary;
+ }
+
+ @Override
+ public String getJavaBinary() {
+ return javaBinary;
+ }
+
+ @Override
+ public void setRegistryPort(int registryPort) {
+ this.registryPort = registryPort;
+ }
+
+ @Override
+ public int getRegistryPort() {
+ return registryPort;
+ }
+
+ @Override
+ public void setRegistryHost(String registryHost) {
+ this.registryHost = registryHost;
+ }
+
+ @Override
+ public String getRegistryHost() {
+ return registryHost;
+ }
+
+ @Override
+ public void setServerForkerJar(String serverForkerJar) {
+ this.serverForkerJar = serverForkerJar;
+ }
+
+ @Override
+ public String getServerForkerJar() {
+ return serverForkerJar;
+ }
+
+ @Override
+ public void setPasswordFile(String passwordFile) {
+ this.passwordFile = passwordFile;
+ }
+
+ @Override
+ public String getPasswordFile() {
+ return passwordFile;
+ }
+
+ @Override
+ public void setOperatingLimit(int operatingLimit) {
+ this.operatingLimit = operatingLimit;
+ }
+
+ @Override
+ public int getOperatingLimit() {
+ return operatingLimit;
+ }
+
+ @Override
+ public List<URI> getPermittedWorkflowURIs() {
+ String[] pw = this.permittedWorkflows;
+ if (pw == null)
+ return new ArrayList<>();
+ List<URI> uris = new ArrayList<>(pw.length);
+ for (String uri : pw)
+ uris.add(URI.create(uri));
+ return uris;
+ }
+
+ @Override
+ public void setPermittedWorkflowURIs(List<URI> permittedWorkflows) {
+ String[] pw = new String[permittedWorkflows.size()];
+ for (int i = 0; i < pw.length; i++)
+ pw[i] = permittedWorkflows.get(i).toString();
+ this.permittedWorkflows = pw;
+ }
+
+ @Override
+ public String getRegistryJar() {
+ return registryJar;
+ }
+
+ @Override
+ public void setRegistryJar(String registryJar) {
+ this.registryJar = registryJar;
+ }
+
+ @Override
+ public boolean getGenerateProvenance() {
+ return generateProvenance > 0;
+ }
+
+ @Override
+ public void setGenerateProvenance(boolean generateProvenance) {
+ this.generateProvenance = (generateProvenance ? 1 : 0);
+ }
+}
\ 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/localworker/StreamLogger.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java
new file mode 100644
index 0000000..f361e17
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java
@@ -0,0 +1,62 @@
+package org.taverna.server.master.localworker;
+
+import static java.lang.Thread.interrupted;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.commons.logging.Log;
+
+abstract class StreamLogger {
+ protected final Log log;
+ private Thread t;
+ private InputStream in;
+
+ protected StreamLogger(final String name, InputStream is) {
+ log = getLog("Taverna.Server.LocalWorker." + name);
+ in = is;
+ t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try (BufferedReader br = new BufferedReader(
+ new InputStreamReader(in))) {
+ String line;
+ while (!interrupted() && (line = br.readLine()) != null)
+ if (!line.isEmpty())
+ write(line);
+ } catch (IOException e) {
+ // Do nothing...
+ } catch (Exception e) {
+ log.warn("failure in reading from " + name, e);
+ }
+ }
+ }, name + ".StreamLogger");
+ t.setContextClassLoader(null);
+ t.setDaemon(true);
+ t.start();
+ }
+
+ /**
+ * Write a line read from the subprocess to the log.
+ * <p>
+ * This needs to be implemented by subclasses in order for the log to be
+ * correctly written with the class name.
+ *
+ * @param msg
+ * The message to write. Guaranteed to have no newline characters
+ * in it and to be non-empty.
+ */
+ protected abstract void write(String msg);
+
+ public void stop() {
+ log.info("trying to close down " + t.getName());
+ t.interrupt();
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java
new file mode 100644
index 0000000..7139dd7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Implementation of a Taverna Server back-end that works by forking off
+ * workflow executors on the local system.
+ */
+package org.taverna.server.master.localworker;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java
new file mode 100644
index 0000000..3e27806
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.notification;
+
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.mail.MailSender;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+
+/**
+ * How to send a plain text message by email to someone.
+ *
+ * @author Donal Fellows
+ */
+public class EmailDispatcher extends RateLimitedDispatcher {
+ @Override
+ public String getName() {
+ return "mailto";
+ }
+
+ /**
+ * @param from
+ * Email address that the notification is to come from.
+ */
+ @Required
+ public void setFrom(String from) {
+ this.from = valid(from, "");
+ }
+
+ /**
+ * @param host
+ * The outgoing SMTP server address.
+ */
+ @Required
+ public void setSmtpHost(String host) {
+ this.host = valid(host, "");
+ }
+
+ /**
+ * @param contentType
+ * The content type of the message to be sent. For example, "
+ * <tt>text/plain</tt>".
+ */
+ public void setMessageContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ /**
+ * @param sender
+ * the sender to set
+ */
+ public void setSender(MailSender sender) {
+ this.sender = sender;
+ }
+
+ private String from;
+ private String host;
+ private MailSender sender;
+ @SuppressWarnings("unused")
+ private String contentType = TEXT_PLAIN;
+
+ /**
+ * Try to perform the lookup of the email service. This is called during
+ * configuration so that any failure happens at a useful, predictable time.
+ */
+ @PostConstruct
+ public void tryLookup() {
+ if (!isAvailable()) {
+ log.warn("no mail support; disabling email dispatch");
+ sender = null;
+ return;
+ }
+ try {
+ if (sender instanceof JavaMailSender)
+ ((JavaMailSender) sender).createMimeMessage();
+ } catch (Throwable t) {
+ log.warn("sender having problems constructing messages; "
+ + "disabling...", t);
+ sender = null;
+ }
+ }
+
+ @Override
+ public void dispatch(String messageSubject, String messageContent, String to)
+ throws Exception {
+ // Simple checks for acceptability
+ if (!to.matches(".+@.+")) {
+ log.info("did not send email notification: improper email address \""
+ + to + "\"");
+ return;
+ }
+
+ SimpleMailMessage message = new SimpleMailMessage();
+ message.setFrom(from);
+ message.setTo(to.trim());
+ message.setSubject(messageSubject);
+ message.setText(messageContent);
+ sender.send(message);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return (host != null && !host.isEmpty() && sender != null
+ && from != null && !from.isEmpty());
+ }
+}
[18/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
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
[27/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png b/server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png
deleted file mode 100644
index c664c51..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_diagonals-small_25_c5ddfc_40x40.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png b/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png
deleted file mode 100644
index 6aed97a..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_20_e69700_40x40.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png b/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png
deleted file mode 100644
index 43ba34e..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_22_1484e6_40x40.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png b/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png
deleted file mode 100644
index 68306d1..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_diagonals-thick_26_2293f7_40x40.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png b/server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png
deleted file mode 100644
index f567c28..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_flat_0_e69700_40x100.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png b/server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png
deleted file mode 100644
index 5c5494f..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_flat_0_e6b900_40x100.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png b/server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png
deleted file mode 100644
index 9a46d19..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_highlight-soft_100_f9f9f9_1x100.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png b/server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png
deleted file mode 100644
index f811f30..0000000
Binary files a/server-webapp/src/main/resources/static/ui-bg_inset-hard_100_eeeeee_1x100.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png b/server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png
deleted file mode 100644
index 755fe99..0000000
Binary files a/server-webapp/src/main/resources/static/ui-icons_0a82eb_256x240.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png b/server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png
deleted file mode 100644
index 98705f9..0000000
Binary files a/server-webapp/src/main/resources/static/ui-icons_0b54d5_256x240.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png b/server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png
deleted file mode 100644
index 3f67eca..0000000
Binary files a/server-webapp/src/main/resources/static/ui-icons_5fa5e3_256x240.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png b/server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png
deleted file mode 100644
index de76ce2..0000000
Binary files a/server-webapp/src/main/resources/static/ui-icons_fcdd4a_256x240.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png b/server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png
deleted file mode 100644
index 42f8f99..0000000
Binary files a/server-webapp/src/main/resources/static/ui-icons_ffffff_256x240.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/version.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/version.properties b/server-webapp/src/main/resources/version.properties
deleted file mode 100644
index 7ddb7d3..0000000
--- a/server-webapp/src/main/resources/version.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-# What is the version of the server? Bind this in automatically.
-tavernaserver.version=${project.version}
-tavernaserver.revision.describe=${git.commit.id.describe}
-tavernaserver.branch=${git.branch}
-tavernaserver.timestamp=${git.build.time}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/welcome.html
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/welcome.html b/server-webapp/src/main/resources/welcome.html
deleted file mode 100644
index f80da4a..0000000
--- a/server-webapp/src/main/resources/welcome.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
-<title>Taverna Server %{VERSION}</title>
-</head>
-<body>
-<h1>Taverna Server %{VERSION}</h1>
-<div style="text-align;center">
- <p>
- <i>Note that this is a pre-release version. Significant known
- issues remain open and it is not guaranteed that the service API
- will be stable.</i>
- </p>
-</div>
-<p>For a full list of operations, see the <a
- href="%{BASEURL}/services">service listing</a> generated by Apache
-CXF, which indicates where to access the WSDL and WADL descriptions of
-the T2Server interface.</p>
-<p>What follows below is a simple guide to using the server. It does
-<i>not</i> cover all the features; a much more extensive guide is available on
-<a href="http://www.mygrid.org.uk/dev/wiki/display/taverna/Taverna+Server+2.4"
->the myGrid website</a>.</p>
-<h2>5 Minute Guide to Using the REST API</h2>
-<p>Taverna Server %{VERSION} supports both REST and SOAP APIs; you may use either API
-to access the service and any of the workflow runs hosted by the service. This
-simple guide just discusses the REST API.</p>
-<ol>
- <li>
- <p>The client starts by creating a workflow run. This is done by POSTing a
- T2flow document to the service at the address <tt>%{BASEURL}/rest/runs</tt>
- with the content type <tt>application/vnd.taverna.t2flow+xml</tt>.</p>
- <p>The result of the POST is an <tt>HTTP 201 Created</tt> that gives the
- location of the created run (in a <tt>Location</tt> header),
- <tt>%{BASEURL}/rest/runs/<b>UUID</b></tt> (where <tt><b>UUID</b></tt> is a
- unique string that identifies the particular run; this is also the name of
- the run that you would use in the SOAP interface). Note that the run is not
- yet actually doing anything.</p>
- </li>
- <li>
- <p>Next, you need to set up the inputs to the workflow ports. To set the
- input port, <tt><b>FOO</b></tt>, to have the value <tt><b>BAR</b></tt>, you
- would PUT a message like this to the URI
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/input/input/<b>FOO</b></tt>
- </p>
- <blockquote><pre><t2sr:runInput xmlns:t2sr="http://ns.taverna.org.uk/2010/xml/server/rest/">
- <t2sr:value><b>BAR</b></t2sr:value>
-</t2sr:runInput></pre></blockquote>
- </li>
- <li>
- <p>Now you can start the file running. This is done by using a PUT to set
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/status</tt> to the plain text value
- <tt>Operating</tt>.</p>
- </li>
- <li>
- <p>Now you need to poll, waiting for the workflow to finish. To discover the
- state of a run, you can (at any time) do a GET on
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/status</tt>; when the workflow has
- finished executing, this will return <tt>Finished</tt> instead of
- <tt>Operating</tt> (or <tt>Initialized</tt>, the starting state).</p>
- </li>
- <li>
- <p>Every workflow run has an expiry time, after which it will be destroyed
- and all resources (i.e., local files) associated with it cleaned up. By
- default in this release, this is 20 minutes after initial creation. To see
- when a particular run is scheduled to be disposed of, do a GET on
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/expiry</tt>; you may set the time when
- the run is disposed of by PUTting a new time to that same URI. Note that
- this includes not just the time when the workflow is executing, but also
- when the input files are being created beforehand and when the results are
- being downloaded afterwards; you are advised to make your clients regularly
- advance the expiry time while the run is in use.</p>
- </li>
- <li>
- <p>The outputs from the workflow are files created in the <tt>out</tt>
- subdirectory of the run's working directory. The contents of the
- subdirectory can be read by doing a GET on
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/wd/out</tt> which will return an XML
- document describing the contents of the directory, with links to each of the
- files within it. Doing a GET on those links will retrieve the actual created
- files (as uninterpreted binary data).</p>
- <p>Thus, if a single output <tt><b>FOO.OUT</b></tt> was produced from the
- workflow, it would be written to the file that can be retrieved from
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/wd/out/<b>FOO.OUT</b></tt> and the
- result of the GET on <tt>%{BASEURL}/rest/runs/<b>UUID</b>/wd/out</tt> would
- look something like this:</p>
- <blockquote><pre><t2sr:directoryContents xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:t2sr="http://ns.taverna.org.uk/2010/xml/server/rest"
- xmlns:t2s="http://ns.taverna.org.uk/2010/xml/server/">
- <t2s:file xlink:href="%{BASEURL}/rest/runs/<b>UUID</b>/wd/out/<b>FOO.OUT</b>"
- t2sr:name="<b>FOO.OUT</b>">out/<b>FOO.OUT</b></t2s:file>
-</t2sr:directoryContents></pre></blockquote>
- </li>
- <li>
- <p>The standard output and standard error from the T2 Command Line Executor
- subprocess can be read via properties of the special I/O listener. To do
- that, do a GET on
- <tt>%{BASEURL}/rest/runs/<b>UUID</b>/listeners/io/properties/<b>stdout</b></tt>
- (or <tt>.../<b>stderr</b></tt>). Once the subprocess has finished executing,
- the I/O listener will provide a third property containing the exit code of
- the subprocess, called <tt>exitcode</tt>.</p> <p>Note that the supported set
- of listeners and properties will be subject to change in future versions of
- the server, and should not be relied upon.</p>
- </li>
- <li>
- <p>Once you have finished, destroy the run by doing a DELETE on
- <tt>%{BASEURL}/rest/runs/<b>UUID</b></tt>. Once you have done that, none of
- the resources associated with the run (including both input and output
- files) will exist any more. If the run is still executing, this will also
- cause it to be stopped.</p>
- </li>
-</ol>
-<p>All operations described above have equivalents in the
-<a href="%{BASEURL}/soap?wsdl">SOAP service interface</a>.</p>
-
-<div>
-<hr>
-<p><small>Copyright © 2010–2014. The University of Manchester.</small></p>
-<p><small>Software Release ID: ${project.version} (commit: ${git.branch})</small></p>
-</div>
-</body>
-</html>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/META-INF/MANIFEST.MF b/server-webapp/src/main/webapp/META-INF/MANIFEST.MF
deleted file mode 100644
index 5e94951..0000000
--- a/server-webapp/src/main/webapp/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Class-Path:
-
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger b/server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger
deleted file mode 100644
index 4fd9372..0000000
--- a/server-webapp/src/main/webapp/META-INF/cxf/org.apache.cxf.Logger
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.cxf.common.logging.Log4jLogger
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/META-INF/persistence.xml b/server-webapp/src/main/webapp/META-INF/persistence.xml
deleted file mode 100644
index afd640a..0000000
--- a/server-webapp/src/main/webapp/META-INF/persistence.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<persistence version="1.0"
- xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd ">
- <persistence-unit name="TavernaServer">
- <class>org.taverna.server.master.WebappState</class>
- <class>org.taverna.server.master.identity.User</class>
- <class>org.taverna.server.master.localworker.PersistedState</class>
- <class>org.taverna.server.master.notification.atom.Event</class>
- <class>org.taverna.server.master.usage.UsageRecord</class>
- <class>org.taverna.server.master.worker.RunConnection</class>
- <exclude-unlisted-classes>true</exclude-unlisted-classes>
- </persistence-unit>
-</persistence>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/beans.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/beans.xml b/server-webapp/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index 73990a7..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,518 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
- default-lazy-init="false"
- xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
-
- <bean id="webapp" class="org.taverna.server.master.TavernaServer">
- <property name="policy" ref="worker.policy" />
- <property name="runStore" ref="worker.rundb" />
- <property name="fileUtils" ref="fileUtils" />
- <property name="contentsDescriptorBuilder" ref="contentsDescriptorBuilder" />
- <property name="notificationEngine" ref="notificationFabric" />
- <property name="support" ref="webapp.support" />
- <property name="eventSource" ref="dispatch.atom" />
- <property name="interactionFeed" value="${taverna.interaction.feed_path}" />
- <lookup-method name="makeRunInterface" bean="run.coreView.prototype" />
- <lookup-method name="getPolicyDescription" bean="webapp.policyView" />
- </bean>
-
- <bean id="webapp.support" class="org.taverna.server.master.TavernaServerSupport">
- <property name="policy" ref="worker.policy" />
- <property name="listenerFactory" ref="localworker.factory" />
- <property name="runFactory" ref="localworker.factory" />
- <property name="fileUtils" ref="fileUtils" />
- <property name="runStore" ref="worker.rundb" />
- <property name="stateModel" ref="webapp.state" />
- <property name="idMapper" ref="IdentityMapper" />
- <property name="invocationCounter" ref="webapp.invocationCounter" />
- <property name="webapp" ref="webapp" />
- <property name="contentTypeMap">
- <map key-type="java.lang.String" value-type="java.lang.String">
- <description>Maps suffixes (post '.') to content types.</description>
- <entry key="baclava" value="application/vnd.taverna.baclava+xml" />
- <entry key="robundle.zip" value="application/vnd.wf4ever.robundle+zip" />
- </map>
- </property>
- <property name="capabilitySource" ref="capabilities" />
- </bean>
-
- <bean id="capabilities" class="org.taverna.server.master.utils.CapabilityLister" />
-
- <bean id="webapp.policyView" class="org.taverna.server.master.PolicyREST">
- <property name="support" ref="webapp.support" />
- <property name="policy" ref="worker.policy" />
- <property name="listenerFactory" ref="localworker.factory" />
- <property name="notificationEngine" ref="notificationFabric" />
- </bean>
-
- <bean id="contentsDescriptorBuilder" class="org.taverna.server.master.ContentsDescriptorBuilder">
- <property name="uriBuilderFactory" ref="webapp" />
- <property name="fileUtils" ref="fileUtils" />
- </bean>
-
- <bean id="webapp.state" class="org.taverna.server.master.ManagementState">
- <description>The initial state of the webapp.</description>
- <property name="logIncomingWorkflows" value="${default.logworkflows}" />
- <property name="allowNewWorkflowRuns" value="${default.permitsubmit}" />
- <property name="logOutgoingExceptions" value="${default.logexceptions}" />
- <property name="persistenceManagerBuilder" ref="pmb" />
- <property name="self" ref="webapp.state" />
- </bean>
-
- <bean id="webapp.invocationCounter" class="org.taverna.server.master.utils.InvocationCounter" />
- <bean id="webapp.perfLogger" class="org.taverna.server.master.utils.CallTimeLogger">
- <property name="threshold" value="${calltime.logthreshold:4000000}" />
- </bean>
-
- <bean id="run.coreView.prototype" scope="prototype"
- class="org.taverna.server.master.RunREST">
- <property name="support" ref="webapp.support" />
- <property name="cdBuilder" ref="contentsDescriptorBuilder" />
- <lookup-method name="makeSecurityInterface" bean="run.securityView.prototype" />
- <lookup-method name="makeInputInterface" bean="run.inputView.prototype" />
- <lookup-method name="makeListenersInterface" bean="run.listenersView.prototype" />
- <lookup-method name="makeDirectoryInterface" bean="run.directoryView.prototype" />
- <lookup-method name="makeInteractionFeed" bean="run.interactionFeed.prototype" />
- </bean>
-
- <bean id="run.directoryView.prototype" scope="prototype"
- class="org.taverna.server.master.DirectoryREST">
- <property name="support" ref="webapp.support" />
- <property name="fileUtils" ref="fileUtils" />
- </bean>
-
- <bean id="run.listenersView.prototype" scope="prototype"
- class="org.taverna.server.master.ListenersREST">
- <property name="support" ref="webapp.support" />
- <lookup-method name="makeListenerInterface" bean="run.singleListenerView.prototype" />
- </bean>
-
- <bean id="run.singleListenerView.prototype" scope="prototype"
- class="org.taverna.server.master.SingleListenerREST">
- <lookup-method name="makePropertyInterface" bean="run.propertyView.prototype" />
- </bean>
-
- <bean id="run.propertyView.prototype" scope="prototype"
- class="org.taverna.server.master.ListenerPropertyREST">
- <property name="support" ref="webapp.support" />
- </bean>
-
- <bean id="run.inputView.prototype" scope="prototype"
- class="org.taverna.server.master.InputREST">
- <property name="support" ref="webapp.support" />
- <property name="cdBuilder" ref="contentsDescriptorBuilder" />
- <property name="fileUtils" ref="fileUtils" />
- </bean>
-
- <bean id="run.securityView.prototype" scope="prototype"
- class="org.taverna.server.master.RunSecurityREST">
- <property name="support" ref="webapp.support" />
- </bean>
-
- <bean id="run.interactionFeed.prototype" scope="prototype"
- class="org.taverna.server.master.InteractionFeed">
- <property name="interactionFeedSupport" ref="interactionFeed" />
- </bean>
-
- <bean id="feed" class="org.taverna.server.master.notification.atom.AtomFeed">
- <property name="eventSource" ref="dispatch.atom" />
- <property name="support" ref="webapp.support" />
- <property name="feedLanguage" value="${atom.language}" />
- <property name="abdera" ref="abdera" />
- </bean>
-
- <bean id="admin" class="org.taverna.server.master.admin.AdminBean">
- <property name="adminHtmlFile" value="/admin.html" />
- <property name="counter" ref="webapp.invocationCounter" />
- <property name="factory" ref="localworker.factory" />
- <property name="localWorkerModel" ref="localworker.state" />
- <property name="runDB" ref="worker.rundb" />
- <property name="state" ref="webapp.state" />
- <property name="usageRecords" ref="usageRecordSink" />
- <property name="userStore" ref="userStore" />
- </bean>
-
- <bean id="IdentityMapper" class="org.taverna.server.master.identity.CompositeIDMapper">
- <property name="identityMappers">
- <list>
- <bean id="AuthorityBased"
- class="org.taverna.server.master.identity.AuthorityDerivedIDMapper">
- <description>Derives the local user identity to use for execution
- from the LOCALUSER_* Spring Security authority. Thus, if the user
- has "LOCALUSER_foo", they will be executing as the local
- user id "foo".</description>
- </bean>
- <bean id="SelfAccess"
- class="org.taverna.server.master.identity.WorkflowInternalAuthProvider.WorkflowSelfIDMapper">
- <description>Handles the case where a workflow is accessing itself for
- the purpose of publishing interactions.</description>
- <property name="runStore" ref="worker.rundb" />
- </bean>
- <bean id="Extracting" class="org.taverna.server.master.identity.NameIDMapper">
- <description>An alternate mechanism for mapping users. This tries
- to use an RE to extract the user name from the principal name.
- </description>
- <property name="regexp" value="${localusernameregexp}">
- <description>An optional regexp to extract the local user name
- from the principal's string description. The first capturing
- group will be the result of the mapping operation.
- </description>
- </property>
- </bean>
- <bean id="Constant" class="org.taverna.server.master.identity.ConstantIDMapper">
- <description>How to map web principals to local users. This one
- maps everyone to the same user, "taverna".
- </description>
- <property name="constantId" value="${default.localusername}" />
- </bean>
- </list>
- </property>
- </bean>
-
- <bean id="passwordEncoder"
- class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
- <bean class="org.taverna.server.master.identity.UserStore" id="userStore">
- <property name="persistenceManagerBuilder" ref="pmb" />
- <property name="baselineUserProperties">
- <util:properties location="/WEB-INF/security/users.properties" />
- </property>
- <property name="defaultLocalUser" value="${default.localusername}" />
- <property name="encoder" ref="passwordEncoder" />
- </bean>
-
- <!-- <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
- <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties">
- <props> <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
- <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> <property
- name="annotatedClasses"> <list> </list> </property> </bean> -->
- <bean id="pmb" class="org.taverna.server.master.utils.JDOSupport.PersistenceManagerBuilder">
- <property name="persistenceManagerFactory">
- <bean id="pmf" class="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"
- destroy-method="close">
- <property name="connectionFactory" ref="dataSource" />
- <property name="nontransactionalRead" value="true" />
- <property name="persistenceProperties">
- <props>
- <prop key="datanucleus.storeManagerType">rdbms</prop>
- <prop key="datanucleus.autoCreateTables">true</prop>
- <prop key="datanucleus.autoCreateTables">true</prop>
- <prop key="datanucleus.validateTables">true</prop>
- <prop key="datanucleus.autoCreateColumns">true</prop>
- <prop key="datanucleus.autoCreateConstraints">true</prop>
- <prop key="datanucleus.validateConstraints">true</prop>
- <prop key="datanucleus.autoCreateSchema">true</prop>
- <prop key="datanucleus.PersistenceUnitName">TavernaServer</prop>
- <prop key="datanucleus.rdbms.datastoreAdapterClassName"
- >org.taverna.server.master.utils.LoggingDerbyAdapter</prop>
- </props>
- </property>
- </bean>
- </property>
- </bean>
- <bean id="transactionAspect"
- class="org.taverna.server.master.utils.JDOSupport.TransactionAspect" />
-
- <bean id="systemPrereqs" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
- <description>http://stackoverflow.com/questions/3339736/set-system-property-with-spring-configuration-file</description>
- <property name="targetObject" value="#{@systemProperties}" />
- <property name="targetMethod" value="putAll" />
- <property name="arguments">
- <util:properties>
- <prop key="derby.stream.error.field">org.taverna.server.master.utils.DerbyUtils.TO_LOG</prop>
- <prop key="derby.stream.error.logSeverityLevel">30000</prop>
- </util:properties>
- </property>
- </bean>
- <!-- TODO: control the location of the database properly, or move to JNDI
- TODO: review whether what we are doing now is correct! -->
- <bean id="dataSource" class="org.taverna.server.master.utils.WebappAwareDataSource">
- <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
- <property name="url"
- value="jdbc:derby:directory:%{WEBAPPROOT}tavernaserver;create=true" />
- <!-- Needed for Derby... -->
- <property name="shutdownUrl"
- value="jdbc:derby:directory:%{WEBAPPROOT}tavernaserver;shutdown=true" />
- <property name="username" value="taverna" />
- <property name="password" value="" />
- <property name="contextualizer" ref="contextualizer" />
- </bean>
-
- <bean id="contextualizer" class="org.taverna.server.master.utils.Contextualizer" />
-
- <bean id="usageRecordSink" class="org.taverna.server.master.usage.UsageRecordRecorder">
- <property name="state" ref="webapp.state" />
- <property name="contextualizer" ref="contextualizer" />
- <property name="persistenceManagerBuilder" ref="pmb" />
- <property name="self" ref="usageRecordSink" />
- <property name="disableDB" value="${usage.disableDB}" />
- <property name="logFile" value="${usage.logFile}" />
- </bean>
-
- <context:property-placeholder
- ignore-unresolvable="true" order="2" properties-ref="default-factory-properties" />
- <util:properties id="default-factory-properties">
- <prop key="backEndFactory">org.taverna.server.master.localworker.IdAwareForkRunFactory</prop>
- </util:properties>
-
- <!-- This bean configuration replaced with org.taverna.server.master.localworker.LocalWorkerFactory -->
- <!-- <bean id="localworker.factory" scope="singleton" lazy-init="false"
- class="${backEndFactory}"> <description> The simple policy manager and factory
- for the baseline localworker case. </description> <property name="state"
- ref="localworker.state" /> <property name="runDB" ref="worker.rundb"
- /> -->
- <!-- Handled by autowiring to make type-resilient. -->
- <!-- <property name="idMapper" ref="IdentityMapper" /> -->
- <!-- <property name="securityContextFactory" ref="worker.securityContext"
- /> <property name="usageRecordSink" ref="usageRecordSink" /> <property name="URProcessorPool"
- ref="URThreads" /> </bean> -->
-
- <!-- <task:executor id="URThreads" pool-size="${pool.size}" /> -->
-
- <bean id="worker.securityContext"
- class="org.taverna.server.master.worker.SecurityContextFactory">
- <property name="runDatabase" ref="worker.rundb" />
- <property name="filenameConverter" ref="fileUtils" />
- <property name="x500Utils" ref="x500Utils" />
- <property name="httpRealm" value="${http.realmName}" />
- <property name="uriSource" ref="webapp" />
- <property name="certificateFetcher" ref="certificateChainFetcher" />
- <property name="passwordIssuer" ref="passwordIssuer" />
- </bean>
-
- <bean id="passwordIssuer" class="org.taverna.server.master.worker.PasswordIssuer">
- <!-- <property name="length" value="8" /> -->
- </bean>
-
- <bean id="certificateChainFetcher" class="org.taverna.server.master.utils.CertificateChainFetcher">
- <property name="secure" value="${fetchCertificateChain}" />
- </bean>
-
- <bean id="localworker.state" class="org.taverna.server.master.localworker.LocalWorkerState"
- scope="singleton" lazy-init="false">
- <description>
- The state of the simple factory for the identity-aware
- local worker.
- </description>
- <property name="defaultLifetime" value="${default.lifetime}">
- <description>How long the run lasts for by default, in seconds.
- </description>
- </property>
- <property name="maxRuns" value="${default.runlimit}">
- <description>The maximum simultaneous number of runs.</description>
- </property>
- <property name="operatingLimit" value="${default.operatinglimit}">
- <description>
- The maximum number of runs that are in the Operating state,
- i.e., actually running with a process consuming resources.
- </description>
- </property>
- <property name="extraArgs">
- <description>Any extra arguments (memory control, etc.) to pass to
- the spawned subprocesses.
- </description>
- <list>
- </list>
- </property>
- <property name="waitSeconds" value="40">
- <description>An upper bound (in seconds) on the time to wait for a
- subprocess to start before failing it.
- </description>
- </property>
- <property name="sleepMS" value="1000">
- <description>The time to wait (in milliseconds) between polling for
- the subprocess to complete its registration.
- </description>
- </property>
- <property name="persistenceManagerBuilder" ref="pmb" />
- <!-- <property name="javaBinary"> <description>The name of the java executable
- used to run the server worker. Defaults to the executable used to run the
- hosting environment.</description> </property> -->
- <!-- <property name="serverWorkerJar"> <description>The full path to the
- executable JAR file containing the implementation of the server worker.</description>
- </property> -->
- <!-- <property name="executeWorkflowScript"> <description>The full path
- to the executeworkflow.sh in either the Taverna 2 Workbench distribution
- or the Taverna 2 Command Line distribution.</description> </property> -->
- <property name="self" ref="localworker.state" />
- <property name="defaultExecuteWorkflowScript" value="${executeWorkflowScript:NONE}" />
- </bean>
-
- <bean id="worker.policy" class="org.taverna.server.master.worker.PolicyImpl">
- <description>
- The implementation of the access control policy supported
- by the localworker run engine.
- </description>
- <property name="limits" ref="localworker.state" />
- <property name="runDB" ref="worker.rundb" />
- </bean>
- <bean id="worker.rundb" class="org.taverna.server.master.worker.RunDatabase">
- <property name="notifier" ref="worker.notifier" />
- <property name="typeNotifiers">
- <list>
- <ref bean="cn.email" />
- <ref bean="cn.sms" />
- <ref bean="cn.twitter" />
- <!-- <ref bean="cn.xmpp"/> -->
- </list>
- </property>
- <property name="notificationEngine" ref="notificationFabric" />
- <property name="dao" ref="worker.runDAO" />
- </bean>
- <bean id="cn.email"
- class="org.taverna.server.master.worker.VelocityCompletionNotifier">
- <property name="name" value="email" />
- <property name="subject" value="Workflow run finished executing" />
- <property name="velocityEngine" ref="velocity" />
- <property name="uriBuilderFactory" ref="webapp" />
- </bean>
- <bean id="cn.sms"
- class="org.taverna.server.master.worker.VelocityCompletionNotifier">
- <property name="name" value="sms" />
- <property name="subject" value="Run finished" />
- <property name="velocityEngine" ref="velocity" />
- <property name="uriBuilderFactory" ref="webapp" />
- </bean>
- <bean id="cn.twitter"
- class="org.taverna.server.master.worker.VelocityCompletionNotifier">
- <property name="name" value="twitter" />
- <property name="subject" value="Run finished" />
- <property name="velocityEngine" ref="velocity" />
- <property name="uriBuilderFactory" ref="webapp" />
- </bean>
-
- <bean id="worker.runDAO" class="org.taverna.server.master.worker.RunDatabaseDAO">
- <description>
- The implementation of the catalog of workflow runs
- supported by the localworker run engine.
- </description>
- <property name="persistenceManagerBuilder" ref="pmb" />
- <property name="facade" ref="worker.rundb" />
- </bean>
- <task:scheduled-tasks scheduler="taskScheduler">
- <task:scheduled ref="worker.rundb" method="cleanNow"
- fixed-delay="${purge.interval}" />
- <task:scheduled ref="worker.rundb" method="checkForFinishNow"
- fixed-delay="${finish.interval}" />
- <task:scheduled ref="dispatch.atom" method="deleteExpiredEvents"
- fixed-delay="${atom.cleaninterval}" />
- </task:scheduled-tasks>
-
- <bean id="notificationFabric"
- class="org.taverna.server.master.notification.NotificationEngine">
- <property name="dispatchers">
- <list>
- <ref bean="dispatch.email" />
- <ref bean="dispatch.twitter" />
- <ref bean="dispatch.xmpp" />
- <ref bean="dispatch.sms" />
- </list>
- </property>
- <property name="universalDispatchers">
- <list>
- <ref bean="dispatch.atom" />
- </list>
- </property>
- </bean>
-
- <bean id="dispatch.email" class="org.taverna.server.master.notification.EmailDispatcher">
- <property name="from" value="${email.from}" />
- <property name="messageContentType" value="${email.type}" />
- <property name="cooldownSeconds" value="${message.cooldown}" />
- <property name="smtpHost" value="${email.host}" />
- <property name="sender">
- <bean class="org.springframework.mail.javamail.JavaMailSenderImpl"
- id="javamail">
- <property name="host" value="${email.host}" />
- </bean>
- </property>
- </bean>
- <bean id="dispatch.twitter"
- class="org.taverna.server.master.notification.TwitterDispatcher">
- <property name="cooldownSeconds" value="${message.cooldown}" />
- <property name="accessToken" value="${twitter.oauth.accessToken}" />
- <property name="accessSecret" value="${twitter.oauth.accessTokenSecret}" />
- </bean>
- <bean id="dispatch.xmpp" class="org.taverna.server.master.notification.JabberDispatcher">
- <property name="resource" value="${xmpp.resource}" />
- <property name="host" value="${xmpp.service}" />
- <property name="username" value="${xmpp.user}" />
- <property name="password" value="${xmpp.password}" />
- </bean>
- <bean id="dispatch.sms" class="org.taverna.server.master.notification.SMSDispatcher">
- <property name="usernameField" value="${sms.userfield}" />
- <property name="passwordField" value="${sms.passfield}" />
- <property name="destinationField" value="${sms.destfield}" />
- <property name="messageField" value="${sms.msgfield}" />
- <property name="cooldownSeconds" value="${message.cooldown}" />
- </bean>
-
- <bean id="dispatch.atom" class="org.taverna.server.master.notification.atom.EventDAO">
- <property name="expiryAgeDays" value="${atom.lifespan}" />
- <property name="persistenceManagerBuilder" ref="pmb" />
- <property name="uriBuilderFactory" ref="feed" />
- <property name="self" ref="dispatch.atom" />
- </bean>
-
- <bean id="worker.notifier"
- class="org.taverna.server.master.worker.SimpleFormattedCompletionNotifier">
- <property name="subject" value="${message.termination.subject}" />
- <property name="messageFormat" value="${message.termination.body}" />
- <property name="name" value="fallback"/>
- </bean>
-
- <bean id="fileUtils" class="org.taverna.server.master.utils.FilenameUtils" />
- <bean id="x500Utils" class="org.taverna.server.master.utils.X500Utils" />
- <task:scheduler id="taskScheduler" pool-size="${pool.size}" />
-
- <bean class="org.taverna.server.master.utils.JCECheck" id="JCECheck" />
-
- <bean class="org.taverna.server.master.interaction.InteractionFeedSupport"
- id="interactionFeed" scope="singleton">
- <property name="abdera" ref="abdera" />
- <property name="support" ref="webapp.support" />
- <property name="uriBuilder" ref="webapp" />
- <property name="utils" ref="fileUtils" />
- </bean>
- <bean class="org.taverna.server.master.rest.handler.FeedHandler" id="atomFeedHandler">
- <property name="abdera" ref="abdera" />
- </bean>
- <bean class="org.taverna.server.master.rest.handler.EntryHandler" id="atomEntryHandler">
- <property name="abdera" ref="abdera" />
- </bean>
-
- <bean id="authProvider" class="org.taverna.server.master.identity.StrippedDownAuthProvider">
- <property name="passwordEncoder" ref="passwordEncoder" />
- <property name="userDetailsService">
- <bean class="org.taverna.server.master.identity.UserStore.CachedUserStore">
- <property name="realStore" ref="userStore" />
- </bean>
- </property>
- </bean>
- <bean id="workflowInternalAuthProvder"
- class="org.taverna.server.master.identity.WorkflowInternalAuthProvider">
- <property name="dao" ref="worker.runDAO" />
- <property name="cacheBound" value="${default.runlimit}" />
- </bean>
- <bean id="velocity" class="org.apache.velocity.app.VelocityEngine"
- init-method="init" lazy-init="false">
- <constructor-arg>
- <props>
- <prop key="input.encoding">UTF-8</prop>
- <prop key="output.encoding">UTF-8</prop>
- <prop key="runtime.log.logsystem.class">org.apache.velocity.runtime.log.Log4JLogChute</prop>
- <prop key="runtime.log.logsystem.log4j.logger">org.taverna.server.master.worker.VelocityCompletionNotifier</prop>
- <prop key="resource.loader">class</prop>
- <prop key="class.resource.loader.description">Velocity Classpath Resource Loader</prop>
- <prop key="class.resource.loader.class">org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader</prop>
- </props>
- </constructor-arg>
- </bean>
- <bean id="abdera" class="org.apache.abdera.Abdera"/>
-</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/insecure.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/insecure.xml b/server-webapp/src/main/webapp/WEB-INF/insecure.xml
deleted file mode 100644
index 92c0b03..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/insecure.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2010-2012 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:security="http://www.springframework.org/schema/security"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
-
- <description>
- The Taverna Server bean, plus supporting configuration.
- THIS IS AN INSECURE CONFIGURATION!
- </description>
-
- <import resource="webappBeans.xml" />
-
- <context:property-placeholder order="0" ignore-unresolvable="true"
- properties-ref="security.override.properties" />
- <util:properties id="security.override.properties">
- <prop key="backEndFactory">org.taverna.server.master.localworker.ForkRunFactory</prop>
- <prop key="fetchCertificateChain">false</prop>
- <prop key="suppressRewriteEngine">true</prop>
- <prop key="requiredChannel">any</prop>
- </util:properties>
-
- <!-- No JMX support; assume too unsafe. -->
-</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl b/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl
deleted file mode 100644
index d706fed..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_email.vtmpl
+++ /dev/null
@@ -1,15 +0,0 @@
-Your workflow, $name, has #if( $prop_exitcode == 0)finished#{else}failed#{end}.
-
-It started execution at ${startTime}.
-It finished execution at ${finishTime}.
-
-For further information, go to $uriBuilder.build() before the run is
-automatically deleted (currently scheduled to happen at ${expiryTime}).
-
-#if( $prop_exitcode == 0)
-Exit code: $prop_exitcode
-Standard error:
-$prop_stderr
-#end
-
-(This message was automatically generated by Taverna Server ${serverVersion}.)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl b/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl
deleted file mode 100644
index b595931..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_sms.vtmpl
+++ /dev/null
@@ -1 +0,0 @@
-Taverna Server ${serverVersion}: Workflow "$name" from ${startTime} has #if( $prop_exitcode == 0)finished#{else}failed#{end}.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl b/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl
deleted file mode 100644
index cd920a7..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/lib/org.taverna.server.master.worker.VelocityCompletionNotifier_twitter.vtmpl
+++ /dev/null
@@ -1 +0,0 @@
-Your workflow, $name, has #if( $prop_exitcode == 0)finished#{else}failed#{end}. $uriBuilder.build() #TavernaServer ${serverVersion}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/partsecure.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/partsecure.xml b/server-webapp/src/main/webapp/WEB-INF/partsecure.xml
deleted file mode 100644
index 2e27b81..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/partsecure.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2011-2012 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:security="http://www.springframework.org/schema/security"
- xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
-
- <description>
- The Taverna Server bean, plus supporting configuration.
- THIS IS THE CONFIGURATION FOR SEMI-SECURE OPERATION ON WINDOWS.
- </description>
-
- <import resource="webappBeans.xml" />
-
- <!-- This is all the same as the secure config *EXCEPT* for this override. -->
- <context:property-placeholder order="0" ignore-unresolvable="true"
- properties-ref="security.override.properties" />
- <util:properties id="security.override.properties">
- <prop key="backEndFactory">org.taverna.server.master.localworker.ForkRunFactory</prop>
- <prop key="fetchCertificateChain">true</prop>
- <prop key="suppressRewriteEngine">false</prop>
- <prop key="requiredChannel">https</prop>
- </util:properties>
-
- <bean id="MBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
- <property name="locateExistingServerIfPossible" value="true" />
- </bean>
- <context:mbean-export server="MBeanServer"
- default-domain="${my.domain}" registration="ignoreExisting" />
-</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/providers.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/providers.xml b/server-webapp/src/main/webapp/WEB-INF/providers.xml
deleted file mode 100644
index 43531ab..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/providers.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
-
- <import resource="beans.xml" />
-
- <bean id="ExceptionProvider.BadInputPortName" class="org.taverna.server.master.rest.handler.BadInputPortNameHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.BadPropertyValue" class="org.taverna.server.master.rest.handler.BadPropertyValueHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.BadStateChange" class="org.taverna.server.master.rest.handler.BadStateChangeHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.FilesystemAccess" class="org.taverna.server.master.rest.handler.FilesystemAccessHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.GeneralFailure" class="org.taverna.server.master.rest.handler.GeneralFailureHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.IllegalArgument" class="org.taverna.server.master.rest.handler.IllegalArgumentHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.ImplementationProblem"
- class="org.taverna.server.master.rest.handler.ImplementationProblemHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.InvalidCredential" class="org.taverna.server.master.rest.handler.InvalidCredentialHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NoCreate" class="org.taverna.server.master.rest.handler.NoCreateHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.Overloaded" class="org.taverna.server.master.rest.handler.OverloadedHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NoCredential" class="org.taverna.server.master.rest.handler.NoCredentialHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NoDestroy" class="org.taverna.server.master.rest.handler.NoDestroyHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NoDirectoryEntry" class="org.taverna.server.master.rest.handler.NoDirectoryEntryHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NoListener" class="org.taverna.server.master.rest.handler.NoListenerHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NoUpdate" class="org.taverna.server.master.rest.handler.NoUpdateHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NotOwner" class="org.taverna.server.master.rest.handler.NotOwnerHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.UnknownRun" class="org.taverna.server.master.rest.handler.UnknownRunHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.JAXBException" class="org.taverna.server.master.rest.handler.JAXBExceptionHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.AccessDenied" class="org.taverna.server.master.rest.handler.AccessDeniedHandler">
- <property name="managementModel" ref="webapp.state" />
- </bean>
- <bean id="ExceptionProvider.NegotiationFailed" class="org.taverna.server.master.rest.handler.NegotiationFailedHandler">
- </bean>
- <bean id="MessagingProvider.File" class="org.taverna.server.master.rest.handler.FileMessageHandler">
- <property name="maxChunkSize" value="${default.messageSize}" />
- </bean>
- <bean id="MessagingProvider.FileConcatenation" class="org.taverna.server.master.rest.handler.FileConcatenationHandler">
- <property name="maxChunkSize" value="${default.messageSize}" />
- </bean>
- <bean id="MessagingProvider.FileSegment" class="org.taverna.server.master.rest.handler.FileSegmentHandler">
- <property name="maxChunkSize" value="${default.messageSize}" />
- </bean>
- <bean id="MessagingProvider.InputStream"
- class="org.taverna.server.master.rest.handler.InputStreamMessageHandler">
- </bean>
- <bean id="MessagingProvider.T2flow" class="org.taverna.server.master.rest.handler.T2FlowDocumentHandler">
- </bean>
- <bean id="MessagingProvider.Permission" class="org.taverna.server.master.rest.handler.PermissionHandler">
- </bean>
-
- <bean id="Provider.RuntimeExceptionRemapping" class="org.taverna.server.master.utils.RuntimeExceptionWrapper" />
- <bean id="MessagingProvider.ZipStream" class="org.taverna.server.master.rest.handler.ZipStreamHandler" />
- <bean id="MessagingProvider.URIList" class="org.taverna.server.master.rest.handler.URIListHandler" />
- <bean id="Interceptor.FlushThreadLocalCache"
- class="org.taverna.server.master.utils.FlushThreadLocalCacheInterceptor"
- lazy-init="false">
- </bean>
-</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/secure.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/secure.xml b/server-webapp/src/main/webapp/WEB-INF/secure.xml
deleted file mode 100644
index cf08083..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/secure.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2010-2012 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:security="http://www.springframework.org/schema/security"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
-
- <description>
- The Taverna Server bean, plus supporting configuration.
- THIS IS THE CONFIGURATION FOR SECURE OPERATION.
- </description>
-
- <import resource="webappBeans.xml" />
-
- <context:property-placeholder order="0" ignore-unresolvable="true"
- properties-ref="security.override.properties" />
- <util:properties id="security.override.properties">
- <prop key="fetchCertificateChain">true</prop>
- <prop key="suppressRewriteEngine">false</prop>
- <prop key="requiredChannel">https</prop>
- </util:properties>
-
- <bean id="MBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
- <property name="locateExistingServerIfPossible" value="true" />
- </bean>
- <context:mbean-export server="MBeanServer"
- default-domain="${my.domain}" registration="ignoreExisting" />
-</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/security/users.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/security/users.properties b/server-webapp/src/main/webapp/WEB-INF/security/users.properties
deleted file mode 100644
index 03f8436..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/security/users.properties
+++ /dev/null
@@ -1,48 +0,0 @@
-# This is a Java properties file that defines the default users supported by
-# Taverna Server. The keys are the user names, and the values are comma-
-# -separated lists of values: the first is the password (which must not have
-# any spaces or commas in) and the last is "enabled" or "disabled" to indicate
-# whether this user is actually allowed to log in or not. The values between
-# are the authorities associated with the user: these are either roles (which
-# describe a particular set of permissions for the user) or user mappings.
-#
-# The supported set of authorities are:
-#
-# ROLE_tavernauser - may use the standard Taverna Server interfaces
-#
-# ROLE_tavernasuperuser - may use the admin interfaces and see *all*
-# workflow runs irrespective of permissions
-#
-# LOCALUSER_* - map the server user to the given local system
-# account (i.e., the account name is in place of the
-# "*" in the authority); don't grant two of these
-# authorities at once, or confusion will reign
-#
-# Note that it is usually better to define accounts via the administrative
-# interface or through the JMX interface because those can then be modified
-# without restarting the server; anything in this file is fixed until the
-# next server restart. This file exists mainly to allow permissions for the
-# admin interface to be boot-strapped.
-
-# ---------------------------------------------------------------------
-
-# A normal user. Must have given role (ROLE_tavernauser) to use Taverna Server.
-# The user has password "taverna" and is enabled. The default mapping to user
-# accounts - using the user name - will be used.
-
-taverna: taverna,ROLE_tavernauser,enabled
-
-# Another normal user (username: "taverna_alt"). Will be mapped to the system
-# account called "taverna", but the user is currently disabled.
-
-taverna_alt: qwerty,ROLE_tavernauser,LOCALUSER_taverna,disabled
-
-# The default admin user, who has password "admin". You should change this!
-# Admin users also have ROLE_tavernasuperuser, which grants access to the
-# server's /admin pages and allows all workflow runs to be seen (if the
-# ROLE_tavernauser is also assigned, as below; one does not imply the other).
-# If you don't have any enabled admin users, you'll need to use JMX to do
-# management operations (JMX is only accessible from the local host and by
-# the overall container user or the system administrator).
-
-admin: admin,ROLE_tavernauser,ROLE_tavernasuperuser,LOCALUSER_taverna,enabled
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties b/server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties
deleted file mode 100644
index 9616a45..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/tavernaserver.properties
+++ /dev/null
@@ -1,77 +0,0 @@
-# Override the hostname, port and webapp; leave at 'NONE' if no override
-# desired. If set, set it to something like:
-# foo.example.com:8000/tav-serv
-default.webapp: NONE
-# User name to use if nothing else specified
-default.localusername: taverna
-# How to pick a user name out of a global identity
-localusernameregexp: ^TAVERNAUSER=(.*)$
-# General defaults
-default.logworkflows: false
-default.logexceptions: false
-default.permitsubmit: true
-default.lifetime: 1440
-default.runlimit: 100
-default.operatinglimit: 10
-default.messageSize: 65536
-#taverna.preferredUserUri: https://some.host:8443/tavernaserver/rest/
-http.realmName: tavernaserver
-
-rmi.localhostOnly: true
-helio.cis.enableTokenPassing: false
-log.security.details: false
-
-#executeWorkflowScript: /usr/taverna/executeworkflow.sh
-#secureForkPasswordFile: /usr/local/tomcat6.0/conf/sudopass.txt
-
-# Usage Record handling
-usage.logFile: none
-usage.disableDB: no
-
-# Delays used in the task executor
-purge.interval: 30000
-finish.interval: 10000
-
-# Static configuration of messaging
-
-### Email
-email.from: taverna.server@localhost
-email.type: text/plain
-#email.host: localhost
-
-### Jabber
-#xmpp.server: xmpp://some.host:5222
-xmpp.resource: TavernaServer
-#xmpp.user: taverna
-#xmpp.password: *******
-
-### Atom/RSS; lifespan in days, cleaninterval in milliseconds
-atom.language: en
-atom.lifespan: 7
-atom.cleaninterval: 3600000
-
-### SMS
-#sms.service: https://www.intellisoftware.co.uk/smsgateway/sendmsg.aspx
-sms.userfield: username
-sms.passfield: password
-sms.destfield: to
-sms.msgfield: text
-#sms.user: taverna
-#sms.pass: *******
-
-### Twitter
-#twitter.oauth.accessToken: ...
-#twitter.oauth.accessTokenSecret: ...
-
-### General; cooldown in seconds
-message.cooldown: 300
-message.termination.subject: Taverna workflow run finished
-message.termination.body: Your job with ID={0} has finished with exit code {1,number,integer}.
-
-# Thread pool sizing
-pool.size: 2
-
-taverna.interaction.host: none
-taverna.interaction.port: none
-taverna.interaction.webdav_path: none
-taverna.interaction.feed_path: none
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/web-nosec.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/web-nosec.xml b/server-webapp/src/main/webapp/WEB-INF/web-nosec.xml
deleted file mode 100644
index d6c6ee7..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/web-nosec.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE web-app
- PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
-
-<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<web-app id="TAVSERV-2.5.4">
- <display-name>Taverna 2.5.4 Server</display-name>
- <description>This is the front-end engine for Taverna 2.5.4 Server.</description>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>WEB-INF/insecure.xml</param-value>
- <description>Where Spring is to load its bean definitions from. DO NOT
- CHANGE WITHOUT CONSULTING DOCUMENTATION.</description>
- </context-param>
- <context-param>
- <param-name>log4jExposeWebAppRoot</param-name>
- <param-value>false</param-value>
- <description>
- THIS IS STUPID! We have to do this so that Tomcat webapps do not
- leak their configurations into each other via the log4j support
- trying to be "smart".
- http://javacolors.blogspot.co.uk/2010/08/tomcat-and-webxmls-webapprootkey.html
- If you change this, good luck hunting down the weird crashes.
- </description>
- </context-param>
-
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <listener>
- <listener-class>
- org.springframework.web.context.request.RequestContextListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.util.Log4jConfigListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
-
- <servlet>
- <servlet-name>CXFServlet</servlet-name>
- <display-name>CXF Servlet</display-name>
- <servlet-class>
- org.apache.cxf.transport.servlet.CXFServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>CXFServlet</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
- <resource-ref>
- <description>
- Resource reference to a factory for javax.mail.Session
- instances that may be used for sending electronic mail
- messages, preconfigured to connect to the appropriate
- SMTP server.
- </description>
- <res-ref-name>mail/Session</res-ref-name>
- <res-type>javax.mail.Session</res-type>
- <res-auth>Container</res-auth>
- <res-sharing-scope>Shareable</res-sharing-scope>
- </resource-ref>
-</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/web-partsec.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/web-partsec.xml b/server-webapp/src/main/webapp/WEB-INF/web-partsec.xml
deleted file mode 100644
index a2b545e..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/web-partsec.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE web-app
- PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
-
-<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<web-app id="TAVSERV-2.5.4">
- <display-name>Taverna 2.5.4 Server</display-name>
- <description>This is the front-end engine for Taverna 2.5.4 Server.</description>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>WEB-INF/partsecure.xml</param-value>
- <description>Where Spring is to load its bean definitions from. DO NOT
- CHANGE WITHOUT CONSULTING DOCUMENTATION.</description>
- </context-param>
- <context-param>
- <param-name>log4jExposeWebAppRoot</param-name>
- <param-value>false</param-value>
- <description>
- THIS IS STUPID! We have to do this so that Tomcat webapps do not
- leak their configurations into each other via the log4j support
- trying to be "smart".
- http://javacolors.blogspot.co.uk/2010/08/tomcat-and-webxmls-webapprootkey.html
- If you change this, good luck hunting down the weird crashes.
- </description>
- </context-param>
-
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <listener>
- <listener-class>
- org.springframework.web.context.request.RequestContextListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.util.Log4jConfigListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
-
- <servlet>
- <servlet-name>CXFServlet</servlet-name>
- <display-name>CXF Servlet</display-name>
- <servlet-class>
- org.apache.cxf.transport.servlet.CXFServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>CXFServlet</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
- <resource-ref>
- <description>
- Resource reference to a factory for javax.mail.Session
- instances that may be used for sending electronic mail
- messages, preconfigured to connect to the appropriate
- SMTP server.
- </description>
- <res-ref-name>mail/Session</res-ref-name>
- <res-type>javax.mail.Session</res-type>
- <res-auth>Container</res-auth>
- <res-sharing-scope>Shareable</res-sharing-scope>
- </resource-ref>
-</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/web-sec.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/web-sec.xml b/server-webapp/src/main/webapp/WEB-INF/web-sec.xml
deleted file mode 100644
index 9a5395a..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/web-sec.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE web-app
- PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
-
-<!-- Copyright (C) 2010-2011 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<web-app id="TAVSERV-2.5.4">
- <display-name>Taverna 2.5.4 Server</display-name>
- <description>This is the front-end engine for Taverna 2.5.4 Server.</description>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>WEB-INF/secure.xml</param-value>
- <description>Where Spring is to load its bean definitions from. DO NOT
- CHANGE WITHOUT CONSULTING DOCUMENTATION.</description>
- </context-param>
- <context-param>
- <param-name>log4jExposeWebAppRoot</param-name>
- <param-value>false</param-value>
- <description>
- THIS IS STUPID! We have to do this so that Tomcat webapps do not
- leak their configurations into each other via the log4j support
- trying to be "smart".
- http://javacolors.blogspot.co.uk/2010/08/tomcat-and-webxmls-webapprootkey.html
- If you change this, good luck hunting down the weird crashes.
- </description>
- </context-param>
-
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <listener>
- <listener-class>
- org.springframework.web.context.request.RequestContextListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.util.Log4jConfigListener
- </listener-class>
- </listener>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
-
- <servlet>
- <servlet-name>CXFServlet</servlet-name>
- <display-name>CXF Servlet</display-name>
- <servlet-class>
- org.apache.cxf.transport.servlet.CXFServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>CXFServlet</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
- <resource-ref>
- <description>
- Resource reference to a factory for javax.mail.Session
- instances that may be used for sending electronic mail
- messages, preconfigured to connect to the appropriate
- SMTP server.
- </description>
- <res-ref-name>mail/Session</res-ref-name>
- <res-type>javax.mail.Session</res-type>
- <res-auth>Container</res-auth>
- <res-sharing-scope>Shareable</res-sharing-scope>
- </resource-ref>
-</web-app>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/webapp/WEB-INF/webappBeans.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/webapp/WEB-INF/webappBeans.xml b/server-webapp/src/main/webapp/WEB-INF/webappBeans.xml
deleted file mode 100644
index 22e74b3..0000000
--- a/server-webapp/src/main/webapp/WEB-INF/webappBeans.xml
+++ /dev/null
@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2010-2012 The University of Manchester See the file "LICENSE"
- for license terms. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:jaxrs="http://cxf.apache.org/jaxrs"
- xmlns:jaxws="http://cxf.apache.org/jaxws"
- xmlns:cxf="http://cxf.apache.org/core"
- xmlns:security="http://www.springframework.org/schema/security"
- xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
- http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
- http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
- http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
-
- <description>
- The Taverna Server bean, plus supporting configuration.
- </description>
-
- <import resource="classpath:META-INF/cxf/cxf.xml" />
- <import resource="providers.xml" />
-
- <context:annotation-config />
- <context:component-scan base-package="org.taverna.server" />
- <bean id="servletContextPropertyConfigurer"
- class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
- <property name="ignoreUnresolvablePlaceholders" value="true" />
- <property name="localOverride" value="true" />
- <property name="order" value="0" />
- <property name="location" value="/WEB-INF/tavernaserver.properties" />
- </bean>
-
- <jaxws:server id="master_SOAP"
- serviceClass="org.taverna.server.master.TavernaServer" address="/soap">
- <jaxws:serviceBean>
- <ref bean="webapp" />
- </jaxws:serviceBean>
- <jaxws:properties>
- <entry key="mtom-enabled" value="true" />
- </jaxws:properties>
- <!-- <jaxws:dataBinding><ref bean="addStylesheet"/></jaxws:dataBinding> -->
- </jaxws:server>
-
- <jaxrs:server id="root_REST" address="/">
- <jaxrs:serviceBeans>
- <ref bean="root_facade" />
- </jaxrs:serviceBeans>
- <jaxrs:properties>
- <entry key="org.apache.cxf.endpoint.private" value="true" />
- </jaxrs:properties>
- </jaxrs:server>
-
- <jaxrs:server id="master_REST" address="/rest"
- staticSubresourceResolution="true">
- <jaxrs:serviceBeans>
- <ref bean="webapp" />
- </jaxrs:serviceBeans>
- <jaxrs:features>
- <!-- <cxf:logging /> --><!-- NOISY! -->
- </jaxrs:features>
- <jaxrs:providers>
- <ref bean="ExceptionProvider.AccessDenied" />
- <ref bean="ExceptionProvider.BadInputPortName" />
- <ref bean="ExceptionProvider.BadPropertyValue" />
- <ref bean="ExceptionProvider.BadStateChange" />
- <ref bean="ExceptionProvider.FilesystemAccess" />
- <ref bean="ExceptionProvider.GeneralFailure" />
- <ref bean="ExceptionProvider.IllegalArgument" />
- <ref bean="ExceptionProvider.ImplementationProblem" />
- <ref bean="ExceptionProvider.InvalidCredential" />
- <ref bean="ExceptionProvider.JAXBException" />
- <ref bean="ExceptionProvider.NegotiationFailed" />
- <ref bean="ExceptionProvider.NoCreate" />
- <ref bean="ExceptionProvider.NoCredential" />
- <ref bean="ExceptionProvider.NoDestroy" />
- <ref bean="ExceptionProvider.NoDirectoryEntry" />
- <ref bean="ExceptionProvider.NoListener" />
- <ref bean="ExceptionProvider.NoUpdate" />
- <ref bean="ExceptionProvider.NotOwner" />
- <ref bean="ExceptionProvider.Overloaded" />
- <ref bean="ExceptionProvider.UnknownRun" />
- <ref bean="MessagingProvider.File" />
- <ref bean="MessagingProvider.FileConcatenation" />
- <ref bean="MessagingProvider.FileSegment" />
- <ref bean="MessagingProvider.InputStream" />
- <ref bean="MessagingProvider.T2flow" />
- <ref bean="MessagingProvider.Permission" />
- <ref bean="MessagingProvider.URIList" />
- <ref bean="MessagingProvider.ZipStream" />
- <ref bean="jsonProvider" />
- <ref bean="atomEntryHandler" />
- <ref bean="atomFeedHandler" />
- <bean class="org.apache.cxf.jaxrs.model.wadl.WadlGenerator">
- <property name="addResourceAndMethodIds" value="true"/>
- </bean>
- </jaxrs:providers>
- <jaxrs:outInterceptors>
- <ref bean="Interceptor.FlushThreadLocalCache" />
- </jaxrs:outInterceptors>
- </jaxrs:server>
-
- <jaxrs:server id="AtomFeed" address="/feed">
- <jaxrs:serviceBeans>
- <ref bean="feed" />
- </jaxrs:serviceBeans>
- <jaxrs:properties>
- <entry key="org.apache.cxf.endpoint.private" value="true" />
- </jaxrs:properties>
- <jaxrs:providers>
- <ref bean="atomEntryHandler" />
- <ref bean="atomFeedHandler" />
- </jaxrs:providers>
- </jaxrs:server>
-
- <jaxrs:server id="AdministrationInterface" address="/admin"
- staticSubresourceResolution="true">
- <jaxrs:serviceBeans>
- <ref bean="admin" />
- </jaxrs:serviceBeans>
- <jaxrs:providers>
- <ref bean="jsonProvider" />
- </jaxrs:providers>
- </jaxrs:server>
-
- <bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
- <property name="ignoreNamespaces" value="true" />
- <property name="namespaceMap" ref="jsonNamespaceMap" />
- </bean>
- <util:map id="jsonNamespaceMap" key-type="java.lang.String"
- value-type="java.lang.String">
- <entry key="http://www.w3.org/1999/xlink" value="" />
- <entry key="http://www.w3.org/2000/09/xmldsig#" value="" />
- <entry key="http://schema.ogf.org/urf/2003/09/urf" value="" />
- <entry key="http://ns.taverna.org.uk/2010/xml/server/" value="" />
- <entry key="http://ns.taverna.org.uk/2010/xml/server/rest/" value="" />
- <entry key="http://ns.taverna.org.uk/2010/xml/server/soap/" value="" />
- <entry key="http://ns.taverna.org.uk/2010/xml/server/feed/" value="" />
- <entry key="http://ns.taverna.org.uk/2010/xml/server/admin/" value="" />
- <entry key="http://ns.taverna.org.uk/2010/port/" value="" />
- <entry key="http://ns.taverna.org.uk/2010/run/" value="" />
- </util:map>
-
- <bean id="root_facade" class="org.taverna.server.master.facade.Facade">
- <property name="file" value="/welcome.html" />
- <property name="contextualizer" ref="contextualizer" />
- </bean>
-
- <bean class="org.taverna.server.master.common.Uri.Rewriter"
- autowire="byType" id="URI-Rewriter-Thunk">
- <property name="suppressSecurity" value="${suppressRewriteEngine}" />
- <property name="rewriteTarget" value="${default.webapp}" />
- </bean>
- <security:authentication-manager>
- <security:authentication-provider ref="workflowInternalAuthProvder" />
- <security:authentication-provider ref="authProvider" />
- </security:authentication-manager>
-
- <bean id="WSDLHeadOptionsInterceptor"
- class="org.taverna.server.master.utils.WSDLHeadOptionsInterceptor" />
- <cxf:bus>
- <cxf:inInterceptors>
- <ref bean="WSDLHeadOptionsInterceptor" />
- </cxf:inInterceptors>
- </cxf:bus>
-
- <aop:aspectj-autoproxy proxy-target-class="true" />
- <security:global-method-security
- jsr250-annotations="enabled" />
-
- <security:http realm="${http.realmName}" create-session="never"
- use-expressions="true">
- <security:http-basic />
- <security:intercept-url pattern="/"
- requires-channel="any" access="permitAll" />
- <security:intercept-url pattern="/rest"
- requires-channel="${requiredChannel}" access="permitAll" />
- <security:intercept-url pattern="/rest/"
- requires-channel="${requiredChannel}" access="permitAll" />
- <security:intercept-url pattern="/rest/policy"
- requires-channel="${requiredChannel}" access="permitAll" />
- <security:intercept-url pattern="/rest/policy/"
- requires-channel="${requiredChannel}" access="permitAll" />
- <security:intercept-url pattern="/services/**"
- requires-channel="${requiredChannel}" access="permitAll" />
- <security:intercept-url pattern="/soap/**" method="GET"
- requires-channel="${requiredChannel}" access="permitAll" />
- <security:intercept-url pattern="/soap/**" method="POST"
- requires-channel="${requiredChannel}"
- access="hasRole('ROLE_tavernauser')" />
- <security:intercept-url pattern="/admin"
- requires-channel="${requiredChannel}"
- access="hasRole('ROLE_tavernasuperuser')" />
- <security:intercept-url pattern="/admin/**"
- requires-channel="${requiredChannel}"
- access="hasRole('ROLE_tavernasuperuser')" />
- <security:intercept-url pattern="/rest/**"
- requires-channel="${requiredChannel}"
- access="hasAnyRole('ROLE_tavernauser','ROLE_tavernaworkflow')" />
- <security:intercept-url pattern="/feed"
- requires-channel="${requiredChannel}"
- access="hasRole('ROLE_tavernauser')" />
- <security:intercept-url pattern="/feed/**"
- requires-channel="${requiredChannel}"
- access="hasRole('ROLE_tavernauser')" />
- </security:http>
-</beans>
[04/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js b/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js
new file mode 100644
index 0000000..7835454
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js
@@ -0,0 +1,125 @@
+/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.core.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.23",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number
"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelectio
n:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.cre
atePseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScr
oll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;return b[d]>0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.widget.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){return c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}}),d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;return e=!f&&g.length?a.extend.apply(null,[!0,e
].concat(g)):e,f&&e.charAt(0)==="_"?h:(f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b)return h=f,!1}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))}),h)}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(
this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}return this._setOptions(e),this},_setOptions:function(b){var c=this;return a.each(b,function(a,b){c._setOption(a,b)}),this},_setOption:function(a,b){return this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||
c.isDefaultPrevented())}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.mouse.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent"))return a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(b){if(c)return;this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.del
ay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted)return b.preventDefault(),!0}return!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0,!0},_mouseMove:function(b){return!a.browser.msie||document.documentMode>=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this.
_mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.position.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),
n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left
)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.
curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),a.curCSS||(a.curCSS=a.css),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuer
y);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.draggable.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!this.element.data("draggable"))return;return this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy(),this},_mouseCapture:function(b){var c=this.options;return thi
s.helper||c.disabled||a(b.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(b),this.handle?(c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(b){var c=this.options;return this.helper=this._createHelper(b),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),rel
ative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment(),this._trigger("start",b)===!1?(this._clear(),!1):(this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b),!0)},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1)return this._mouseUp({}),!1;this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!
this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);var d=this.element[0],e=!1;while(d&&(d=d.parentNode))d==document&&(e=!0);if(!e&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var f=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){f._trigger("stop",b)!==!1&&f._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){return this.options.iframeFix===!0&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b),a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(b){var c=!this.options.handle
||!a(this.options.handle,this.element).length?!0:!1;return a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)}),c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute"),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){thi
s.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop")
,10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|wind
ow|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="abs
olute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h
=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.left<h[0]&&(f=h[0]+this.offset.click.left),b.pageY-this.offset.click.top<h[1]&&(g=h[1]+this.offset.click.top),b.pageX-this.offset.click.left>h[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.top<h[1]||j-this.offset.click.top>h[3]?j-this.offset.click.top<h[1]?j+c.grid[1]:j-c.grid[1]:j:j;var k=c.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0]:this.originalPageX;f=h?k-this.offset.click.left<h[0]||k-this.offset.click.left>h[2]?k-this.offset.click.left<h[0]?k+c.grid[0]:k-c.grid[0]:k:k}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&a.browser.version
<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(b,c,d){return d=d||this._uiHash(),a.ui.plugin.call(this,b,[c,d]),b=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),a.Widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(a){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),a.extend(a.ui.draggable,{version:"1.8.23"}),a.ui.plugin.add("draggable","connectToSortable",{start:function(b,c){var d=a(
this).data("draggable"),e=d.options,f=a.extend({},c,{item:d.element});d.sortables=[],a(e.connectToSortable).each(function(){var c=a.data(this,"sortable");c&&!c.options.disabled&&(d.sortables.push({instance:c,shouldRevert:c.options.revert}),c.refreshPositions(),c._trigger("activate",b,f))})},stop:function(b,c){var d=a(this).data("draggable"),e=a.extend({},c,{item:d.element});a.each(d.sortables,function(){this.instance.isOver?(this.instance.isOver=0,d.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(b),this.instance.options.helper=this.instance.options._helper,d.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",b,e))})},drag:function(b,c){var d=a(this).data("draggable"),e=this,f=function(b){var c=this.offset.click.top,d=this.offset.click.left,e=this.positionAbs.top,f=this.positionAbs.left,g
=b.height,h=b.width,i=b.top,j=b.left;return a.ui.isOver(e+c,f+d,i,j,g,h)};a.each(d.sortables,function(f){this.instance.positionAbs=d.positionAbs,this.instance.helperProportions=d.helperProportions,this.instance.offset.click=d.offset.click,this.instance._intersectsWith(this.instance.containerCache)?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=a(e).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return c.helper[0]},b.target=this.instance.currentItem[0],this.instance._mouseCapture(b,!0),this.instance._mouseStart(b,!0,!0),this.instance.offset.click.top=d.offset.click.top,this.instance.offset.click.left=d.offset.click.left,this.instance.offset.parent.left-=d.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=d.offset.parent.top-this.instance.offset.parent.top,d._trigger("toSortable",b),d.dropped=
this.instance.element,d.currentItem=d.element,this.instance.fromOutside=d),this.instance.currentItem&&this.instance._mouseDrag(b)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",b,this.instance._uiHash(this.instance)),this.instance._mouseStop(b,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),d._trigger("fromSortable",b),d.dropped=!1)})}}),a.ui.plugin.add("draggable","cursor",{start:function(b,c){var d=a("body"),e=a(this).data("draggable").options;d.css("cursor")&&(e._cursor=d.css("cursor")),d.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;d._cursor&&a("body").css("cursor",d._cursor)}}),a.ui.plugin.add("draggable","opacity",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("opacity")&&(e._opacity=d.css("opacity")
),d.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;d._opacity&&a(c.helper).css("opacity",d._opacity)}}),a.ui.plugin.add("draggable","scroll",{start:function(b,c){var d=a(this).data("draggable");d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"&&(d.overflowOffset=d.scrollParent.offset())},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=!1;if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"){if(!e.axis||e.axis!="x")d.overflowOffset.top+d.scrollParent[0].offsetHeight-b.pageY<e.scrollSensitivity?d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop+e.scrollSpeed:b.pageY-d.overflowOffset.top<e.scrollSensitivity&&(d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop-e.scrollSpeed);if(!e.axis||e.axis!="y")d.overflowOffset.left+d.scrollParent[0].offsetWidth-b.pageX<e.scrollSensitivity?d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft+e.scrollSpeed:b.pageX-d.overflowOffset.left<e.scrollSensit
ivity&&(d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft-e.scrollSpeed)}else{if(!e.axis||e.axis!="x")b.pageY-a(document).scrollTop()<e.scrollSensitivity?f=a(document).scrollTop(a(document).scrollTop()-e.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<e.scrollSensitivity&&(f=a(document).scrollTop(a(document).scrollTop()+e.scrollSpeed));if(!e.axis||e.axis!="y")b.pageX-a(document).scrollLeft()<e.scrollSensitivity?f=a(document).scrollLeft(a(document).scrollLeft()-e.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<e.scrollSensitivity&&(f=a(document).scrollLeft(a(document).scrollLeft()+e.scrollSpeed))}f!==!1&&a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(d,b)}}),a.ui.plugin.add("draggable","snap",{start:function(b,c){var d=a(this).data("draggable"),e=d.options;d.snapElements=[],a(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var b=a(this),c=b.offset();this!=d.element[0]&&d.snapElements.pu
sh({item:this,width:b.outerWidth(),height:b.outerHeight(),top:c.top,left:c.left})})},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=e.snapTolerance,g=c.offset.left,h=g+d.helperProportions.width,i=c.offset.top,j=i+d.helperProportions.height;for(var k=d.snapElements.length-1;k>=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f<g&&g<m+f&&n-f<i&&i<o+f||l-f<g&&g<m+f&&n-f<j&&j<o+f||l-f<h&&h<m+f&&n-f<i&&i<o+f||l-f<h&&h<m+f&&n-f<j&&j<o+f)){d.snapElements[k].snapping&&d.options.snap.release&&d.options.snap.release.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=!1;continue}if(e.snapMode!="inner"){var p=Math.abs(n-j)<=f,q=Math.abs(o-i)<=f,r=Math.abs(l-h)<=f,s=Math.abs(m-g)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n-d.helperProportions.height,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o,left
:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l-d.helperProportions.width}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m}).left-d.margins.left)}var t=p||q||r||s;if(e.snapMode!="outer"){var p=Math.abs(n-i)<=f,q=Math.abs(o-j)<=f,r=Math.abs(l-g)<=f,s=Math.abs(m-h)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o-d.helperProportions.height,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m-d.helperProportions.width}).left-d.margins.left)}!d.snapElements[k].snapping&&(p||q||r||s||t)&&d.options.snap.snap&&d.options.snap.snap.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=p||q||r||s||t}}}),a.ui.plugin.add("draggable","stack",{st
art:function(b,c){var d=a(this).data("draggable").options,e=a.makeArray(a(d.stack)).sort(function(b,c){return(parseInt(a(b).css("zIndex"),10)||0)-(parseInt(a(c).css("zIndex"),10)||0)});if(!e.length)return;var f=parseInt(e[0].style.zIndex)||0;a(e).each(function(a){this.style.zIndex=f+a}),this[0].style.zIndex=f+e.length}}),a.ui.plugin.add("draggable","zIndex",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("zIndex")&&(e._zIndex=d.css("zIndex")),d.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;d._zIndex&&a(c.helper).css("zIndex",d._zIndex)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.droppable.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var b=this.options,c=b.accept;this.isover=0,this.isout=1,this.accept=a.isFunction(c)?c:function(a){return a.is(c)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},a.ui.ddmanager.droppables[b.scope]=a.ui.ddmanager.droppables[b.scope]||[],a.ui.ddmanager.droppables[b.scope].push(this),b.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++)b[c]==this&&b.splice(c,1);return this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable"),this},_setOption:function(b,c){b=="accept"&&(this.accept=a.isFunction(c)?c:function(a){return a.is(c)}),a.Widget.prototype._setOption.apply(this,arguments)},_activate:function(b){var c=
a.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),c&&this._trigger("activate",b,this.ui(c))},_deactivate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),c&&this._trigger("deactivate",b,this.ui(c))},_over:function(b){var c=a.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return;this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",b,this.ui(c)))},_out:function(b){var c=a.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return;this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;r
eturn this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&&b.accept.call(b.element[0],d.currentItem||d.element)&&a.ui.intersect(d,a.extend(b,{offset:b.element.offset()}),b.options.tolerance))return e=!0,!1}),e?!1:this.accept.call(this.element[0],d.currentItem||d.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",b,this.ui(d)),this.element):!1},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}}),a.extend(a.ui.droppable,{version:"1.8.23"}),a.ui.intersect=function(b,c,d){if(!c.offset)return!1;var e=(b.positionAbs||b.position.absolute).left,f=e+b.helperProportions.width,g=(b.positionAbs||b.position.absolute).top,h=g+b.helperProportions.height,i=c.offset.lef
t,j=i+c.proportions.width,k=c.offset.top,l=k+c.proportions.height;switch(d){case"fit":return i<=e&&f<=j&&k<=g&&h<=l;case"intersect":return i<e+b.helperProportions.width/2&&f-b.helperProportions.width/2<j&&k<g+b.helperProportions.height/2&&h-b.helperProportions.height/2<l;case"pointer":var m=(b.positionAbs||b.position.absolute).left+(b.clickOffset||b.offset.click).left,n=(b.positionAbs||b.position.absolute).top+(b.clickOffset||b.offset.click).top,o=a.ui.isOver(n,m,k,i,c.proportions.height,c.proportions.width);return o;case"touch":return(g>=k&&g<=l||h>=k&&h<=l||g<k&&h>l)&&(e>=i&&e<=j||f>=i&&f<=j||e<i&&f>j);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();g:for(var h=0;h<d.length;h++){if(d[h].options.disabled||b&&!d[h].accept.call(d[h].element[0],b.currentItem||b.element))continue;for(var i=0;i<f.lengt
h;i++)if(f[i]==d[h].element[0]){d[h].proportions.height=0;continue g}d[h].visible=d[h].element.css("display")!="none";if(!d[h].visible)continue;e=="mousedown"&&d[h]._activate.call(d[h],c),d[h].offset=d[h].element.offset(),d[h].proportions={width:d[h].element[0].offsetWidth,height:d[h].element[0].offsetHeight}}},drop:function(b,c){var d=!1;return a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)&&(d=this._drop.call(this,c)||d),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],b.currentItem||b.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,c))}),d},dragStart:function(b,c){b.element.parents(":not(body,html)").bind("scroll.droppable",function(){b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)})},drag:function(b,c){b.options.refreshPositions&&a.ui.ddmanager.prepareOffsets(b,c),a.each(a.ui.ddmanager.droppables[b.opt
ions.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var d=a.ui.intersect(b,this,this.options.tolerance),e=!d&&this.isover==1?"isout":d&&this.isover==0?"isover":null;if(!e)return;var f;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");g.length&&(f=a.data(g[0],"droppable"),f.greedyChild=e=="isover"?1:0)}f&&e=="isover"&&(f.isover=0,f.isout=1,f._out.call(f,c)),this[e]=1,this[e=="isout"?"isover":"isout"]=0,this[e=="isover"?"_over":"_out"].call(this,c),f&&e=="isout"&&(f.isout=0,f.isover=1,f._over.call(f,c))})},dragStop:function(b,c){b.element.parents(":not(body,html)").unbind("scroll.droppable"),b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.resizable.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data(
"resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne
,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e<d.length;e++){var f=a.trim(d[e]),g="ui-resizable-"+f,h=a('<div class="ui-resizable-handle '+g+'"></div>');h.css({zIndex:c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseov
er(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){if(c.disabled)return;a(this).removeClass("ui-resizable-autohide"),b._handles.show()},function(){if(c.disabled)return;b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement),this},_mouseCaptu
re:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalM
ousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");return a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b),!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);return l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigg
er("resize",b,this.ui()),!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}return a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.mi
nHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),e<h.maxWidth&&(h.maxWidth=e),g<h.maxHeight&&(h.maxHeight=g);this._vBoundaries=h},_updateCache:function(a){var b=this.options;this.offset=this.helper.offset(),d(a.left)&&(this.position.left=a.left),d(a.top)&&(this.position.top=a.top),d(a.height)&&(this.size.height=a.height),d(a.width)&&(this.size.width=a.width)},_updateRatio:function(a,b){var c=this.options,e=this.position,f=this.size,g=this.axis;return d(a.height)?a.width=a.height*this.aspectRatio:d(a.width)&&(a.height=a.width/this.aspectRatio),g=="sw"&&(a.left=e.left+(f.width-a.width),a.top=null),g=="nw"&&(a.top=e.top+(f.height-a.height),a.left=e.left+(f.width-a.width)),a},_respectSize:function(a,b){var c=this.helper,e=this._vBoundaries,f=this._aspectRatio||b.shiftKey,g=thi
s.axis,h=d(a.width)&&e.maxWidth&&e.maxWidth<a.width,i=d(a.height)&&e.maxHeight&&e.maxHeight<a.height,j=d(a.width)&&e.minWidth&&e.minWidth>a.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;return p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null),a},_proportionallyResize:function(){var b=this.options;if(!this._proportionallyResizeElements.length)return;var c=this.helper||this.element;for(var d=0;d<this._proportionallyResizeElements.length;d++){var e=this._proportionallyResizeElements[d];if(!this.borderDif){var f=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borde
rLeftWidth")],g=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];this.borderDif=a.map(f,function(a,b){var c=parseInt(a,10)||0,d=parseInt(g[b],10)||0;return c+d})}if(!a.browser.msie||!a(c).is(":hidden")&&!a(c).parents(":hidden").length)e.css({height:c.height()-this.borderDif[0]-this.borderDif[2]||0,width:c.width()-this.borderDif[1]-this.borderDif[3]||0});else continue}},_renderProxy:function(){var b=this.element,c=this.options;this.elementOffset=b.offset();if(this._helper){this.helper=this.helper||a('<div style="overflow:hidden;"></div>');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSiz
e.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:thi
s.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.23"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?[
"width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),1
0),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!i)return;e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i
,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/d.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*d.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d
.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.
originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.
width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.selectable.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("<div class='ui-selectable-helper'></div>")},destroy:function(){return this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy(),this},_mou
seStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(this.options.disabled)return;var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");return d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unsele
cting:d.element}),!1}})},_mouseDrag:function(b){var c=this;this.dragged=!0;if(this.options.disabled)return;var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}return this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!i||i.element==c.element[0])return;var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.right<e||i.top>h||i.bottom<f):d.tolerance=="fit"&&(j=i.left>e&&i.right<g&&i.top>f&&i.bottom<h),j?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,c._trigger("selecting",b,{selecting:i.element}))):(i.selecting&&((b.metaKey||b.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selec
ting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),c._trigger("unselecting",b,{unselecting:i.element}))),i.selected&&!b.metaKey&&!b.ctrlKey&&!i.startselected&&(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,c._trigger("unselecting",b,{unselecting:i.element})))}),!1},_mouseStop:function(b){var c=this;this.dragged=!1;var d=this.options;return a(".ui-unselecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-unselecting"),d.unselecting=!1,d.startselected=!1,c._trigger("unselected",b,{unselected:d.element})}),a(".ui-selecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected"),d.selecting=!1,d.selected=!0,d.startselected=!0,c._trigger("selected",b,{selected:d.element})}),this._trigger("stop",b),this.helper.remove(),!1}}),a.extend(a.ui.selectable,{version:"1.8.23"})})
(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.sortable.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.sortable",a.ui.mouse,{widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return thi
s},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f)return e=a(this),!1});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}return this.currentItem=e,this._removeCurrentsFromItems(),!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset
(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIn
dex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));return a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b),!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY<c.scrollSensitivity?this.scro
llParent[0].scrollTop=d=this.scrollParent[0].scrollTop+c.scrollSpeed:b.pageY-this.overflowOffset.top<c.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-c.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-b.pageX<c.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+c.scrollSpeed:b.pageX-this.overflowOffset.left<c.scrollSensitivity&&(this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft-c.scrollSpeed)):(b.pageY-a(document).scrollTop()<c.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-c.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<c.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+c.scrollSpeed)),b.pageX-a(document).scrollLeft()<c.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-c.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<c.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollL
eft()+c.scrollSpeed))),d!==!1&&a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var e=this.items.length-1;e>=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}return this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseS
top:function(b,c){if(!b)return;a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}return
this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"="),d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")}),d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top
,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+j<i&&b+k>f&&b+k<g;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?l:f<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<g&&h<d+this.helperProportions.height/2&&e-this.helperProportions.height/2<i},_intersectsWithPointer:function(b){var c=this.options.axis==="x"||a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top,b.height),d=this.options.axis==="y"||a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left,b.width),e=c&&d,f=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();return e?this.floating?g&&g=="right"||f=="down"?2:1:f&&(f=="down"?2:1):!1},_intersectsWithSides:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.c
lick.top,b.top+b.height/2,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left+b.width/2,b.width),e=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:e&&(e=="down"&&c||e=="up"&&!c)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){return this._refreshItems(a),this.refreshPositions(),this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options
.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(b){this.items=[],this.containers=[this];var c=this.items,d=this,e=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]],f=this._connectWith();if(f&&this.ready)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=
a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i<m;i++){var n=a(l[i]);n.data(this.widgetName+"-item",k),c.push({item:n,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var c=this.items.length-1;c>=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.con
tainers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return e||(b.style.visibility="hidden"),b},update:function(a,b){if(e&&!d.forcePlaceholderSize)return;b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft
")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui
.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.containers[d].floating?this.items[i].item.offset().left:this.items[i].item.offset().top;Math.abs(j-h)<f&&(f=Math.abs(j-h),g=this.items[i],this.direction=j-h>0?"down":"up")}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;return d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]
),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height()),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.cont
ains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}}
,_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("bo
rderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d
)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(f=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(g=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click
.top<this.containment[1]||h-this.offset.click.top>this.containment[3]?h-this.offset.click.top<this.containment[1]?h+c.grid[1]:h-c.grid[1]:h:h;var i=this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0];f=this.containment?i-this.offset.click.left<this.containment[0]||i-this.offset.click.left>this.containment[2]?i-this.offset.click.left<this.containment[0]?i+c.grid[0]:i-c.grid[0]:i:i}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_rearrange:function(a,b,c,d){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling)
,this.counter=this.counter?++this.counter:1;var e=this,f=this.counter;window.setTimeout(function(){f==e.counter&&e.refreshPositions(!d)},0)},_clear:function(b,c){this.reverting=!1;var d=[],e=this;!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!c&&d.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!c&&d.push(function(a){this._trigger("update",a,this._uiHash())});if(!a.ui.contains(this.element[0],this.currentItem[0])){c||d.push(function(a){this._trigger("remove",a,this._u
iHash())});for(var f=this.containers.length-1;f>=0;f--)a.ui.contains(this.containers[f].element[0],this.currentItem[0])&&!c&&(d.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,this.containers[f])),d.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.containers[f])))}for(var f=this.containers.length-1;f>=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._t
rigger("beforeStop",b,this._uiHash());for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return this.fromOutside=!1,!1}c||this._trigger("beforeStop",b,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!c){for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){a.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(b){var c=b||this;return{helper:c.helper,placeholder:c.placeholder||a([]),position:c.position,originalPosition:c.originalPosition,offset:c.positionAbs,item:c.currentItem,sender:b?b.element:null}}}),a.extend(a.ui.sortable,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
+* https://github.com/jquery/jquery-ui
+* Includes: jquery.ui.accordion.js
+* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
+(function(a,b){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:!0,clearStyle:!1,collapsible:!1,event:"click",fillSpace:!1,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){if(c.disabled)return;a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){if(c.disabled)return;a(this)
.removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("
tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a("<span></span>").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex
"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");return(b.autoHeight||b.fillHeight)&&c.css("height",""),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(this.options.disabled||b.altKey||b.ctrlKey)return;var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._c
<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/t2cogs.png
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/t2cogs.png b/taverna-server-webapp/src/main/resources/static/t2cogs.png
new file mode 100644
index 0000000..a93b3bd
Binary files /dev/null and b/taverna-server-webapp/src/main/resources/static/t2cogs.png differ
[49/49] incubator-taverna-server git commit: simplified in
some poms
Posted by st...@apache.org.
simplified <name> in some poms
Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/commit/8d121b2b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/tree/8d121b2b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/diff/8d121b2b
Branch: refs/heads/master
Commit: 8d121b2b07cb4ab6580ba58fd30ec64fb34566cb
Parents: 2c71f9a
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Feb 23 15:36:47 2015 +0000
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Feb 23 15:36:47 2015 +0000
----------------------------------------------------------------------
taverna-server-port-description/pom.xml | 2 +-
taverna-server-runinterface/pom.xml | 5 +++--
taverna-server-worker/pom.xml | 6 ++++--
3 files changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/8d121b2b/taverna-server-port-description/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-port-description/pom.xml b/taverna-server-port-description/pom.xml
index 99582ed..c49310e 100644
--- a/taverna-server-port-description/pom.xml
+++ b/taverna-server-port-description/pom.xml
@@ -23,7 +23,7 @@ limitations under the License.
<version>3.1.0-incubating-SNAPSHOT</version>
</parent>
<artifactId>taverna-server-port-description</artifactId>
- <name>Apache Taverna Server Workflow Port Descriptor Types</name>
+ <name>Apache Taverna Server Workflow Port Descriptors</name>
<description>The structural types used to describe ports on workflows, as exported by Taverna Server.</description>
<properties>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/8d121b2b/taverna-server-runinterface/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-runinterface/pom.xml b/taverna-server-runinterface/pom.xml
index efd3763..3509180 100644
--- a/taverna-server-runinterface/pom.xml
+++ b/taverna-server-runinterface/pom.xml
@@ -24,7 +24,8 @@ limitations under the License.
</parent>
<artifactId>taverna-server-runinterface</artifactId>
- <name>Apache Taverna Server RMI Interface: Webapp <-> Worker</name>
- <description>This is the implementation of the RMI interface between the workflow run factory and the web-app service front-end.</description>
+ <name>Apache Taverna Server Run interface (RMI)</name>
+ <description>RMI Interface: Webapp <-> Worker.
+ This is the implementation of the RMI interface between the workflow run factory and the web-app service front-end.</description>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/8d121b2b/taverna-server-worker/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-worker/pom.xml b/taverna-server-worker/pom.xml
index 8006c6d..f368b1b 100644
--- a/taverna-server-worker/pom.xml
+++ b/taverna-server-worker/pom.xml
@@ -23,8 +23,10 @@ limitations under the License.
<version>3.1.0-incubating-SNAPSHOT</version>
</parent>
<artifactId>taverna-server-worker</artifactId>
- <name>Apache Taverna Server Workflow Executor/File System Access Process Implementation</name>
- <description>This is the implementation of the factory process that is started up by the web application to manage executing Taverna Workflow executeworkflow.sh calls. Also provides per-user access to filestore.</description>
+ <name>Apache Taverna Server Worker</name>
+ <description>
+ Apache Taverna Server Workflow Executor/File System Access Process Implementation.
+ This is the implementation of the factory process that is started up by the web application to manage executing Taverna Workflow executeworkflow.sh calls. Also provides per-user access to filestore.</description>
<properties>
<workerMainClass>org.taverna.server.localworker.impl.TavernaRunManager</workerMainClass>
[41/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java b/server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java
deleted file mode 100644
index 69c3622..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE.txt" 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.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-/**
- * Description of the profiles that can apply to a workflow.
- *
- * @author Donal K. Fellows
- */
-@XmlRootElement(name = "profiles")
-@XmlType(name = "ProfileList")
-public class ProfileList {
- public List<ProfileList.Info> profile = new ArrayList<ProfileList.Info>();
-
- /**
- * Description of a single workflow profile.
- *
- * @author Donal Fellows
- */
- @XmlRootElement(name = "profile")
- @XmlType(name = "Profile")
- public static class Info {
- @XmlValue
- public String name;
- /**
- * Whether this is the main profile.
- */
- @XmlAttribute(name = "isMain")
- public Boolean main;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/Roles.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Roles.java b/server-webapp/src/main/java/org/taverna/server/master/common/Roles.java
deleted file mode 100644
index 8079b1c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Roles.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.common;
-
-/**
- * The roles defined in this webapp.
- *
- * @author Donal Fellows
- */
-public interface Roles {
- /** The role of a normal user. */
- static final String USER = "ROLE_tavernauser";
- /**
- * The role of an administrator. Administrators <i>should</i> have the
- * normal user role as well.
- */
- static final String ADMIN = "ROLE_tavernasuperuser";
- /**
- * The role of a workflow accessing itself. Do not give users this role.
- */
- static final String SELF = "ROLE_tavernaworkflow";
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java b/server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java
deleted file mode 100644
index 3486bf7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.SERVER;
-import static org.taverna.server.master.common.Namespaces.XLINK;
-import static org.taverna.server.master.common.VersionedElement.VERSION;
-
-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;
-
-/**
- * A reference to a single workflow run, described using JAXB.
- *
- * @author Donal Fellows
- * @see org.taverna.server.master.interfaces.TavernaRun TavernaRun
- */
-@XmlRootElement
-@XmlType(name = "TavernaRun")
-@XmlSeeAlso( { Workflow.class, DirEntryReference.class })
-public class RunReference {
- /**
- * Where to get information about the run. For REST.
- */
- @XmlAttribute(name = "href", namespace = XLINK)
- @XmlSchemaType(name = "anyURI")
- public URI link;
- /** What version of server produced this element? */
- @XmlAttribute(namespace = SERVER)
- public String serverVersion;
- /**
- * The name of the run. For SOAP.
- */
- @XmlValue
- public String name;
-
- /**
- * Make a blank run reference.
- */
- public RunReference() {
- }
-
- /**
- * Make a reference to the given workflow run.
- *
- * @param name
- * The name of the run.
- * @param ub
- * A factory for URIs, or <tt>null</tt> if none is to be made.
- */
- public RunReference(String name, UriBuilder ub) {
- this.serverVersion = VERSION;
- this.name = name;
- if (ub != null)
- this.link = ub.build(name);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/Status.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Status.java b/server-webapp/src/main/java/org/taverna/server/master/common/Status.java
deleted file mode 100644
index 8e360dc..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Status.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 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.XmlType;
-
-/**
- * States of a workflow run. They are {@link #Initialized Initialized},
- * {@link #Operating Operating}, {@link #Stopped Stopped}, and {@link #Finished
- * Finished}. Conceptually, there is also a <tt>Destroyed</tt> state, but the
- * workflow run does not exist (and hence can't have its state queried or set)
- * in that case.
- *
- * @author Donal Fellows
- */
-@XmlEnum
-@XmlType(name = "Status")
-public enum Status {
- /**
- * The workflow run has been created, but is not yet running. The run will
- * need to be manually moved to {@link #Operating Operating} when ready.
- */
- Initialized,
- /**
- * The workflow run is going, reading input, generating output, etc. Will
- * eventually either move automatically to {@link #Finished Finished} or can
- * be moved manually to {@link #Stopped Stopped} (where supported).
- */
- Operating,
- /**
- * The workflow run is paused, and will need to be moved back to
- * {@link #Operating Operating} manually.
- */
- Stopped,
- /**
- * The workflow run has ceased; data files will continue to exist until the
- * run is destroyed (which may be manual or automatic).
- */
- Finished
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/Trust.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Trust.java b/server-webapp/src/main/java/org/taverna/server/master/common/Trust.java
deleted file mode 100644
index 6d77aa7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Trust.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.security.cert.Certificate;
-import java.util.Collection;
-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.XmlTransient;
-import javax.xml.bind.annotation.XmlType;
-
-/**
- * A description of a trusted identity or identities. This description is
- * characterised by a file visible to the workflow run that contains one or more
- * certificates.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "TrustDescriptor")
-@XmlRootElement(name = "trustedIdentity")
-@SuppressWarnings("serial")
-public final class Trust 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 file containing the certificate(s). This is resolved with respect to
- * the workflow run working directory.
- */
- @XmlElement
- public String certificateFile;
- /**
- * The type of certificate file. Defaults to <tt>X.509</tt> if unspecified.
- */
- @XmlElement
- public String fileType;
- /**
- * The encoded serialized keystore containing the certificate(s).
- */
- @XmlElement
- public byte[] certificateBytes;
- /**
- * The names of the server(s) identified by this trust.
- */
- @XmlElement
- public List<String> serverName;
- /**
- * The collection of certificates loaded from the specified file. This is
- * always <tt>null</tt> before validation.
- */
- public transient Collection<? extends Certificate> loadedCertificates;
-
- @Override
- public int hashCode() {
- return id.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == null || !(o instanceof Trust))
- return false;
- return id.equals(((Trust) o).id);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/Uri.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Uri.java b/server-webapp/src/main/java/org/taverna/server/master/common/Uri.java
deleted file mode 100644
index d6d057c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Uri.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.common;
-
-import static javax.ws.rs.core.UriBuilder.fromUri;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.common.Namespaces.XLINK;
-
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.util.Map;
-
-import javax.annotation.PreDestroy;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriBuilderException;
-import javax.ws.rs.core.UriInfo;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.web.PortMapper;
-
-import javax.annotation.Nonnull;
-
-/**
- * A class that makes it simpler to work with an element with a {@link URI} in
- * an <tt>href</tt> attribute. Done with JAXB.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "Location")
-public class Uri {
- static Log log = getLog("Taverna.Server.UriRewriter");
- private static final String SECURE_SCHEME = "https";
- /**
- * This type is characterised by an attribute that is the reference to some
- * other element.
- */
- @XmlAttribute(name = "href", namespace = XLINK)
- @XmlSchemaType(name = "anyURI")
- public URI ref;
-
- /** Make a reference that points nowhere. */
- public Uri() {
- }
-
- /**
- * Make a reference to the given location.
- *
- * @param ref
- * Where to point to.
- */
- public Uri(@Nonnull URI ref) {
- this.ref = secure(ref);
- }
-
- /**
- * Make a reference from the factory with the given parameters.
- *
- * @param ub
- * The configured factory.
- * @param strings
- * The parameters to the factory.
- */
- public Uri(@Nonnull UriBuilder ub, String... strings) {
- ref = secure(ub).build((Object[]) strings);
- }
-
- /**
- * Make a reference from the factory with the given parameters.
- *
- * @param ui
- * The factory factory.
- * @param path
- * The path to configure the factory with.
- * @param strings
- * The parameters to the factory.
- */
- public Uri(@Nonnull UriInfo ui, @Nonnull String path, String... strings) {
- this(ui, true, path, strings);
- }
-
- /**
- * Make a reference from the factory with the given parameters.
- *
- * @param ui
- * The factory factory.
- * @param secure
- * Whether the URI should be required to use HTTPS.
- * @param path
- * The path to configure the factory with.
- * @param strings
- * The parameters to the factory.
- */
- public Uri(@Nonnull UriInfo ui, boolean secure, @Nonnull String path,
- String... strings) {
- UriBuilder ub = ui.getAbsolutePathBuilder();
- if (secure) {
- ub = secure(ub);
- }
- ref = ub.path(path).build((Object[]) strings);
- }
-
- public static UriBuilder secure(UriBuilder ub) {
- return Rewriter.getInstance().getSecuredUriBuilder(ub);
- }
-
- public static UriBuilder secure(UriInfo ui) {
- return secure(ui.getAbsolutePathBuilder());
- }
-
- public static URI secure(URI uri) {
- URI newURI = secure(fromUri(uri)).build();
- if (log.isDebugEnabled())
- log.debug("rewrote " + uri + " to " + newURI);
- return newURI;
- }
-
- public static URI secure(URI base, String uri) {
- URI newURI = secure(fromUri(base.resolve(uri))).build();
- if (log.isDebugEnabled())
- log.debug("rewrote " + uri + " to " + newURI);
- return newURI;
- }
-
- /**
- * A bean that allows configuration of how to rewrite generated URIs to be
- * secure.
- *
- * @author Donal Fellows
- */
- public static class Rewriter {
- private static Rewriter instance;
- private PortMapper portMapper;
- private boolean suppress;
- private String rewriteRE = "://[^/]+/[^/]+";
- private String rewriteTarget;
-
- static Rewriter getInstance() {
- if (instance == null)
- new Rewriter();
- return instance;
- }
-
- @Autowired
- public void setPortMapper(PortMapper portMapper) {
- this.portMapper = portMapper;
- }
-
- /**
- * Whether to suppress rewriting of URIs to be secure.
- *
- * @param suppressSecurity
- * True if no rewriting should be done.
- */
- public void setSuppressSecurity(boolean suppressSecurity) {
- suppress = suppressSecurity;
- }
-
- public void setRewriteRegexp(String rewriteRegexp) {
- this.rewriteRE = rewriteRegexp;
- }
-
- /**
- * What to rewrite the host, port and web-app name to be.
- *
- * @param rewriteTarget
- * What to rewrite to, or "<tt>NONE</tt>" for no rewrite.
- */
- public void setRewriteTarget(String rewriteTarget) {
- if (rewriteTarget.isEmpty())
- this.rewriteTarget = null;
- else if (rewriteTarget.equals("NONE"))
- this.rewriteTarget = null;
- else if (rewriteTarget.startsWith("${"))
- this.rewriteTarget = null;
- else
- this.rewriteTarget = "://" + rewriteTarget;
- }
-
- private Integer lookupHttpsPort(URI uri) {
- if (portMapper != null)
- return portMapper.lookupHttpsPort(uri.getPort());
- return null;
- }
-
- public Rewriter() {
- instance = this;
- }
-
- @PreDestroy
- public void done() {
- instance = null;
- Uri.log = null;
- }
-
- @Nonnull
- URI rewrite(@Nonnull String url) {
- if (rewriteTarget != null)
- url = url.replaceFirst(rewriteRE, rewriteTarget);
- return URI.create(url);
- }
-
- @Nonnull
- public UriBuilder getSecuredUriBuilder(@Nonnull UriBuilder uribuilder) {
- if (suppress)
- return uribuilder.clone();
- UriBuilder ub = new RewritingUriBuilder(uribuilder);
- Integer secPort = null;
- try {
- secPort = lookupHttpsPort(ub.build());
- } catch (Exception e) {
- /*
- * Do not log this; we know why it happens and don't actually
- * care to do anything about it. All it does is fill up the log
- * with pointless scariness!
- */
-
- // log.debug("failed to extract current URI port", e);
- }
- if (secPort == null || secPort.intValue() == -1)
- return ub.scheme(SECURE_SCHEME);
- return ub.scheme(SECURE_SCHEME).port(secPort);
- }
-
- /**
- * {@link UriBuilder} that applies a rewrite rule to the URIs produced
- * by the wrapped builder.
- *
- * @author Donal Fellows
- */
- class RewritingUriBuilder extends UriBuilder {
- private UriBuilder wrapped;
-
- RewritingUriBuilder(UriBuilder builder) {
- wrapped = builder.clone();
- }
-
- private URI rewrite(URI uri) {
- return Rewriter.this.rewrite(uri.toString());
- }
-
- @Override
- public UriBuilder clone() {
- return new RewritingUriBuilder(wrapped);
- }
-
- @Override
- public URI buildFromMap(Map<String, ?> values)
- throws IllegalArgumentException, UriBuilderException {
- return rewrite(wrapped.buildFromMap(values));
- }
-
- @Override
- public URI buildFromEncodedMap(Map<String, ? extends Object> values)
- throws IllegalArgumentException, UriBuilderException {
- return rewrite(wrapped.buildFromEncodedMap(values));
- }
-
- @Override
- public URI build(Object... values) throws IllegalArgumentException,
- UriBuilderException {
- return rewrite(wrapped.build(values));
- }
-
- @Override
- public URI build(Object[] values, boolean encodeSlashInPath)
- throws IllegalArgumentException, UriBuilderException {
- return rewrite(wrapped.build(values, encodeSlashInPath));
- }
-
- @Override
- public URI buildFromEncoded(Object... values)
- throws IllegalArgumentException, UriBuilderException {
- return rewrite(wrapped.buildFromEncoded(values));
- }
-
- @Override
- public URI buildFromMap(Map<String, ?> values,
- boolean encodeSlashInPath) throws IllegalArgumentException,
- UriBuilderException {
- return rewrite(wrapped.buildFromEncoded(values,
- encodeSlashInPath));
- }
-
- @Override
- public UriBuilder uri(URI uri) throws IllegalArgumentException {
- wrapped.uri(uri);
- return this;
- }
-
- @Override
- public UriBuilder uri(String uriTemplate)
- throws IllegalArgumentException {
- wrapped.uri(uriTemplate);
- return this;
- }
-
- @Override
- public String toTemplate() {
- return wrapped.toTemplate();
- }
-
- @Override
- public UriBuilder scheme(String scheme)
- throws IllegalArgumentException {
- wrapped.scheme(scheme);
- return this;
- }
-
- @Override
- public UriBuilder schemeSpecificPart(String ssp)
- throws IllegalArgumentException {
- wrapped.schemeSpecificPart(ssp);
- return this;
- }
-
- @Override
- public UriBuilder userInfo(String ui) {
- wrapped.userInfo(ui);
- return this;
- }
-
- @Override
- public UriBuilder host(String host) throws IllegalArgumentException {
- wrapped.host(host);
- return this;
- }
-
- @Override
- public UriBuilder port(int port) throws IllegalArgumentException {
- wrapped.port(port);
- return this;
- }
-
- @Override
- public UriBuilder replacePath(String path) {
- wrapped.replacePath(path);
- return this;
- }
-
- @Override
- public UriBuilder path(String path) throws IllegalArgumentException {
- wrapped.path(path);
- return this;
- }
-
- @Override
- public UriBuilder path(
- @java.lang.SuppressWarnings("rawtypes") Class resource)
- throws IllegalArgumentException {
- wrapped.path(resource);
- return this;
- }
-
- @Override
- public UriBuilder path(
- @java.lang.SuppressWarnings("rawtypes") Class resource,
- String method) throws IllegalArgumentException {
- wrapped.path(resource, method);
- return this;
- }
-
- @Override
- public UriBuilder path(Method method)
- throws IllegalArgumentException {
- wrapped.path(method);
- return this;
- }
-
- @Override
- public UriBuilder segment(String... segments)
- throws IllegalArgumentException {
- wrapped.segment(segments);
- return this;
- }
-
- @Override
- public UriBuilder replaceMatrix(String matrix)
- throws IllegalArgumentException {
- wrapped.replaceMatrix(matrix);
- return this;
- }
-
- @Override
- public UriBuilder matrixParam(String name, Object... values)
- throws IllegalArgumentException {
- wrapped.matrixParam(name, values);
- return this;
- }
-
- @Override
- public UriBuilder replaceMatrixParam(String name, Object... values)
- throws IllegalArgumentException {
- wrapped.replaceMatrixParam(name, values);
- return this;
- }
-
- @Override
- public UriBuilder replaceQuery(String query)
- throws IllegalArgumentException {
- wrapped.replaceQuery(query);
- return this;
- }
-
- @Override
- public UriBuilder queryParam(String name, Object... values)
- throws IllegalArgumentException {
- wrapped.queryParam(name, values);
- return this;
- }
-
- @Override
- public UriBuilder replaceQueryParam(String name, Object... values)
- throws IllegalArgumentException {
- wrapped.replaceQueryParam(name, values);
- return this;
- }
-
- @Override
- public UriBuilder fragment(String fragment) {
- wrapped.fragment(fragment);
- return this;
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java b/server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java
deleted file mode 100644
index 6eddf2d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.common;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.common.Namespaces.SERVER;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-import org.apache.commons.logging.Log;
-
-/**
- * The type of an element that declares the version of the server that produced
- * it.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "VersionedElement", namespace = SERVER)
-public abstract class VersionedElement {
- /** What version of server produced this element? */
- @XmlAttribute(namespace = SERVER)
- public String serverVersion;
- /** What revision of server produced this element? Derived from SCM commit. */
- @XmlAttribute(namespace = SERVER)
- public String serverRevision;
- /** When was the server built? */
- @XmlAttribute(namespace = SERVER)
- public String serverBuildTimestamp;
- public static final String VERSION, REVISION, TIMESTAMP;
- static {
- Log log = getLog("Taverna.Server.Webapp");
- Properties p = new Properties();
- try {
- try (InputStream is = VersionedElement.class
- .getResourceAsStream("/version.properties")) {
- p.load(is);
- }
- } catch (IOException e) {
- log.warn("failed to read /version.properties", e);
- }
- VERSION = p.getProperty("tavernaserver.version", "unknownVersion");
- REVISION = String.format("%s (tag: %s)",
- p.getProperty("tavernaserver.branch", "unknownRevision"),
- p.getProperty("tavernaserver.revision.describe", "unknownTag"));
- TIMESTAMP = p
- .getProperty("tavernaserver.timestamp", "unknownTimestamp");
- }
-
- public VersionedElement() {
- }
-
- protected VersionedElement(boolean ignored) {
- serverVersion = VERSION;
- serverRevision = REVISION;
- serverBuildTimestamp = TIMESTAMP;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java b/server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java
deleted file mode 100644
index ba6a68c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.common;
-
-import static javax.xml.bind.Marshaller.JAXB_ENCODING;
-import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT;
-import static javax.xml.bind.annotation.XmlAccessType.NONE;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.rest.handler.Scufl2DocumentHandler.SCUFL2;
-import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;
-import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_NS;
-import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_ROOTNAME;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Serializable;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.net.URL;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAnyElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.taverna.server.master.rest.handler.Scufl2DocumentHandler;
-import org.taverna.server.master.rest.handler.T2FlowDocumentHandler;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-
-import uk.org.taverna.scufl2.api.common.NamedSet;
-import uk.org.taverna.scufl2.api.container.WorkflowBundle;
-import uk.org.taverna.scufl2.api.io.ReaderException;
-import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
-import uk.org.taverna.scufl2.api.io.WriterException;
-import uk.org.taverna.scufl2.api.profiles.Profile;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Encapsulation of a T2flow or Scufl2 document.
- *
- * @author Donal K. Fellows
- */
-@XmlRootElement(name = "workflow")
-@XmlType(name = "Workflow")
-@XmlAccessorType(NONE)
-public class Workflow implements Serializable, Externalizable {
- /** Literal document, if present. */
- @XmlAnyElement(lax = true)
- private Element content;
- /** SCUFL2 bundle, if present. */
- @XmlTransient
- private WorkflowBundle bundle;
- /** Which came first, the bundle or the t2flow document. */
- @XmlTransient
- private boolean isBundleFirst;
-
- private static Marshaller marshaller;
- private static Unmarshaller unmarshaller;
- private final static String ENCODING = "UTF-8";
- private final static WorkflowBundleIO io;
- static {
- try {
- JAXBContext context = JAXBContext.newInstance(Workflow.class);
- marshaller = context.createMarshaller();
- unmarshaller = context.createUnmarshaller();
- marshaller.setProperty(JAXB_ENCODING, ENCODING);
- marshaller.setProperty(JAXB_FORMATTED_OUTPUT, false);
- } catch (JAXBException e) {
- getLog("Taverna.Server.Webapp").fatal(
- "failed to build JAXB context for working with "
- + Workflow.class, e);
- }
- io = new WorkflowBundleIO();
- }
-
- public enum ContentType {
- T2FLOW(T2FlowDocumentHandler.T2FLOW), SCUFL2(
- Scufl2DocumentHandler.SCUFL2);
- private String type;
-
- ContentType(String type) {
- this.type = type;
- }
-
- public String getContentType() {
- return type;
- }
- }
-
- public Workflow() {
- }
-
- public Workflow(Element element) {
- this.content = element;
- this.isBundleFirst = false;
- }
-
- public Workflow(WorkflowBundle bundle) {
- this.bundle = bundle;
- this.isBundleFirst = true;
- }
-
- public Workflow(URL url) throws ReaderException, IOException {
- this(io.readBundle(url, null));
- }
-
- /**
- * What content type would this workflow "prefer" to be?
- */
- public ContentType getPreferredContentType() {
- if (isBundleFirst)
- return ContentType.SCUFL2;
- else
- return ContentType.T2FLOW;
- }
-
- /**
- * Retrieves the workflow as a SCUFL2 document, converting it if necessary.
- *
- * @return The SCUFL2 document.
- * @throws IOException
- * If anything goes wrong.
- */
- public WorkflowBundle getScufl2Workflow() throws IOException {
- try {
- if (bundle == null)
- bundle = io.readBundle(new ByteArrayInputStream(getAsT2Flow()),
- T2FLOW);
- return bundle;
- } catch (IOException e) {
- throw e;
- } catch (Exception e) {
- throw new IOException("problem when converting to SCUFL2", e);
- }
- }
-
- /**
- * Get the bytes of the serialized SCUFL2 workflow.
- *
- * @return Array of bytes.
- * @throws IOException
- * If serialization fails.
- * @throws WriterException
- * If conversion fails.
- */
- public byte[] getScufl2Bytes() throws IOException, WriterException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- io.writeBundle(getScufl2Workflow(), baos, SCUFL2);
- return baos.toByteArray();
- }
-
- /**
- * Retrieves the workflow as a T2Flow document, converting it if necessary.
- *
- * @return The T2Flow document.
- * @throws IOException
- * If anything goes wrong.
- */
- public Element getT2flowWorkflow() throws IOException {
- try {
- if (content != null)
- return content;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- io.writeBundle(bundle, baos, T2FLOW);
- Document doc;
- try {
- DocumentBuilderFactory dbf = DocumentBuilderFactory
- .newInstance();
- dbf.setNamespaceAware(true);
- doc = dbf.newDocumentBuilder().parse(
- new ByteArrayInputStream(baos.toByteArray()));
- } catch (SAXException e) {
- throw new IOException("failed to convert to DOM tree", e);
- }
- Element e = doc.getDocumentElement();
- if (e.getNamespaceURI().equals(T2FLOW_NS)
- && e.getNodeName().equals(T2FLOW_ROOTNAME))
- return content = e;
- throw new IOException(
- "unexpected element when converting to T2Flow: {"
- + e.getNamespaceURI() + "}" + e.getNodeName());
- } catch (IOException e) {
- throw e;
- } catch (Exception e) {
- throw new IOException("problem when converting to SCUFL2", e);
- }
- }
-
- /**
- * @return The name of the main workflow profile, or <tt>null</tt> if there
- * is none.
- */
- public String getMainProfileName() {
- try {
- return getScufl2Workflow().getMainProfile().getName();
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
- * @return The set of profiles supported over this workflow.
- */
- public NamedSet<Profile> getProfiles() {
- try {
- return getScufl2Workflow().getProfiles();
- } catch (IOException e) {
- return new NamedSet<Profile>();
- }
- }
-
- /**
- * Convert from marshalled form.
- *
- * @throws JAXBException
- * If the conversion fails.
- */
- public static Workflow unmarshal(String representation)
- throws JAXBException {
- StringReader sr = new StringReader(representation);
- return (Workflow) unmarshaller.unmarshal(sr);
- }
-
- /**
- * Convert to marshalled form.
- */
- public String marshal() throws JAXBException {
- StringWriter sw = new StringWriter();
- marshaller.marshal(this, sw);
- return sw.toString();
- }
-
- @Override
- public void readExternal(ObjectInput in) throws IOException,
- ClassNotFoundException {
- try {
- ByteArrayInputStream bytes = readbytes(in);
- if (bytes != null)
- try (Reader r = new InputStreamReader(bytes, ENCODING)) {
- content = ((Workflow) unmarshaller.unmarshal(r)).content;
- }
- bytes = readbytes(in);
- if (bytes != null)
- bundle = io.readBundle(bytes, SCUFL2);
- isBundleFirst = in.readBoolean();
- return;
- } catch (JAXBException e) {
- throw new IOException("failed to unmarshal", e);
- } catch (ClassCastException e) {
- throw new IOException("bizarre result of unmarshalling", e);
- } catch (ReaderException e) {
- throw new IOException("failed to unmarshal", e);
- }
- }
-
- private byte[] getAsT2Flow() throws IOException, JAXBException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- OutputStreamWriter w = new OutputStreamWriter(baos, ENCODING);
- marshaller.marshal(this, w);
- w.close();
- return baos.toByteArray();
- }
-
- private byte[] getAsScufl2() throws IOException, WriterException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- io.writeBundle(bundle, baos, SCUFL2);
- baos.close();
- return baos.toByteArray();
- }
-
- @Override
- public void writeExternal(ObjectOutput out) throws IOException {
- try {
- writebytes(out, (content != null) ? getAsT2Flow() : null);
- } catch (JAXBException e) {
- throw new IOException("failed to marshal t2flow", e);
- }
- try {
- writebytes(out, (bundle != null) ? getAsScufl2() : null);
- } catch (WriterException e) {
- throw new IOException("failed to marshal scufl2", e);
- }
- out.writeBoolean(isBundleFirst);
- }
-
- private ByteArrayInputStream readbytes(ObjectInput in) throws IOException {
- int len = in.readInt();
- if (len > 0) {
- byte[] bytes = new byte[len];
- in.readFully(bytes);
- return new ByteArrayInputStream(bytes);
- }
- return null;
- }
-
- private void writebytes(ObjectOutput out, byte[] data) throws IOException {
- out.writeInt(data == null ? 0 : data.length);
- if (data != null && data.length > 0)
- out.write(data);
- }
-
- /**
- * Make up for the lack of an integrated XPath engine.
- *
- * @param name
- * The element names to look up from the root of the contained
- * document.
- * @return The looked up element, or <tt>null</tt> if it doesn't exist.
- */
- private Element getEl(String... name) {
- Element el = content;
- boolean skip = true;
- for (String n : name) {
- if (skip) {
- skip = false;
- continue;
- }
- if (el == null)
- return null;
- NodeList nl = el.getElementsByTagNameNS(T2FLOW_NS, n);
- if (nl.getLength() == 0)
- return null;
- Node node = nl.item(0);
- if (node instanceof Element)
- el = (Element) node;
- else
- return null;
- }
- return el;
- }
-
- /**
- * @return The content of the embedded
- * <tt><workflow><dataflow><name></tt> element.
- */
- @XmlTransient
- public String getName() {
- return getEl("workflow", "dataflow", "name").getTextContent();
- }
-
- /**
- * @return The embedded <tt><workflow></tt> element.
- */
- @XmlTransient
- public Element getWorkflowRoot() {
- return getEl("workflow");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/common/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/common/package-info.java
deleted file mode 100644
index fd040de..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/package-info.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains the common XML elements used throughout Taverna Server's various interfaces.
- * @author Donal Fellows
- */
-@XmlSchema(namespace = SERVER, 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) })
-package org.taverna.server.master.common;
-
-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.XLINK;
-
-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/server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java b/server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java
deleted file mode 100644
index e9c58a9..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.common.version;
-
-import static org.taverna.server.master.common.version.Constants.PATCH;
-import static org.taverna.server.master.common.version.Constants.VERSION;
-
-/**
- * Common location for describing the version of the server.
- *
- * @author Donal Fellows
- */
-public interface Version {
- public static final String JAVA = VERSION + Constants.releaseChar + PATCH;
- public static final String HTML = VERSION + Constants.releaseHEnt + PATCH;
- public static final String XML = VERSION + Constants.releaseXEnt + PATCH;
-}
-
-/**
- * The pieces of a version string.
- *
- * @author Donal Fellows
- */
-interface Constants {
- static final String MAJOR = "2";
- static final String MINOR = "5";
- static final String PATCH = "4";
-
- static final char alphaChar = '\u03b1';
- static final char betaChar = '\u03b2';
- static final char releaseChar = '.';
- static final String alphaHEnt = "α";
- static final String betaHEnt = "β";
- static final String releaseHEnt = ".";
- static final String alphaXEnt = "α";
- static final String betaXEnt = "β";
- static final String releaseXEnt = ".";
-
- static final String VERSION = MAJOR + "." + MINOR;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java b/server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java
deleted file mode 100644
index c2a2bc9..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.defaults;
-
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.localworker.LocalWorkerState;
-
-/**
- * This defines a collection of default values, collecting them from various
- * parts of the server.
- *
- * @author Donal Fellows
- */
-public interface Default {
- /** The default value of the <tt>prefix</tt> property. */
- static final String AUTHORITY_PREFIX = "LOCALUSER_";
-
- /**
- * The name of the resource that is the implementation of the subprocess
- * that this class will fork off.
- */
- static final String SERVER_WORKER_IMPLEMENTATION_JAR = "util/server.worker.jar";
-
- /**
- * The name of the resource that is the implementation of the subprocess
- * that manages secure forking.
- */
- static final String SECURE_FORK_IMPLEMENTATION_JAR = "util/secure.fork.jar";
-
- /**
- * The name of the resource that is the implementation of the subprocess
- * that acts as the RMI registry.
- */
- static final String REGISTRY_JAR = "util/rmi.daemon.jar";
-
- /** Initial lifetime of runs, in minutes. */
- static final int RUN_LIFE_MINUTES = 20;
-
- /**
- * Maximum number of runs to exist at once. Note that this includes when
- * they are just existing for the purposes of file transfer (
- * {@link Status#Initialized}/{@link Status#Finished} states).
- */
- static final int RUN_COUNT_MAX = 5;
-
- /**
- * Prefix to use for RMI names.
- */
- static final String RMI_PREFIX = "ForkRunFactory.";
-
- /** Default value for {@link LocalWorkerState#passwordFile}. */
- static final String PASSWORD_FILE = null;
-
- /**
- * The extra arguments to pass to the subprocess.
- */
- static final String[] EXTRA_ARGUMENTS = new String[0];
-
- /**
- * How long to wait for subprocess startup, in seconds.
- */
- static final int SUBPROCESS_START_WAIT = 40;
-
- /**
- * Polling interval to use during startup, in milliseconds.
- */
- static final int SUBPROCESS_START_POLL_SLEEP = 1000;
-
- /**
- * Maximum number of {@link Status#Operating} runs at any time.
- */
- static final int RUN_OPERATING_LIMIT = 10;
-
- /**
- * What fields of a certificate we look at when understanding who it is
- * talking about, in the order that we look.
- */
- static final String[] CERTIFICATE_FIELD_NAMES = { "CN", "COMMONNAME",
- "COMMON NAME", "COMMON_NAME", "OU", "ORGANIZATIONALUNITNAME",
- "ORGANIZATIONAL UNIT NAME", "O", "ORGANIZATIONNAME",
- "ORGANIZATION NAME" };
-
- /** The type of certificates that are processed if we don't say otherwise. */
- static final String CERTIFICATE_TYPE = "X.509";
-
- /** Max size of credential file, in kiB. */
- static final int CREDENTIAL_FILE_SIZE_LIMIT = 20;
-
- /**
- * The notification message format to use if none is configured.
- */
- public static final String NOTIFY_MESSAGE_FORMAT = "Your job with ID={0} has finished with exit code {1,number,integer}.";
-
- /** The address of the SMS gateway service used. */
- public static final String SMS_GATEWAY_URL = "https://www.intellisoftware.co.uk/smsgateway/sendmsg.aspx";
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java
deleted file mode 100644
index 239b260..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * This package contains information about the various default values supported by the server.
- * @author Donal Fellows
- */
-package org.taverna.server.master.defaults;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java
deleted file mode 100644
index 0b6247e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Indicates that the port name was not recognized.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "BadInputPortNameFault")
-@SuppressWarnings("serial")
-public class BadInputPortNameException extends Exception {
- public BadInputPortNameException(String msg) {
- super(msg);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java
deleted file mode 100644
index 303b19b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Indicates a bad property value.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "BadPropertyValueFault")
-public class BadPropertyValueException extends NoListenerException {
- private static final long serialVersionUID = -8459491388504556875L;
-
- public BadPropertyValueException(String msg) {
- super(msg);
- }
-
- public BadPropertyValueException(String msg, Throwable e) {
- super(msg, e);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java
deleted file mode 100644
index 4b843e2..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Exception that is thrown to indicate that the state change requested for a
- * run is impossible.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NoUpdateFault")
-public class BadStateChangeException extends NoUpdateException {
- private static final long serialVersionUID = -4490826388447601775L;
-
- public BadStateChangeException() {
- super("cannot do that state change");
- }
-
- public BadStateChangeException(Throwable t) {
- super("cannot do that state change", t);
- }
-
- public BadStateChangeException(String msg, Throwable t) {
- super(msg, t);
- }
-
- public BadStateChangeException(String message) {
- super(message);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java
deleted file mode 100644
index 0b6cf07..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import java.rmi.RemoteException;
-
-import javax.xml.ws.WebFault;
-
-/**
- * An exception that happened when the underlying filesystem was accessed.
- * @author Donal Fellows
- */
-@WebFault(name = "FilesystemAccessFault")
-public class FilesystemAccessException extends Exception {
- private static final long serialVersionUID = 8715937300989820318L;
-
- public FilesystemAccessException(String msg) {
- super(msg);
- }
-
- public FilesystemAccessException(String string, Throwable cause) {
- super(string, getRealCause(cause));
- }
-
- private static Throwable getRealCause(Throwable t) {
- if (t instanceof RemoteException) {
- RemoteException remote = (RemoteException) t;
- if (remote.detail != null)
- return remote.detail;
- }
- if (t.getCause() != null)
- return t.getCause();
- return t;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java
deleted file mode 100644
index 11d47c7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Some sort of exception that occurred which we can't map any other way. This
- * is generally indicative of a problem server-side.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "GeneralFailureFault", targetNamespace = SERVER_SOAP)
-@SuppressWarnings("serial")
-public class GeneralFailureException extends RuntimeException {
- public GeneralFailureException(Throwable cause) {
- super(cause.getMessage(), cause);
- }
-
- public GeneralFailureException(String message, Throwable cause) {
- super(message, cause);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java
deleted file mode 100644
index 67ba551..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-/**
- * An exception that is thrown to indicate that a credential-descriptor or
- * trust-descriptor supplied as part of a credential or trust management
- * operation is invalid.
- *
- * @author Donal Fellows
- *
- */
-@SuppressWarnings("serial")
-public class InvalidCredentialException extends Exception {
- private static final String MSG = "that credential is invalid";
-
- public InvalidCredentialException() {
- super(MSG);
- }
-
- public InvalidCredentialException(String reason) {
- super(MSG + ": " + reason);
- }
-
- public InvalidCredentialException(String reason, Throwable cause) {
- this(reason);
- initCause(cause);
- }
-
- public InvalidCredentialException(Throwable cause) {
- this(cause.getMessage(), cause);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java
deleted file mode 100644
index e2ddf4c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-
-/**
- * Exception that is thrown to indicate that the user is not permitted to
- * create something.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NoCreateFault")
-public class NoCreateException extends NoUpdateException {
- private static final long serialVersionUID = 270413810410167235L;
-
- public NoCreateException() {
- super("not permitted to create");
- }
-
- public NoCreateException(String string) {
- super(string);
- }
-
- public NoCreateException(String string, Throwable e) {
- super(string, e);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java
deleted file mode 100644
index 7077fc4..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-/**
- * Exception that indicates the absence of an expected credential.
- *
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-public class NoCredentialException extends Exception {
- public NoCredentialException() {
- super("no such credential");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java
deleted file mode 100644
index d7b0d29..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-
-/**
- * Exception that is thrown to indicate that the user is not permitted to
- * destroy something.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NoDestroyFault")
-public class NoDestroyException extends NoUpdateException {
- private static final long serialVersionUID = 6207448533265237933L;
-
- public NoDestroyException() {
- super("not permitted to destroy");
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java
deleted file mode 100644
index 0d6ca63..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Indicates that the file or directory name was not recognized.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NoDirectoryEntryFault")
-@SuppressWarnings("serial")
-public class NoDirectoryEntryException extends Exception {
- public NoDirectoryEntryException(String msg) {
- super(msg);
- }
- public NoDirectoryEntryException(String msg,Exception cause) {
- super(msg, cause);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java
deleted file mode 100644
index f4b8e81..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.bind.annotation.XmlSeeAlso;
-import javax.xml.ws.WebFault;
-
-/**
- * Exception thrown to indicate that no listener by that name exists, or that
- * some other problem with listeners has occurred.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NoListenerFault")
-@XmlSeeAlso(BadPropertyValueException.class)
-public class NoListenerException extends Exception {
- private static final long serialVersionUID = -2550897312787546547L;
-
- public NoListenerException() {
- super("no such listener");
- }
-
- public NoListenerException(String msg) {
- super(msg);
- }
-
- public NoListenerException(String msg, Throwable t) {
- super(msg, t);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java
deleted file mode 100644
index c49d111..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.bind.annotation.XmlSeeAlso;
-import javax.xml.ws.WebFault;
-
-/**
- * Exception that is thrown to indicate that the user is not permitted to update
- * something.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NoUpdateFault")
-@XmlSeeAlso( { NoCreateException.class, NoDestroyException.class, BadStateChangeException.class })
-public class NoUpdateException extends Exception {
- private static final long serialVersionUID = 4230987102653846379L;
-
- public NoUpdateException() {
- super("not permitted to update");
- }
-
- public NoUpdateException(String msg) {
- super(msg);
- }
-
- public NoUpdateException(String string, Throwable e) {
- super(string, e);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java
deleted file mode 100644
index 6e1f792..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * An exception thrown when an operation is attempted which only the owner is
- * permitted to do. Notably, permissions may <i>only</i> be manipulated by the
- * owner.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "NotOwnerFault")
-@SuppressWarnings("serial")
-public class NotOwnerException extends Exception {
- public NotOwnerException() {
- super("not permitted; not the owner");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java
deleted file mode 100644
index dda371e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Exception that is thrown to indicate that the state change requested for a
- * run is currently impossible due to excessive server load.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "OverloadedFault")
-public class OverloadedException extends BadStateChangeException {
- private static final long serialVersionUID = 490826388447601776L;
-
- public OverloadedException() {
- super("server too busy; try later please");
- }
-
- public OverloadedException(Throwable t) {
- super("server too busy; try later please", t);
- }
-
- public OverloadedException(String msg, Throwable t) {
- super(msg, t);
- }
-
- public OverloadedException(String message) {
- super(message);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java
deleted file mode 100644
index 4632d4a..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.exceptions;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Exception thrown to indicate that the handle of the run is unknown (or
- * unacceptable to the current user).
- *
- * @author Donal Fellows
- */
-@WebFault(name = "UnknownRunFault")
-public class UnknownRunException extends Exception {
- private static final long serialVersionUID = -3028749401786242841L;
-
- public UnknownRunException() {
- super("unknown run UUID");
- }
-
- public UnknownRunException(Throwable t) {
- super("implementation problems", t);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java
deleted file mode 100644
index 29ccacd..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains the exceptions/faults thrown by Taverna Server.
- * @author Donal Fellows
- */
-@XmlSchema(namespace = SERVER, 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) })
-package org.taverna.server.master.exceptions;
-
-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.XLINK;
-
-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/server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java b/server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java
deleted file mode 100644
index 0015754..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.facade;
-
-import static javax.ws.rs.core.MediaType.TEXT_HTML_TYPE;
-import static javax.ws.rs.core.Response.ok;
-
-import java.io.IOException;
-import java.net.URL;
-
-import javax.ws.rs.GET;
-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.UriInfo;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.utils.Contextualizer;
-
-/**
- * This is a simple class that is used to serve up a file (with a simple
- * substitution applied) as the root of the T2Server webapp.
- *
- * @author Donal Fellows
- */
-@Path("/")
-public class Facade {
- private Log log = LogFactory.getLog("Taverna.Server.Utils");
- private String welcome;
- private Contextualizer contextualizer;
-
- /**
- * Set what resource file to use as the template for the response.
- *
- * @param file
- * The file from which to load the data (presumed HTML) to serve
- * up as the root content.
- * @throws IOException
- * If the file doesn't exist.
- */
- public void setFile(String file) throws IOException {
- URL full = Facade.class.getResource(file);
- log.info("setting " + full + " as source of root page");
- this.welcome = IOUtils.toString(full);
- }
-
- @Required
- public void setContextualizer(Contextualizer contextualizer) {
- this.contextualizer = contextualizer;
- }
-
- /**
- * Serve up some HTML as the root of the service.
- *
- * @param ui
- * A reference to how we were accessed by the service.
- * @return The response, containing the HTML.
- */
- @GET
- @Path("{dummy:.*}")
- @Produces("text/html")
- public Response get(@Context UriInfo ui) {
- return ok(contextualizer.contextualize(ui, welcome), TEXT_HTML_TYPE)
- .build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java
deleted file mode 100644
index 73c884f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Simple facade used at the top level of the Taverna Server in order to
- * provide an entry splash page.
- */
-package org.taverna.server.master.facade;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java b/server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java
deleted file mode 100644
index 954b6f1..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.factories;
-
-/**
- * Interface to run factories for the purpose of configuration.
- *
- * @author Donal Fellows
- */
-public interface ConfigurableRunFactory extends RunFactory {
- /** Where is the registry? Getter */
- String getRegistryHost();
-
- /** Where is the registry? Setter */
- void setRegistryHost(String host);
-
- /** Where is the registry? Getter */
- int getRegistryPort();
-
- /** Where is the registry? Setter */
- void setRegistryPort(int port);
-
- /** How much can be done at once? Getter */
- int getMaxRuns();
-
- /** How much can be done at once? Setter */
- void setMaxRuns(int maxRuns);
-
- /** How long will things live? Getter */
- int getDefaultLifetime();
-
- /** How long will things live? Setter */
- void setDefaultLifetime(int defaultLifetime);
-
- /** How often do we probe for info? Getter */
- int getSleepTime();
-
- /** How often do we probe for info? Setter */
- void setSleepTime(int sleepTime);
-
- /** How long do we allow for actions? Getter */
- int getWaitSeconds();
-
- /** How long do we allow for actions? Setter */
- void setWaitSeconds(int seconds);
-
- /** How do we start the workflow engine? Getter */
- String getExecuteWorkflowScript();
-
- /** How do we start the workflow engine? Setter */
- void setExecuteWorkflowScript(String executeWorkflowScript);
-
- /** How do we start the file system access process? Getter */
- String getServerWorkerJar();
-
- /** How do we start the file system access process? Setter */
- void setServerWorkerJar(String serverWorkerJar);
-
- /**
- * How do we start the file system access process? Extra arguments to pass.
- * Getter
- */
- String[] getExtraArguments();
-
- /**
- * How do we start the file system access process? Extra arguments to pass.
- * Setter
- */
- void setExtraArguments(String[] firstArguments);
-
- /** Where is Java? Getter */
- String getJavaBinary();
-
- /** Where is Java? Setter */
- void setJavaBinary(String javaBinary);
-
- /** Where do we get passwords from? Getter */
- String getPasswordFile();
-
- /** Where do we get passwords from? Setter */
- void setPasswordFile(String newValue);
-
- /** How do we switch users? Getter */
- String getServerForkerJar();
-
- /** How do we switch users? Setter */
- void setServerForkerJar(String newValue);
-
- /** How many runs have there been? */
- int getTotalRuns();
-
- /** How long did the last subprocess startup take? */
- int getLastStartupCheckCount();
-
- /** What are the current runs? */
- String[] getCurrentRunNames();
-
- /** What is the RMI ID of the factory process? */
- String getFactoryProcessName();
-
- /** What was the last observed exit code? */
- Integer getLastExitCode();
-
- /** What factory process to use for a particular user? */
- String[] getFactoryProcessMapping();
-
- /** How many runs can be operating at once? Setter */
- void setOperatingLimit(int operatingLimit);
-
- /** How many runs can be operating at once? Getter */
- int getOperatingLimit();
-
- /**
- * How many runs are actually operating?
- *
- * @throws Exception
- * if anything goes wrong
- */
- int getOperatingCount() throws Exception;
-
- /** How do we start the RMI registry process? Getter */
- String getRmiRegistryJar();
-
- /** How do we start the RMI registry process? Setter */
- void setRmiRegistryJar(String rmiRegistryJar);
-
- boolean getGenerateProvenance();
-
- void setGenerateProvenance(boolean generateProvenance);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java b/server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java
deleted file mode 100644
index ecc13cd..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.factories;
-
-import java.util.List;
-
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.TavernaRun;
-
-/**
- * How to make event listeners of various types that are attached to a workflow
- * instance.
- *
- * @author Donal Fellows
- */
-public interface ListenerFactory {
- /**
- * Make an event listener.
- *
- * @param run
- * The workflow instance to attach the event listener to.
- * @param listenerType
- * The type of event listener to create. Must be one of the
- * strings returned by {@link #getSupportedListenerTypes()}.
- * @param configuration
- * A configuration document to pass to the listener.
- * @return The event listener that was created.
- * @throws NoListenerException
- * If the <b>listenerType</b> is unrecognized or the
- * <b>configuration</b> is bad in some way.
- */
- public Listener makeListener(TavernaRun run, String listenerType,
- String configuration) throws NoListenerException;
-
- /**
- * What types of listener are supported? Note that we assume that the list
- * of types is the same for all users and all workflow instances.
- *
- * @return A list of supported listener types.
- */
- public List<String> getSupportedListenerTypes();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java b/server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java
deleted file mode 100644
index eeacad7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.factories;
-
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * How to construct a Taverna Server Workflow Run.
- *
- * @author Donal Fellows
- */
-public interface RunFactory {
- /**
- * Make a Taverna Server workflow run that is bound to a particular user
- * (the "creator") and able to run a particular workflow.
- *
- * @param creator
- * The user creating the workflow instance.
- * @param workflow
- * The workflow to instantiate
- * @return An object representing the run.
- * @throws NoCreateException
- * On failure.
- */
- TavernaRun create(UsernamePrincipal creator, Workflow workflow)
- throws NoCreateException;
-
- /**
- * Check whether the factory is permitting runs to actually start operating.
- *
- * @return Whether a run should start.
- */
- boolean isAllowingRunsToStart();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java
deleted file mode 100644
index 39b9ac6..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * These interfaces define the principal way for the <i>factories</i> of
- * worker classes to be invoked.
- */
-package org.taverna.server.master.factories;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java b/server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java
deleted file mode 100644
index 63402ef..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Extracts the local user id from the set of Spring Security authorities
- * granted to the current user. This is done by scanning the set of authorities
- * to see if any of them start with the substring listed in the <tt>prefix</tt>
- * property; the username is the rest of the authority string in that case.
- *
- * @author Donal Fellows
- */
-public class AuthorityDerivedIDMapper implements LocalIdentityMapper {
- private String prefix = AUTHORITY_PREFIX;
-
- public String getPrefix() {
- return prefix;
- }
-
- public void setPrefix(String prefix) {
- this.prefix = prefix;
- }
-
- @Override
- public String getUsernameForPrincipal(UsernamePrincipal user) {
- Authentication auth = SecurityContextHolder.getContext()
- .getAuthentication();
- if (auth == null || !auth.isAuthenticated())
- return null;
- for (GrantedAuthority authority : auth.getAuthorities()) {
- String token = authority.getAuthority();
- if (token == null)
- continue;
- if (token.startsWith(prefix))
- return token.substring(prefix.length());
- }
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java b/server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java
deleted file mode 100644
index b5fcd5a..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.util.List;
-import java.util.Map.Entry;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * An identity mapper that composes the results from other mappers, using the
- * identity mappers in order until one can provide a non-<tt>null</tt> answer.
- *
- * @author Donal Fellows.
- */
-public class CompositeIDMapper implements LocalIdentityMapper,
- ApplicationContextAware {
- private Log log = getLog("Taverna.Server.IdentityMapper");
- private List<LocalIdentityMapper> mappers;
- private ApplicationContext context;
-
- /**
- * @param mappers
- * The list of mappers to delegate to. Order is significant.
- */
- public void setIdentityMappers(List<LocalIdentityMapper> mappers) {
- this.mappers = mappers;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- context = applicationContext;
- }
-
- @Override
- public String getUsernameForPrincipal(UsernamePrincipal user) {
- if (mappers == null)
- return null;
- for (LocalIdentityMapper m : mappers) {
- String u = m.getUsernameForPrincipal(user);
- if (u == null)
- continue;
- for (Entry<String, ? extends LocalIdentityMapper> entry : context
- .getBeansOfType(m.getClass()).entrySet())
- if (m == entry.getValue()) {
- log.info("used " + entry.getKey() + " LIM to map " + user
- + " to " + u);
- break;
- }
- return u;
- }
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java b/server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java
deleted file mode 100644
index e81f926..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * A trivial principal to user mapper that always uses the same ID.
- * @author Donal Fellows
- */
-public class ConstantIDMapper implements LocalIdentityMapper {
- private String id;
-
- /**
- * Sets what local user ID all users should be mapped to.
- *
- * @param id
- * The local user ID.
- */
- public void setConstantId(String id) {
- this.id = id;
- }
-
- @Override
- public String getUsernameForPrincipal(UsernamePrincipal user) {
- return id;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java b/server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java
deleted file mode 100644
index 42a3874..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.identity;
-
-import static java.util.regex.Pattern.compile;
-
-import java.security.Principal;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * A trivial identity mapper that just uses the name out of the
- * {@link Principal}, or uses a regular expression to extract it from the string
- * representation of the principal.
- *
- * @author Donal Fellows
- */
-public class NameIDMapper implements LocalIdentityMapper {
- private Pattern pat;
-
- /**
- * @param regexp
- * The regular expression to use. The first capturing group
- * within the RE will be the result of the extraction.
- * @throws PatternSyntaxException
- * If the pattern is invalid.
- */
- public void setRegexp(String regexp) throws PatternSyntaxException {
- pat = compile(regexp);
- }
-
- @Override
- public String getUsernameForPrincipal(UsernamePrincipal user) {
- if (pat != null) {
- Matcher m = pat.matcher(user.toString());
- if (m.find() && m.groupCount() > 0) {
- return m.group(1);
- }
- return null;
- }
- return user.getName();
- }
-}
[34/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java b/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java
deleted file mode 100644
index aead6fa..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- *
- */
-package org.taverna.server.master.utils;
-
-import static java.lang.String.format;
-import static java.lang.System.nanoTime;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.io.IOException;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-
-/**
- * Logs the time it takes to service HTTP calls into Taverna Server.
- * <p>
- * This class is currently not used.
- *
- * @author Donal Fellows
- */
-public class CallTimingFilter implements Filter {
- private Log log;
- private String name;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- log = getLog("Taverna.Server.Performance");
- name = filterConfig.getInitParameter("name");
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- if (request instanceof HttpServletRequest)
- doFilter((HttpServletRequest) request,
- (HttpServletResponse) response, chain);
- else
- chain.doFilter(request, response);
- }
-
- public void doFilter(HttpServletRequest request,
- HttpServletResponse response, FilterChain chain)
- throws IOException, ServletException {
- long start = nanoTime();
- chain.doFilter(request, response);
- long elapsedTime = nanoTime() - start;
- log.info(format("%s call to %s %s took %.3fms", name,
- request.getMethod(), request.getRequestURI(),
- elapsedTime / 1000000.0));
- }
-
- @Override
- public void destroy() {
- log = null;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java b/server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java
deleted file mode 100644
index 54b0420..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.taverna.server.master.utils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Properties;
-
-import javax.annotation.PostConstruct;
-
-import org.taverna.server.master.common.Capability;
-
-/**
- * Utility for listing the capabilities supported by this Taverna Server
- * installation.
- *
- * @author Donal Fellows
- */
-public class CapabilityLister {
- public static final String CAPABILITY_RESOURCE_FILE = "/capabilities.properties";
- private Properties properties = new Properties();
-
- @PostConstruct
- void loadCapabilities() throws IOException {
- try (InputStream is = getClass().getResourceAsStream(
- CAPABILITY_RESOURCE_FILE)) {
- if (is != null)
- properties.load(is);
- }
- }
-
- public List<Capability> getCapabilities() {
- List<Capability> caps = new ArrayList<>();
- for (Entry<Object, Object> entry : properties.entrySet()) {
- Capability c = new Capability();
- c.capability = URI.create(entry.getKey().toString());
- c.version = entry.getValue().toString();
- caps.add(c);
- }
- return caps;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java b/server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java
deleted file mode 100644
index c27502f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.unmodifiableList;
-
-import java.io.IOException;
-import java.net.URI;
-import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-import javax.xml.ws.Holder;
-
-/**
- * Obtains the certificate chain for an arbitrary SSL service. Maintains a
- * cache.
- *
- * @author Donal Fellows
- */
-public class CertificateChainFetcher {
- public String getProtocol() {
- return protocol;
- }
-
- public void setProtocol(String protocol) {
- this.protocol = protocol;
- }
-
- public String getKeystoreType() {
- return keystoreType;
- }
-
- public void setKeystoreType(String keystoreType) {
- this.keystoreType = keystoreType;
- }
-
- public String getAlgorithm() {
- return algorithm;
- }
-
- public void setAlgorithm(String algorithm) {
- this.algorithm = algorithm;
- }
-
- public int getTimeout() {
- return timeout;
- }
-
- public void setTimeout(int timeout) {
- this.timeout = timeout;
- }
-
- public void setSecure(boolean secure) {
- this.secure = secure;
- }
-
- private boolean secure = true;
- private String protocol = "TLS";
- private String keystoreType = KeyStore.getDefaultType();
- private String algorithm = TrustManagerFactory.getDefaultAlgorithm();
- private int timeout = 10000;
-
- /**
- * Get the certificate chain for a service.
- *
- * @param host
- * The host (name or IP address) to contact the service on.
- * @param port
- * The port to contact the service on.
- * @return The certificate chain, or <tt>null</tt> if no credentials are
- * available.
- * @throws NoSuchAlgorithmException
- * If the trust manager cannot be set up because of algorithm
- * problems.
- * @throws KeyStoreException
- * If the trust manager cannot be set up because of problems
- * with the keystore type.
- * @throws CertificateException
- * If a bad certificate is present in the default keystore;
- * <i>should be impossible</i>.
- * @throws IOException
- * If problems happen when trying to contact the service.
- * @throws KeyManagementException
- * If the SSL context can't have its special context manager
- * installed.
- */
- private X509Certificate[] getCertificateChainForService(String host,
- int port) throws NoSuchAlgorithmException, KeyStoreException,
- CertificateException, IOException, KeyManagementException {
- KeyStore ks = KeyStore.getInstance(keystoreType);
- SSLContext context = SSLContext.getInstance(protocol);
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
- ks.load(null, null);
- tmf.init(ks);
- final Holder<X509Certificate[]> chain = new Holder<>();
- final X509TrustManager defaultTrustManager = (X509TrustManager) tmf
- .getTrustManagers()[0];
- context.init(null, new TrustManager[] { new X509TrustManager() {
- @Override
- public void checkClientTrusted(X509Certificate[] clientChain,
- String authType) throws CertificateException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] serverChain,
- String authType) throws CertificateException {
- chain.value = serverChain;
- defaultTrustManager.checkServerTrusted(serverChain, authType);
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- throw new UnsupportedOperationException();
- }
- } }, null);
- SSLSocketFactory factory = context.getSocketFactory();
- try (SSLSocket socket = (SSLSocket) factory.createSocket(host, port)) {
- socket.setSoTimeout(timeout);
- socket.startHandshake();
- } catch (SSLException e) {
- // Ignore
- }
- return chain.value;
- }
-
- private Map<URI, List<X509Certificate>> cache = new HashMap<>();
-
- /**
- * Gets the certificate chain for a service identified by URI.
- *
- * @param uri
- * The URI of the (secure) service to identify.
- * @return The certificate chain. Will be <tt>null</tt> if the service is
- * not secure.
- * @throws IOException
- * If the service is unreachable or other connection problems
- * occur.
- * @throws GeneralSecurityException
- * If any of a number of security-related problems occur, such
- * as an inability to match detailed security protocols.
- */
- public List<X509Certificate> getTrustsForURI(URI uri) throws IOException,
- GeneralSecurityException {
- if (!secure)
- return null;
- synchronized (this) {
- if (!cache.containsKey(uri)) {
- int port = uri.getPort();
- if (port == -1)
- switch (uri.getScheme()) {
- case "http":
- port = 80;
- break;
- case "https":
- port = 443;
- break;
- default:
- return null;
- }
- X509Certificate[] chain = getCertificateChainForService(
- uri.getHost(), port);
- if (chain != null)
- cache.put(uri, unmodifiableList(asList(chain)));
- else
- cache.put(uri, null);
- }
- return cache.get(uri);
- }
- }
-
- /**
- * Flushes the cache.
- */
- public void flushCache() {
- synchronized (this) {
- cache.clear();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java b/server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java
deleted file mode 100644
index 884ff94..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import javax.servlet.ServletContext;
-import javax.ws.rs.core.UriInfo;
-
-import org.springframework.web.context.ServletContextAware;
-import org.taverna.server.master.common.version.Version;
-
-/**
- * Convert a string (URL, etc) to a version that is contextualized to the
- * web-application.
- *
- * @author Donal Fellows
- */
-public class Contextualizer implements ServletContextAware {
- static final String ROOT_PLACEHOLDER = "%{WEBAPPROOT}";
- static final String VERSION_PLACEHOLDER = "%{VERSION}";
- static final String BASE_PLACEHOLDER = "%{BASEURL}";
-
- /**
- * Apply the contextualization operation. This consists of replacing the
- * string <tt>{@value #ROOT_PLACEHOLDER}</tt> with the real root of the webapp.
- *
- * @param input
- * the string to contextualize
- * @return the contextualized string
- */
- public String contextualize(String input) {
- // Hack to work around bizarre CXF bug
- String path = context.getRealPath("/").replace("%2D", "-");
- return input.replace(ROOT_PLACEHOLDER, path).replace(
- VERSION_PLACEHOLDER, Version.JAVA);
- }
-
- /**
- * Apply the contextualization operation. This consists of replacing the
- * string <tt>{@value #ROOT_PLACEHOLDER}</tt> with the real root of the
- * webapp.
- *
- * @param ui
- * Where to get information about the URL used to access the
- * webapp.
- * @param input
- * the string to contextualize
- * @return the contextualized string
- */
- public String contextualize(UriInfo ui, String input) {
- // Hack to work around bizarre CXF bug
- String baseuri = ui.getBaseUri().toString().replace("%2D", "-");
- if (baseuri.endsWith("/"))
- baseuri = baseuri.substring(0, baseuri.length() - 1);
- return contextualize(input).replace(BASE_PLACEHOLDER, baseuri);
- }
-
- private ServletContext context;
-
- @Override
- public void setServletContext(ServletContext servletContext) {
- context = servletContext;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java b/server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java
deleted file mode 100644
index f8b39e3..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.taverna.server.master.utils;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.Writer;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Utility class, used to make Derby less broken.
- *
- * @see <a
- * href="http://stackoverflow.com/questions/1004327/getting-rid-of-derby-log">
- * Getting rid of derby.log </a>
- * @see <a
- * href="http://stackoverflow.com/questions/3339736/set-system-property-with-spring-configuration-file">
- * Set system property with Spring configuration file </a>
- */
-public class DerbyUtils {
- /**
- * A writer that channels things on to the log.
- */
- public static final Writer TO_LOG = new DBLog();
- // Hack
- public static final Writer DEV_NULL = TO_LOG;
-}
-
-class DBLog extends Writer {
- private Log log = LogFactory.getLog("Taverna.Server.Database");
- private StringBuilder sb = new StringBuilder();
- private boolean closed = false;
-
- @Override
- public void write(char[] cbuf, int off, int len) throws IOException {
- if (closed)
- throw new EOFException();
- if (!log.isInfoEnabled())
- return;
- sb.append(cbuf, off, len);
- while (!closed) {
- int idx = sb.indexOf("\n"), realIdx = idx;
- if (idx < 0)
- break;
- char ch;
- while (idx > 0 && ((ch = sb.charAt(idx - 1)) == '\r' || ch == ' ' || ch == '\t'))
- idx--;
- if (idx > 0)
- log.info(sb.substring(0, idx));
- sb.delete(0, realIdx + 1);
- }
- }
-
- @Override
- public void flush() throws IOException {
- if (sb.length() > 0) {
- log.info(sb.toString());
- sb = new StringBuilder();
- }
- }
-
- @Override
- public void close() throws IOException {
- flush();
- closed = true;
- sb = null;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java b/server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java
deleted file mode 100644
index 19299e2..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import java.util.List;
-
-import javax.ws.rs.core.PathSegment;
-
-import org.taverna.server.master.common.DirEntryReference;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.TavernaRun;
-
-/**
- * Utility functions for getting entries from directories.
- *
- * @author Donal Fellows
- */
-public class FilenameUtils {
- private static final String TYPE_ERROR = "trying to take subdirectory of file";
- private static final String NO_FILE = "no such directory entry";
- private static final String NOT_A_FILE = "not a file";
- private static final String NOT_A_DIR = "not a directory";
-
- /**
- * Get a named directory entry from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param name
- * The name of the directory entry to look up.
- * @return The directory entry whose name is equal to the last part of the
- * path; an empty path will retrieve the working directory handle
- * itself.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- * @throws FilesystemAccessException
- * If the directory isn't specified or isn't readable.
- */
- public DirectoryEntry getDirEntry(TavernaRun run, String name)
- throws FilesystemAccessException, NoDirectoryEntryException {
- Directory dir = run.getWorkingDirectory();
- if (name == null || name.isEmpty())
- return dir;
- DirectoryEntry found = dir;
- boolean mustBeLast = false;
-
- // Must be nested loops; avoids problems with %-encoded "/" chars
- for (String bit : name.split("/")) {
- if (mustBeLast)
- throw new FilesystemAccessException(TYPE_ERROR);
- found = getEntryFromDir(bit, dir);
- dir = null;
- if (found instanceof Directory) {
- dir = (Directory) found;
- mustBeLast = false;
- } else
- mustBeLast = true;
- }
- return found;
- }
-
- /**
- * Get a named directory entry from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param d
- * The path segments describing what to look up.
- * @return The directory entry whose name is equal to the last part of the
- * path; an empty path will retrieve the working directory handle
- * itself.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- * @throws FilesystemAccessException
- * If the directory isn't specified or isn't readable.
- */
- public DirectoryEntry getDirEntry(TavernaRun run, List<PathSegment> d)
- throws FilesystemAccessException, NoDirectoryEntryException {
- Directory dir = run.getWorkingDirectory();
- if (d == null || d.isEmpty())
- return dir;
- DirectoryEntry found = dir;
- boolean mustBeLast = false;
-
- // Must be nested loops; avoids problems with %-encoded "/" chars
- for (PathSegment segment : d)
- for (String bit : segment.getPath().split("/")) {
- if (mustBeLast)
- throw new FilesystemAccessException(TYPE_ERROR);
- found = getEntryFromDir(bit, dir);
- dir = null;
- if (found instanceof Directory) {
- dir = (Directory) found;
- mustBeLast = false;
- } else
- mustBeLast = true;
- }
- return found;
- }
-
- /**
- * Get a named directory entry from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param d
- * The directory reference describing what to look up.
- * @return The directory entry whose name is equal to the last part of the
- * path in the directory reference; an empty path will retrieve the
- * working directory handle itself.
- * @throws FilesystemAccessException
- * If the directory isn't specified or isn't readable.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- */
- public DirectoryEntry getDirEntry(TavernaRun run, DirEntryReference d)
- throws FilesystemAccessException, NoDirectoryEntryException {
- Directory dir = run.getWorkingDirectory();
- if (d == null || d.path == null || d.path.isEmpty())
- return dir;
- DirectoryEntry found = dir;
- boolean mustBeLast = false;
-
- for (String bit : d.path.split("/")) {
- if (mustBeLast)
- throw new FilesystemAccessException(TYPE_ERROR);
- found = getEntryFromDir(bit, dir);
- dir = null;
- if (found instanceof Directory) {
- dir = (Directory) found;
- mustBeLast = false;
- } else
- mustBeLast = true;
- }
- return found;
- }
-
- /**
- * Get a named directory entry from a directory.
- *
- * @param name
- * The name of the entry; must be "<tt>/</tt>"-free.
- * @param dir
- * The directory to look in.
- * @return The directory entry whose name is equal to the given name.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- * @throws FilesystemAccessException
- * If the directory isn't specified or isn't readable.
- */
- private DirectoryEntry getEntryFromDir(String name, Directory dir)
- throws FilesystemAccessException, NoDirectoryEntryException {
- if (dir == null)
- throw new FilesystemAccessException(NO_FILE);
- for (DirectoryEntry entry : dir.getContents())
- if (entry.getName().equals(name))
- return entry;
- throw new NoDirectoryEntryException(NO_FILE);
- }
-
- /**
- * Get a named directory from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param d
- * The directory reference describing what to look up.
- * @return The directory whose name is equal to the last part of the path in
- * the directory reference; an empty path will retrieve the working
- * directory handle itself.
- * @throws FilesystemAccessException
- * If the directory isn't specified or isn't readable, or if the
- * name doesn't refer to a directory.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- */
- public Directory getDirectory(TavernaRun run, DirEntryReference d)
- throws FilesystemAccessException, NoDirectoryEntryException {
- DirectoryEntry dirEntry = getDirEntry(run, d);
- if (dirEntry instanceof Directory)
- return (Directory) dirEntry;
- throw new FilesystemAccessException(NOT_A_DIR);
- }
-
- /**
- * Get a named directory from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param name
- * The name of the directory to look up.
- * @return The directory.
- * @throws FilesystemAccessException
- * If the directory isn't specified or isn't readable, or if the
- * name doesn't refer to a directory.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- */
- public Directory getDirectory(TavernaRun run, String name)
- throws FilesystemAccessException, NoDirectoryEntryException {
- DirectoryEntry dirEntry = getDirEntry(run, name);
- if (dirEntry instanceof Directory)
- return (Directory) dirEntry;
- throw new FilesystemAccessException(NOT_A_DIR);
- }
-
- /**
- * Get a named file from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param d
- * The directory reference describing what to look up.
- * @return The file whose name is equal to the last part of the path in the
- * directory reference; an empty path will retrieve the working
- * directory handle itself.
- * @throws FilesystemAccessException
- * If the file isn't specified or isn't readable, or if the name
- * doesn't refer to a file.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- */
- public File getFile(TavernaRun run, DirEntryReference d)
- throws FilesystemAccessException, NoDirectoryEntryException {
- DirectoryEntry dirEntry = getDirEntry(run, d);
- if (dirEntry instanceof File)
- return (File) dirEntry;
- throw new FilesystemAccessException(NOT_A_FILE);
- }
-
- /**
- * Get a named file from a workflow run.
- *
- * @param run
- * The run whose working directory is to be used as the root of
- * the search.
- * @param name
- * The name of the file to look up.
- * @return The file whose name is equal to the last part of the path in the
- * directory reference; an empty path will retrieve the working
- * directory handle itself.
- * @throws FilesystemAccessException
- * If the file isn't specified or isn't readable, or if the name
- * doesn't refer to a file.
- * @throws NoDirectoryEntryException
- * If there is no such entry.
- */
- public File getFile(TavernaRun run, String name)
- throws FilesystemAccessException, NoDirectoryEntryException {
- DirectoryEntry dirEntry = getDirEntry(run, name);
- if (dirEntry instanceof File)
- return (File) dirEntry;
- throw new FilesystemAccessException(NOT_A_FILE);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java b/server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java
deleted file mode 100644
index ff52e81..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.taverna.server.master.utils;
-
-import org.apache.cxf.jaxrs.provider.ProviderFactory;
-import org.apache.cxf.message.Message;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
-import org.apache.cxf.phase.Phase;
-
-public class FlushThreadLocalCacheInterceptor extends
- AbstractPhaseInterceptor<Message> {
- public FlushThreadLocalCacheInterceptor() {
- super(Phase.USER_LOGICAL_ENDING);
- }
-
- @Override
- public void handleMessage(Message message) {
- ProviderFactory.getInstance(message).clearThreadLocalProxies();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java b/server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java
deleted file mode 100644
index 55a260b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-
-/**
- * This class is responsible for counting all invocations of publicly-exposed
- * methods of the webapp. It's connected to the webapp primarily through an
- * AspectJ-style pointcut.
- *
- * @author Donal Fellows
- */
-@Aspect
-public class InvocationCounter {
- private int count;
-
- @Before("@annotation(org.taverna.server.master.utils.InvocationCounter.CallCounted)")
- public synchronized void count() {
- count++;
- }
-
- public synchronized int getCount() {
- return count;
- }
-
- /**
- * Mark methods that should be counted by the invocation counter.
- *
- * @author Donal Fellows
- */
- @Retention(RUNTIME)
- @Documented
- @Target(METHOD)
- public static @interface CallCounted {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java b/server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java
deleted file mode 100644
index 252e316..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static java.lang.Integer.MAX_VALUE;
-import static javax.crypto.Cipher.getMaxAllowedKeyLength;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.security.GeneralSecurityException;
-import java.security.NoSuchAlgorithmException;
-
-import javax.annotation.PostConstruct;
-
-import org.apache.commons.logging.Log;
-
-/**
- * Trivial bean that checks for whether the JCE policy files that allow
- * unlimited strength security are present, and warns in the log if not.
- *
- * @author Donal Fellows
- */
-public class JCECheck {
- /**
- * Write a message to the log that says whether an unlimited strength
- * {@linkplain #Cipher cipher} is present. This is the official proxy for
- * whether the unlimited strength JCE policy files have been installed; if
- * absent, the message is logged as a warning, otherwise it is just
- * informational.
- */
- @PostConstruct
- public void checkForUnlimitedJCE() {
- Log log = getLog("Taverna.Server.Utils");
-
- try {
- if (getMaxAllowedKeyLength("AES") < MAX_VALUE)
- log.warn("maximum key length very short; unlimited "
- + "strength JCE policy files maybe missing");
- else
- log.info("unlimited strength JCE policy in place");
- } catch (GeneralSecurityException e) {
- log.warn("problem computing key length limits!", e);
- }
- }
-
- /**
- * @return Whether the unlimited strength JCE policy files are present (or
- * rather whether an unlimited strength {@linkplain #Cipher cipher}
- * is permitted).
- */
- public boolean isUnlimitedStrength() {
- try {
- return getMaxAllowedKeyLength("AES") == MAX_VALUE;
- } catch (NoSuchAlgorithmException e) {
- return false;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java b/server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java
deleted file mode 100644
index ba9ec81..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import java.util.WeakHashMap;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.PreDestroy;
-import javax.jdo.JDOException;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
-import javax.jdo.Query;
-import javax.jdo.Transaction;
-
-import org.apache.commons.logging.Log;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.springframework.beans.factory.annotation.Required;
-
-/**
- * Simple support class that wraps up and provides access to the correct parts
- * of JDO.
- *
- * @author Donal Fellows
- *
- * @param <T> The context class that the subclass will be working with.
- */
-public abstract class JDOSupport<T> {
- private Class<T> contextClass;
- private PersistenceManagerBuilder pmb;
-
- /**
- * Instantiate this class, supplying it a handle to the class that will be
- * used to provide context for queries and accesses.
- *
- * @param contextClass
- * Must match the type parameter to the class itself.
- */
- protected JDOSupport(@Nonnull Class<T> contextClass) {
- this.contextClass = contextClass;
- }
-
- /**
- * @param persistenceManagerBuilder
- * The JDO engine to use for managing persistence.
- */
- @Required
- public void setPersistenceManagerBuilder(
- PersistenceManagerBuilder persistenceManagerBuilder) {
- pmb = persistenceManagerBuilder;
- }
-
- private PersistenceManager pm() {
- if (isPersistent())
- return pmb.getPersistenceManager();
- return null;
- }
-
- /**
- * Has this class actually been configured with a persistence manager by
- * Spring?
- *
- * @return Whether there is a persistence manager installed.
- */
- protected boolean isPersistent() {
- return pmb != null;
- }
-
- /**
- * Get an instance of a query in JDOQL.
- *
- * @param filter
- * The filter part of the query.
- * @return The query, which should be executed to retrieve the results.
- */
- @Nonnull
- protected Query query(@Nonnull String filter) {
- return pm().newQuery(contextClass, filter);
- }
-
- /**
- * Get an instance of a named query attached to the context class (as an
- * annotation).
- *
- * @param name
- * The name of the query.
- * @return The query, which should be executed to retrieve the results.
- * @see javax.jdo.annotations.Query
- */
- @Nonnull
- protected Query namedQuery(@Nonnull String name) {
- return pm().newNamedQuery(contextClass, name);
- }
-
- /**
- * Make an instance of the context class persist in the database. It's
- * identity must not already exist.
- *
- * @param value
- * The instance to persist.
- * @return The persistence-coupled instance.
- */
- @Nullable
- protected T persist(@Nullable T value) {
- if (value == null)
- return null;
- return pm().makePersistent(value);
- }
-
- /**
- * Make a non-persistent (i.e., will hold its value past the end of the
- * transaction) copy of a persistence-coupled instance of the context class.
- *
- * @param value
- * The value to decouple.
- * @return The non-persistent copy.
- */
- @Nullable
- protected T detach(@Nullable T value) {
- if (value == null)
- return null;
- return pm().detachCopy(value);
- }
-
- /**
- * Look up an instance of the context class by its identity.
- *
- * @param id
- * The identity of the object.
- * @return The instance, which is persistence-coupled.
- */
- @Nullable
- protected T getById(Object id) {
- try {
- return pm().getObjectById(contextClass, id);
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Delete a persistence-coupled instance of the context class.
- *
- * @param value
- * The value to delete.
- */
- protected void delete(@Nullable T value) {
- if (value != null)
- pm().deletePersistent(value);
- }
-
- /**
- * Manages integration of JDO transactions with Spring.
- *
- * @author Donal Fellows
- */
- @Aspect
- public static class TransactionAspect {
- private Object lock = new Object();
- private Log log = getLog("Taverna.Server.Utils");
- private volatile int txid;
-
- @Around(value = "@annotation(org.taverna.server.master.utils.JDOSupport.WithinSingleTransaction) && target(support)", argNames = "support")
- Object applyTransaction(ProceedingJoinPoint pjp, JDOSupport<?> support)
- throws Throwable {
- synchronized (lock) {
- PersistenceManager pm = support.pm();
- int id = ++txid;
- Transaction tx = (pm == null) ? null : pm.currentTransaction();
- if (tx != null && tx.isActive())
- tx = null;
- if (tx != null) {
- if (log.isDebugEnabled())
- log.debug("starting transaction #" + id);
- tx.begin();
- }
- try {
- Object result = pjp.proceed();
- if (tx != null) {
- tx.commit();
- if (log.isDebugEnabled())
- log.debug("committed transaction #" + id);
- }
- tx = null;
- return result;
- } catch (Throwable t) {
- try {
- if (tx != null) {
- tx.rollback();
- if (log.isDebugEnabled())
- log.debug("rolled back transaction #" + id);
- }
- } catch (JDOException e) {
- log.warn("rollback failed unexpectedly", e);
- }
- throw t;
- }
- }
- }
- }
-
- /**
- * Mark a method (of a subclass of {@link JDOSupport}) as having a
- * transaction wrapped around it. The transactions are managed correctly in
- * the multi-threaded case.
- *
- * @author Donal Fellows
- */
- @Target(METHOD)
- @Retention(RUNTIME)
- @Documented
- public @interface WithinSingleTransaction {
- }
-
- /**
- * Manages {@linkplain PersistenceManager persistence managers} in a way
- * that doesn't cause problems when the web application is unloaded.
- *
- * @author Donal Fellows
- */
- public static class PersistenceManagerBuilder {
- private PersistenceManagerFactory pmf;
- private WeakHashMap<Thread, PersistenceManager> cache = new WeakHashMap<>();
-
- /**
- * @param persistenceManagerFactory
- * The JDO engine to use for managing persistence.
- */
- @Required
- public void setPersistenceManagerFactory(
- PersistenceManagerFactory persistenceManagerFactory) {
- pmf = persistenceManagerFactory;
- }
-
- @Nonnull
- public PersistenceManager getPersistenceManager() {
- if (cache == null)
- return pmf.getPersistenceManager();
- Thread t = Thread.currentThread();
- PersistenceManager pm = cache.get(t);
- if (pm == null && pmf != null) {
- pm = pmf.getPersistenceManager();
- cache.put(t, pm);
- }
- return pm;
- }
-
- @PreDestroy
- void clearThreadCache() {
- WeakHashMap<Thread, PersistenceManager> cache = this.cache;
- this.cache = null;
- for (PersistenceManager pm : cache.values())
- if (pm != null)
- pm.close();
- cache.clear();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java b/server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java
deleted file mode 100644
index a8aa937..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.taverna.server.master.utils;
-
-import static java.lang.System.currentTimeMillis;
-import static java.lang.Thread.sleep;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.sql.DatabaseMetaData;
-import java.util.Properties;
-
-import org.apache.commons.logging.Log;
-import org.datanucleus.store.rdbms.adapter.DerbyAdapter;
-import org.datanucleus.store.rdbms.identifier.IdentifierFactory;
-import org.datanucleus.store.rdbms.key.CandidateKey;
-import org.datanucleus.store.rdbms.key.ForeignKey;
-import org.datanucleus.store.rdbms.key.Index;
-import org.datanucleus.store.rdbms.key.PrimaryKey;
-import org.datanucleus.store.rdbms.sql.SQLTable;
-import org.datanucleus.store.rdbms.table.Column;
-import org.datanucleus.store.rdbms.table.Table;
-import org.datanucleus.store.rdbms.table.TableImpl;
-import org.datanucleus.store.rdbms.table.ViewImpl;
-
-/**
- * Evil hack to allow logging of the DDL spat out to Derby.
- *
- * @author Donal Fellows
- */
-public class LoggingDerbyAdapter extends DerbyAdapter {
- Log log = getLog("Taverna.Server.SQL");
-
- private StringBuilder ddl = new StringBuilder();
- private volatile long timeout;
- private Thread timer;
-
- private synchronized void logDDL() {
- if (ddl.length() > 0) {
- log.info("Data definition language:\n" + ddl);
- ddl.setLength(0);
- }
- timer = null;
- }
-
- private synchronized void doLog(String item) {
- ddl.append(item);
- if (!item.endsWith("\n"))
- ddl.append('\n');
- timeout = currentTimeMillis() + 5000;
- if (timer == null)
- timer = new OneShotThread("DDL logger timeout", new Runnable() {
- @Override
- public void run() {
- try {
- while (timeout > currentTimeMillis())
- sleep(1000);
- } catch (InterruptedException e) {
- // Ignore
- }
- logDDL();
- }
- });
- }
-
- /**
- * Creates an Apache Derby adapter based on the given metadata which logs
- * the DDL it creates.
- */
- public LoggingDerbyAdapter(DatabaseMetaData metadata) {
- super(metadata);
- }
-
- @Override
- public String getCreateTableStatement(TableImpl table, Column[] columns,
- Properties props, IdentifierFactory factory) {
- String statement = super.getCreateTableStatement(table, columns, props,
- factory);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getCreateIndexStatement(Index index, IdentifierFactory factory) {
- String statement = super.getCreateIndexStatement(index, factory);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getAddCandidateKeyStatement(CandidateKey ck,
- IdentifierFactory factory) {
- String statement = super.getAddCandidateKeyStatement(ck, factory);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getAddPrimaryKeyStatement(PrimaryKey pk,
- IdentifierFactory factory) {
- String statement = super.getAddPrimaryKeyStatement(pk, factory);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getAddColumnStatement(Table table, Column col) {
- String statement = super.getAddColumnStatement(table, col);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getAddForeignKeyStatement(ForeignKey fk,
- IdentifierFactory factory) {
- String statement = super.getAddForeignKeyStatement(fk, factory);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getDeleteTableStatement(SQLTable tbl) {
- String statement = super.getDeleteTableStatement(tbl);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getDropTableStatement(Table table) {
- String statement = super.getDropTableStatement(table);
- doLog(statement);
- return statement;
- }
-
- @Override
- public String getDropViewStatement(ViewImpl view) {
- String statement = super.getDropViewStatement(view);
- doLog(statement);
- return statement;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java b/server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java
deleted file mode 100644
index 68b813d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.taverna.server.master.utils;
-
-public class OneShotThread extends Thread {
- public OneShotThread(String name, Runnable target) {
- super(target, name);
- setContextClassLoader(null);
- setDaemon(true);
- start();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java b/server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java
deleted file mode 100644
index a892b52..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.core.Response;
-
-/**
- * Utilities that make it easier to write REST services.
- *
- * @author Donal Fellows
- */
-public class RestUtils {
- /**
- * Generate a response to an HTTP OPTIONS request.
- *
- * @param methods
- * The state-changing methods supported, if any.
- * @return the required response
- * @see OPTIONS
- */
- public static Response opt(String... methods) {
- StringBuilder sb = new StringBuilder("GET,");
- for (String m : methods)
- sb.append(m).append(",");
- sb.append("HEAD,OPTIONS");
- return Response.ok().header("Allow", sb.toString()).entity("").build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java b/server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java
deleted file mode 100644
index 0b2d4ea..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import org.aspectj.lang.annotation.AfterThrowing;
-import org.aspectj.lang.annotation.Aspect;
-import org.taverna.server.master.exceptions.GeneralFailureException;
-
-/**
- * Aspect used to convert {@linkplain RuntimeException runtime exceptions} into
- * a form that can be nicely conveyed to the outside world as HTTP errors.
- *
- * @author Donal Fellows
- */
-@Aspect
-public class RuntimeExceptionWrapper {
- /**
- * Map an unexpected exception to one that can be correctly reported as a
- * problem.
- *
- * @param exn
- * The runtime exception being trapped.
- * @throws GeneralFailureException
- * The known exception type that it is mapped to.
- */
- @AfterThrowing(pointcut = "execution(* org.taverna.server.master.rest..*(..)) && !bean(*Provider.*)", throwing = "exn")
- public void wrapRuntimeException(RuntimeException exn)
- throws GeneralFailureException {
- // Exclude security-related exceptions
- if (exn.getClass().getName().startsWith("org.springframework.security."))
- return;
- throw new GeneralFailureException(exn);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java b/server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java
deleted file mode 100644
index 9bbcc2f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import java.io.Serializable;
-import java.security.Principal;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.userdetails.UserDetails;
-
-/**
- * A simple serializable principal that just records the name.
- *
- * @author Donal Fellows
- */
-public class UsernamePrincipal implements Principal, Serializable {
- private static final long serialVersionUID = 2703493248562435L;
- public UsernamePrincipal(String username) {
- this.name = username;
- }
-
- public UsernamePrincipal(Principal other) {
- this.name = other.getName();
- }
-
- public UsernamePrincipal(Authentication auth) {
- this(auth.getPrincipal());
- }
-
- public UsernamePrincipal(Object principal) {
- if (principal instanceof Principal)
- this.name = ((Principal) principal).getName();
- else if (principal instanceof String)
- this.name = (String) principal;
- else if (principal instanceof UserDetails)
- this.name = ((UserDetails) principal).getUsername();
- else
- this.name = principal.toString();
- }
-
- private String name;
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String toString() {
- return "Principal<" + name + ">";
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof Principal) {
- Principal p = (Principal) o;
- return name.equals(p.getName());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java b/server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
deleted file mode 100644
index 96cdc6d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.taverna.server.master.utils;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.apache.cxf.common.util.UrlUtils.parseQueryString;
-import static org.apache.cxf.message.Message.HTTP_REQUEST_METHOD;
-import static org.apache.cxf.message.Message.QUERY_STRING;
-import static org.apache.cxf.message.Message.REQUEST_URL;
-import static org.apache.cxf.phase.Phase.READ;
-
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.cxf.binding.soap.interceptor.EndpointSelectionInterceptor;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.message.Message;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
-
-
-/**
- * Thunk for TAVSERV-293.
- *
- * @author Donal Fellows (based on work by Daniel Hagen)
- */
-public class WSDLHeadOptionsInterceptor extends
- AbstractPhaseInterceptor<Message> {
- public static final Log log = getLog("Taverna.Server.Utils");
-
- public WSDLHeadOptionsInterceptor() {
- super(READ);
- getAfter().add(EndpointSelectionInterceptor.class.getName());
- }
-
- @Override
- public void handleMessage(Message message) throws Fault {
- String method = (String) message.get(HTTP_REQUEST_METHOD);
- String query = (String) message.get(QUERY_STRING);
-
- if (("HEAD".equals(method) || "OPTIONS".equals(method))
- && query != null && !query.trim().isEmpty()
- && isRecognizedQuery(query)) {
- log.debug("adjusting message request method " + method + " for "
- + message.get(REQUEST_URL) + " to GET");
- message.put(HTTP_REQUEST_METHOD, "GET");
- }
- }
-
- /*
- * Stolen from http://permalink.gmane.org/gmane.comp.apache.cxf.user/20037
- * which is itself in turn stolen from
- * org.apache.cxf.frontend.WSDLGetInterceptor.isRecognizedQuery
- */
- /**
- * Is this a query for WSDL or XSD relating to it?
- *
- * @param query
- * The query string to check
- * @return If the query is one to handle.
- * @see org.apache.cxf.frontend.WSDLGetInterceptor#isRecognizedQuery(Map,String,String,org.apache.cxf.service.model.EndpointInfo)
- * WSDLGetInterceptor
- */
- private boolean isRecognizedQuery(String query) {
- Map<String, String> map = parseQueryString(query);
- return map.containsKey("wsdl") || map.containsKey("xsd");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java b/server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
deleted file mode 100644
index 03fc749..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static java.lang.Thread.currentThread;
-import static java.sql.DriverManager.deregisterDriver;
-import static java.sql.DriverManager.getDrivers;
-import static org.taverna.server.master.utils.Contextualizer.ROOT_PLACEHOLDER;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Enumeration;
-
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.dbcp.BasicDataSource;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-
-/**
- * Add some awareness of the context so that we can locate databases internally
- * to the webapp.
- *
- * @author Donal Fellows
- */
-public class WebappAwareDataSource extends BasicDataSource {
- Log log = LogFactory.getLog("Taverna.Server.Utils");
- private transient boolean init;
- private Contextualizer ctxt;
- private String shutdownUrl;
-
- @Required
- public void setContextualizer(Contextualizer ctxt) {
- this.ctxt = ctxt;
- }
-
- /**
- * A JDBC connection URL to use on shutting down the database. If not set,
- * do nothing special.
- *
- * @param url
- */
- public void setShutdownUrl(String url) {
- shutdownUrl = url;
- }
-
- private void doInit() {
- synchronized (this) {
- if (!init) {
- setDriverClassLoader(currentThread().getContextClassLoader());
- String url = getUrl();
- if (url.contains(ROOT_PLACEHOLDER)) {
- String newurl = ctxt.contextualize(url);
- setUrl(newurl);
- log.info("mapped " + url + " to " + newurl);
- } else {
- log.info("did not find " + ROOT_PLACEHOLDER + " in " + url);
- }
- init = true;
- }
- }
- }
-
- // -=-=-=-=-=-=-=-=-=-=- HOOKS -=-=-=-=-=-=-=-=-=-=-
-
- @Override
- public Connection getConnection() throws SQLException {
- doInit();
- return super.getConnection();
- }
-
- @Override
- public void setLogWriter(PrintWriter pw) throws SQLException {
- doInit();
- super.setLogWriter(pw);
- }
-
- @Override
- public void setLoginTimeout(int num) throws SQLException {
- doInit();
- super.setLoginTimeout(num);
- }
-
- @Override
- public PrintWriter getLogWriter() throws SQLException {
- doInit();
- return super.getLogWriter();
- }
-
- @Override
- public int getLoginTimeout() throws SQLException {
- doInit();
- return super.getLoginTimeout();
- }
-
- @PreDestroy
- void realClose() {
- try {
- close();
- } catch (SQLException e) {
- log.warn("problem shutting down DB connection", e);
- }
- try {
- if (shutdownUrl != null)
- DriverManager.getConnection(ctxt.contextualize(shutdownUrl));
- } catch (SQLException e) {
- // Expected; ignore it
- }
- log = null;
- dropDriver();
- }
-
- private void dropDriver() {
- Enumeration<Driver> drivers = getDrivers();
- while (drivers.hasMoreElements()) {
- Driver d = drivers.nextElement();
- if (d.getClass().getClassLoader() == getDriverClassLoader()
- && d.getClass().getName().equals(getDriverClassName())) {
- try {
- deregisterDriver(d);
- } catch (SQLException e) {
- }
- break;
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java b/server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
deleted file mode 100644
index da4cff0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static javax.security.auth.x500.X500Principal.RFC2253;
-
-import java.math.BigInteger;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.PreDestroy;
-import javax.security.auth.x500.X500Principal;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Support class that factors out some of the messier parts of working with
- * X.500 identities and X.509 certificates.
- *
- * @author Donal Fellows
- */
-public class X500Utils {
- private Log log = LogFactory.getLog("Taverna.Server.Utils");
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- private static final char DN_SEPARATOR = ',';
- private static final char DN_ESCAPE = '\\';
- private static final char DN_QUOTE = '"';
-
- /**
- * Parse the DN from the Principal and extract the CN field.
- *
- * @param id
- * The identity to extract the distinguished name from.
- * @param fields
- * The names to look at when finding the field to return. Each
- * should be an upper-cased string.
- * @return The common-name part of the distinguished name, or the literal
- * string "<tt>none</tt>" if there is no CN.
- */
- public String getName(X500Principal id, String... fields) {
- String dn = id.getName(RFC2253);
-
- int i = 0;
- int startIndex = 0;
- boolean ignoreThisChar = false;
- boolean inQuotes = false;
- Map<String, String> tokenized = new HashMap<>();
-
- for (i = 0; i < dn.length(); i++)
- if (ignoreThisChar)
- ignoreThisChar = false;
- else if (dn.charAt(i) == DN_QUOTE)
- inQuotes = !inQuotes;
- else if (inQuotes)
- continue;
- else if (dn.charAt(i) == DN_ESCAPE)
- ignoreThisChar = true;
- else if ((dn.charAt(i) == DN_SEPARATOR) && !ignoreThisChar) {
- storeDNField(tokenized, dn.substring(startIndex, i).trim()
- .split("=", 2));
- startIndex = i + 1;
- }
- if (inQuotes || ignoreThisChar)
- log.warn("was parsing invalid DN format");
- // Add last token - after the last delimiter
- storeDNField(tokenized, dn.substring(startIndex).trim().split("=", 2));
-
- for (String field : fields) {
- String value = tokenized.get(field);
- if (value != null)
- return value;
- }
- return "none";
- }
-
- private void storeDNField(Map<String, String> container, String[] split) {
- if (split == null || split.length != 2)
- return;
- String key = split[0].toUpperCase();
- if (container.containsKey(key))
- log.warn("duplicate field in DN: " + key);
- // LATER: Should the field be de-quoted?
- container.put(key, split[1]);
- }
-
- /**
- * Get the serial number from a certificate as a hex string.
- *
- * @param cert
- * The certificate to extract from.
- * @return A hex string, in upper-case.
- */
- public String getSerial(X509Certificate cert) {
- return new BigInteger(1, cert.getSerialNumber().toByteArray())
- .toString(16).toUpperCase();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
deleted file mode 100644
index 612e61c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Miscellaneous utility classes. Includes aspects that might be attached
- * for purposes such as transaction management and invocation tracking.
- */
-package org.taverna.server.master.utils;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java b/server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
deleted file mode 100644
index 10b3830..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-
-/**
- * How to convert a notification about the completion of a job into a message.
- *
- * @author Donal Fellows
- */
-public interface CompletionNotifier {
- /**
- * @return The name of this notifier.
- */
- String getName();
-
- /**
- * Called to get the content of a message that a workflow run has finished.
- *
- * @param name
- * The name of the run.
- * @param run
- * What run are we talking about.
- * @param code
- * What the exit code was.
- * @return The plain-text content of the message.
- */
- String makeCompletionMessage(String name, RemoteRunDelegate run, int code);
-
- /**
- * Called to get the subject of the message to dispatch.
- *
- * @param name
- * The name of the run.
- * @param run
- * What run are we talking about.
- * @param code
- * What the exit code was.
- * @return The plain-text subject of the message.
- */
- String makeMessageSubject(String name, RemoteRunDelegate run, int code);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java b/server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
deleted file mode 100644
index 5d0f371..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import org.taverna.server.master.notification.atom.EventDAO;
-
-/**
- * What the remote run really needs of its factory.
- *
- * @author Donal Fellows
- */
-public interface FactoryBean {
- /**
- * @return Whether a run can actually be started at this time.
- */
- boolean isAllowingRunsToStart();
-
- /**
- * @return a handle to the master Atom event feed (<i>not</i> the per-run
- * feed)
- */
- EventDAO getMasterEventFeed();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java b/server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
deleted file mode 100644
index d3c5b8a..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.taverna.server.master.worker;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * A simple password issuing bean.
- *
- * @author Donal Fellows
- */
-public class PasswordIssuer {
- private static final char[] ALPHABET = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
- 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
- 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', '0', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
- ',', '.', '<', '>', '/', '?', ':', ';', '-', '_', '+', '[', ']',
- '{', '}', '`', '~' };
- private Log log = LogFactory.getLog("Taverna.Server.Worker");
- private SecureRandom r;
- private int length;
-
- public PasswordIssuer() {
- r = new SecureRandom();
- log.info("constructing passwords with " + r.getAlgorithm());
- setLength(8);
- }
-
- public PasswordIssuer(String algorithm) throws NoSuchAlgorithmException {
- r = SecureRandom.getInstance(algorithm);
- log.info("constructing passwords with " + r.getAlgorithm());
- setLength(8);
- }
-
- public void setLength(int length) {
- this.length = length;
- log.info("issued password will be " + this.length
- + " symbols chosen from " + ALPHABET.length);
- }
-
- /**
- * Issue a password.
- *
- * @return The new password.
- */
- public String issue() {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < length; i++)
- sb.append(ALPHABET[r.nextInt(ALPHABET.length)]);
- log.info("issued new password of length " + sb.length());
- return sb.toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java b/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
deleted file mode 100644
index f5613c7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static org.taverna.server.master.identity.WorkflowInternalAuthProvider.PREFIX;
-
-import java.net.URI;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.taverna.server.master.common.Roles;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Basic policy implementation that allows any workflow to be instantiated by
- * any user, but which does not permit users to access each others workflow
- * runs. It also imposes a global limit on the number of workflow runs at once.
- *
- * @author Donal Fellows
- */
-class PolicyImpl implements Policy {
- Log log = LogFactory.getLog("Taverna.Server.Worker.Policy");
- private PolicyLimits limits;
- private RunDBSupport runDB;
-
- @Required
- public void setLimits(PolicyLimits limits) {
- this.limits = limits;
- }
-
- @Required
- public void setRunDB(RunDBSupport runDB) {
- this.runDB = runDB;
- }
-
- @Override
- public int getMaxRuns() {
- return limits.getMaxRuns();
- }
-
- @Override
- public Integer getMaxRuns(UsernamePrincipal user) {
- return null;
- }
-
- @Override
- public int getOperatingLimit() {
- return limits.getOperatingLimit();
- }
-
- @Override
- public List<URI> listPermittedWorkflowURIs(UsernamePrincipal user) {
- return limits.getPermittedWorkflowURIs();
- }
-
- private boolean isSelfAccess(String runId) {
- Authentication auth = SecurityContextHolder.getContext()
- .getAuthentication();
- boolean self = false;
- String id = null;
- for (GrantedAuthority a : auth.getAuthorities()) {
- String aa = a.getAuthority();
- if (aa.equals(Roles.SELF)) {
- self = true;
- continue;
- }
- if (!aa.startsWith(PREFIX))
- continue;
- id = aa.substring(PREFIX.length());
- }
- return self && runId.equals(id);
- }
-
- @Override
- public boolean permitAccess(UsernamePrincipal user, TavernaRun run) {
- String username = user.getName();
- TavernaSecurityContext context = run.getSecurityContext();
- if (context.getOwner().getName().equals(username)) {
- if (log.isDebugEnabled())
- log.debug("granted access by " + user.getName() + " to "
- + run.getId());
- return true;
- }
- if (isSelfAccess(run.getId())) {
- if (log.isDebugEnabled())
- log.debug("access by workflow to itself: " + run.getId());
- return true;
- }
- if (log.isDebugEnabled())
- log.debug("considering access by " + user.getName() + " to "
- + run.getId());
- return context.getPermittedReaders().contains(username);
- }
-
- @Override
- public void permitCreate(UsernamePrincipal user, Workflow workflow)
- throws NoCreateException {
- if (user == null)
- throw new NoCreateException(
- "anonymous workflow creation not allowed");
- if (runDB.countRuns() >= getMaxRuns())
- throw new NoCreateException("server load exceeded; please wait");
- }
-
- @Override
- public synchronized void permitDestroy(UsernamePrincipal user, TavernaRun run)
- throws NoDestroyException {
- if (user == null)
- throw new NoDestroyException();
- String username = user.getName();
- TavernaSecurityContext context = run.getSecurityContext();
- if (context.getOwner() == null
- || context.getOwner().getName().equals(username))
- return;
- if (!context.getPermittedDestroyers().contains(username))
- throw new NoDestroyException();
- }
-
- @Override
- public void permitUpdate(UsernamePrincipal user, TavernaRun run)
- throws NoUpdateException {
- if (user == null)
- throw new NoUpdateException(
- "workflow run not owned by you and you're not granted access");
- TavernaSecurityContext context = run.getSecurityContext();
- if (context.getOwner().getName().equals(user.getName()))
- return;
- if (isSelfAccess(run.getId())) {
- if (log.isDebugEnabled())
- log.debug("update access by workflow to itself: " + run.getId());
- return;
- }
- if (!context.getPermittedUpdaters().contains(user.getName()))
- throw new NoUpdateException(
- "workflow run not owned by you and you're not granted access");
- }
-
- @Override
- public void setPermittedWorkflowURIs(UsernamePrincipal user,
- List<URI> permitted) {
- limits.setPermittedWorkflowURIs(permitted);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java b/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
deleted file mode 100644
index 8cbc7ea..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import java.net.URI;
-import java.util.List;
-
-import org.taverna.server.master.common.Status;
-
-/**
- * The worker policy delegates certain limits to the state model of the
- * particular worker.
- *
- * @author Donal Fellows
- */
-public interface PolicyLimits {
- /**
- * @return the maximum number of extant workflow runs in any state
- */
- int getMaxRuns();
-
- /**
- * @return the maximum number of workflow runs in the
- * {@linkplain Status#Operating operating} state.
- */
- int getOperatingLimit();
-
- /**
- * @return the list of URIs to workflows that may be used to create workflow
- * runs. If empty or <tt>null</tt>, no restriction is present.
- */
- List<URI> getPermittedWorkflowURIs();
-
- /**
- * @param permitted
- * the list of URIs to workflows that may be used to create
- * workflow runs.
- */
- void setPermittedWorkflowURIs(List<URI> permitted);
-}
[43/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java b/server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java
deleted file mode 100644
index 0f98da6..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java
+++ /dev/null
@@ -1,1425 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static java.lang.Math.min;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.sort;
-import static java.util.UUID.randomUUID;
-import static javax.ws.rs.core.Response.created;
-import static javax.ws.rs.core.UriBuilder.fromUri;
-import static javax.xml.ws.handler.MessageContext.HTTP_REQUEST_HEADERS;
-import static javax.xml.ws.handler.MessageContext.PATH_INFO;
-import static org.apache.commons.io.IOUtils.toByteArray;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.TavernaServerSupport.PROV_BUNDLE;
-import static org.taverna.server.master.common.DirEntryReference.newInstance;
-import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
-import static org.taverna.server.master.common.Roles.ADMIN;
-import static org.taverna.server.master.common.Roles.SELF;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.common.Status.Initialized;
-import static org.taverna.server.master.common.Uri.secure;
-import static org.taverna.server.master.soap.DirEntry.convert;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.PreDestroy;
-import javax.annotation.Resource;
-import javax.annotation.security.DeclareRoles;
-import javax.annotation.security.RolesAllowed;
-import javax.jws.WebService;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-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.ws.WebServiceContext;
-
-import org.apache.commons.logging.Log;
-import org.apache.cxf.annotations.WSDLDocumentation;
-import org.ogf.usage.JobUsageRecord;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.api.SupportAware;
-import org.taverna.server.master.api.TavernaServerBean;
-import org.taverna.server.master.common.Capability;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.DirEntryReference;
-import org.taverna.server.master.common.InputDescription;
-import org.taverna.server.master.common.Permission;
-import org.taverna.server.master.common.ProfileList;
-import org.taverna.server.master.common.RunReference;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.common.version.Version;
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-import org.taverna.server.master.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.InvalidCredentialException;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoCredentialException;
-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.exceptions.OverloadedException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.factories.ListenerFactory;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.RunStore;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-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.rest.TavernaServerREST.EnabledNotificationFabrics;
-import org.taverna.server.master.rest.TavernaServerREST.PermittedListeners;
-import org.taverna.server.master.rest.TavernaServerREST.PermittedWorkflows;
-import org.taverna.server.master.rest.TavernaServerREST.PolicyView;
-import org.taverna.server.master.rest.TavernaServerRunREST;
-import org.taverna.server.master.soap.DirEntry;
-import org.taverna.server.master.soap.FileContents;
-import org.taverna.server.master.soap.PermissionList;
-import org.taverna.server.master.soap.TavernaServerSOAP;
-import org.taverna.server.master.soap.WrappedWorkflow;
-import org.taverna.server.master.soap.ZippedDirectory;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.FilenameUtils;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-import org.taverna.server.port_description.OutputDescription;
-
-/**
- * The core implementation of the web application.
- *
- * @author Donal Fellows
- */
-@Path("/")
-@DeclareRoles({ USER, ADMIN })
-@WebService(endpointInterface = "org.taverna.server.master.soap.TavernaServerSOAP", serviceName = "TavernaServer", targetNamespace = SERVER_SOAP)
-@WSDLDocumentation("An instance of Taverna " + Version.JAVA + " Server.")
-public abstract class TavernaServer implements TavernaServerSOAP,
- TavernaServerREST, TavernaServerBean {
- /**
- * The root of descriptions of the server in JMX.
- */
- public static final String JMX_ROOT = "Taverna:group=Server-"
- + Version.JAVA + ",name=";
-
- /** The logger for the server framework. */
- public Log log = getLog("Taverna.Server.Webapp");
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // CONNECTIONS TO JMX, SPRING AND CXF
-
- @Resource
- WebServiceContext jaxws;
- @Context
- private HttpHeaders jaxrsHeaders;
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // STATE VARIABLES AND SPRING SETTERS
-
- /**
- * For building descriptions of the expected inputs and actual outputs of a
- * workflow.
- */
- private ContentsDescriptorBuilder cdBuilder;
- /**
- * Utilities for accessing files on the local-worker.
- */
- private FilenameUtils fileUtils;
- /** How notifications are dispatched. */
- private NotificationEngine notificationEngine;
- /** Main support class. */
- private TavernaServerSupport support;
- /** A storage facility for workflow runs. */
- private RunStore runStore;
- /** Encapsulates the policies applied by this server. */
- private Policy policy;
- /** Where Atom events come from. */
- EventDAO eventSource;
- /** Reference to the main interaction feed. */
- private String interactionFeed;
-
- @Override
- @Required
- public void setFileUtils(FilenameUtils converter) {
- this.fileUtils = converter;
- }
-
- @Override
- @Required
- public void setContentsDescriptorBuilder(ContentsDescriptorBuilder cdBuilder) {
- this.cdBuilder = cdBuilder;
- }
-
- @Override
- @Required
- public void setNotificationEngine(NotificationEngine notificationEngine) {
- this.notificationEngine = notificationEngine;
- }
-
- /**
- * @param support
- * the support to set
- */
- @Override
- @Required
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- @Required
- public void setRunStore(RunStore runStore) {
- this.runStore = runStore;
- }
-
- @Override
- @Required
- public void setPolicy(Policy policy) {
- this.policy = policy;
- }
-
- @Override
- @Required
- public void setEventSource(EventDAO eventSource) {
- this.eventSource = eventSource;
- }
-
- /**
- * The location of a service-wide interaction feed, derived from a
- * properties file. Expected to be <i>actually</i> not set (to a real
- * value).
- *
- * @param interactionFeed
- * The URL, which will be resolved relative to the location of
- * the webapp, or the string "<tt>none</tt>" (which corresponds
- * to a <tt>null</tt>).
- */
- public void setInteractionFeed(String interactionFeed) {
- if ("none".equals(interactionFeed))
- interactionFeed = null;
- else if (interactionFeed != null && interactionFeed.startsWith("${"))
- interactionFeed = null;
- this.interactionFeed = interactionFeed;
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // REST INTERFACE
-
- @Override
- @CallCounted
- @PerfLogged
- public ServerDescription describeService(UriInfo ui) {
- jaxrsUriInfo.set(new WeakReference<>(ui));
- return new ServerDescription(ui, resolve(interactionFeed));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public RunList listUsersRuns(UriInfo ui) {
- jaxrsUriInfo.set(new WeakReference<>(ui));
- return new RunList(runs(), secure(ui).path("{name}"));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response submitWorkflow(Workflow workflow, UriInfo ui)
- throws NoUpdateException {
- jaxrsUriInfo.set(new WeakReference<>(ui));
- checkCreatePolicy(workflow);
- String name = support.buildWorkflow(workflow);
- return created(secure(ui).path("{uuid}").build(name)).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response submitWorkflowByURL(List<URI> referenceList, UriInfo ui)
- throws NoCreateException {
- jaxrsUriInfo.set(new WeakReference<>(ui));
- if (referenceList == null || referenceList.size() == 0)
- throw new NoCreateException("no workflow URI supplied");
- URI workflowURI = referenceList.get(0);
- checkCreatePolicy(workflowURI);
- Workflow workflow;
- try {
- workflow = support.getWorkflowDocumentFromURI(workflowURI);
- } catch (IOException e) {
- throw new NoCreateException("could not read workflow", e);
- }
- String name = support.buildWorkflow(workflow);
- return created(secure(ui).path("{uuid}").build(name)).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public int getServerMaxRuns() {
- return support.getMaxSimultaneousRuns();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public TavernaServerRunREST getRunResource(String runName, UriInfo ui)
- throws UnknownRunException {
- jaxrsUriInfo.set(new WeakReference<>(ui));
- RunREST rr = makeRunInterface();
- rr.setRun(support.getRun(runName));
- rr.setRunName(runName);
- return rr;
- }
-
- private ThreadLocal<Reference<UriInfo>> jaxrsUriInfo = new InheritableThreadLocal<>();
-
- private UriInfo getUriInfo() {
- if (jaxrsUriInfo.get() == null)
- return null;
- return jaxrsUriInfo.get().get();
- }
-
- @Override
- @CallCounted
- public abstract PolicyView getPolicyDescription();
-
- @Override
- @CallCounted
- public Response serviceOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response runsOptions() {
- return opt("POST");
- }
-
- /**
- * Construct a RESTful interface to a run.
- *
- * @return The handle to the interface, as decorated by Spring.
- */
- protected abstract RunREST makeRunInterface();
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // SOAP INTERFACE
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public RunReference[] listRuns() {
- ArrayList<RunReference> ws = new ArrayList<>();
- UriBuilder ub = getRunUriBuilder();
- for (String runName : runs().keySet())
- ws.add(new RunReference(runName, ub));
- return ws.toArray(new RunReference[ws.size()]);
- }
-
- private void checkCreatePolicy(Workflow workflow) throws NoCreateException {
- List<URI> pwu = policy
- .listPermittedWorkflowURIs(support.getPrincipal());
- if (pwu == null || pwu.size() == 0)
- return;
- throw new NoCreateException("server policy: will only start "
- + "workflows sourced from permitted URI list");
- }
-
- private void checkCreatePolicy(URI workflowURI) throws NoCreateException {
- List<URI> pwu = policy
- .listPermittedWorkflowURIs(support.getPrincipal());
- if (pwu == null || pwu.size() == 0 || pwu.contains(workflowURI))
- return;
- throw new NoCreateException("workflow URI not on permitted list");
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public RunReference submitWorkflow(Workflow workflow)
- throws NoUpdateException {
- checkCreatePolicy(workflow);
- String name = support.buildWorkflow(workflow);
- return new RunReference(name, getRunUriBuilder());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public RunReference submitWorkflowMTOM(WrappedWorkflow workflow)
- throws NoUpdateException {
- Workflow wf;
- try {
- wf = workflow.getWorkflow();
- } catch (IOException e) {
- throw new NoCreateException(e.getMessage(), e);
- }
- checkCreatePolicy(wf);
- String name = support.buildWorkflow(wf);
- return new RunReference(name, getRunUriBuilder());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public RunReference submitWorkflowByURI(URI workflowURI)
- throws NoCreateException {
- checkCreatePolicy(workflowURI);
- Workflow workflow;
- try {
- workflow = support.getWorkflowDocumentFromURI(workflowURI);
- } catch (IOException e) {
- throw new NoCreateException("could not read workflow", e);
- }
- String name = support.buildWorkflow(workflow);
- return new RunReference(name, getRunUriBuilder());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public URI[] getServerWorkflows() {
- return support.getPermittedWorkflowURIs();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String[] getServerListeners() {
- List<String> types = support.getListenerTypes();
- return types.toArray(new String[types.size()]);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String[] getServerNotifiers() {
- List<String> dispatchers = notificationEngine
- .listAvailableDispatchers();
- return dispatchers.toArray(new String[dispatchers.size()]);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public List<Capability> getServerCapabilities() {
- return support.getCapabilities();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void destroyRun(String runName) throws UnknownRunException,
- NoUpdateException {
- support.unregisterRun(runName, null);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunDescriptiveName(String runName)
- throws UnknownRunException {
- return support.getRun(runName).getName();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunDescriptiveName(String runName, String descriptiveName)
- throws UnknownRunException, NoUpdateException {
- TavernaRun run = support.getRun(runName);
- support.permitUpdate(run);
- run.setName(descriptiveName);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Workflow getRunWorkflow(String runName) throws UnknownRunException {
- return support.getRun(runName).getWorkflow();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public WrappedWorkflow getRunWorkflowMTOM(String runName)
- throws UnknownRunException {
- WrappedWorkflow ww = new WrappedWorkflow();
- ww.setWorkflow(support.getRun(runName).getWorkflow());
- return ww;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public ProfileList getRunWorkflowProfiles(String runName)
- throws UnknownRunException {
- return support.getProfileDescriptor(support.getRun(runName)
- .getWorkflow());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Date getRunExpiry(String runName) throws UnknownRunException {
- return support.getRun(runName).getExpiry();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunExpiry(String runName, Date d)
- throws UnknownRunException, NoUpdateException {
- support.updateExpiry(support.getRun(runName), d);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Date getRunCreationTime(String runName) throws UnknownRunException {
- return support.getRun(runName).getCreationTimestamp();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Date getRunFinishTime(String runName) throws UnknownRunException {
- return support.getRun(runName).getFinishTimestamp();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Date getRunStartTime(String runName) throws UnknownRunException {
- return support.getRun(runName).getStartTimestamp();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Status getRunStatus(String runName) throws UnknownRunException {
- return support.getRun(runName).getStatus();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String setRunStatus(String runName, Status s)
- throws UnknownRunException, NoUpdateException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- if (s == Status.Operating && w.getStatus() == Status.Initialized) {
- if (!support.getAllowStartWorkflowRuns())
- throw new OverloadedException();
- try {
- String issue = w.setStatus(s);
- if (issue == null)
- return "";
- if (issue.isEmpty())
- return "unknown reason for partial change";
- return issue;
- } catch (RuntimeException | NoUpdateException e) {
- log.info("failed to start run " + runName, e);
- throw e;
- }
- } else {
- w.setStatus(s);
- return "";
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunStdout(String runName) throws UnknownRunException {
- try {
- return support.getProperty(runName, "io", "stdout");
- } catch (NoListenerException e) {
- return "";
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunStderr(String runName) throws UnknownRunException {
- try {
- return support.getProperty(runName, "io", "stderr");
- } catch (NoListenerException e) {
- return "";
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public JobUsageRecord getRunUsageRecord(String runName)
- throws UnknownRunException {
- try {
- String ur = support.getProperty(runName, "io", "usageRecord");
- if (ur.isEmpty())
- return null;
- return JobUsageRecord.unmarshal(ur);
- } catch (NoListenerException e) {
- return null;
- } catch (JAXBException e) {
- log.info("failed to deserialize non-empty usage record", e);
- return null;
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunLog(String runName) throws UnknownRunException {
- try {
- return support.getLogs(support.getRun(runName)).get("UTF-8");
- } catch (UnsupportedEncodingException e) {
- log.warn("unexpected encoding problem", e);
- return "";
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public FileContents getRunBundle(String runName)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- File f = fileUtils.getFile(support.getRun(runName), PROV_BUNDLE);
- FileContents fc = new FileContents();
- // We *know* the content type, by definition
- fc.setFile(f, "application/vnd.wf4ever.robundle+zip");
- return fc;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public boolean getRunGenerateProvenance(String runName)
- throws UnknownRunException {
- return support.getRun(runName).getGenerateProvenance();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunGenerateProvenance(String runName, boolean generate)
- throws UnknownRunException, NoUpdateException {
- TavernaRun run = support.getRun(runName);
- support.permitUpdate(run);
- run.setGenerateProvenance(generate);
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // SOAP INTERFACE - Security
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunOwner(String runName) throws UnknownRunException {
- return support.getRun(runName).getSecurityContext().getOwner()
- .getName();
- }
-
- /**
- * Look up a security context, applying access control rules for access to
- * the parts of the context that are only open to the owner.
- *
- * @param runName
- * The name of the workflow run.
- * @param initialOnly
- * Whether to check if we're in the initial state.
- * @return The security context. Never <tt>null</tt>.
- * @throws UnknownRunException
- * @throws NotOwnerException
- * @throws BadStateChangeException
- */
- private TavernaSecurityContext getRunSecurityContext(String runName,
- boolean initialOnly) throws UnknownRunException, NotOwnerException,
- BadStateChangeException {
- TavernaRun run = support.getRun(runName);
- TavernaSecurityContext c = run.getSecurityContext();
- if (!c.getOwner().equals(support.getPrincipal()))
- throw new NotOwnerException();
- if (initialOnly && run.getStatus() != Initialized)
- throw new BadStateChangeException();
- return c;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Credential[] getRunCredentials(String runName)
- throws UnknownRunException, NotOwnerException {
- try {
- return getRunSecurityContext(runName, false).getCredentials();
- } catch (BadStateChangeException e) {
- Error e2 = new Error("impossible");
- e2.initCause(e);
- throw e2;
- }
- }
-
- private Credential findCredential(TavernaSecurityContext c, String id)
- throws NoCredentialException {
- for (Credential t : c.getCredentials())
- if (t.id.equals(id))
- return t;
- throw new NoCredentialException();
- }
-
- private Trust findTrust(TavernaSecurityContext c, String id)
- throws NoCredentialException {
- for (Trust t : c.getTrusted())
- if (t.id.equals(id))
- return t;
- throw new NoCredentialException();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String setRunCredential(String runName, String credentialID,
- Credential credential) throws UnknownRunException,
- NotOwnerException, InvalidCredentialException,
- NoCredentialException, BadStateChangeException {
- TavernaSecurityContext c = getRunSecurityContext(runName, true);
- if (credentialID == null || credentialID.isEmpty()) {
- credential.id = randomUUID().toString();
- } else {
- credential.id = findCredential(c, credentialID).id;
- }
- URI uri = getRunUriBuilder().path("security/credentials/{credid}")
- .build(runName, credential.id);
- credential.href = uri.toString();
- c.validateCredential(credential);
- c.addCredential(credential);
- return credential.id;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void deleteRunCredential(String runName, String credentialID)
- throws UnknownRunException, NotOwnerException,
- NoCredentialException, BadStateChangeException {
- getRunSecurityContext(runName, true).deleteCredential(
- new Credential.Dummy(credentialID));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Trust[] getRunCertificates(String runName)
- throws UnknownRunException, NotOwnerException {
- try {
- return getRunSecurityContext(runName, false).getTrusted();
- } catch (BadStateChangeException e) {
- Error e2 = new Error("impossible");
- e2.initCause(e);
- throw e2;
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String setRunCertificates(String runName, String certificateID,
- Trust certificate) throws UnknownRunException, NotOwnerException,
- InvalidCredentialException, NoCredentialException,
- BadStateChangeException {
- TavernaSecurityContext c = getRunSecurityContext(runName, true);
- if (certificateID == null || certificateID.isEmpty()) {
- certificate.id = randomUUID().toString();
- } else {
- certificate.id = findTrust(c, certificateID).id;
- }
- URI uri = getRunUriBuilder().path("security/trusts/{certid}").build(
- runName, certificate.id);
- certificate.href = uri.toString();
- c.validateTrusted(certificate);
- c.addTrusted(certificate);
- return certificate.id;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void deleteRunCertificates(String runName, String certificateID)
- throws UnknownRunException, NotOwnerException,
- NoCredentialException, BadStateChangeException {
- TavernaSecurityContext c = getRunSecurityContext(runName, true);
- Trust toDelete = new Trust();
- toDelete.id = certificateID;
- c.deleteTrusted(toDelete);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public PermissionList listRunPermissions(String runName)
- throws UnknownRunException, NotOwnerException {
- PermissionList pl = new PermissionList();
- pl.permission = new ArrayList<>();
- Map<String, Permission> perm;
- try {
- perm = support.getPermissionMap(getRunSecurityContext(runName,
- false));
- } catch (BadStateChangeException e) {
- log.error("unexpected error from internal API", e);
- perm = emptyMap();
- }
- List<String> users = new ArrayList<>(perm.keySet());
- sort(users);
- for (String user : users)
- pl.permission.add(new PermissionList.SinglePermissionMapping(user,
- perm.get(user)));
- return pl;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunPermission(String runName, String userName,
- Permission permission) throws UnknownRunException,
- NotOwnerException {
- try {
- support.setPermission(getRunSecurityContext(runName, false),
- userName, permission);
- } catch (BadStateChangeException e) {
- log.error("unexpected error from internal API", e);
- }
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // SOAP INTERFACE - Filesystem connection
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public OutputDescription getRunOutputDescription(String runName)
- throws UnknownRunException, BadStateChangeException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun run = support.getRun(runName);
- if (run.getStatus() == Initialized)
- throw new BadStateChangeException(
- "may not get output description in initial state");
- return cdBuilder.makeOutputDescriptor(run, null);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public DirEntry[] getRunDirectoryContents(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- List<DirEntry> result = new ArrayList<>();
- for (DirectoryEntry e : fileUtils.getDirectory(support.getRun(runName),
- convert(d)).getContents())
- result.add(convert(newInstance(null, e)));
- return result.toArray(new DirEntry[result.size()]);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public byte[] getRunDirectoryAsZip(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- try {
- return toByteArray(fileUtils.getDirectory(support.getRun(runName),
- convert(d)).getContentsAsZip());
- } catch (IOException e) {
- throw new FilesystemAccessException("problem serializing ZIP data",
- e);
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public ZippedDirectory getRunDirectoryAsZipMTOM(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- return new ZippedDirectory(fileUtils.getDirectory(
- support.getRun(runName), convert(d)));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public DirEntry makeRunDirectory(String runName, DirEntry parent,
- String name) throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- Directory dir = fileUtils.getDirectory(w, convert(parent))
- .makeSubdirectory(support.getPrincipal(), name);
- return convert(newInstance(null, dir));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public DirEntry makeRunFile(String runName, DirEntry parent, String name)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- File f = fileUtils.getDirectory(w, convert(parent)).makeEmptyFile(
- support.getPrincipal(), name);
- return convert(newInstance(null, f));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void destroyRunDirectoryEntry(String runName, DirEntry d)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- fileUtils.getDirEntry(w, convert(d)).destroy();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public byte[] getRunFileContents(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- File f = fileUtils.getFile(support.getRun(runName), convert(d));
- return f.getContents(0, -1);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunFileContents(String runName, DirEntry d,
- byte[] newContents) throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- fileUtils.getFile(w, convert(d)).setContents(newContents);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public FileContents getRunFileContentsMTOM(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- File f = fileUtils.getFile(support.getRun(runName), convert(d));
- FileContents fc = new FileContents();
- fc.setFile(f, support.getEstimatedContentType(f));
- return fc;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunFileContentsFromURI(String runName,
- DirEntryReference file, URI reference)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun run = support.getRun(runName);
- support.permitUpdate(run);
- File f = fileUtils.getFile(run, file);
- try {
- support.copyDataToFile(reference, f);
- } catch (IOException e) {
- throw new FilesystemAccessException(
- "problem transferring data from URI", e);
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunFileContentsMTOM(String runName, FileContents newContents)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- TavernaRun run = support.getRun(runName);
- support.permitUpdate(run);
- File f = fileUtils.getFile(run, newContents.name);
- f.setContents(new byte[0]);
- support.copyDataToFile(newContents.fileData, f);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunFileType(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- return support.getEstimatedContentType(fileUtils.getFile(
- support.getRun(runName), convert(d)));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public long getRunFileLength(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- return fileUtils.getFile(support.getRun(runName), convert(d)).getSize();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Date getRunFileModified(String runName, DirEntry d)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException {
- return fileUtils.getFile(support.getRun(runName), convert(d))
- .getModificationDate();
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // SOAP INTERFACE - Run listeners
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String[] getRunListeners(String runName) throws UnknownRunException {
- TavernaRun w = support.getRun(runName);
- List<String> result = new ArrayList<>();
- for (Listener l : w.getListeners())
- result.add(l.getName());
- return result.toArray(new String[result.size()]);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String addRunListener(String runName, String listenerType,
- String configuration) throws UnknownRunException,
- NoUpdateException, NoListenerException {
- return support.makeListener(support.getRun(runName), listenerType,
- configuration).getName();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunListenerConfiguration(String runName,
- String listenerName) throws UnknownRunException,
- NoListenerException {
- return support.getListener(runName, listenerName).getConfiguration();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String[] getRunListenerProperties(String runName, String listenerName)
- throws UnknownRunException, NoListenerException {
- return support.getListener(runName, listenerName).listProperties()
- .clone();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunListenerProperty(String runName, String listenerName,
- String propName) throws UnknownRunException, NoListenerException {
- return support.getListener(runName, listenerName).getProperty(propName);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunListenerProperty(String runName, String listenerName,
- String propName, String value) throws UnknownRunException,
- NoUpdateException, NoListenerException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- Listener l = support.getListener(w, listenerName);
- try {
- l.getProperty(propName); // sanity check!
- l.setProperty(propName, value);
- } catch (RuntimeException e) {
- throw new NoListenerException("problem setting property: "
- + e.getMessage(), e);
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public InputDescription getRunInputs(String runName)
- throws UnknownRunException {
- return new InputDescription(support.getRun(runName));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getRunOutputBaclavaFile(String runName)
- throws UnknownRunException {
- return support.getRun(runName).getOutputBaclavaFile();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunInputBaclavaFile(String runName, String fileName)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, BadStateChangeException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- w.setInputBaclavaFile(fileName);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunInputPortFile(String runName, String portName,
- String portFilename) throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, BadStateChangeException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- Input i = support.getInput(w, portName);
- if (i == null)
- i = w.makeInput(portName);
- i.setFile(portFilename);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunInputPortValue(String runName, String portName,
- String portValue) throws UnknownRunException, NoUpdateException,
- BadStateChangeException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- Input i = support.getInput(w, portName);
- if (i == null)
- i = w.makeInput(portName);
- i.setValue(portValue);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunInputPortListDelimiter(String runName, String portName,
- String delimiter) throws UnknownRunException, NoUpdateException,
- BadStateChangeException, BadPropertyValueException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- Input i = support.getInput(w, portName);
- if (i == null)
- i = w.makeInput(portName);
- if (delimiter != null && delimiter.isEmpty())
- delimiter = null;
- if (delimiter != null) {
- if (delimiter.length() > 1)
- throw new BadPropertyValueException("delimiter too long");
- if (delimiter.charAt(0) < 1 || delimiter.charAt(0) > 127)
- throw new BadPropertyValueException(
- "delimiter character must be non-NUL ASCII");
- }
- i.setDelimiter(delimiter);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public void setRunOutputBaclavaFile(String runName, String outputFile)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, BadStateChangeException {
- TavernaRun w = support.getRun(runName);
- support.permitUpdate(w);
- w.setOutputBaclavaFile(outputFile);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public org.taverna.server.port_description.InputDescription getRunInputDescriptor(
- String runName) throws UnknownRunException {
- return cdBuilder.makeInputDescriptor(support.getRun(runName), null);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getServerStatus() {
- return support.getAllowNewWorkflowRuns() ? "operational" : "suspended";
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- // SUPPORT METHODS
-
- @Override
- public boolean initObsoleteSOAPSecurity(TavernaSecurityContext c) {
- try {
- javax.xml.ws.handler.MessageContext msgCtxt = (jaxws == null ? null
- : jaxws.getMessageContext());
- if (msgCtxt == null)
- return true;
- c.initializeSecurityFromSOAPContext(msgCtxt);
- return false;
- } catch (IllegalStateException e) {
- /* ignore; not much we can do */
- return true;
- }
- }
-
- @Override
- public boolean initObsoleteRESTSecurity(TavernaSecurityContext c) {
- if (jaxrsHeaders == null)
- return true;
- c.initializeSecurityFromRESTContext(jaxrsHeaders);
- return false;
- }
-
- /**
- * A creator of substitute {@link URI} builders.
- *
- * @return A URI builder configured so that it takes a path parameter that
- * corresponds to the run ID (but with no such ID applied).
- */
- UriBuilder getRunUriBuilder() {
- return getBaseUriBuilder().path("runs/{uuid}");
- }
-
- @Override
- public UriBuilder getRunUriBuilder(TavernaRun run) {
- return fromUri(getRunUriBuilder().build(run.getId()));
- }
-
- private final String DEFAULT_HOST = "localhost:8080"; // Crappy default
-
- private String getHostLocation() {
- @java.lang.SuppressWarnings("unchecked")
- Map<String, List<String>> headers = (Map<String, List<String>>) jaxws
- .getMessageContext().get(HTTP_REQUEST_HEADERS);
- if (headers != null) {
- List<String> host = headers.get("HOST");
- if (host != null && !host.isEmpty())
- return host.get(0);
- }
- return DEFAULT_HOST;
- }
-
- @Nonnull
- private URI getPossiblyInsecureBaseUri() {
- // See if JAX-RS can supply the info
- UriInfo ui = getUriInfo();
- if (ui != null && ui.getBaseUri() != null)
- return ui.getBaseUri();
- // See if JAX-WS *cannot* supply the info
- if (jaxws == null || jaxws.getMessageContext() == null)
- // Hack to make the test suite work
- return URI.create("http://" + DEFAULT_HOST
- + "/taverna-server/rest/");
- String pathInfo = (String) jaxws.getMessageContext().get(PATH_INFO);
- pathInfo = pathInfo.replaceFirst("/soap$", "/rest/");
- pathInfo = pathInfo.replaceFirst("/rest/.+$", "/rest/");
- return URI.create("http://" + getHostLocation() + pathInfo);
- }
-
- @Override
- public UriBuilder getBaseUriBuilder() {
- return secure(fromUri(getPossiblyInsecureBaseUri()));
- }
-
- @Override
- @Nullable
- public String resolve(@Nullable String uri) {
- if (uri == null)
- return null;
- return secure(getPossiblyInsecureBaseUri(), uri).toString();
- }
-
- private Map<String, TavernaRun> runs() {
- return runStore.listRuns(support.getPrincipal(), policy);
- }
-}
-
-/**
- * RESTful interface to the policies of a Taverna Server installation.
- *
- * @author Donal Fellows
- */
-class PolicyREST implements PolicyView, SupportAware {
- private TavernaServerSupport support;
- private Policy policy;
- private ListenerFactory listenerFactory;
- private NotificationEngine notificationEngine;
-
- @Override
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Required
- public void setPolicy(Policy policy) {
- this.policy = policy;
- }
-
- @Required
- public void setListenerFactory(ListenerFactory listenerFactory) {
- this.listenerFactory = listenerFactory;
- }
-
- @Required
- public void setNotificationEngine(NotificationEngine notificationEngine) {
- this.notificationEngine = notificationEngine;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public PolicyDescription getDescription(UriInfo ui) {
- return new PolicyDescription(ui);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public int getMaxSimultaneousRuns() {
- Integer limit = policy.getMaxRuns(support.getPrincipal());
- if (limit == null)
- return policy.getMaxRuns();
- return min(limit.intValue(), policy.getMaxRuns());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public PermittedListeners getPermittedListeners() {
- return new PermittedListeners(
- listenerFactory.getSupportedListenerTypes());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public PermittedWorkflows getPermittedWorkflows() {
- return new PermittedWorkflows(policy.listPermittedWorkflowURIs(support
- .getPrincipal()));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public EnabledNotificationFabrics getEnabledNotifiers() {
- return new EnabledNotificationFabrics(
- notificationEngine.listAvailableDispatchers());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public int getMaxOperatingRuns() {
- return policy.getOperatingLimit();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public CapabilityList getCapabilities() {
- CapabilityList cl = new CapabilityList();
- cl.capability.addAll(support.getCapabilities());
- return cl;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java b/server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java
deleted file mode 100644
index ce36bd3..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java
+++ /dev/null
@@ -1,957 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static eu.medsea.util.MimeUtil.UNKNOWN_MIME_TYPE;
-import static eu.medsea.util.MimeUtil.getExtensionMimeTypes;
-import static eu.medsea.util.MimeUtil.getMimeType;
-import static java.lang.Math.min;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.springframework.jmx.support.MetricType.COUNTER;
-import static org.springframework.jmx.support.MetricType.GAUGE;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-import static org.taverna.server.master.common.Roles.ADMIN;
-import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.activation.DataHandler;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.PreDestroy;
-import javax.ws.rs.WebApplicationException;
-import javax.xml.bind.JAXBException;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedMetric;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.taverna.server.master.api.ManagementModel;
-import org.taverna.server.master.api.TavernaServerBean;
-import org.taverna.server.master.common.Capability;
-import org.taverna.server.master.common.Permission;
-import org.taverna.server.master.common.ProfileList;
-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.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-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.UnknownRunException;
-import org.taverna.server.master.factories.ListenerFactory;
-import org.taverna.server.master.factories.RunFactory;
-import org.taverna.server.master.identity.WorkflowInternalAuthProvider.WorkflowSelfAuthority;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.RunStore;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.rest.handler.T2FlowDocumentHandler;
-import org.taverna.server.master.utils.CapabilityLister;
-import org.taverna.server.master.utils.FilenameUtils;
-import org.taverna.server.master.utils.InvocationCounter;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-import uk.org.taverna.scufl2.api.profiles.Profile;
-
-/**
- * Web application support utilities.
- *
- * @author Donal Fellows
- */
-@ManagedResource(objectName = JMX_ROOT + "Webapp", description = "The main Taverna Server "
- + Version.JAVA + " web-application interface.")
-public class TavernaServerSupport {
- /** The main webapp log. */
- private Log log = getLog("Taverna.Server.Webapp");
- private Log accessLog = getLog("Taverna.Server.Webapp.Access");;
- /** Bean used to log counts of external calls. */
- private InvocationCounter counter;
- /** A storage facility for workflow runs. */
- private RunStore runStore;
- /** Encapsulates the policies applied by this server. */
- private Policy policy;
- /** Connection to the persistent state of this service. */
- private ManagementModel stateModel;
- /** A factory for event listeners to attach to workflow runs. */
- private ListenerFactory listenerFactory;
- /** A factory for workflow runs. */
- private RunFactory runFactory;
- /** How to map the user ID to who to run as. */
- private LocalIdentityMapper idMapper;
- /** The code that is coupled to CXF. */
- private TavernaServerBean webapp;
- /** How to handle files. */
- private FilenameUtils fileUtils;
- /** How to get the server capabilities. */
- private CapabilityLister capabilitySource;
- /**
- * Whether to log failures during principal retrieval. Should be normally on
- * as it indicates a serious problem, but can be switched off for testing.
- */
- private boolean logGetPrincipalFailures = true;
- private Map<String, String> contentTypeMap;
- /** Number of bytes to read when guessing the MIME type. */
- private static final int SAMPLE_SIZE = 1024;
- /** Number of bytes to ask for when copying a stream to a file. */
- private static final int TRANSFER_SIZE = 32768;
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- /**
- * @return Count of the number of external calls into this webapp.
- */
- @ManagedMetric(description = "Count of the number of external calls into this webapp.", metricType = COUNTER, category = "throughput")
- public int getInvocationCount() {
- return counter.getCount();
- }
-
- /**
- * @return Current number of runs.
- */
- @ManagedMetric(description = "Current number of runs.", metricType = GAUGE, category = "utilization")
- public int getCurrentRunCount() {
- return runStore.listRuns(null, policy).size();
- }
-
- /**
- * @return Whether to write submitted workflows to the log.
- */
- @ManagedAttribute(description = "Whether to write submitted workflows to the log.")
- public boolean getLogIncomingWorkflows() {
- return stateModel.getLogIncomingWorkflows();
- }
-
- /**
- * @param logIncomingWorkflows
- * Whether to write submitted workflows to the log.
- */
- @ManagedAttribute(description = "Whether to write submitted workflows to the log.")
- public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
- stateModel.setLogIncomingWorkflows(logIncomingWorkflows);
- }
-
- /**
- * @return Whether outgoing exceptions should be logged before being
- * converted to responses.
- */
- @ManagedAttribute(description = "Whether outgoing exceptions should be logged before being converted to responses.")
- public boolean getLogOutgoingExceptions() {
- return stateModel.getLogOutgoingExceptions();
- }
-
- /**
- * @param logOutgoing
- * Whether outgoing exceptions should be logged before being
- * converted to responses.
- */
- @ManagedAttribute(description = "Whether outgoing exceptions should be logged before being converted to responses.")
- public void setLogOutgoingExceptions(boolean logOutgoing) {
- stateModel.setLogOutgoingExceptions(logOutgoing);
- }
-
- /**
- * @return Whether to permit any new workflow runs to be created.
- */
- @ManagedAttribute(description = "Whether to permit any new workflow runs to be created; has no effect on existing runs.")
- public boolean getAllowNewWorkflowRuns() {
- return stateModel.getAllowNewWorkflowRuns();
- }
-
- /**
- * @param allowNewWorkflowRuns
- * Whether to permit any new workflow runs to be created.
- */
- @ManagedAttribute(description = "Whether to permit any new workflow runs to be created; has no effect on existing runs.")
- public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
- stateModel.setAllowNewWorkflowRuns(allowNewWorkflowRuns);
- }
-
- /**
- * @return The server's version identifier.
- */
- @ManagedAttribute(description = "The installed version of the server.")
- public String getServerVersion() {
- return VersionedElement.VERSION + " " + VersionedElement.REVISION + " "
- + VersionedElement.TIMESTAMP;
- }
-
- @ManagedAttribute(description = "The URIs of the workfows that this server will allow to be instantiated.")
- public URI[] getPermittedWorkflowURIs() {
- List<URI> pw = policy.listPermittedWorkflowURIs(null);
- if (pw == null)
- return new URI[0];
- return pw.toArray(new URI[pw.size()]);
- }
-
- @ManagedAttribute(description = "The URIs of the workfows that this server will allow to be instantiated.")
- public void setPermittedWorkflowURIs(URI[] pw) {
- if (pw == null)
- policy.setPermittedWorkflowURIs(null, new ArrayList<URI>());
- else
- policy.setPermittedWorkflowURIs(null, Arrays.asList(pw));
- }
-
- public int getMaxSimultaneousRuns() {
- Integer limit = policy.getMaxRuns(getPrincipal());
- if (limit == null)
- return policy.getMaxRuns();
- return min(limit.intValue(), policy.getMaxRuns());
- }
-
- @Autowired
- private T2FlowDocumentHandler t2flowHandler;
-
- public Workflow getWorkflowDocumentFromURI(URI uri)
- throws WebApplicationException, IOException {
- URLConnection conn = uri.toURL().openConnection();
- conn.setRequestProperty("Accept", T2FLOW);
- conn.connect();
- // Tricky point: we know the reader part of the handler only cares
- // about the stream argument.
- return t2flowHandler.readFrom(null, null, null, null, null,
- conn.getInputStream());
- }
-
- public List<String> getListenerTypes() {
- return listenerFactory.getSupportedListenerTypes();
- }
-
- /**
- * @param policy
- * The policy being installed by Spring.
- */
- @Required
- public void setPolicy(Policy policy) {
- this.policy = policy;
- }
-
- /**
- * @param listenerFactory
- * The listener factory being installed by Spring.
- */
- @Required
- public void setListenerFactory(ListenerFactory listenerFactory) {
- this.listenerFactory = listenerFactory;
- }
-
- /**
- * @param runFactory
- * The run factory being installed by Spring.
- */
- @Required
- public void setRunFactory(RunFactory runFactory) {
- this.runFactory = runFactory;
- }
-
- /**
- * @param runStore
- * The run store being installed by Spring.
- */
- @Required
- public void setRunStore(RunStore runStore) {
- this.runStore = runStore;
- }
-
- /**
- * @param stateModel
- * The state model engine being installed by Spring.
- */
- @Required
- public void setStateModel(ManagementModel stateModel) {
- this.stateModel = stateModel;
- }
-
- /**
- * @param mapper
- * The identity mapper being installed by Spring.
- */
- @Required
- public void setIdMapper(LocalIdentityMapper mapper) {
- this.idMapper = mapper;
- }
-
- /**
- * @param counter
- * The object whose job it is to manage the counting of
- * invocations. Installed by Spring.
- */
- @Required
- public void setInvocationCounter(InvocationCounter counter) {
- this.counter = counter;
- }
-
- /**
- * @param webapp
- * The web-app being installed by Spring.
- */
- @Required
- public void setWebapp(TavernaServerBean webapp) {
- this.webapp = webapp;
- }
-
- /**
- * @param fileUtils
- * The file handling utilities.
- */
- @Required
- public void setFileUtils(FilenameUtils fileUtils) {
- this.fileUtils = fileUtils;
- }
-
- /**
- * @param logthem
- * Whether to log failures relating to principals.
- */
- public void setLogGetPrincipalFailures(boolean logthem) {
- logGetPrincipalFailures = logthem;
- }
-
- public Map<String, String> getContentTypeMap() {
- return contentTypeMap;
- }
-
- /**
- * Mapping from filename suffixes (e.g., "baclava") to content types.
- *
- * @param contentTypeMap
- * The mapping to install.
- */
- @Required
- public void setContentTypeMap(Map<String, String> contentTypeMap) {
- this.contentTypeMap = contentTypeMap;
- }
-
- @Required
- public void setCapabilitySource(CapabilityLister capabilitySource) {
- this.capabilitySource = capabilitySource;
- }
-
- /**
- * Test whether the current user can do updates to the given run.
- *
- * @param run
- * The workflow run to do the test on.
- * @throws NoUpdateException
- * If the current user is not permitted to update the run.
- */
- public void permitUpdate(@Nonnull TavernaRun run) throws NoUpdateException {
- if (isSuperUser()) {
- accessLog
- .warn("check for admin powers passed; elevated access rights granted for update");
- return; // Superusers are fully authorized to access others things
- }
- if (getSelfAuthority() != null) {
- // At this point, must already be accessing self as that is checked
- // in getRun().
- return;
- }
- policy.permitUpdate(getPrincipal(), run);
- }
-
- /**
- * Test whether the current user can destroy or control the lifespan of the
- * given run.
- *
- * @param run
- * The workflow run to do the test on.
- * @throws NoDestroyException
- * If the current user is not permitted to destroy the run.
- */
- public void permitDestroy(TavernaRun run) throws NoDestroyException {
- if (isSuperUser()) {
- accessLog
- .warn("check for admin powers passed; elevated access rights granted for destroy");
- return; // Superusers are fully authorized to access others things
- }
- if (getSelfAuthority() != null)
- throw new NoDestroyException();
- policy.permitDestroy(getPrincipal(), run);
- }
-
- /**
- * Gets the identity of the user currently accessing the webapp, which is
- * stored in a thread-safe way in the webapp's container's context.
- *
- * @return The identity of the user accessing the webapp.
- */
- @Nonnull
- public UsernamePrincipal getPrincipal() {
- try {
- Authentication auth = SecurityContextHolder.getContext()
- .getAuthentication();
- if (auth == null || !auth.isAuthenticated()) {
- if (logGetPrincipalFailures)
- log.warn("failed to get auth; going with <NOBODY>");
- return new UsernamePrincipal("<NOBODY>");
- }
- return new UsernamePrincipal(auth);
- } catch (RuntimeException e) {
- if (logGetPrincipalFailures)
- log.info("failed to map principal", e);
- throw e;
- }
- }
-
- private WorkflowSelfAuthority getSelfAuthority() {
- try {
- Authentication a = SecurityContextHolder.getContext()
- .getAuthentication();
- for (GrantedAuthority ga : a.getAuthorities())
- if (ga instanceof WorkflowSelfAuthority)
- return (WorkflowSelfAuthority) ga;
- } catch (RuntimeException e) {
- }
- return null;
- }
-
- /**
- * Obtain the workflow run with a particular name.
- *
- * @param name
- * The name of the run to look up.
- * @return A workflow run handle that the current user has at least
- * permission to read.
- * @throws UnknownRunException
- * If the workflow run doesn't exist or the current user doesn't
- * have permission to see it.
- */
- @Nonnull
- public TavernaRun getRun(@Nonnull String name) throws UnknownRunException {
- if (isSuperUser()) {
- accessLog
- .info("check for admin powers passed; elevated access rights granted for read");
- return runStore.getRun(name);
- }
- WorkflowSelfAuthority wsa = getSelfAuthority();
- if (wsa != null) {
- if (wsa.getWorkflowID().equals(name))
- return runStore.getRun(name);
- throw new UnknownRunException();
- }
- return runStore.getRun(getPrincipal(), policy, name);
- }
-
- /**
- * Construct a listener attached to the given run.
- *
- * @param run
- * The workflow run to attach the listener to.
- * @param type
- * The name of the type of run to create.
- * @param configuration
- * The configuration description to pass into the listener. The
- * format of this string is up to the listener to define.
- * @return A handle to the listener which can be used to further configure
- * any properties.
- * @throws NoListenerException
- * If the listener type is unrecognized or the configuration is
- * invalid.
- * @throws NoUpdateException
- * If the run does not permit the current user to add listeners
- * (or perform other types of update).
- */
- @Nonnull
- public Listener makeListener(@Nonnull TavernaRun run, @Nonnull String type,
- @Nonnull String configuration) throws NoListenerException,
- NoUpdateException {
- permitUpdate(run);
- return listenerFactory.makeListener(run, type, configuration);
- }
-
- /**
- * Obtain a listener that is already attached to a workflow run.
- *
- * @param run
- * The workflow run to search.
- * @param listenerName
- * The name of the listener to look up.
- * @return The listener instance interface.
- * @throws NoListenerException
- * If no listener with that name exists.
- */
- @Nonnull
- public Listener getListener(TavernaRun run, String listenerName)
- throws NoListenerException {
- for (Listener l : run.getListeners())
- if (l.getName().equals(listenerName))
- return l;
- throw new NoListenerException();
- }
-
- /**
- * Obtain a property from a listener that is already attached to a workflow
- * run.
- *
- * @param runName
- * The ID of the workflow run to search.
- * @param listenerName
- * The name of the listener to look up in.
- * @param propertyName
- * The name of the property to fetch.
- * @return The property value.
- * @throws NoListenerException
- * If no listener with that name exists, or no property with
- * that name exists.
- * @throws UnknownRunException
- * If no run with that name exists.
- */
- @Nonnull
- public String getProperty(String runName, String listenerName,
- String propertyName) throws NoListenerException,
- UnknownRunException {
- return getListener(runName, listenerName).getProperty(propertyName);
- }
-
- /**
- * Obtain a property from a listener that is already attached to a workflow
- * run.
- *
- * @param run
- * The workflow run to search.
- * @param listenerName
- * The name of the listener to look up in.
- * @param propertyName
- * The name of the property to fetch.
- * @return The property value.
- * @throws NoListenerException
- * If no listener with that name exists, or no property with
- * that name exists.
- */
- @Nonnull
- public String getProperty(TavernaRun run, String listenerName,
- String propertyName) throws NoListenerException {
- return getListener(run, listenerName).getProperty(propertyName);
- }
-
- /**
- * Get the permission description for the given user.
- *
- * @param context
- * A security context associated with a particular workflow run.
- * Note that only the owner of a workflow run may get the
- * security context in the first place.
- * @param userName
- * The name of the user to look up the permission for.
- * @return A permission description.
- */
- @Nonnull
- public Permission getPermission(@Nonnull TavernaSecurityContext context,
- @Nonnull String userName) {
- if (context.getPermittedDestroyers().contains(userName))
- return Permission.Destroy;
- if (context.getPermittedUpdaters().contains(userName))
- return Permission.Update;
- if (context.getPermittedReaders().contains(userName))
- return Permission.Read;
- return Permission.None;
- }
-
- /**
- * Set the permissions for the given user.
- *
- * @param context
- * A security context associated with a particular workflow run.
- * Note that only the owner of a workflow run may get the
- * security context in the first place.
- * @param userName
- * The name of the user to set the permission for.
- * @param permission
- * The description of the permission to grant. Note that the
- * owner of a workflow run always has the equivalent of
- * {@link Permission#Destroy}; this is always enforced before
- * checking for other permissions.
- */
- public void setPermission(TavernaSecurityContext context, String userName,
- Permission permission) {
- Set<String> permSet;
- boolean doRead = false, doWrite = false, doKill = false;
-
- switch (permission) {
- case Destroy:
- doKill = true;
- case Update:
- doWrite = true;
- case Read:
- doRead = true;
- default:
- break;
- }
-
- permSet = context.getPermittedReaders();
- if (doRead) {
- if (!permSet.contains(userName)) {
- permSet = new HashSet<>(permSet);
- permSet.add(userName);
- context.setPermittedReaders(permSet);
- }
- } else if (permSet.contains(userName)) {
- permSet = new HashSet<>(permSet);
- permSet.remove(userName);
- context.setPermittedReaders(permSet);
- }
-
- permSet = context.getPermittedUpdaters();
- if (doWrite) {
- if (!permSet.contains(userName)) {
- permSet = new HashSet<>(permSet);
- permSet.add(userName);
- context.setPermittedUpdaters(permSet);
- }
- } else if (permSet.contains(userName)) {
- permSet = new HashSet<>(permSet);
- permSet.remove(userName);
- context.setPermittedUpdaters(permSet);
- }
-
- permSet = context.getPermittedDestroyers();
- if (doKill) {
- if (!permSet.contains(userName)) {
- permSet = new HashSet<>(permSet);
- permSet.add(userName);
- context.setPermittedDestroyers(permSet);
- }
- } else if (permSet.contains(userName)) {
- permSet = new HashSet<>(permSet);
- permSet.remove(userName);
- context.setPermittedDestroyers(permSet);
- }
- }
-
- public Map<String, Permission> getPermissionMap(
- TavernaSecurityContext context) {
- Map<String, Permission> perm = new HashMap<>();
- for (String u : context.getPermittedReaders())
- perm.put(u, Permission.Read);
- for (String u : context.getPermittedUpdaters())
- perm.put(u, Permission.Update);
- for (String u : context.getPermittedDestroyers())
- perm.put(u, Permission.Destroy);
- return perm;
- }
-
- /**
- * Stops a run from being possible to be looked up and destroys it.
- *
- * @param runName
- * The name of the run.
- * @param run
- * The workflow run. <i>Must</i> correspond to the name.
- * @throws NoDestroyException
- * If the user is not permitted to destroy the workflow run.
- * @throws UnknownRunException
- * If the run is unknown (e.g., because it is already
- * destroyed).
- */
- public void unregisterRun(@Nonnull String runName, @Nonnull TavernaRun run)
- throws NoDestroyException, UnknownRunException {
- if (run == null)
- run = getRun(runName);
- permitDestroy(run);
- runStore.unregisterRun(runName);
- run.destroy();
- }
-
- /**
- * Changes the expiry date of a workflow run. The expiry date is when the
- * workflow run becomes eligible for automated destruction.
- *
- * @param run
- * The handle to the workflow run.
- * @param date
- * When the workflow run should be expired.
- * @return When the workflow run will actually be expired.
- * @throws NoDestroyException
- * If the user is not permitted to destroy the workflow run.
- * (Note that lifespan management requires the ability to
- * destroy.)
- */
- @Nonnull
- public Date updateExpiry(@Nonnull TavernaRun run, @Nonnull Date date)
- throws NoDestroyException {
- permitDestroy(run);
- run.setExpiry(date);
- return run.getExpiry();
- }
-
- /**
- * Manufacture a workflow run instance.
- *
- * @param workflow
- * The workflow document (t2flow, scufl2?) to instantiate.
- * @return The ID of the created workflow run.
- * @throws NoCreateException
- * If the user is not permitted to create workflows.
- */
- public String buildWorkflow(Workflow workflow) throws NoCreateException {
- UsernamePrincipal p = getPrincipal();
- if (getSelfAuthority() != null)
- throw new NoCreateException(
- "runs may not create workflows on their host server");
- if (!stateModel.getAllowNewWorkflowRuns())
- throw new NoCreateException("run creation not currently enabled");
- try {
- if (stateModel.getLogIncomingWorkflows()) {
- log.info(workflow.marshal());
- }
- } catch (JAXBException e) {
- log.warn("problem when logging workflow", e);
- }
-
- // Security checks
- policy.permitCreate(p, workflow);
- if (idMapper != null && idMapper.getUsernameForPrincipal(p) == null) {
- log.error("cannot map principal to local user id");
- throw new NoCreateException(
- "failed to map security token to local user id");
- }
-
- TavernaRun run;
- try {
- run = runFactory.create(p, workflow);
- TavernaSecurityContext c = run.getSecurityContext();
- c.initializeSecurityFromContext(SecurityContextHolder.getContext());
- /*
- * These next pieces of security initialisation are (hopefully)
- * obsolete now that we use Spring Security, but we keep them Just
- * In Case.
- */
- boolean doRESTinit = webapp.initObsoleteSOAPSecurity(c);
- if (doRESTinit)
- webapp.initObsoleteRESTSecurity(c);
- } catch (Exception e) {
- log.error("failed to build workflow run worker", e);
- throw new NoCreateException("failed to build workflow run worker");
- }
-
- return runStore.registerRun(run);
- }
-
- private boolean isSuperUser() {
- try {
- Authentication auth = SecurityContextHolder.getContext()
- .getAuthentication();
- if (auth == null || !auth.isAuthenticated())
- return false;
- UserDetails details = (UserDetails) auth.getPrincipal();
- if (log.isDebugEnabled())
- log.debug("checking for admin role for user <" + auth.getName()
- + "> in collection " + details.getAuthorities());
- return details.getAuthorities().contains(ADMIN);
- } catch (ClassCastException e) {
- return false;
- }
- }
-
- /**
- * Get a particular input to a workflow run.
- *
- * @param run
- * The workflow run to search.
- * @param portName
- * The name of the input.
- * @return The handle of the input, or <tt>null</tt> if no such handle
- * exists.
- */
- @Nullable
- public Input getInput(TavernaRun run, String portName) {
- for (Input i : run.getInputs())
- if (i.getName().equals(portName))
- return i;
- return null;
- }
-
- /**
- * Get a listener attached to a run.
- *
- * @param runName
- * The name of the run to look up
- * @param listenerName
- * The name of the listener.
- * @return The handle of the listener.
- * @throws NoListenerException
- * If no such listener exists.
- * @throws UnknownRunException
- * If no such workflow run exists, or if the user does not have
- * permission to access it.
- */
- public Listener getListener(String runName, String listenerName)
- throws NoListenerException, UnknownRunException {
- return getListener(getRun(runName), listenerName);
- }
-
- /**
- * Given a file, produce a guess at its content type. This uses the content
- * type map property, and if that search fails it falls back on the Medsea
- * mime type library.
- *
- * @param f
- * The file handle.
- * @return The content type. If all else fails, produces good old
- * "application/octet-stream".
- */
- @Nonnull
- public String getEstimatedContentType(@Nonnull File f) {
- String name = f.getName();
- for (int idx = name.indexOf('.'); idx != -1; idx = name.indexOf('.',
- idx + 1)) {
- String mt = contentTypeMap.get(name.substring(idx + 1));
- if (mt != null)
- return mt;
- }
- @Nonnull
- String type = getExtensionMimeTypes(name);
- if (!type.equals(UNKNOWN_MIME_TYPE))
- return type;
- try {
- return getMimeType(new ByteArrayInputStream(f.getContents(0,
- SAMPLE_SIZE)));
- } catch (FilesystemAccessException e) {
- return type;
- }
- }
-
- public void copyDataToFile(DataHandler handler, File file)
- throws FilesystemAccessException {
- try {
- copyStreamToFile(handler.getInputStream(), file);
- } catch (IOException e) {
- throw new FilesystemAccessException(
- "problem constructing stream from data source", e);
- }
- }
-
- public void copyDataToFile(URI uri, File file)
- throws MalformedURLException, FilesystemAccessException,
- IOException {
- copyStreamToFile(uri.toURL().openStream(), file);
- }
-
- public void copyStreamToFile(InputStream stream, File file)
- throws FilesystemAccessException {
- String name = file.getFullName();
- long total = 0;
- try {
- byte[] buffer = new byte[TRANSFER_SIZE];
- boolean first = true;
- while (true) {
- int len = stream.read(buffer);
- if (len < 0)
- break;
- total += len;
- if (log.isDebugEnabled())
- log.debug("read " + len
- + " bytes from source stream (total: " + total
- + ") bound for " + name);
- if (len == buffer.length) {
- if (first)
- file.setContents(buffer);
- else
- file.appendContents(buffer);
- } else {
- byte[] newBuf = new byte[len];
- System.arraycopy(buffer, 0, newBuf, 0, len);
- if (first)
- file.setContents(newBuf);
- else
- file.appendContents(newBuf);
- }
- first = false;
- }
- } catch (IOException exn) {
- throw new FilesystemAccessException("failed to transfer bytes", exn);
- }
- }
-
- /**
- * Build a description of the profiles supported by a workflow. Note that we
- * expect the set of profiles to be fairly small.
- *
- * @param workflow
- * The workflow to describe the profiles of.
- * @return The descriptor (which might be empty).
- */
- public ProfileList getProfileDescriptor(Workflow workflow) {
- ProfileList result = new ProfileList();
- String main = workflow.getMainProfileName();
- for (Profile p : workflow.getProfiles()) {
- ProfileList.Info i = new ProfileList.Info();
- i.name = p.getName();
- if (main != null && main.equals(i.name))
- i.main = true;
- result.profile.add(i);
- }
- return result;
- }
-
- public boolean getAllowStartWorkflowRuns() {
- return runFactory.isAllowingRunsToStart();
- }
-
- /**
- * The list of filenames that logs may occupy.
- */
- private static final String[] LOGS = { "logs/detail.log.4",
- "logs/detail.log.3", "logs/detail.log.2", "logs/detail.log.1",
- "logs/detail.log" };
-
- public FileConcatenation getLogs(TavernaRun run) {
- FileConcatenation fc = new FileConcatenation();
- for (String name : LOGS) {
- try {
- fc.add(fileUtils.getFile(run, name));
- } catch (FilesystemAccessException | NoDirectoryEntryException e) {
- // Ignore
- }
- }
- return fc;
- }
-
- @Nonnull
- public List<Capability> getCapabilities() {
- return capabilitySource.getCapabilities();
- }
-
- static final String PROV_BUNDLE = "out.bundle.zip";
-
- public FileConcatenation getProv(TavernaRun run) {
- FileConcatenation fc = new FileConcatenation();
- try {
- fc.add(fileUtils.getFile(run, PROV_BUNDLE));
- } catch (FilesystemAccessException | NoDirectoryEntryException e) {
- // Ignore
- }
- return fc;
- }
-}
[39/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java
deleted file mode 100644
index b227bfa..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/TavernaSecurityContext.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.Principal;
-import java.util.Set;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.xml.ws.handler.MessageContext;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.exceptions.InvalidCredentialException;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Security context for a workflow run.
- *
- * @author Donal Fellows
- */
-public interface TavernaSecurityContext {
- /**
- * @return Who owns the security context.
- */
- UsernamePrincipal getOwner();
-
- /**
- * Describe the names of the users (as extracted from their
- * {@link Principal} objects) that may destroy the run or manipulate its
- * lifetime.
- *
- * @return The names of the users who may use destroy operations. Read-only.
- */
- Set<String> getPermittedDestroyers();
-
- /**
- * Sets the collection of names of users (as extracted from their
- * {@link Principal} objects) that may destroy the run or manipulate its
- * lifetime.
- *
- * @param destroyers
- * The names of the users who may use destroy operations.
- */
- void setPermittedDestroyers(Set<String> destroyers);
-
- /**
- * Describe the names of the users (as extracted from their
- * {@link Principal} objects) that may update the run (including writing to
- * files).
- *
- * @return The names of the users who may use update operations. Read-only.
- */
- Set<String> getPermittedUpdaters();
-
- /**
- * Sets the collection of names of users (as extracted from their
- * {@link Principal} objects) that may update the run (including writing to
- * its files).
- *
- * @param updaters
- * The names of the users who may use update operations.
- */
- void setPermittedUpdaters(Set<String> updaters);
-
- /**
- * Describe the names of the users (as extracted from their
- * {@link Principal} objects) that may read from the run (including its
- * files).
- *
- * @return The names of the users who may use read operations. Read-only.
- */
- Set<String> getPermittedReaders();
-
- /**
- * Sets the collection of names of users (as extracted from their
- * {@link Principal} objects) that may read from the run (including its
- * files).
- *
- * @param readers
- * The names of the users who may use read operations.
- */
- void setPermittedReaders(Set<String> readers);
-
- /**
- * @return The credentials owned by the user. Never <tt>null</tt>.
- */
- Credential[] getCredentials();
-
- /**
- * Add a credential to the owned set or replaces the old version with the
- * new one.
- *
- * @param toAdd
- * The credential to add.
- */
- void addCredential(Credential toAdd);
-
- /**
- * Remove a credential from the owned set. It's not a failure to remove
- * something that isn't in the set.
- *
- * @param toDelete
- * The credential to remove.
- */
- void deleteCredential(Credential toDelete);
-
- /**
- * Tests if the credential is valid. This includes testing whether the
- * underlying credential file exists and can be unlocked by the password in
- * the {@link Credential} object.
- *
- * @param c
- * The credential object to validate.
- * @throws InvalidCredentialException
- * If it is invalid.
- */
- void validateCredential(Credential c) throws InvalidCredentialException;
-
- /**
- * @return The identities trusted by the user. Never <tt>null</tt>.
- */
- Trust[] getTrusted();
-
- /**
- * Add an identity to the trusted set.
- *
- * @param toAdd
- * The identity to add.
- */
- void addTrusted(Trust toAdd);
-
- /**
- * Remove an identity from the trusted set. It's not a failure to remove
- * something that isn't in the set.
- *
- * @param toDelete
- * The identity to remove.
- */
- void deleteTrusted(Trust toDelete);
-
- /**
- * Tests if the trusted identity descriptor is valid. This includes checking
- * whether the underlying trusted identity file exists.
- *
- * @param t
- * The trusted identity descriptor to check.
- * @throws InvalidCredentialException
- * If it is invalid.
- */
- void validateTrusted(Trust t) throws InvalidCredentialException;
-
- /**
- * Establish the security context from how the owning workflow run was
- * created. In particular, this gives an opportunity for boot-strapping
- * things with any delegateable credentials.
- *
- * @param securityContext
- * The security context associated with the request that caused
- * the workflow to be created.
- * @throws Exception
- * If anything goes wrong.
- */
- void initializeSecurityFromContext(SecurityContext securityContext)
- throws Exception;
-
- /**
- * Establish the security context from how the owning workflow run was
- * created. In particular, this gives an opportunity for boot-strapping
- * things with any delegateable credentials.
- *
- * @param context
- * The full information about the request that caused the
- * workflow to be created.
- */
- void initializeSecurityFromSOAPContext(MessageContext context);
-
- /**
- * Establish the security context from how the owning workflow run was
- * created. In particular, this gives an opportunity for boot-strapping
- * things with any delegateable credentials.
- *
- * @param headers
- * The full information about the request that caused the
- * workflow to be created.
- */
- void initializeSecurityFromRESTContext(HttpHeaders headers);
-
- /**
- * Transfer the security context to the remote system.
- *
- * @throws IOException
- * If the communication fails.
- * @throws GeneralSecurityException
- * If the assembly of the context fails.
- * @throws ImplementationException
- * If the local worker has problems with creating the realized
- * security context.
- */
- void conveySecurity() throws GeneralSecurityException, IOException,
- ImplementationException;
-
- /**
- * @return The factory that created this security context.
- */
- SecurityContextFactory getFactory();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java
deleted file mode 100644
index e5cd02c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/UriBuilderFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.interfaces;
-
-import java.net.URI;
-
-import javax.ws.rs.core.UriBuilder;
-
-/**
- * How to manufacture URIs to workflow runs.
- *
- * @author Donal Fellows
- */
-public interface UriBuilderFactory {
- /**
- * Given a run, get a factory for RESTful URIs to resources associated
- * with it.
- *
- * @param run
- * The run in question.
- * @return The {@link URI} factory.
- */
- UriBuilder getRunUriBuilder(TavernaRun run);
-
- /**
- * @return a URI factory that is preconfigured to point to the base of
- * the webapp.
- */
- UriBuilder getBaseUriBuilder();
-
- /**
- * Resolves a URI with respect to the base URI of the factory.
- *
- * @param uri
- * The URI to resolve, or <tt>null</tt>.
- * @return The resolved URI, or <tt>null</tt> if <b>uri</b> is
- * <tt>null</tt>.
- */
- String resolve(String uri);
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java
deleted file mode 100644
index cfbbe79..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/interfaces/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Interfaces to the main worker classes that provide the magical power
- * that drives the webapp front-end.
- */
-package org.taverna.server.master.interfaces;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java
deleted file mode 100644
index fc7f881..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/AbstractRemoteRunFactory.java
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.localworker;
-
-import static java.lang.System.getSecurityManager;
-import static java.lang.System.setProperty;
-import static java.lang.System.setSecurityManager;
-import static java.rmi.registry.LocateRegistry.createRegistry;
-import static java.rmi.registry.LocateRegistry.getRegistry;
-import static java.rmi.registry.Registry.REGISTRY_PORT;
-import static java.util.UUID.randomUUID;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-import static org.taverna.server.master.rest.TavernaServerRunREST.PathNames.DIR;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.net.URI;
-import java.net.URL;
-import java.rmi.MarshalledObject;
-import java.rmi.RMISecurityManager;
-import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.Resource;
-import javax.xml.bind.JAXBException;
-
-import org.apache.commons.io.IOUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.taverna.server.localworker.remote.RemoteRunFactory;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.factories.ListenerFactory;
-import org.taverna.server.master.factories.RunFactory;
-import org.taverna.server.master.interaction.InteractionFeedSupport;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.SecurityContextFactory;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-import org.taverna.server.master.notification.atom.EventDAO;
-import org.taverna.server.master.usage.UsageRecordRecorder;
-import org.taverna.server.master.utils.UsernamePrincipal;
-import org.taverna.server.master.worker.FactoryBean;
-import org.taverna.server.master.worker.RemoteRunDelegate;
-import org.taverna.server.master.worker.RunFactoryConfiguration;
-
-import uk.org.taverna.scufl2.api.io.WriterException;
-
-/**
- * Bridge to remote runs via RMI.
- *
- * @author Donal Fellows
- */
-@ManagedResource(objectName = JMX_ROOT + "Factory", description = "The factory for runs")
-public abstract class AbstractRemoteRunFactory extends RunFactoryConfiguration
- implements ListenerFactory, RunFactory, FactoryBean {
- /**
- * Whether to apply stronger limitations than normal to RMI. It is
- * recommended that this be true!
- */
- @Value("${rmi.localhostOnly}")
- private boolean rmiLocalhostOnly;
- /** The interaction host name. */
- private String interhost;
- /** The interaction port number. */
- private String interport;
- private Process registryProcess;
- /**
- * The interaction WebDAV location. Will be resolved before being passed to
- * the back-end.
- */
- private String interwebdav;
- /**
- * The interaction ATOM feed location. Will be resolved before being passed
- * to the back-end.
- */
- private String interfeed;
- /** Used for doing URI resolution. */
- @Resource(name = "webapp")
- private UriBuilderFactory baseurifactory;
- @Autowired
- private InteractionFeedSupport interactionFeedSupport;
-
- @Value("${taverna.interaction.host}")
- void setInteractionHost(String host) {
- if (host != null && host.equals("none"))
- host = null;
- interhost = host;
- }
-
- @Value("${taverna.interaction.port}")
- void setInteractionPort(String port) {
- if (port != null && port.equals("none"))
- port = null;
- interport = port;
- }
-
- @Value("${taverna.interaction.webdav_path}")
- void setInteractionWebdav(String webdav) {
- if (webdav != null && webdav.equals("none"))
- webdav = null;
- interwebdav = webdav;
- }
-
- @Value("${taverna.interaction.feed_path}")
- void setInteractionFeed(String feed) {
- if (feed != null && feed.equals("none"))
- feed = null;
- interfeed = feed;
- }
-
- @Override
- protected void reinitRegistry() {
- registry = null;
- if (registryProcess != null) {
- registryProcess.destroy();
- registryProcess = null;
- }
- }
-
- protected void initInteractionDetails(RemoteRunFactory factory)
- throws RemoteException {
- if (interhost != null) {
- String feed = baseurifactory.resolve(interfeed);
- String webdav = baseurifactory.resolve(interwebdav);
- factory.setInteractionServiceDetails(interhost, interport, webdav,
- feed);
- }
- }
-
- protected static final Process launchSubprocess(ProcessBuilder b)
- throws IOException {
- Thread t = Thread.currentThread();
- ClassLoader ccl = t.getContextClassLoader();
- try {
- t.setContextClassLoader(null);
- return b.start();
- } finally {
- t.setContextClassLoader(ccl);
- }
- }
-
- /** Get a handle to a new instance of the RMI registry. */
- private Registry makeRegistry(int port) throws RemoteException {
- ProcessBuilder p = new ProcessBuilder(getJavaBinary());
- p.command().add("-jar");
- p.command().add(getRmiRegistryJar());
- p.command().add(Integer.toString(port));
- p.command().add(Boolean.toString(rmiLocalhostOnly));
- try {
- Process proc = launchSubprocess(p);
- Thread.sleep(getSleepTime());
- try {
- if (proc.exitValue() == 0)
- return null;
- String error = IOUtils.toString(proc.getErrorStream());
- throw new RemoteException(error);
- } catch (IllegalThreadStateException ise) {
- // Still running!
- }
- try (ObjectInputStream ois = new ObjectInputStream(
- proc.getInputStream())) {
- @SuppressWarnings("unchecked")
- Registry r = ((MarshalledObject<Registry>) ois.readObject())
- .get();
- registryProcess = proc;
- return r;
- }
- } catch (RemoteException e) {
- throw e;
- } catch (ClassNotFoundException e) {
- throw new RemoteException("unexpected registry type", e);
- } catch (IOException e) {
- throw new RemoteException("unexpected IO problem with registry", e);
- } catch (InterruptedException e) {
- throw new RemoteException("unexpected interrupt");
- }
- }
-
- /**
- * @return A handle to the current RMI registry.
- */
- protected Registry getTheRegistry() {
- try {
- if (registry != null) {
- registry.list();
- return registry;
- }
- } catch (RemoteException e) {
- log.warn("non-functioning existing registry handle", e);
- registry = null;
- }
- try {
- registry = getRegistry(getRegistryHost(), getRegistryPort());
- registry.list();
- return registry;
- } catch (RemoteException e) {
- log.warn("Failed to get working RMI registry handle.");
- registry = null;
- log.warn("Will build new registry, "
- + "but service restart ability is at risk.");
- try {
- registry = makeRegistry(getRegistryPort());
- registry.list();
- return registry;
- } catch (RemoteException e2) {
- log.error(
- "failed to create local working RMI registry on port "
- + getRegistryPort(), e2);
- log.info("original connection exception", e);
- }
- }
- try {
- registry = getRegistry(getRegistryHost(), REGISTRY_PORT);
- registry.list();
- return registry;
- } catch (RemoteException e) {
- log.warn("Failed to get working RMI registry handle on backup port.");
- try {
- registry = makeRegistry(REGISTRY_PORT);
- registry.list();
- return registry;
- } catch (RemoteException e2) {
- log.fatal(
- "totally failed to get registry handle, even on fallback!",
- e2);
- log.info("original connection exception", e);
- registry = null;
- throw new RuntimeException("No RMI Registry Available");
- }
- }
- }
-
- private Registry registry;
- /**
- * The name of the resource that describes the default security policy to
- * install.
- */
- public static final String SECURITY_POLICY_FILE = "security.policy";
- private SecurityContextFactory securityFactory;
- UsageRecordRecorder usageRecordSink;
- private EventDAO masterEventFeed;
-
- @Autowired(required = true)
- void setSecurityContextFactory(SecurityContextFactory factory) {
- this.securityFactory = factory;
- }
-
- @Autowired(required = true)
- void setMasterEventFeed(EventDAO masterEventFeed) {
- this.masterEventFeed = masterEventFeed;
- }
-
- @Autowired(required = true)
- void setUsageRecordSink(UsageRecordRecorder usageRecordSink) {
- this.usageRecordSink = usageRecordSink;
- }
-
- /**
- * Configures the Java security model. Not currently used, as it is
- * viciously difficult to get right!
- */
- @SuppressWarnings("unused")
- private static void installSecurityManager() {
- if (getSecurityManager() == null) {
- setProperty("java.security.policy", AbstractRemoteRunFactory.class
- .getClassLoader().getResource(SECURITY_POLICY_FILE)
- .toExternalForm());
- setSecurityManager(new RMISecurityManager());
- }
- }
-
- // static {
- // installSecurityManager();
- // }
-
- /**
- * Set up the run expiry management engine.
- *
- * @throws JAXBException
- */
- public AbstractRemoteRunFactory() throws JAXBException {
- try {
- registry = LocateRegistry.getRegistry();
- registry.list();
- } catch (RemoteException e) {
- log.warn("Failed to get working RMI registry handle.");
- log.warn("Will build new registry, but service restart ability is at risk.");
- try {
- registry = createRegistry(REGISTRY_PORT);
- registry.list();
- } catch (RemoteException e2) {
- log.error("failed to create working RMI registry", e2);
- log.info("original connection exception", e);
- }
- }
- }
-
- @Override
- public List<String> getSupportedListenerTypes() {
- try {
- RemoteRunDelegate rrd = runDB.pickArbitraryRun();
- if (rrd != null)
- return rrd.getListenerTypes();
- log.warn("no remote runs; no listener types");
- } catch (Exception e) {
- log.warn("failed to get list of listener types", e);
- }
- return new ArrayList<>();
- }
-
- @Override
- public Listener makeListener(TavernaRun run, String listenerType,
- String configuration) throws NoListenerException {
- if (run instanceof RemoteRunDelegate)
- return ((RemoteRunDelegate) run).makeListener(listenerType,
- configuration);
- throw new NoListenerException("unexpected run type: " + run.getClass());
- }
-
- @Override
- public TavernaRun create(UsernamePrincipal creator, Workflow workflow)
- throws NoCreateException {
- try {
- Date now = new Date();
- UUID id = randomUUID();
- RemoteSingleRun rsr = getRealRun(creator, workflow, id);
- RemoteRunDelegate run = new RemoteRunDelegate(now, workflow, rsr,
- state.getDefaultLifetime(), runDB, id,
- state.getGenerateProvenance(), this);
- run.setSecurityContext(securityFactory.create(run, creator));
- @Nonnull
- URI feed = interactionFeedSupport.getFeedURI(run);
- @Nonnull
- URL feedUrl = feed.toURL();
- @Nonnull
- URL webdavUrl = baseurifactory.getRunUriBuilder(run)
- .path(DIR + "/interactions").build().toURL();
- @Nullable
- URL pub = interactionFeedSupport.getLocalFeedBase(feed);
- rsr.setInteractionServiceDetails(feedUrl, webdavUrl, pub);
- return run;
- } catch (NoCreateException e) {
- log.warn("failed to build run instance", e);
- throw e;
- } catch (Exception e) {
- log.warn("failed to build run instance", e);
- throw new NoCreateException("failed to build run instance", e);
- }
- }
-
- /**
- * Gets the RMI connector for a new run.
- *
- * @param creator
- * Who is creating the workflow run.
- * @param workflow
- * What workflow are they instantiating.
- * @param id
- * The identity token for the run, newly minted.
- * @return The remote interface to the run.
- * @throws Exception
- * Just about anything can go wrong...
- */
- protected abstract RemoteSingleRun getRealRun(UsernamePrincipal creator,
- Workflow workflow, UUID id) throws Exception;
-
- /**
- * How to convert a wrapped workflow into XML.
- *
- * @param workflow
- * The wrapped workflow.
- * @return The XML version of the document.
- * @throws JAXBException
- * If serialization fails.
- */
- protected byte[] serializeWorkflow(Workflow workflow) throws JAXBException {
- try {
- return workflow.getScufl2Bytes();
- } catch (IOException e) {
- throw new JAXBException("problem converting to scufl2", e);
- } catch (WriterException e) {
- throw new JAXBException("problem converting to scufl2", e);
- }
- }
-
- private void acceptUsageRecord(String usageRecord) {
- if (usageRecordSink != null)
- usageRecordSink.storeUsageRecord(usageRecord);
- runDB.checkForFinishNow();
- }
-
- /**
- * Make a Remote object that can act as a consumer for usage records.
- *
- * @param creator
- *
- * @return The receiver, or <tt>null</tt> if the construction fails.
- */
- protected UsageRecordReceiver makeURReciver(UsernamePrincipal creator) {
- try {
- @SuppressWarnings("serial")
- class URReceiver extends UnicastRemoteObject implements
- UsageRecordReceiver {
- public URReceiver() throws RemoteException {
- super();
- }
-
- @Override
- public void acceptUsageRecord(String usageRecord) {
- AbstractRemoteRunFactory.this.acceptUsageRecord(usageRecord);
- }
- }
- return new URReceiver();
- } catch (RemoteException e) {
- log.warn("failed to build usage record receiver", e);
- return null;
- }
- }
-
- @Override
- public EventDAO getMasterEventFeed() {
- return masterEventFeed;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java
deleted file mode 100644
index b67e121..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/ForkRunFactory.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.localworker;
-
-import static java.lang.System.getProperty;
-import static java.lang.Thread.sleep;
-import static java.util.Arrays.asList;
-import static java.util.Calendar.SECOND;
-import static java.util.UUID.randomUUID;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-
-import java.io.File;
-import java.rmi.ConnectException;
-import java.rmi.ConnectIOException;
-import java.rmi.NotBoundException;
-import java.rmi.RemoteException;
-import java.util.Calendar;
-import java.util.UUID;
-
-import javax.annotation.Nonnull;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.xml.bind.JAXBException;
-
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.taverna.server.localworker.remote.RemoteRunFactory;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.factories.ConfigurableRunFactory;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * A simple factory for workflow runs that forks runs from a subprocess.
- *
- * @author Donal Fellows
- */
-@ManagedResource(objectName = JMX_ROOT + "RunFactory", description = "The factory for simple singleton forked run.")
-public class ForkRunFactory extends AbstractRemoteRunFactory implements
- ConfigurableRunFactory {
- private int lastStartupCheckCount;
- private Integer lastExitCode;
- private RemoteRunFactory factory;
- private Process factoryProcess;
- private String factoryProcessName;
-
- /**
- * Create a factory for remote runs that works by forking off a subprocess.
- *
- * @throws JAXBException
- * Shouldn't happen.
- */
- public ForkRunFactory() throws JAXBException {
- }
-
- @PostConstruct
- protected void initRegistry() {
- log.info("waiting for availability of default RMI registry");
- getTheRegistry();
- }
-
- @Override
- protected void reinitFactory() {
- boolean makeFactory = factory != null;
- killFactory();
- try {
- if (makeFactory)
- initFactory();
- } catch (Exception e) {
- log.fatal("failed to make connection to remote run factory", e);
- }
- }
-
- private RemoteRunFactory getFactory() throws RemoteException {
- try {
- initFactory();
- } catch (RemoteException e) {
- throw e;
- } catch (Exception e) {
- throw new RemoteException("problem constructing factory", e);
- }
- return factory;
- }
-
- /**
- * @return How many checks were done for the worker process the last time a
- * spawn was tried.
- */
- @ManagedAttribute(description = "How many checks were done for the worker process the last time a spawn was tried.", currencyTimeLimit = 60)
- @Override
- public int getLastStartupCheckCount() {
- return lastStartupCheckCount;
- }
-
- /**
- * @return What was the exit code from the last time the factory subprocess
- * was killed?
- */
- @ManagedAttribute(description = "What was the exit code from the last time the factory subprocess was killed?")
- @Override
- public Integer getLastExitCode() {
- return lastExitCode;
- }
-
- /**
- * @return What the factory subprocess's main RMI interface is registered
- * as.
- */
- @ManagedAttribute(description = "What the factory subprocess's main RMI interface is registered as.", currencyTimeLimit = 60)
- @Override
- public String getFactoryProcessName() {
- return factoryProcessName;
- }
-
- /**
- * Makes the subprocess that manufactures runs.
- *
- * @throws Exception
- * If anything goes wrong.
- */
- public void initFactory() throws Exception {
- if (factory != null)
- return;
- // Generate the arguments to use when spawning the subprocess
- factoryProcessName = state.getFactoryProcessNamePrefix() + randomUUID();
- ProcessBuilder p = new ProcessBuilder(getJavaBinary());
- p.command().add("-jar");
- p.command().add(getServerWorkerJar());
- if (getExecuteWorkflowScript() == null)
- log.fatal("no execute workflow script");
- p.command().add(getExecuteWorkflowScript());
- p.command().addAll(asList(getExtraArguments()));
- p.command().add(factoryProcessName);
- p.redirectErrorStream(true);
- p.directory(new File(getProperty("javax.servlet.context.tempdir",
- getProperty("java.io.tmpdir"))));
-
- // Spawn the subprocess
- log.info("about to create subprocess: " + p.command());
-
- factoryProcess = launchSubprocess(p);
- outlog = new StreamLogger("FactoryStdout", factoryProcess.getInputStream()) {
- @Override
- protected void write(String msg) {
- log.info(msg);
- }
- };
- errlog = new StreamLogger("FactoryStderr", factoryProcess.getErrorStream()) {
- @Override
- protected void write(String msg) {
- log.info(msg);
- }
- };
-
- // Wait for the subprocess to register itself in the RMI registry
- Calendar deadline = Calendar.getInstance();
- deadline.add(SECOND, state.getWaitSeconds());
- Exception lastException = null;
- lastStartupCheckCount = 0;
- while (deadline.after(Calendar.getInstance())) {
- try {
- sleep(state.getSleepMS());
- lastStartupCheckCount++;
- factory = getRemoteFactoryHandle(factoryProcessName);
- initInteractionDetails(factory);
- return;
- } catch (InterruptedException ie) {
- continue;
- } catch (NotBoundException nbe) {
- lastException = nbe;
- log.info("resource \"" + factoryProcessName
- + "\" not yet registered...");
- continue;
- } catch (RemoteException re) {
- // Unpack a remote exception if we can
- lastException = re;
- try {
- if (re.getCause() != null)
- lastException = (Exception) re.getCause();
- } catch (Throwable t) {
- // Ignore!
- }
- } catch (RuntimeException e) {
- lastException = e;
- }
- }
- if (lastException == null)
- lastException = new InterruptedException();
- throw lastException;
- }
-
- private StreamLogger outlog, errlog;
-
- private void stopLoggers() {
- if (outlog != null)
- outlog.stop();
- outlog = null;
- if (errlog != null)
- errlog.stop();
- errlog = null;
- }
-
- private RemoteRunFactory getRemoteFactoryHandle(String name)
- throws RemoteException, NotBoundException {
- log.info("about to look up resource called " + name);
- try {
- // Validate registry connection first
- getTheRegistry().list();
- } catch (ConnectException | ConnectIOException e) {
- log.warn("connection problems with registry", e);
- }
- RemoteRunFactory rrf = (RemoteRunFactory) getTheRegistry().lookup(name);
- log.info("successfully connected to factory subprocess "
- + factoryProcessName);
- return rrf;
- }
-
- /**
- * Destroys the subprocess that manufactures runs.
- */
- @PreDestroy
- public void killFactory() {
- if (factory != null) {
- log.info("requesting shutdown of " + factoryProcessName);
- try {
- factory.shutdown();
- sleep(700);
- } catch (RemoteException e) {
- log.warn(factoryProcessName + " failed to shut down nicely", e);
- } catch (InterruptedException e) {
- if (log.isDebugEnabled())
- log.debug("interrupted during wait after asking "
- + factoryProcessName + " to shut down", e);
- } finally {
- factory = null;
- }
- }
-
- if (factoryProcess != null) {
- int code = -1;
- try {
- lastExitCode = code = factoryProcess.exitValue();
- log.info(factoryProcessName + " already dead?");
- } catch (RuntimeException e) {
- log.info("trying to force death of " + factoryProcessName);
- try {
- factoryProcess.destroy();
- sleep(350); // takes a little time, even normally
- lastExitCode = code = factoryProcess.exitValue();
- } catch (Exception e2) {
- code = -1;
- }
- } finally {
- factoryProcess = null;
- stopLoggers();
- }
- if (code > 128) {
- log.info(factoryProcessName + " died with signal="
- + (code - 128));
- } else if (code >= 0) {
- log.info(factoryProcessName + " process killed: code=" + code);
- } else {
- log.warn(factoryProcessName + " not yet dead");
- }
- }
- }
-
- /**
- * The real core of the run builder, factored out from its reliability
- * support.
- *
- * @param creator
- * Who created this workflow?
- * @param wf
- * The serialized workflow.
- * @return The remote handle of the workflow run.
- * @throws RemoteException
- * If anything fails (communications error, etc.)
- */
- private RemoteSingleRun getRealRun(@Nonnull UsernamePrincipal creator,
- @Nonnull byte[] wf, UUID id) throws RemoteException {
- @Nonnull
- String globaluser = "Unknown Person";
- if (creator != null)
- globaluser = creator.getName();
- RemoteSingleRun rsr = getFactory().make(wf, globaluser,
- makeURReciver(creator), id);
- incrementRunCount();
- return rsr;
- }
-
- @Override
- protected RemoteSingleRun getRealRun(UsernamePrincipal creator,
- Workflow workflow, UUID id) throws Exception {
- @Nonnull
- byte[] wf = serializeWorkflow(workflow);
- for (int i = 0; i < 3; i++) {
- initFactory();
- try {
- return getRealRun(creator, wf, id);
- } catch (ConnectException | ConnectIOException e) {
- // factory was lost; try to recreate
- }
- killFactory();
- }
- throw new NoCreateException("total failure to connect to factory "
- + factoryProcessName + "despite attempting restart");
- }
-
- @Override
- public String[] getFactoryProcessMapping() {
- return new String[0];
- }
-
- @Override
- protected int operatingCount() throws Exception {
- return getFactory().countOperatingRuns();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java
deleted file mode 100644
index e449373..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/IdAwareForkRunFactory.java
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.localworker;
-
-import static java.lang.System.getProperty;
-import static java.lang.Thread.sleep;
-import static java.util.Arrays.asList;
-import static java.util.Calendar.SECOND;
-import static java.util.UUID.randomUUID;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-import static org.taverna.server.master.localworker.AbstractRemoteRunFactory.launchSubprocess;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.rmi.ConnectException;
-import java.rmi.ConnectIOException;
-import java.rmi.NotBoundException;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.annotation.Nonnull;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.xml.bind.JAXBException;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.annotation.Order;
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.taverna.server.localworker.remote.RemoteRunFactory;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.factories.ConfigurableRunFactory;
-import org.taverna.server.master.interfaces.LocalIdentityMapper;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * A simple factory for workflow runs that forks runs from a subprocess.
- *
- * @author Donal Fellows
- */
-@ManagedResource(objectName = JMX_ROOT + "RunFactory", description = "The factory for a user-specific forked run.")
-public class IdAwareForkRunFactory extends AbstractRemoteRunFactory implements
- ConfigurableRunFactory {
- private MetaFactory forker;
- private Map<String, RemoteRunFactory> factory;
- private Map<String, String> factoryProcessName;
-
- /**
- * Create a factory for remote runs that works by forking off a subprocess.
- *
- * @throws JAXBException
- * Shouldn't happen.
- */
- public IdAwareForkRunFactory() throws JAXBException {
- factory = new HashMap<>();
- factoryProcessName = new HashMap<>();
- }
-
- @Override
- protected void reinitFactory() {
- boolean makeForker = forker != null;
- try {
- killForker();
- } catch (Exception e) {
- log.warn("exception when killing secure-fork process", e);
- }
- try {
- if (makeForker)
- initMetaFactory();
- } catch (Exception e) {
- log.fatal("failed to make secure-fork process", e);
- }
- }
-
- /**
- * @return How many checks were done for the worker process the last time a
- * spawn was tried.
- */
- @Override
- @ManagedAttribute(description = "How many checks were done for the worker process the last time a spawn was tried.", currencyTimeLimit = 60)
- public int getLastStartupCheckCount() {
- return forker == null ? 0 : forker.lastStartupCheckCount();
- }
-
- /**
- * @return What was the exit code from the last time the factory subprocess
- * was killed?
- */
- @Override
- @ManagedAttribute(description = "What was the exit code from the last time the factory subprocess was killed?")
- public Integer getLastExitCode() {
- return forker == null ? null : forker.lastExitCode();
- }
-
- /**
- * @return The mapping of user names to RMI factory IDs.
- */
- @Override
- @ManagedAttribute(description = "The mapping of user names to RMI factory IDs.", currencyTimeLimit = 60)
- public String[] getFactoryProcessMapping() {
- ArrayList<String> result = new ArrayList<>();
- ArrayList<String> keys = new ArrayList<>(factoryProcessName.keySet());
- String[] ks = keys.toArray(new String[keys.size()]);
- Arrays.sort(ks);
- for (String k : ks) {
- result.add(k);
- result.add(factoryProcessName.get(k));
- }
- return result.toArray(new String[result.size()]);
- }
-
- /**
- * How construction of factories is actually done.
- *
- * @author Donal Fellows
- */
- public interface MetaFactory {
- /**
- * Make a factory for the given user.
- *
- * @param username
- * Who to make it for.
- * @return Handle of the factory.
- * @throws Exception
- * If anything goes wrong.
- */
- RemoteRunFactory make(String username) throws Exception;
-
- /**
- * Shut down the meta-factory. It is not defined whether factories
- * created by it are also shut down at the same time.
- *
- * @throws IOException
- * If something goes wrong when communicating with the
- * meta-factory.
- * @throws InterruptedException
- * If something stops us waiting for the shut down to
- * happen.
- */
- void close() throws IOException, InterruptedException;
-
- int lastStartupCheckCount();
-
- Integer lastExitCode();
- }
-
- void registerFactory(String username, String fpn, RemoteRunFactory f) {
- factoryProcessName.put(username, fpn);
- factory.put(username, f);
- }
-
- /**
- * Makes the connection to the meta-factory that makes factories.
- *
- * @throws IOException
- * If the connection fails.
- */
- @PostConstruct
- void initMetaFactory() throws IOException {
- log.info("waiting for availability of default RMI registry");
- getTheRegistry();
- log.info("constructing secure fork subprocess");
- forker = new SecureFork(this, state, log);
- }
-
- private void killForker() throws IOException, InterruptedException {
- try {
- if (forker != null)
- forker.close();
- } finally {
- forker = null;
- }
- }
-
- /**
- * Makes the subprocess that manufactures runs.
- *
- * @throws Exception
- * If anything goes wrong.
- */
- private void initFactory(String username) throws Exception {
- if (factory.containsKey(username))
- return;
- if (forker == null)
- initMetaFactory();
- forker.make(username);
- }
-
- /**
- * Destroys the subprocess that manufactures runs.
- */
- @PreDestroy
- public void killFactories() {
- if (!factory.isEmpty()) {
- Iterator<String> keys = factory.keySet().iterator();
- while (keys.hasNext()) {
- String key = keys.next();
- log.info("requesting shutdown of "
- + factoryProcessName.get(key));
- try {
- factory.get(key).shutdown();
- } catch (RemoteException e) {
- log.warn(factoryProcessName.get(key)
- + " failed to shut down nicely", e);
- } finally {
- keys.remove();
- factoryProcessName.remove(key);
- }
- }
- try {
- sleep(700);
- } catch (InterruptedException e) {
- if (log.isDebugEnabled())
- log.debug("interrupted during wait after "
- + "asking factories to shut down", e);
- }
- }
-
- try {
- killForker();
- } catch (Exception e) {
- if (log.isDebugEnabled())
- log.debug("exception in shutdown of secure-fork process", e);
- }
- }
-
- @Override
- protected void finalize() throws Throwable {
- killFactories();
- super.finalize();
- }
-
- @Autowired
- public void setIdMapper(LocalIdentityMapper mapper) {
- this.mapper = mapper;
- }
-
- private LocalIdentityMapper mapper;
-
- /**
- * The real core of the run builder, factored out from its reliability
- * support.
- *
- * @param creator
- * Who created this workflow?
- * @param username
- * What user account is this workflow to be executed in?
- * @param wf
- * The serialized workflow.
- * @return The remote handle of the workflow run.
- * @throws RemoteException
- * If anything fails (communications error, etc.)
- */
- private RemoteSingleRun getRealRun(@Nonnull UsernamePrincipal creator,
- @Nonnull String username, @Nonnull byte[] wf, UUID id)
- throws RemoteException {
- String globaluser = "Unknown Person";
- if (creator != null)
- globaluser = creator.getName();
- RemoteSingleRun rsr = factory.get(username).make(wf, globaluser,
- makeURReciver(creator), id);
- incrementRunCount();
- return rsr;
- }
-
- @Override
- protected RemoteSingleRun getRealRun(UsernamePrincipal creator,
- Workflow workflow, UUID id) throws Exception {
- byte[] wf = serializeWorkflow(workflow);
- String username = mapper == null ? null : mapper
- .getUsernameForPrincipal(creator);
- if (username == null)
- throw new Exception("cannot determine who to run workflow as; "
- + "local identity mapper returned null");
- for (int i = 0; i < 3; i++) {
- if (!factory.containsKey(username))
- initFactory(username);
- try {
- return getRealRun(creator, username, wf, id);
- } catch (ConnectException | ConnectIOException e) {
- // factory was lost; try to recreate
- }
- factory.remove(username);
- }
- throw new NoCreateException("total failure to connect to factory "
- + factoryProcessName + "despite attempting restart");
- }
-
- @Value("${secureForkPasswordFile}")
- @Order(20)
- public void setPasswordSource(String passwordSource) {
- if (passwordSource == null || passwordSource.isEmpty()
- || passwordSource.startsWith("${"))
- state.setDefaultPasswordFile(null);
- else
- state.setDefaultPasswordFile(passwordSource);
- if (state.getPasswordFile() == null)
- log.info("assuming password-free forking enabled");
- else
- log.info("configured secureForkPasswordFile from context as "
- + state.getPasswordFile());
- }
-
- @Override
- public String getFactoryProcessName() {
- return "<PROPERTY-NOT-SUPPORTED>";
- }
-
- @Override
- protected int operatingCount() throws Exception {
- int total = 0;
- for (RemoteRunFactory rrf : factory.values())
- total += rrf.countOperatingRuns();
- return total;
- }
-}
-
-/**
- * The connector that handles the secure fork process itself.
- *
- * @author Donal Fellows
- */
-class SecureFork implements IdAwareForkRunFactory.MetaFactory {
- private IdAwareForkRunFactory main;
- private Process process;
- private PrintWriter channel;
- private int lastStartupCheckCount;
- private Integer lastExitCode;
- private Log log;
- private LocalWorkerState state;
- private StreamLogger out, err;
-
- /**
- * Construct the command to run the meta-factory process.
- *
- * @param args
- * The live list of arguments to pass.
- */
- public void initFactoryArgs(List<String> args) {
- args.add(main.getJavaBinary());
- String pwf = main.getPasswordFile();
- if (pwf != null) {
- args.add("-Dpassword.file=" + pwf);
- }
- args.add("-jar");
- args.add(main.getServerForkerJar());
- args.add(main.getJavaBinary());
- args.add("-jar");
- args.add(main.getServerWorkerJar());
- if (main.getExecuteWorkflowScript() == null)
- log.fatal("no execute workflow script");
- args.add(main.getExecuteWorkflowScript());
- args.addAll(asList(main.getExtraArguments()));
- }
-
- SecureFork(IdAwareForkRunFactory main, LocalWorkerState state, Log log)
- throws IOException {
- this.main = main;
- this.log = log;
- this.state = state;
- ProcessBuilder p = new ProcessBuilder();
- initFactoryArgs(p.command());
- p.redirectErrorStream(true);
- p.directory(new File(getProperty("javax.servlet.context.tempdir",
- getProperty("java.io.tmpdir"))));
-
- // Spawn the subprocess
- log.info("about to create subprocess: " + p.command());
- log.info("subprocess directory: " + p.directory());
- process = launchSubprocess(p);
- channel = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
- process.getOutputStream())), true);
- // Log the responses
- out = new StreamLogger("ForkedStdout", process.getInputStream()) {
- @Override
- protected void write(String msg) {
- log.info(msg);
- }
- };
- err = new StreamLogger("ForkedStderr", process.getErrorStream()) {
- @Override
- protected void write(String msg) {
- log.info(msg);
- }
- };
- }
-
- @Override
- public void close() throws IOException, InterruptedException {
- try {
- if (process != null) {
- log.info("about to close down subprocess");
- channel.close();
- int code = -1;
- try {
- try {
- code = process.exitValue();
- log.info("secure-fork process already dead?");
- } catch (IllegalThreadStateException e) {
- try {
- code = process.waitFor();
- } catch (InterruptedException e1) {
- log.info("interrupted waiting for natural death of secure-fork process?!");
- process.destroy();
- code = process.waitFor();
- }
- }
- } finally {
- lastExitCode = code;
- if (code > 128) {
- log.info("secure-fork process died with signal="
- + (code - 128));
- } else if (code >= 0) {
- log.info("secure-fork process killed: code=" + code);
- } else {
- log.warn("secure-fork process not yet dead");
- }
- }
- }
- } finally {
- process = null;
- channel = null;
- out.stop();
- err.stop();
- }
- }
-
- protected void make(String username, String fpn) {
- log.info("about to request subprocess creation for " + username
- + " producing ID " + fpn);
- channel.println(username + " " + fpn);
- }
-
- @Override
- public RemoteRunFactory make(String username) throws Exception {
- try {
- main.getTheRegistry().list(); // Validate registry connection first
- } catch (ConnectException | ConnectIOException e) {
- log.warn("connection problems with registry", e);
- } catch (RemoteException e) {
- if (e.getCause() != null && e.getCause() instanceof Exception) {
- throw (Exception) e.getCause();
- }
- log.warn("connection problems with registry", e);
- }
-
- String fpn = state.getFactoryProcessNamePrefix() + randomUUID();
- make(username, fpn);
-
- // Wait for the subprocess to register itself in the RMI registry
- Calendar deadline = Calendar.getInstance();
- deadline.add(SECOND, state.getWaitSeconds());
- Exception lastException = null;
- lastStartupCheckCount = 0;
- while (deadline.after(Calendar.getInstance())) {
- try {
- sleep(state.getSleepMS());
- lastStartupCheckCount++;
- log.info("about to look up resource called " + fpn);
- RemoteRunFactory f = (RemoteRunFactory) main.getTheRegistry()
- .lookup(fpn);
- log.info("successfully connected to factory subprocess " + fpn);
- main.initInteractionDetails(f);
- main.registerFactory(username, fpn, f);
- return f;
- } catch (InterruptedException ie) {
- continue;
- } catch (NotBoundException nbe) {
- lastException = nbe;
- log.info("resource \"" + fpn + "\" not yet registered...");
- continue;
- } catch (RemoteException re) {
- // Unpack a remote exception if we can
- lastException = re;
- try {
- if (re.getCause() != null)
- lastException = (Exception) re.getCause();
- } catch (Throwable t) {
- // Ignore!
- }
- } catch (Exception e) {
- lastException = e;
- }
- }
- if (lastException == null)
- lastException = new InterruptedException();
- throw lastException;
- }
-
- @Override
- public Integer lastExitCode() {
- return lastExitCode;
- }
-
- @Override
- public int lastStartupCheckCount() {
- return lastStartupCheckCount;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java
deleted file mode 100644
index f890204..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.localworker;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Provider of the configuration of the "localworker.factory" bean, which is
- * sufficiently complex to be too hard to manufacture directly from the XML
- * configuration.
- *
- * @author Donal Fellows
- */
-@Configuration
-public class LocalWorkerFactory {
- @Bean(name = "localworker.factory")
- AbstractRemoteRunFactory getLocalworkerFactory(
- @Value("${backEndFactory}") String mode) throws Exception {
- if (mode == null || mode.isEmpty() || mode.startsWith("${"))
- throw new Exception("no value for ${backEndFactory}");
- Class<?> c = Class.forName(mode);
- if (AbstractRemoteRunFactory.class.isAssignableFrom(c))
- return (AbstractRemoteRunFactory) c.newInstance();
- throw new Exception("unknown remote run factory: " + mode);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java
deleted file mode 100644
index 9f0f39b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/LocalWorkerState.java
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.localworker;
-
-import static java.io.File.separator;
-import static java.lang.System.getProperty;
-import static java.rmi.registry.Registry.REGISTRY_PORT;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.unmodifiableList;
-import static org.taverna.server.master.defaults.Default.EXTRA_ARGUMENTS;
-import static org.taverna.server.master.defaults.Default.PASSWORD_FILE;
-import static org.taverna.server.master.defaults.Default.REGISTRY_JAR;
-import static org.taverna.server.master.defaults.Default.RMI_PREFIX;
-import static org.taverna.server.master.defaults.Default.RUN_LIFE_MINUTES;
-import static org.taverna.server.master.defaults.Default.RUN_OPERATING_LIMIT;
-import static org.taverna.server.master.defaults.Default.SECURE_FORK_IMPLEMENTATION_JAR;
-import static org.taverna.server.master.defaults.Default.SERVER_WORKER_IMPLEMENTATION_JAR;
-import static org.taverna.server.master.defaults.Default.SUBPROCESS_START_POLL_SLEEP;
-import static org.taverna.server.master.defaults.Default.SUBPROCESS_START_WAIT;
-import static org.taverna.server.master.localworker.PersistedState.KEY;
-import static org.taverna.server.master.localworker.PersistedState.makeInstance;
-
-import java.io.File;
-import java.io.FilenameFilter;
-import java.net.URI;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-import javax.jdo.annotations.PersistenceAware;
-
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.defaults.Default;
-import org.taverna.server.master.utils.JDOSupport;
-import org.taverna.server.master.worker.WorkerModel;
-
-/**
- * The persistent state of a local worker factory.
- *
- * @author Donal Fellows
- */
-@PersistenceAware
-public class LocalWorkerState extends JDOSupport<PersistedState> implements
- WorkerModel {
- public LocalWorkerState() {
- super(PersistedState.class);
- }
-
- private LocalWorkerState self;
-
- @Required
- public void setSelf(LocalWorkerState self) {
- this.self = self;
- }
-
- /** Initial lifetime of runs, in minutes. */
- int defaultLifetime;
- /**
- * Maximum number of runs to exist at once. Note that this includes when
- * they are just existing for the purposes of file transfer (
- * {@link Status#Initialized}/{@link Status#Finished} states).
- */
- int maxRuns;
- /**
- * Prefix to use for RMI names.
- */
- String factoryProcessNamePrefix;
- /**
- * Full path name of the script used to start running a workflow; normally
- * expected to be "<i>somewhere/</i><tt>executeWorkflow.sh</tt>".
- */
- String executeWorkflowScript;
- /** Default value for {@link #executeWorkflowScript}. */
- private transient String defaultExecuteWorkflowScript;
- /**
- * Full path name of the file containing the password used to launch workers
- * as other users. The file is normally expected to contain a single line,
- * the password, and to be thoroughly locked down so only the user running
- * the server (e.g., "<tt>tomcat</tt>") can read it; it will probably reside
- * in either the user's home directory or in a system configuration
- * directory.
- */
- String passwordFile;
- /** Default value for {@link #passwordFile}. */
- private transient String defaultPasswordFile = PASSWORD_FILE;
- /**
- * The extra arguments to pass to the subprocess.
- */
- String[] extraArgs;
- /**
- * How long to wait for subprocess startup, in seconds.
- */
- int waitSeconds;
- /**
- * Polling interval to use during startup, in milliseconds.
- */
- int sleepMS;
- /**
- * Full path name to the worker process's implementation JAR.
- */
- String serverWorkerJar;
- private static final String DEFAULT_WORKER_JAR = LocalWorkerState.class
- .getClassLoader().getResource(SERVER_WORKER_IMPLEMENTATION_JAR)
- .getFile();
- /**
- * Full path name to the Java binary to use to run the subprocess.
- */
- String javaBinary;
- private static final String DEFAULT_JAVA_BINARY = getProperty("java.home")
- + separator + "bin" + separator + "java";
- /**
- * Full path name to the secure fork process's implementation JAR.
- */
- String serverForkerJar;
- private static final String DEFAULT_FORKER_JAR = LocalWorkerState.class
- .getClassLoader().getResource(SECURE_FORK_IMPLEMENTATION_JAR)
- .getFile();
-
- String registryHost;
- int registryPort;
-
- int operatingLimit;
-
- URI[] permittedWorkflows;
- private String registryJar;
- private static final String DEFAULT_REGISTRY_JAR = LocalWorkerState.class
- .getClassLoader().getResource(REGISTRY_JAR).getFile();
-
- @Override
- public void setDefaultLifetime(int defaultLifetime) {
- this.defaultLifetime = defaultLifetime;
- if (loadedState)
- self.store();
- }
-
- @Override
- public int getDefaultLifetime() {
- return defaultLifetime < 1 ? RUN_LIFE_MINUTES : defaultLifetime;
- }
-
- @Override
- public void setMaxRuns(int maxRuns) {
- this.maxRuns = maxRuns;
- if (loadedState)
- self.store();
- }
-
- @Override
- public int getMaxRuns() {
- return maxRuns < 1 ? Default.RUN_COUNT_MAX : maxRuns;
- }
-
- @Override
- public int getOperatingLimit() {
- return operatingLimit < 1 ? RUN_OPERATING_LIMIT : operatingLimit;
- }
-
- @Override
- public void setOperatingLimit(int operatingLimit) {
- this.operatingLimit = operatingLimit;
- if (loadedState)
- self.store();
- }
-
- @Override
- public void setFactoryProcessNamePrefix(String factoryProcessNamePrefix) {
- this.factoryProcessNamePrefix = factoryProcessNamePrefix;
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getFactoryProcessNamePrefix() {
- return factoryProcessNamePrefix == null ? RMI_PREFIX
- : factoryProcessNamePrefix;
- }
-
- @Override
- public void setExecuteWorkflowScript(String executeWorkflowScript) {
- this.executeWorkflowScript = executeWorkflowScript;
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getExecuteWorkflowScript() {
- return executeWorkflowScript == null ? defaultExecuteWorkflowScript
- : executeWorkflowScript;
- }
-
- private static String guessWorkflowScript() {
- File utilDir = new File(DEFAULT_WORKER_JAR).getParentFile();
- File[] dirs = utilDir.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return name.startsWith("taverna-commandline-");
- }
- });
- assert dirs.length > 0;
- return new File(dirs[0], "executeworkflow.sh").toString();
- }
-
- /**
- * Set what executeworkflow script to use by default. This is the value that
- * is used if not overridden by the administration interface.
- *
- * @param defaultScript
- * Full path to the script to use.
- */
- public void setDefaultExecuteWorkflowScript(String defaultScript) {
- if (defaultScript.startsWith("${") || defaultScript.equals("NONE")) {
- this.defaultExecuteWorkflowScript = guessWorkflowScript();
- return;
- }
- this.defaultExecuteWorkflowScript = defaultScript;
- }
-
- String getDefaultExecuteWorkflowScript() {
- return defaultExecuteWorkflowScript;
- }
-
- @Override
- public void setExtraArgs(String[] extraArgs) {
- this.extraArgs = extraArgs.clone();
- if (loadedState)
- self.store();
- }
-
- @Override
- public String[] getExtraArgs() {
- return extraArgs == null ? EXTRA_ARGUMENTS : extraArgs.clone();
- }
-
- @Override
- public void setWaitSeconds(int waitSeconds) {
- this.waitSeconds = waitSeconds;
- if (loadedState)
- self.store();
- }
-
- @Override
- public int getWaitSeconds() {
- return waitSeconds < 1 ? SUBPROCESS_START_WAIT : waitSeconds;
- }
-
- @Override
- public void setSleepMS(int sleepMS) {
- this.sleepMS = sleepMS;
- if (loadedState)
- self.store();
- }
-
- @Override
- public int getSleepMS() {
- return sleepMS < 1 ? SUBPROCESS_START_POLL_SLEEP : sleepMS;
- }
-
- @Override
- public void setServerWorkerJar(String serverWorkerJar) {
- this.serverWorkerJar = serverWorkerJar;
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getServerWorkerJar() {
- return serverWorkerJar == null ? DEFAULT_WORKER_JAR : serverWorkerJar;
- }
-
- @Override
- public void setServerForkerJar(String serverForkerJar) {
- this.serverForkerJar = serverForkerJar;
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getServerForkerJar() {
- return serverForkerJar == null ? DEFAULT_FORKER_JAR : serverForkerJar;
- }
-
- @Override
- public void setJavaBinary(String javaBinary) {
- this.javaBinary = javaBinary;
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getJavaBinary() {
- return javaBinary == null ? DEFAULT_JAVA_BINARY : javaBinary;
- }
-
- @Override
- public void setPasswordFile(String passwordFile) {
- this.passwordFile = passwordFile;
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getPasswordFile() {
- return passwordFile == null ? defaultPasswordFile : passwordFile;
- }
-
- void setDefaultPasswordFile(String defaultPasswordFile) {
- this.defaultPasswordFile = defaultPasswordFile;
- }
-
- @Override
- public void setRegistryHost(String registryHost) {
- this.registryHost = (registryHost == null ? "" : registryHost);
- if (loadedState)
- self.store();
- }
-
- @Override
- public String getRegistryHost() {
- return (registryHost == null || registryHost.isEmpty()) ? null
- : registryHost;
- }
-
- @Override
- public void setRegistryPort(int registryPort) {
- this.registryPort = ((registryPort < 1 || registryPort > 65534) ? REGISTRY_PORT
- : registryPort);
- if (loadedState)
- self.store();
- }
-
- @Override
- public int getRegistryPort() {
- return registryPort == 0 ? REGISTRY_PORT : registryPort;
- }
-
- @Override
- public String getRegistryJar() {
- return registryJar == null ? DEFAULT_REGISTRY_JAR : registryJar;
- }
-
- @Override
- public void setRegistryJar(String rmiRegistryJar) {
- this.registryJar = (rmiRegistryJar == null || rmiRegistryJar.isEmpty()) ? null
- : rmiRegistryJar;
- if (loadedState)
- self.store();
- }
-
- @Override
- public List<URI> getPermittedWorkflowURIs() {
- if (permittedWorkflows == null || permittedWorkflows.length == 0)
- return emptyList();
- return unmodifiableList(asList(permittedWorkflows));
- }
-
- @Override
- public void setPermittedWorkflowURIs(List<URI> permittedWorkflows) {
- if (permittedWorkflows == null || permittedWorkflows.isEmpty())
- this.permittedWorkflows = new URI[0];
- else
- this.permittedWorkflows = permittedWorkflows
- .toArray(new URI[permittedWorkflows.size()]);
- if (loadedState)
- self.store();
- }
-
- public static final boolean DEFAULT_GENERATE_PROVENANCE = false;
- private Boolean generateProvenance;
-
- @Override
- public boolean getGenerateProvenance() {
- Boolean g = generateProvenance;
- return g == null ? DEFAULT_GENERATE_PROVENANCE : (boolean) g;
- }
-
- @Override
- public void setGenerateProvenance(boolean generate) {
- this.generateProvenance = generate;
- if (loadedState)
- self.store();
- }
-
- // --------------------------------------------------------------
-
- private boolean loadedState;
-
- @PostConstruct
- @WithinSingleTransaction
- public void load() {
- if (loadedState || !isPersistent())
- return;
- WorkerModel state = getById(KEY);
- if (state == null) {
- store();
- return;
- }
-
- defaultLifetime = state.getDefaultLifetime();
- executeWorkflowScript = state.getExecuteWorkflowScript();
- extraArgs = state.getExtraArgs();
- factoryProcessNamePrefix = state.getFactoryProcessNamePrefix();
- javaBinary = state.getJavaBinary();
- maxRuns = state.getMaxRuns();
- serverWorkerJar = state.getServerWorkerJar();
- serverForkerJar = state.getServerForkerJar();
- passwordFile = state.getPasswordFile();
- sleepMS = state.getSleepMS();
- waitSeconds = state.getWaitSeconds();
- registryHost = state.getRegistryHost();
- registryPort = state.getRegistryPort();
- operatingLimit = state.getOperatingLimit();
- List<URI> pwu = state.getPermittedWorkflowURIs();
- permittedWorkflows = (URI[]) pwu.toArray(new URI[pwu.size()]);
- registryJar = state.getRegistryJar();
- generateProvenance = state.getGenerateProvenance();
-
- loadedState = true;
- }
-
- @WithinSingleTransaction
- public void store() {
- if (!isPersistent())
- return;
- WorkerModel state = getById(KEY);
- if (state == null)
- state = persist(makeInstance());
-
- state.setDefaultLifetime(defaultLifetime);
- state.setExecuteWorkflowScript(executeWorkflowScript);
- state.setExtraArgs(extraArgs);
- state.setFactoryProcessNamePrefix(factoryProcessNamePrefix);
- state.setJavaBinary(javaBinary);
- state.setMaxRuns(maxRuns);
- state.setServerWorkerJar(serverWorkerJar);
- state.setServerForkerJar(serverForkerJar);
- state.setPasswordFile(passwordFile);
- state.setSleepMS(sleepMS);
- state.setWaitSeconds(waitSeconds);
- state.setRegistryHost(registryHost);
- state.setRegistryPort(registryPort);
- state.setOperatingLimit(operatingLimit);
- if (permittedWorkflows != null)
- state.setPermittedWorkflowURIs(asList(permittedWorkflows));
- state.setRegistryJar(registryJar);
- if (generateProvenance != null)
- state.setGenerateProvenance(generateProvenance);
-
- loadedState = true;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java
deleted file mode 100644
index 83d6bda..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/PersistedState.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.localworker;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jdo.annotations.Join;
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.PrimaryKey;
-
-import org.taverna.server.master.worker.WorkerModel;
-
-/**
- * The actual database connector for persisted local worker state.
- *
- * @author Donal Fellows
- */
-/*
- * WARNING! If you change the name of this class, update persistence.xml as
- * well!
- */
-@PersistenceCapable(table = PersistedState.TABLE)
-class PersistedState implements WorkerModel {
- static final String TABLE = "LOCALWORKERSTATE__PERSISTEDSTATE";
-
- static PersistedState makeInstance() {
- PersistedState o = new PersistedState();
- o.ID = KEY;
- return o;
- }
-
- @PrimaryKey(column = "ID")
- protected int ID;
-
- static final int KEY = 32;
-
- @Persistent
- private int defaultLifetime;
- @Persistent
- private int maxRuns;
- @Persistent
- private String factoryProcessNamePrefix;
- @Persistent
- private String executeWorkflowScript;
- @Persistent(serialized = "true")
- private String[] extraArgs;
- @Persistent
- private int waitSeconds;
- @Persistent
- private int sleepMS;
- @Persistent
- private String serverWorkerJar;
- @Persistent
- private String serverForkerJar;
- @Persistent
- private String registryJar;
- @Persistent
- private String passwordFile;
- @Persistent
- private String javaBinary;
- @Persistent
- private int registryPort;
- @Persistent
- private String registryHost;
- @Persistent
- private int operatingLimit;
- @Persistent(defaultFetchGroup = "true")
- @Join(table = TABLE + "_PERMWFURI", column = "ID")
- private String[] permittedWorkflows;
- @Persistent
- private int generateProvenance;
-
- @Override
- public void setDefaultLifetime(int defaultLifetime) {
- this.defaultLifetime = defaultLifetime;
- }
-
- @Override
- public int getDefaultLifetime() {
- return defaultLifetime;
- }
-
- @Override
- public void setMaxRuns(int maxRuns) {
- this.maxRuns = maxRuns;
- }
-
- @Override
- public int getMaxRuns() {
- return maxRuns;
- }
-
- @Override
- public void setFactoryProcessNamePrefix(String factoryProcessNamePrefix) {
- this.factoryProcessNamePrefix = factoryProcessNamePrefix;
- }
-
- @Override
- public String getFactoryProcessNamePrefix() {
- return factoryProcessNamePrefix;
- }
-
- @Override
- public void setExecuteWorkflowScript(String executeWorkflowScript) {
- this.executeWorkflowScript = executeWorkflowScript;
- }
-
- @Override
- public String getExecuteWorkflowScript() {
- return executeWorkflowScript;
- }
-
- @Override
- public void setExtraArgs(String[] extraArgs) {
- this.extraArgs = extraArgs;
- }
-
- @Override
- public String[] getExtraArgs() {
- return extraArgs;
- }
-
- @Override
- public void setWaitSeconds(int waitSeconds) {
- this.waitSeconds = waitSeconds;
- }
-
- @Override
- public int getWaitSeconds() {
- return waitSeconds;
- }
-
- @Override
- public void setSleepMS(int sleepMS) {
- this.sleepMS = sleepMS;
- }
-
- @Override
- public int getSleepMS() {
- return sleepMS;
- }
-
- @Override
- public void setServerWorkerJar(String serverWorkerJar) {
- this.serverWorkerJar = serverWorkerJar;
- }
-
- @Override
- public String getServerWorkerJar() {
- return serverWorkerJar;
- }
-
- @Override
- public void setJavaBinary(String javaBinary) {
- this.javaBinary = javaBinary;
- }
-
- @Override
- public String getJavaBinary() {
- return javaBinary;
- }
-
- @Override
- public void setRegistryPort(int registryPort) {
- this.registryPort = registryPort;
- }
-
- @Override
- public int getRegistryPort() {
- return registryPort;
- }
-
- @Override
- public void setRegistryHost(String registryHost) {
- this.registryHost = registryHost;
- }
-
- @Override
- public String getRegistryHost() {
- return registryHost;
- }
-
- @Override
- public void setServerForkerJar(String serverForkerJar) {
- this.serverForkerJar = serverForkerJar;
- }
-
- @Override
- public String getServerForkerJar() {
- return serverForkerJar;
- }
-
- @Override
- public void setPasswordFile(String passwordFile) {
- this.passwordFile = passwordFile;
- }
-
- @Override
- public String getPasswordFile() {
- return passwordFile;
- }
-
- @Override
- public void setOperatingLimit(int operatingLimit) {
- this.operatingLimit = operatingLimit;
- }
-
- @Override
- public int getOperatingLimit() {
- return operatingLimit;
- }
-
- @Override
- public List<URI> getPermittedWorkflowURIs() {
- String[] pw = this.permittedWorkflows;
- if (pw == null)
- return new ArrayList<>();
- List<URI> uris = new ArrayList<>(pw.length);
- for (String uri : pw)
- uris.add(URI.create(uri));
- return uris;
- }
-
- @Override
- public void setPermittedWorkflowURIs(List<URI> permittedWorkflows) {
- String[] pw = new String[permittedWorkflows.size()];
- for (int i = 0; i < pw.length; i++)
- pw[i] = permittedWorkflows.get(i).toString();
- this.permittedWorkflows = pw;
- }
-
- @Override
- public String getRegistryJar() {
- return registryJar;
- }
-
- @Override
- public void setRegistryJar(String registryJar) {
- this.registryJar = registryJar;
- }
-
- @Override
- public boolean getGenerateProvenance() {
- return generateProvenance > 0;
- }
-
- @Override
- public void setGenerateProvenance(boolean generateProvenance) {
- this.generateProvenance = (generateProvenance ? 1 : 0);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java
deleted file mode 100644
index f361e17..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/StreamLogger.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.taverna.server.master.localworker;
-
-import static java.lang.Thread.interrupted;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-import org.apache.commons.logging.Log;
-
-abstract class StreamLogger {
- protected final Log log;
- private Thread t;
- private InputStream in;
-
- protected StreamLogger(final String name, InputStream is) {
- log = getLog("Taverna.Server.LocalWorker." + name);
- in = is;
- t = new Thread(new Runnable() {
- @Override
- public void run() {
- try (BufferedReader br = new BufferedReader(
- new InputStreamReader(in))) {
- String line;
- while (!interrupted() && (line = br.readLine()) != null)
- if (!line.isEmpty())
- write(line);
- } catch (IOException e) {
- // Do nothing...
- } catch (Exception e) {
- log.warn("failure in reading from " + name, e);
- }
- }
- }, name + ".StreamLogger");
- t.setContextClassLoader(null);
- t.setDaemon(true);
- t.start();
- }
-
- /**
- * Write a line read from the subprocess to the log.
- * <p>
- * This needs to be implemented by subclasses in order for the log to be
- * correctly written with the class name.
- *
- * @param msg
- * The message to write. Guaranteed to have no newline characters
- * in it and to be non-empty.
- */
- protected abstract void write(String msg);
-
- public void stop() {
- log.info("trying to close down " + t.getName());
- t.interrupt();
- try {
- in.close();
- } catch (IOException e) {
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java
deleted file mode 100644
index 7139dd7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/localworker/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Implementation of a Taverna Server back-end that works by forking off
- * workflow executors on the local system.
- */
-package org.taverna.server.master.localworker;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java
deleted file mode 100644
index 3e27806..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/EmailDispatcher.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification;
-
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-
-import javax.annotation.PostConstruct;
-
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.mail.MailSender;
-import org.springframework.mail.SimpleMailMessage;
-import org.springframework.mail.javamail.JavaMailSender;
-
-/**
- * How to send a plain text message by email to someone.
- *
- * @author Donal Fellows
- */
-public class EmailDispatcher extends RateLimitedDispatcher {
- @Override
- public String getName() {
- return "mailto";
- }
-
- /**
- * @param from
- * Email address that the notification is to come from.
- */
- @Required
- public void setFrom(String from) {
- this.from = valid(from, "");
- }
-
- /**
- * @param host
- * The outgoing SMTP server address.
- */
- @Required
- public void setSmtpHost(String host) {
- this.host = valid(host, "");
- }
-
- /**
- * @param contentType
- * The content type of the message to be sent. For example, "
- * <tt>text/plain</tt>".
- */
- public void setMessageContentType(String contentType) {
- this.contentType = contentType;
- }
-
- /**
- * @param sender
- * the sender to set
- */
- public void setSender(MailSender sender) {
- this.sender = sender;
- }
-
- private String from;
- private String host;
- private MailSender sender;
- @SuppressWarnings("unused")
- private String contentType = TEXT_PLAIN;
-
- /**
- * Try to perform the lookup of the email service. This is called during
- * configuration so that any failure happens at a useful, predictable time.
- */
- @PostConstruct
- public void tryLookup() {
- if (!isAvailable()) {
- log.warn("no mail support; disabling email dispatch");
- sender = null;
- return;
- }
- try {
- if (sender instanceof JavaMailSender)
- ((JavaMailSender) sender).createMimeMessage();
- } catch (Throwable t) {
- log.warn("sender having problems constructing messages; "
- + "disabling...", t);
- sender = null;
- }
- }
-
- @Override
- public void dispatch(String messageSubject, String messageContent, String to)
- throws Exception {
- // Simple checks for acceptability
- if (!to.matches(".+@.+")) {
- log.info("did not send email notification: improper email address \""
- + to + "\"");
- return;
- }
-
- SimpleMailMessage message = new SimpleMailMessage();
- message.setFrom(from);
- message.setTo(to.trim());
- message.setSubject(messageSubject);
- message.setText(messageContent);
- sender.send(message);
- }
-
- @Override
- public boolean isAvailable() {
- return (host != null && !host.isEmpty() && sender != null
- && from != null && !from.isEmpty());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java
deleted file mode 100644
index 61640bf..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/JabberDispatcher.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-
-package org.taverna.server.master.notification;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jivesoftware.smack.Chat;
-import org.jivesoftware.smack.ConnectionConfiguration;
-import org.jivesoftware.smack.MessageListener;
-import org.jivesoftware.smack.XMPPConnection;
-import org.jivesoftware.smack.packet.Message;
-import org.taverna.server.master.interfaces.MessageDispatcher;
-import org.taverna.server.master.interfaces.TavernaRun;
-
-/**
- * Send notifications by Jabber/XMPP.
- *
- * @author Donal Fellows
- */
-public class JabberDispatcher implements MessageDispatcher {
- @Override
- public String getName() {
- return "xmpp";
- }
-
- private Log log = LogFactory.getLog("Taverna.Server.Notification");
- private XMPPConnection conn;
- private String resource = "TavernaServer";
- private String host = "";
- private String user = "";
- private String pass = "";
-
- /**
- * @param resource
- * The XMPP resource to use when connecting the server. This
- * defaults to "<tt>TavernaServer</tt>".
- */
- public void setResource(String resource) {
- this.resource = resource;
- }
-
- /**
- * @param service
- * The XMPP service URL.
- */
- public void setHost(String service) {
- if (service == null || service.trim().isEmpty()
- || service.trim().startsWith("$"))
- this.host = "";
- else
- this.host = service.trim();
- }
-
- /**
- * @param user
- * The user identity to use with the XMPP service.
- */
- public void setUsername(String user) {
- if (user == null || user.trim().isEmpty()
- || user.trim().startsWith("$"))
- this.user = "";
- else
- this.user = user.trim();
- }
-
- /**
- * @param pass
- * The password to use with the XMPP service.
- */
- public void setPassword(String pass) {
- if (pass == null || pass.trim().isEmpty()
- || pass.trim().startsWith("$"))
- this.pass = "";
- else
- this.pass = pass.trim();
- }
-
- @PostConstruct
- void setup() {
- try {
- if (host.isEmpty() || user.isEmpty() || pass.isEmpty()) {
- log.info("disabling XMPP support; incomplete configuration");
- conn = null;
- return;
- }
- ConnectionConfiguration cfg = new ConnectionConfiguration(host);
- cfg.setSendPresence(false);
- XMPPConnection c = new XMPPConnection(cfg);
- c.connect();
- c.login(user, pass, resource);
- conn = c;
- log.info("connected to XMPP service <" + host + "> as user <"
- + user + ">");
- } catch (Exception e) {
- log.info("failed to connect to XMPP server", e);
- }
- }
-
- @PreDestroy
- public void close() {
- if (conn != null)
- conn.disconnect();
- conn = null;
- }
-
- @Override
- public boolean isAvailable() {
- return conn != null;
- }
-
- @Override
- public void dispatch(TavernaRun ignored, String messageSubject,
- String messageContent, String targetParameter) throws Exception {
- Chat chat = conn.getChatManager().createChat(targetParameter,
- new DroppingListener());
- Message m = new Message();
- m.addBody(null, messageContent);
- m.setSubject(messageSubject);
- chat.sendMessage(m);
- }
-
- static class DroppingListener implements MessageListener {
- private Log log = LogFactory
- .getLog("Taverna.Server.Notification.Jabber");
-
- @Override
- public void processMessage(Chat chat, Message message) {
- if (log.isDebugEnabled())
- log.debug("unexpectedly received XMPP message from <"
- + message.getFrom() + ">; ignoring");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java b/server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java
deleted file mode 100644
index bc0f60d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/NotificationEngine.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.interfaces.MessageDispatcher;
-import org.taverna.server.master.interfaces.TavernaRun;
-
-/**
- * A common object for handling dispatch of event-driven messages.
- *
- * @author Donal Fellows
- */
-public class NotificationEngine {
- private Log log = LogFactory.getLog("Taverna.Server.Notification");
- private Map<String, MessageDispatcher> dispatchers;
- private List<MessageDispatcher> universalDispatchers;
-
- /**
- * @param dispatchers
- * The various dispatchers we want to install.
- */
- @Required
- public void setDispatchers(List<MessageDispatcher> dispatchers) {
- this.dispatchers = new HashMap<>();
- for (MessageDispatcher d : dispatchers)
- this.dispatchers.put(d.getName(), d);
- }
-
- /**
- * @param dispatcherList
- * A list of dispatch objects to always dispatch to.
- */
- @Required
- public void setUniversalDispatchers(List<MessageDispatcher> dispatcherList) {
- this.universalDispatchers = dispatcherList;
- }
-
- private void dispatchToChosenTarget(TavernaRun originator, String scheme,
- String target, Message message) throws Exception {
- try {
- MessageDispatcher d = dispatchers.get(scheme);
- if (d != null && d.isAvailable())
- d.dispatch(originator, message.getTitle(scheme),
- message.getContent(scheme), target);
- else
- log.warn("no such notification dispatcher for " + scheme);
- } catch (URISyntaxException e) {
- // See if *someone* will handle the message
- Exception e2 = null;
- for (MessageDispatcher d : dispatchers.values())
- try {
- if (d.isAvailable()) {
- d.dispatch(originator, message.getTitle(d.getName()),
- message.getContent(d.getName()), scheme + ":"
- + target);
- return;
- }
- } catch (Exception ex) {
- if (log.isDebugEnabled())
- log.debug("failed in pseudo-directed dispatch of "
- + scheme + ":" + target, ex);
- e2 = ex;
- }
- if (e2 != null)
- throw e2;
- }
- }
-
- private void dispatchUniversally(TavernaRun originator, Message message)
- throws Exception {
- for (MessageDispatcher d : universalDispatchers)
- try {
- if (d.isAvailable())
- d.dispatch(originator, message.getTitle(d.getName()),
- message.getContent(d.getName()), null);
- } catch (Exception e) {
- log.warn("problem in universal dispatcher", e);
- }
- }
-
- /**
- * Dispatch a message over the notification fabric.
- *
- * @param originator
- * What workflow run was the source of this message?
- * @param destination
- * Where the message should get delivered to. The correct format
- * of this is either as a URI of some form (where the scheme
- * determines the dispatcher) or as an invalid URI in which case
- * it is just tried against the possibilities to see if any
- * succeeds.
- * @param subject
- * The subject line of the message.
- * @param message
- * The plain text body of the message.
- * @throws Exception
- * If anything goes wrong with the dispatch process.
- */
- public void dispatchMessage(TavernaRun originator, String destination,
- Message message) throws Exception {
- if (destination != null && !destination.trim().isEmpty()) {
- try {
- URI toURI = new URI(destination.trim());
- dispatchToChosenTarget(originator, toURI.getScheme(),
- toURI.getSchemeSpecificPart(), message);
- } catch (URISyntaxException e) {
- // Ignore
- }
- }
- dispatchUniversally(originator, message);
- }
-
- /**
- * @return The message dispatchers that are actually available (i.e., not
- * disabled by configuration somewhere).
- */
- public List<String> listAvailableDispatchers() {
- ArrayList<String> result = new ArrayList<>();
- for (Map.Entry<String, MessageDispatcher> entry : dispatchers
- .entrySet()) {
- if (entry.getValue().isAvailable())
- result.add(entry.getKey());
- }
- return result;
- }
-
- public interface Message {
- String getContent(String type);
-
- String getTitle(String type);
- }
-}
[26/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/misc/xsd/persistence_1_0.xsd
----------------------------------------------------------------------
diff --git a/server-webapp/src/misc/xsd/persistence_1_0.xsd b/server-webapp/src/misc/xsd/persistence_1_0.xsd
deleted file mode 100644
index a485e30..0000000
--- a/server-webapp/src/misc/xsd/persistence_1_0.xsd
+++ /dev/null
@@ -1,305 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- persistence.xml schema -->
-<xsd:schema targetNamespace="http://java.sun.com/xml/ns/persistence"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:persistence="http://java.sun.com/xml/ns/persistence"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- version="1.0">
-
- <xsd:annotation>
- <xsd:documentation>
- @(#)persistence_1_0.xsd 1.0 Feb 9 2006
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:annotation>
- <xsd:documentation>
-
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
-
- Copyright 2005-2007 Sun Microsystems, Inc. All rights reserved.
-
- The contents of this file are subject to the terms of either the
- GNU General Public License Version 2 only ("GPL") or the Common
- Development and Distribution License("CDDL") (collectively, the
- "License"). You may not use this file except in compliance with
- the License. You can obtain a copy of the License at
- https://glassfish.dev.java.net/public/CDDL+GPL.html or
- glassfish/bootstrap/legal/LICENSE.txt. See the License for the
- specific language governing permissions and limitations under the
- License.
-
- When distributing the software, include this License Header
- Notice in each file and include the License file at
- glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
- particular file as subject to the "Classpath" exception as
- provided by Sun in the GPL Version 2 section of the License file
- that accompanied this code. If applicable, add the following
- below the License Header, with the fields enclosed by brackets []
- replaced by your own identifying information:
- "Portions Copyrighted [year] [name of copyright owner]"
-
- Contributor(s):
-
- If you wish your version of this file to be governed by only the
- CDDL or only the GPL Version 2, indicate your decision by adding
- "[Contributor] elects to include this software in this
- distribution under the [CDDL or GPL Version 2] license." If you
- don't indicate a single choice of license, a recipient has the
- option to distribute your version of this file under either the
- CDDL, the GPL Version 2 or to extend the choice of license to its
- licensees as provided above. However, if you add GPL Version 2
- code and therefore, elected the GPL Version 2 license, then the
- option applies only if the new code is made subject to such
- option by the copyright holder.
-
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:annotation>
- <xsd:documentation><![CDATA[
-
- This is the XML Schema for the persistence configuration file.
- The file must be named "META-INF/persistence.xml" in the
- persistence archive.
- Persistence configuration files must indicate
- the persistence schema by using the persistence namespace:
-
- http://java.sun.com/xml/ns/persistence
-
- and indicate the version of the schema by
- using the version element as shown below:
-
- <persistence xmlns="http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
- http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
- version="1.0">
- ...
- </persistence>
-
- ]]></xsd:documentation>
- </xsd:annotation>
-
- <xsd:simpleType name="versionType">
- <xsd:restriction base="xsd:token">
- <xsd:pattern value="[0-9]+(\.[0-9]+)*"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <!-- **************************************************** -->
-
- <xsd:element name="persistence">
- <xsd:complexType>
- <xsd:sequence>
-
- <!-- **************************************************** -->
-
- <xsd:element name="persistence-unit"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:documentation>
-
- Configuration of a persistence unit.
-
- </xsd:documentation>
- </xsd:annotation>
- <xsd:sequence>
-
- <!-- **************************************************** -->
-
- <xsd:element name="description" type="xsd:string"
- minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
-
- Textual description of this persistence unit.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="provider" type="xsd:string"
- minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
-
- Provider class that supplies EntityManagers for this
- persistence unit.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="jta-data-source" type="xsd:string"
- minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
-
- The container-specific name of the JTA datasource to use.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="non-jta-data-source" type="xsd:string"
- minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
-
- The container-specific name of a non-JTA datasource to use.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="mapping-file" type="xsd:string"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation>
-
- File containing mapping information. Loaded as a resource
- by the persistence provider.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="jar-file" type="xsd:string"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation>
-
- Jar file that should be scanned for entities.
- Not applicable to Java SE persistence units.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="class" type="xsd:string"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation>
-
- Class to scan for annotations. It should be annotated
- with either @Entity, @Embeddable or @MappedSuperclass.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="exclude-unlisted-classes" type="xsd:boolean"
- default="false" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
-
- When set to true then only listed classes and jars will
- be scanned for persistent classes, otherwise the enclosing
- jar or directory will also be scanned. Not applicable to
- Java SE persistence units.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:element name="properties" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
-
- A list of vendor-specific properties.
-
- </xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element name="property"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation>
- A name-value pair.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:attribute name="name" type="xsd:string"
- use="required"/>
- <xsd:attribute name="value" type="xsd:string"
- use="required"/>
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
-
- </xsd:sequence>
-
- <!-- **************************************************** -->
-
- <xsd:attribute name="name" type="xsd:string" use="required">
- <xsd:annotation>
- <xsd:documentation>
-
- Name used in code to reference this persistence unit.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
-
- <!-- **************************************************** -->
-
- <xsd:attribute name="transaction-type"
- type="persistence:persistence-unit-transaction-type">
- <xsd:annotation>
- <xsd:documentation>
-
- Type of transactions used by EntityManagers from this
- persistence unit.
-
- </xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
-
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- <xsd:attribute name="version" type="persistence:versionType"
- fixed="1.0" use="required"/>
- </xsd:complexType>
- </xsd:element>
-
- <!-- **************************************************** -->
-
- <xsd:simpleType name="persistence-unit-transaction-type">
- <xsd:annotation>
- <xsd:documentation>
-
- public enum TransactionType { JTA, RESOURCE_LOCAL };
-
- </xsd:documentation>
- </xsd:annotation>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="JTA"/>
- <xsd:enumeration value="RESOURCE_LOCAL"/>
- </xsd:restriction>
- </xsd:simpleType>
-
-</xsd:schema>
-
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java b/server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java
deleted file mode 100644
index 79c026b..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.Arrays;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.transform.Result;
-import javax.xml.transform.stream.StreamResult;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.taverna.server.master.admin.Admin;
-import org.taverna.server.master.common.Credential.KeyPair;
-import org.taverna.server.master.common.Credential.Password;
-import org.taverna.server.master.common.Capability;
-import org.taverna.server.master.common.DirEntryReference;
-import org.taverna.server.master.common.InputDescription;
-import org.taverna.server.master.common.Permission;
-import org.taverna.server.master.common.ProfileList;
-import org.taverna.server.master.common.RunReference;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.common.Uri;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.rest.DirectoryContents;
-import org.taverna.server.master.rest.ListenerDefinition;
-import org.taverna.server.master.rest.MakeOrUpdateDirEntry;
-import org.taverna.server.master.rest.TavernaServerInputREST.InDesc;
-import org.taverna.server.master.rest.TavernaServerInputREST.InputsDescriptor;
-import org.taverna.server.master.rest.TavernaServerListenersREST.ListenerDescription;
-import org.taverna.server.master.rest.TavernaServerListenersREST.Listeners;
-import org.taverna.server.master.rest.TavernaServerListenersREST.Properties;
-import org.taverna.server.master.rest.TavernaServerListenersREST.PropertyDescription;
-import org.taverna.server.master.rest.TavernaServerREST.EnabledNotificationFabrics;
-import org.taverna.server.master.rest.TavernaServerREST.PermittedListeners;
-import org.taverna.server.master.rest.TavernaServerREST.PermittedWorkflows;
-import org.taverna.server.master.rest.TavernaServerREST.PolicyView.CapabilityList;
-import org.taverna.server.master.rest.TavernaServerREST.PolicyView.PolicyDescription;
-import org.taverna.server.master.rest.TavernaServerREST.RunList;
-import org.taverna.server.master.rest.TavernaServerREST.ServerDescription;
-import org.taverna.server.master.rest.TavernaServerRunREST.RunDescription;
-import org.taverna.server.master.rest.TavernaServerSecurityREST;
-import org.taverna.server.master.rest.TavernaServerSecurityREST.CredentialHolder;
-import org.taverna.server.master.soap.DirEntry;
-import org.taverna.server.master.soap.FileContents;
-import org.taverna.server.master.soap.PermissionList;
-
-/**
- * This test file ensures that the JAXB bindings will work once deployed instead
- * of mysteriously failing in service.
- *
- * @author Donal Fellows
- */
-public class JaxbSanityTest {
- SchemaOutputResolver sink;
- StringWriter schema;
-
- String schema() {
- return schema.toString();
- }
-
- @Before
- public void init() {
- schema = new StringWriter();
- sink = new SchemaOutputResolver() {
- @Override
- public Result createOutput(String namespaceUri,
- String suggestedFileName) throws IOException {
- StreamResult sr = new StreamResult(schema);
- sr.setSystemId("/dev/null");
- return sr;
- }
- };
- assertEquals("", schema());
- }
-
- private boolean printSchema = false;
-
- private void testJAXB(Class<?>... classes) throws Exception {
- JAXBContext.newInstance(classes).generateSchema(sink);
- if (printSchema)
- System.out.println(schema());
- assertTrue(schema().length() > 0);
- }
-
- @Test
- public void testJAXBForDirEntryReference() throws Exception {
- JAXBContext.newInstance(DirEntryReference.class).generateSchema(sink);
- assertTrue(schema().length() > 0);
- }
-
- @Test
- public void testJAXBForInputDescription() throws Exception {
- testJAXB(InputDescription.class);
- }
-
- @Test
- public void testJAXBForRunReference() throws Exception {
- testJAXB(RunReference.class);
- }
-
- @Test
- public void testJAXBForWorkflow() throws Exception {
- testJAXB(Workflow.class);
- }
-
- @Test
- public void testJAXBForStatus() throws Exception {
- testJAXB(Status.class);
- }
-
- @Test
- public void testJAXBForUri() throws Exception {
- testJAXB(Uri.class);
- }
-
- @Test
- public void testJAXBForDirectoryContents() throws Exception {
- testJAXB(DirectoryContents.class);
- }
-
- @Test
- public void testJAXBForListenerDefinition() throws Exception {
- testJAXB(ListenerDefinition.class);
- }
-
- @Test
- public void testJAXBForMakeOrUpdateDirEntry() throws Exception {
- testJAXB(MakeOrUpdateDirEntry.class);
- }
-
- @Test
- public void testJAXBForInDesc() throws Exception {
- testJAXB(InDesc.class);
- }
-
- @Test
- public void testJAXBForInputsDescriptor() throws Exception {
- testJAXB(InputsDescriptor.class);
- }
-
- @Test
- public void testJAXBForListenerDescription() throws Exception {
- testJAXB(ListenerDescription.class);
- }
-
- @Test
- public void testJAXBForListeners() throws Exception {
- testJAXB(Listeners.class);
- }
-
- @Test
- public void testJAXBForProperties() throws Exception {
- testJAXB(Properties.class);
- }
-
- @Test
- public void testJAXBForPropertyDescription() throws Exception {
- testJAXB(PropertyDescription.class);
- }
-
- @Test
- public void testJAXBForPermittedListeners() throws Exception {
- testJAXB(PermittedListeners.class);
- }
-
- @Test
- public void testJAXBForPermittedWorkflows() throws Exception {
- testJAXB(PermittedWorkflows.class);
- }
-
- @Test
- public void testJAXBForEnabledNotifiers() throws Exception {
- testJAXB(EnabledNotificationFabrics.class);
- }
-
- @Test
- public void testJAXBForServerDescription() throws Exception {
- testJAXB(ServerDescription.class);
- }
-
- @Test
- public void testJAXBForRunDescription() throws Exception {
- testJAXB(RunDescription.class);
- }
-
- @Test
- public void testJAXBForRunList() throws Exception {
- testJAXB(RunList.class);
- }
-
- @Test
- public void testJAXBForPolicyDescription() throws Exception {
- testJAXB(PolicyDescription.class);
- }
-
- @Test
- public void testJAXBForSecurityCredential() throws Exception {
- testJAXB(CredentialHolder.class);
- }
-
- @Test
- public void testJAXBForSecurityCredentialList() throws Exception {
- testJAXB(TavernaServerSecurityREST.CredentialList.class);
- }
-
- @Test
- public void testJAXBForSecurityTrust() throws Exception {
- testJAXB(Trust.class);
- }
-
- @Test
- public void testJAXBForSecurityTrustList() throws Exception {
- testJAXB(TavernaServerSecurityREST.TrustList.class);
- }
-
- @Test
- public void testJAXBForPermission() throws Exception {
- testJAXB(Permission.class);
- }
-
- @Test
- public void testJAXBForSecurityPermissionDescription() throws Exception {
- testJAXB(TavernaServerSecurityREST.PermissionDescription.class);
- }
-
- @Test
- public void testJAXBForSecurityPermissionsDescription() throws Exception {
- testJAXB(TavernaServerSecurityREST.PermissionsDescription.class);
- }
-
- @Test
- public void testJAXBForSecurityDescriptor() throws Exception {
- testJAXB(TavernaServerSecurityREST.Descriptor.class);
- }
-
- @Test
- public void testJAXBForProfileList() throws Exception {
- testJAXB(ProfileList.class);
- }
-
- @Test
- public void testJAXBForDirEntry() throws Exception {
- testJAXB(DirEntry.class);
- }
-
- @Test
- public void testJAXBForCapability() throws Exception {
- testJAXB(Capability.class);
- }
-
- @Test
- public void testJAXBForCapabilityList() throws Exception {
- testJAXB(CapabilityList.class);
- }
-
- @Test
- public void testJAXBForEverythingREST() throws Exception {
- testJAXB(DirEntryReference.class, InputDescription.class,
- RunReference.class, Workflow.class, Status.class,
- DirectoryContents.class, InDesc.class,
- ListenerDefinition.class, MakeOrUpdateDirEntry.class,
- InputsDescriptor.class, ListenerDescription.class,
- Listeners.class, Properties.class, PropertyDescription.class,
- PermittedListeners.class, PermittedWorkflows.class,
- EnabledNotificationFabrics.class, ServerDescription.class,
- RunDescription.class, Uri.class, RunList.class,
- PolicyDescription.class, CredentialHolder.class, Trust.class,
- TavernaServerSecurityREST.CredentialList.class,
- TavernaServerSecurityREST.TrustList.class, Permission.class,
- TavernaServerSecurityREST.Descriptor.class,
- TavernaServerSecurityREST.PermissionDescription.class,
- TavernaServerSecurityREST.PermissionsDescription.class,
- ProfileList.class, Capability.class, CapabilityList.class);
- }
-
- @Test
- public void testJAXBForEverythingSOAP() throws Exception {
- testJAXB(DirEntry.class, FileContents.class, InputDescription.class,
- Permission.class, PermissionList.class,
- PermissionList.SinglePermissionMapping.class,
- RunReference.class, Status.class, Trust.class, Uri.class,
- ProfileList.class, Workflow.class, Capability.class);
- }
-
- @Test
- public void testUserPassSerializeDeserialize() throws Exception {
- JAXBContext c = JAXBContext.newInstance(CredentialHolder.class);
-
- Password password = new Password();
- password.username = "foo";
- password.password = "bar";
-
- // Serialize
- StringWriter sw = new StringWriter();
- CredentialHolder credIn = new CredentialHolder(password);
- c.createMarshaller().marshal(credIn, sw);
-
- // Deserialize
- StringReader sr = new StringReader(sw.toString());
- Object credOutObj = c.createUnmarshaller().unmarshal(sr);
-
- // Test value-equivalence
- assertEquals(credIn.getClass(), credOutObj.getClass());
- CredentialHolder credOut = (CredentialHolder) credOutObj;
- assertEquals(credIn.credential.getClass(),
- credOut.credential.getClass());
- assertEquals(credIn.getUserpass().username,
- credOut.getUserpass().username);
- assertEquals(credIn.getUserpass().password,
- credOut.getUserpass().password);
- }
-
- @Test
- public void testKeypairSerializeDeserialize() throws Exception {
- JAXBContext c = JAXBContext.newInstance(CredentialHolder.class);
-
- KeyPair keypair = new KeyPair();
- keypair.credentialName = "foo";
- keypair.credentialBytes = new byte[] { 1, 2, 3 };
-
- // Serialize
- StringWriter sw = new StringWriter();
- CredentialHolder credIn = new CredentialHolder(keypair);
- c.createMarshaller().marshal(credIn, sw);
-
- // Deserialize
- StringReader sr = new StringReader(sw.toString());
- Object credOutObj = c.createUnmarshaller().unmarshal(sr);
-
- // Test value-equivalence
- assertEquals(credIn.getClass(), credOutObj.getClass());
- CredentialHolder credOut = (CredentialHolder) credOutObj;
- assertEquals(credIn.credential.getClass(),
- credOut.credential.getClass());
- assertEquals(credIn.getKeypair().credentialName,
- credOut.getKeypair().credentialName);
- assertTrue(Arrays.equals(credIn.getKeypair().credentialBytes,
- credOut.getKeypair().credentialBytes));
- }
-
- @Test
- public void testJAXBforAdmininstration() throws Exception {
- testJAXB(Admin.AdminDescription.class);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java b/server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java
deleted file mode 100644
index 9665cf0..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-package org.taverna.server.master;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonMap;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.taverna.server.master.api.ManagementModel;
-import org.taverna.server.master.common.RunReference;
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.mocks.ExampleRun;
-import org.taverna.server.master.mocks.MockPolicy;
-import org.taverna.server.master.mocks.SimpleListenerFactory;
-import org.taverna.server.master.mocks.SimpleNonpersistentRunStore;
-
-public class TavernaServerImplTest {
- private TavernaServer server;
- private MockPolicy policy;
- private SimpleNonpersistentRunStore store;
- @java.lang.SuppressWarnings("unused")
- private ExampleRun.Builder runFactory;
- private SimpleListenerFactory lFactory;
- private TavernaServerSupport support;
-
- private String lrunname;
- private String lrunconf;
-
- Listener makeListener(TavernaRun run, final String config) {
- lrunname = run.toString();
- lrunconf = config;
- return new Listener() {
- @Override
- public String getConfiguration() {
- return config;
- }
-
- @Override
- public String getName() {
- return "bar";
- }
-
- @Override
- public String getProperty(String propName)
- throws NoListenerException {
- throw new NoListenerException();
- }
-
- @Override
- public String getType() {
- return "foo";
- }
-
- @Override
- public String[] listProperties() {
- return new String[0];
- }
-
- @Override
- public void setProperty(String propName, String value)
- throws NoListenerException, BadPropertyValueException {
- throw new NoListenerException();
- }
- };
- }
-
- @Before
- public void wireup() throws Exception {
- // Wire everything up; ought to be done with Spring, but this works...
- server = new TavernaServer() {
- @Override
- protected RunREST makeRunInterface() {
- return new RunREST() {
- @Override
- protected ListenersREST makeListenersInterface() {
- return new ListenersREST() {
- @Override
- protected SingleListenerREST makeListenerInterface() {
- return new SingleListenerREST() {
- @Override
- protected ListenerPropertyREST makePropertyInterface() {
- return new ListenerPropertyREST() {
- };
- }
- };
- }
- };
- }
-
- @Override
- protected RunSecurityREST makeSecurityInterface() {
- return new RunSecurityREST() {
- };
- }
-
- @Override
- protected DirectoryREST makeDirectoryInterface() {
- return new DirectoryREST() {
- };
- }
-
- @Override
- protected InputREST makeInputInterface() {
- return new InputREST() {
- };
- }
-
- @Override
- protected InteractionFeed makeInteractionFeed() {
- return null; // TODO...
- }
- };
- }
-
- @Override
- public PolicyView getPolicyDescription() {
- return new PolicyREST();
- }
- };
- support = new TavernaServerSupport();
- server.setSupport(support);
- support.setWebapp(server);
- support.setLogGetPrincipalFailures(false);
- support.setStateModel(new ManagementModel() {
- @Override
- public boolean getAllowNewWorkflowRuns() {
- return true;
- }
-
- @Override
- public boolean getLogIncomingWorkflows() {
- return false;
- }
-
- @Override
- public boolean getLogOutgoingExceptions() {
- return false;
- }
-
- @Override
- public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
- }
-
- @Override
- public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
- }
-
- @Override
- public void setLogOutgoingExceptions(boolean logOutgoingExceptions) {
- }
-
- @Override
- public String getUsageRecordLogFile() {
- return null;
- }
-
- @Override
- public void setUsageRecordLogFile(String usageRecordLogFile) {
- }
- });
- server.setPolicy(policy = new MockPolicy());
- support.setPolicy(policy);
- server.setRunStore(store = new SimpleNonpersistentRunStore());
- support.setRunStore(store);
- store.setPolicy(policy);
- support.setRunFactory(runFactory = new ExampleRun.Builder(1));
- support.setListenerFactory(lFactory = new SimpleListenerFactory());
- lFactory.setBuilders(singletonMap(
- "foo",
- (SimpleListenerFactory.Builder) new SimpleListenerFactory.Builder() {
- @Override
- public Listener build(TavernaRun run, String configuration)
- throws NoListenerException {
- return makeListener(run, configuration);
- }
- }));
- }
-
- @Test
- public void defaults1() {
- assertNotNull(server);
- }
-
- @Test
- public void defaults2() {
- assertEquals(10, server.getServerMaxRuns());
- }
-
- @Test
- public void defaults3() {
- assertEquals(1, server.getServerListeners().length);
- }
-
- @Test
- public void defaults4() {
- assertNotNull(support.getPrincipal());
- }
-
- @Test
- public void serverAsksPolicyForMaxRuns() {
- int oldmax = policy.maxruns;
- try {
- policy.maxruns = 1;
- assertEquals(1, server.getServerMaxRuns());
- } finally {
- policy.maxruns = oldmax;
- }
- }
-
- @Test
- public void makeAndKillARun() throws NoUpdateException, UnknownRunException {
- RunReference rr = server.submitWorkflow(null);
- assertNotNull(rr);
- assertNotNull(rr.name);
- server.destroyRun(rr.name);
- }
-
- @Test
- public void makeListenKillRun() throws Exception {
- RunReference run = server.submitWorkflow(null);
- try {
- lrunname = lrunconf = null;
- assertEquals(asList("foo"), asList(server.getServerListeners()));
- String l = server.addRunListener(run.name, "foo", "foobar");
- assertEquals("bar", l);
- assertEquals("foobar", lrunconf);
- assertEquals(lrunname, support.getRun(run.name).toString());
- assertEquals(asList("default", "bar"),
- asList(server.getRunListeners(run.name)));
- assertEquals(0,
- server.getRunListenerProperties(run.name, "bar").length);
- } finally {
- try {
- server.destroyRun(run.name);
- } catch (Exception e) {
- // Ignore
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java b/server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java
deleted file mode 100644
index 0450317..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.taverna.server.master;
-
-import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_NS;
-import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_ROOTNAME;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.taverna.server.master.common.Workflow;
-import org.w3c.dom.Attr;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-public class WorkflowSerializationTest {
- @Test
- public void testWorkflowSerialization()
- throws ParserConfigurationException, IOException,
- ClassNotFoundException {
- DocumentBuilder db = DocumentBuilderFactory.newInstance()
- .newDocumentBuilder();
- Document doc = db.getDOMImplementation().createDocument(null, null,
- null);
- Element workflow = doc.createElementNS(T2FLOW_NS, T2FLOW_ROOTNAME);
- Element foo = doc.createElementNS("urn:foo:bar", "pqr:foo");
- foo.setTextContent("bar");
- foo.setAttribute("xyz", "abc");
- workflow.appendChild(foo);
- Workflow w = new Workflow(workflow);
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
- oos.writeObject(w);
- }
-
- Object o;
- try (ObjectInputStream ois = new ObjectInputStream(
- new ByteArrayInputStream(baos.toByteArray()))) {
- o = ois.readObject();
- }
-
- Assert.assertNotNull(o);
- Assert.assertEquals(w.getClass(), o.getClass());
- Workflow w2 = (Workflow) o;
- Assert.assertNotNull(w2.getT2flowWorkflow());
- Element e = w2.getT2flowWorkflow();
- Assert.assertEquals(T2FLOW_ROOTNAME, e.getLocalName());
- Assert.assertEquals(T2FLOW_NS, e.getNamespaceURI());
- e = (Element) e.getFirstChild();
- Assert.assertEquals("foo", e.getLocalName());
- Assert.assertEquals("pqr", e.getPrefix());
- Assert.assertEquals("urn:foo:bar", e.getNamespaceURI());
- Assert.assertEquals("bar", e.getTextContent());
- Assert.assertEquals(1, e.getChildNodes().getLength());
- // WARNING: These are dependent on how namespaces are encoded!
- Assert.assertEquals(2, e.getAttributes().getLength());
- Assert.assertEquals("xyz", ((Attr) e.getAttributes().item(1)).getLocalName());
- Assert.assertEquals("abc", e.getAttribute("xyz"));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java b/server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java
deleted file mode 100644
index a2a0791..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.mocks;
-
-import static java.util.Calendar.MINUTE;
-import static java.util.Collections.unmodifiableList;
-import static java.util.UUID.randomUUID;
-import static org.taverna.server.master.common.Status.Initialized;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.ws.rs.core.HttpHeaders;
-import javax.xml.ws.handler.MessageContext;
-
-import org.springframework.security.core.context.SecurityContext;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Trust;
-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.InvalidCredentialException;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.factories.RunFactory;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.SecurityContextFactory;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-@SuppressWarnings("serial")
-public class ExampleRun implements TavernaRun, TavernaSecurityContext {
- String id;
- List<Listener> listeners;
- Workflow workflow;
- Status status;
- Date expiry;
- UsernamePrincipal owner;
- String inputBaclava;
- String outputBaclava;
- java.io.File realRoot;
- List<Input> inputs;
- String name;
-
- public ExampleRun(UsernamePrincipal creator, Workflow workflow, Date expiry) {
- this.id = randomUUID().toString();
- this.listeners = new ArrayList<>();
- this.status = Initialized;
- this.owner = creator;
- this.workflow = workflow;
- this.expiry = expiry;
- this.inputs = new ArrayList<>();
- listeners.add(new DefaultListener());
- }
-
- @Override
- public void addListener(Listener l) {
- listeners.add(l);
- }
-
- @Override
- public void destroy() {
- // This does nothing...
- }
-
- @Override
- public Date getExpiry() {
- return expiry;
- }
-
- @Override
- public List<Listener> getListeners() {
- return listeners;
- }
-
- @Override
- public TavernaSecurityContext getSecurityContext() {
- return this;
- }
-
- @Override
- public Status getStatus() {
- return status;
- }
-
- @Override
- public Workflow getWorkflow() {
- return workflow;
- }
-
- @Override
- public Directory getWorkingDirectory() {
- // LATER: Implement this!
- throw new UnsupportedOperationException("not yet implemented");
- }
-
- @Override
- public void setExpiry(Date d) {
- if (d.after(new Date()))
- this.expiry = d;
- }
-
- @Override
- public String setStatus(Status s) {
- this.status = s;
- return null;
- }
-
- @Override
- public UsernamePrincipal getOwner() {
- return owner;
- }
-
- public static class Builder implements RunFactory {
- private int lifetime;
-
- public Builder(int initialLifetimeMinutes) {
- this.lifetime = initialLifetimeMinutes;
- }
-
- @Override
- public TavernaRun create(UsernamePrincipal creator, Workflow workflow) {
- Calendar c = GregorianCalendar.getInstance();
- c.add(MINUTE, lifetime);
- return new ExampleRun(creator, workflow, c.getTime());
- }
-
- @Override
- public boolean isAllowingRunsToStart() {
- return true;
- }
- }
-
- static final String[] emptyArray = new String[0];
-
- class DefaultListener implements Listener {
- @Override
- public String getConfiguration() {
- return "";
- }
-
- @Override
- public String getName() {
- return "default";
- }
-
- @Override
- public String getType() {
- return "default";
- }
-
- @Override
- public String[] listProperties() {
- return emptyArray;
- }
-
- @Override
- public String getProperty(String propName) throws NoListenerException {
- throw new NoListenerException("no such property");
- }
-
- @Override
- public void setProperty(String propName, String value)
- throws NoListenerException {
- throw new NoListenerException("no such property");
- }
- }
-
- @Override
- public String getInputBaclavaFile() {
- return inputBaclava;
- }
-
- @Override
- public List<Input> getInputs() {
- return unmodifiableList(inputs);
- }
-
- @Override
- public String getOutputBaclavaFile() {
- return outputBaclava;
- }
-
- class ExampleInput implements Input {
- public String name;
- public String file;
- public String value;
- public String delim;
-
- public ExampleInput(String name) {
- this.name = name;
- }
-
- @Override
- public String getFile() {
- return file;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public void setFile(String file) throws FilesystemAccessException,
- BadStateChangeException {
- if (status != Status.Initialized)
- throw new BadStateChangeException();
- checkBadFilename(file);
- this.file = file;
- this.value = null;
- inputBaclava = null;
- }
-
- @Override
- public void setValue(String value) throws BadStateChangeException {
- if (status != Status.Initialized)
- throw new BadStateChangeException();
- this.value = value;
- this.file = null;
- inputBaclava = null;
- }
-
- void reset() {
- this.file = null;
- this.value = null;
- }
-
- @Override
- public String getDelimiter() {
- return delim;
- }
-
- @Override
- public void setDelimiter(String delimiter)
- throws BadStateChangeException {
- if (status != Status.Initialized)
- throw new BadStateChangeException();
- if (delimiter == null)
- delim = null;
- else
- delim = delimiter.substring(0, 1);
- }
- }
-
- @Override
- public Input makeInput(String name) throws BadStateChangeException {
- if (status != Status.Initialized)
- throw new BadStateChangeException();
- Input i = new ExampleInput(name);
- inputs.add(i);
- return i;
- }
-
- static void checkBadFilename(String filename)
- throws FilesystemAccessException {
- if (filename.startsWith("/"))
- throw new FilesystemAccessException("filename may not be absolute");
- if (Arrays.asList(filename.split("/")).contains(".."))
- throw new FilesystemAccessException(
- "filename may not refer to parent");
- }
-
- @Override
- public void setInputBaclavaFile(String filename)
- throws FilesystemAccessException, BadStateChangeException {
- if (status != Status.Initialized)
- throw new BadStateChangeException();
- checkBadFilename(filename);
- inputBaclava = filename;
- for (Input i : inputs)
- ((ExampleInput) i).reset();
- }
-
- @Override
- public void setOutputBaclavaFile(String filename)
- throws FilesystemAccessException, BadStateChangeException {
- if (status != Status.Initialized)
- throw new BadStateChangeException();
- if (filename != null)
- checkBadFilename(filename);
- outputBaclava = filename;
- }
-
- private Date created = new Date();
- @Override
- public Date getCreationTimestamp() {
- return created;
- }
-
- @Override
- public Date getFinishTimestamp() {
- return null;
- }
-
- @Override
- public Date getStartTimestamp() {
- return null;
- }
-
- @Override
- public Credential[] getCredentials() {
- return new Credential[0];
- }
-
- @Override
- public void addCredential(Credential toAdd) {
- }
-
- @Override
- public void deleteCredential(Credential toDelete) {
- }
-
- @Override
- public Trust[] getTrusted() {
- return new Trust[0];
- }
-
- @Override
- public void addTrusted(Trust toAdd) {
- }
-
- @Override
- public void deleteTrusted(Trust toDelete) {
- }
-
- @Override
- public void validateCredential(Credential c)
- throws InvalidCredentialException {
- }
-
- @Override
- public void validateTrusted(Trust t) throws InvalidCredentialException {
- }
-
- @Override
- public void initializeSecurityFromSOAPContext(MessageContext context) {
- // Do nothing
- }
-
- @Override
- public void initializeSecurityFromRESTContext(HttpHeaders headers) {
- // Do nothing
- }
-
- @Override
- public void conveySecurity() throws GeneralSecurityException, IOException {
- // Do nothing
- }
-
- @Override
- public SecurityContextFactory getFactory() {
- return null;
- }
-
- private Set<String> destroyers = new HashSet<String>();
- private Set<String> updaters = new HashSet<String>();
- private Set<String> readers = new HashSet<String>();
- @Override
- public Set<String> getPermittedDestroyers() {
- return destroyers;
- }
-
- @Override
- public void setPermittedDestroyers(Set<String> destroyers) {
- this.destroyers = destroyers;
- updaters.addAll(destroyers);
- readers.addAll(destroyers);
- }
-
- @Override
- public Set<String> getPermittedUpdaters() {
- return updaters;
- }
-
- @Override
- public void setPermittedUpdaters(Set<String> updaters) {
- this.updaters = updaters;
- this.updaters.addAll(destroyers);
- readers.addAll(updaters);
- }
-
- @Override
- public Set<String> getPermittedReaders() {
- return readers;
- }
-
- @Override
- public void setPermittedReaders(Set<String> readers) {
- this.readers = readers;
- this.readers.addAll(destroyers);
- this.readers.addAll(updaters);
- }
-
- @Override
- public String getId() {
- return id;
- }
-
- @Override
- public void initializeSecurityFromContext(SecurityContext securityContext)
- throws Exception {
- // Do nothing
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public void setName(String name) {
- this.name = (name.length() > 5 ? name.substring(0, 5) : name);
- }
-
- @Override
- public void ping() throws UnknownRunException {
- // Do nothing
- }
-
- @Override
- public boolean getGenerateProvenance() {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void setGenerateProvenance(boolean generateProvenance) {
- // TODO Auto-generated method stub
-
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java b/server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java
deleted file mode 100644
index 81dd08c..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.taverna.server.master.mocks;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-public class MockPolicy extends SimpleServerPolicy {
- public MockPolicy() {
- super();
- super.setCleanerInterval(30);
- }
-
- public int maxruns = 10;
- Integer usermaxruns;
- Set<TavernaRun> denyaccess = new HashSet<>();
- boolean exnOnUpdate, exnOnCreate, exnOnDelete;
-
- @Override
- public int getMaxRuns() {
- return maxruns;
- }
-
- @Override
- public Integer getMaxRuns(UsernamePrincipal user) {
- return usermaxruns;
- }
-
- @Override
- public boolean permitAccess(UsernamePrincipal user, TavernaRun run) {
- return !denyaccess.contains(run);
- }
-
- @Override
- public void permitCreate(UsernamePrincipal user, Workflow workflow)
- throws NoCreateException {
- if (this.exnOnCreate)
- throw new NoCreateException();
- }
-
- @Override
- public void permitDestroy(UsernamePrincipal user, TavernaRun run)
- throws NoDestroyException {
- if (this.exnOnDelete)
- throw new NoDestroyException();
- }
-
- @Override
- public void permitUpdate(UsernamePrincipal user, TavernaRun run)
- throws NoUpdateException {
- if (this.exnOnUpdate)
- throw new NoUpdateException();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java b/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java
deleted file mode 100644
index d864214..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.taverna.server.master.mocks;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.factories.ListenerFactory;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.TavernaRun;
-
-/**
- * A factory for event listener. The factory is configured using Spring.
- *
- * @author Donal Fellows
- */
-public class SimpleListenerFactory implements ListenerFactory {
- private Map<String, Builder> builders = new HashMap<>();
-
- public void setBuilders(Map<String, Builder> builders) {
- this.builders = builders;
- }
-
- @Override
- public List<String> getSupportedListenerTypes() {
- return new ArrayList<>(builders.keySet());
- }
-
- @Override
- public Listener makeListener(TavernaRun run, String listenerType,
- String configuration) throws NoListenerException {
- Builder b = builders.get(listenerType);
- if (b == null)
- throw new NoListenerException("no such listener type");
- Listener l = b.build(run, configuration);
- run.addListener(l);
- return l;
- }
-
- /**
- * How to actually construct a listener.
- *
- * @author Donal Fellows
- */
- public interface Builder {
- /**
- * Make an event listener attached to a run.
- *
- * @param run
- * The run to attach to.
- * @param configuration
- * A user-specified configuration document. The constructed
- * listener <i>should</i> process this configuration document
- * and be able to return it to the user when requested.
- * @return The listener object.
- * @throws NoListenerException
- * If the listener construction failed or the
- * <b>configuration</b> document was bad in some way.
- */
- public Listener build(TavernaRun run, String configuration)
- throws NoListenerException;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java b/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java
deleted file mode 100644
index a3751e4..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package org.taverna.server.master.mocks;
-
-import java.lang.ref.WeakReference;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.RunStore;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Example of a store for Taverna Workflow Runs.
- *
- * @author Donal Fellows
- */
-public class SimpleNonpersistentRunStore implements RunStore {
- private Map<String, TavernaRun> store = new HashMap<>();
- private Object lock = new Object();
-
- Timer timer;
- private CleanerTask cleaner;
-
- /**
- * The connection to the main policy store. Suitable for wiring up with
- * Spring.
- *
- * @param p
- * The policy to connect to.
- */
- public void setPolicy(SimpleServerPolicy p) {
- p.store = this;
- cleanerIntervalUpdated(p.getCleanerInterval());
- }
-
- public SimpleNonpersistentRunStore() {
- timer = new Timer("SimpleNonpersistentRunStore.CleanerTimer", true);
- cleanerIntervalUpdated(300);
- }
-
- @Override
- protected void finalize() {
- timer.cancel();
- }
-
- /**
- * Remove and destroy all runs that are expired at the moment that this
- * method starts.
- */
- void clean() {
- Date now = new Date();
- synchronized (lock) {
- // Use an iterator so we have access to its remove() method...
- Iterator<TavernaRun> i = store.values().iterator();
- while (i.hasNext()) {
- TavernaRun w = i.next();
- if (w.getExpiry().before(now)) {
- i.remove();
- try {
- w.destroy();
- } catch (NoDestroyException e) {
- }
- }
- }
- }
- }
-
- /**
- * Reconfigure the cleaner task's call interval. This is called internally
- * and from the Policy when the interval is set there.
- *
- * @param intervalInSeconds
- * How long between runs of the cleaner task, in seconds.
- */
- void cleanerIntervalUpdated(int intervalInSeconds) {
- if (cleaner != null)
- cleaner.cancel();
- cleaner = new CleanerTask(this, intervalInSeconds);
- }
-
- @Override
- public TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
- throws UnknownRunException {
- synchronized (lock) {
- TavernaRun w = store.get(uuid);
- if (w == null || !p.permitAccess(user, w))
- throw new UnknownRunException();
- return w;
- }
- }
-
- @Override
- public TavernaRun getRun(String uuid) throws UnknownRunException {
- synchronized (lock) {
- TavernaRun w = store.get(uuid);
- if (w == null)
- throw new UnknownRunException();
- return w;
- }
- }
-
- @Override
- public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
- Map<String, TavernaRun> filtered = new HashMap<>();
- synchronized (lock) {
- for (Map.Entry<String, TavernaRun> entry : store.entrySet())
- if (p.permitAccess(user, entry.getValue()))
- filtered.put(entry.getKey(), entry.getValue());
- }
- return filtered;
- }
-
- @Override
- public String registerRun(TavernaRun run) {
- synchronized (lock) {
- store.put(run.getId(), run);
- return run.getId();
- }
- }
-
- @Override
- public void unregisterRun(String uuid) {
- synchronized (lock) {
- store.remove(uuid);
- }
- }
-}
-
-class CleanerTask extends TimerTask {
- WeakReference<SimpleNonpersistentRunStore> store;
-
- CleanerTask(SimpleNonpersistentRunStore store, int interval) {
- this.store = new WeakReference<>(store);
- int tms = interval * 1000;
- store.timer.scheduleAtFixedRate(this, tms, tms);
- }
-
- @Override
- public void run() {
- SimpleNonpersistentRunStore s = store.get();
- if (s != null) {
- s.clean();
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java b/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java
deleted file mode 100644
index 1a68d2c..0000000
--- a/server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.taverna.server.master.mocks;
-
-import java.net.URI;
-import java.util.List;
-
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * A very simple (and unsafe) security model. The number of runs is configurable
- * through Spring (or 10 if unconfigured) with no per-user limits supported, all
- * workflows are permitted, and all identified users may create a workflow run.
- * Any user may read off information about any run, but only its owner may
- * modify or destroy it.
- * <p>
- * Note that this is a <i>Policy Enforcement Point</i> for access control to
- * individual workflows.
- *
- * @author Donal Fellows
- */
-public class SimpleServerPolicy implements Policy {
- private int maxRuns = 10;
- private int cleanerInterval;
- SimpleNonpersistentRunStore store;
-
- public void setMaxRuns(int maxRuns) {
- this.maxRuns = maxRuns;
- }
-
- @Override
- public int getMaxRuns() {
- return maxRuns;
- }
-
- @Override
- public Integer getMaxRuns(UsernamePrincipal p) {
- return null; // No per-user limits
- }
-
- public int getCleanerInterval() {
- return cleanerInterval;
- }
-
- /**
- * Sets how often the store of workflow runs will try to clean out expired
- * runs.
- *
- * @param intervalInSeconds
- */
- public void setCleanerInterval(int intervalInSeconds) {
- cleanerInterval = intervalInSeconds;
- if (store != null)
- store.cleanerIntervalUpdated(intervalInSeconds);
- }
-
- @Override
- public boolean permitAccess(UsernamePrincipal p, TavernaRun run) {
- // No secrets here!
- return true;
- }
-
- @Override
- public void permitCreate(UsernamePrincipal p, Workflow workflow)
- throws NoCreateException {
- // Only identified users may create
- if (p == null)
- throw new NoCreateException();
- // Global run count limit enforcement
- if (store.listRuns(p, this).size() >= maxRuns)
- throw new NoCreateException();
- // Per-user run count enforcement would come here
- }
-
- @Override
- public void permitDestroy(UsernamePrincipal p, TavernaRun run)
- throws NoDestroyException {
- // Only the creator may destroy
- if (p == null || !p.equals(run.getSecurityContext().getOwner()))
- throw new NoDestroyException();
- }
-
- @Override
- public void permitUpdate(UsernamePrincipal p, TavernaRun run)
- throws NoUpdateException {
- // Only the creator may change
- if (p == null || !p.equals(run.getSecurityContext().getOwner()))
- throw new NoUpdateException();
- }
-
- @Override
- public int getOperatingLimit() {
- return 1;
- }
-
- @Override
- public List<URI> listPermittedWorkflowURIs(UsernamePrincipal user) {
- return null;
- }
-
- @Override
- public void setPermittedWorkflowURIs(UsernamePrincipal user,
- List<URI> permitted) {
- // Ignore
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/resources/example.xml
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/resources/example.xml b/server-webapp/src/test/resources/example.xml
deleted file mode 100644
index 14cc242..0000000
--- a/server-webapp/src/test/resources/example.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
-
- <bean id="policy" class="org.taverna.server.master.mocks.SimpleServerPolicy"
- lazy-init="false" scope="singleton">
- <property name="maxRuns" value="1">
- <description>
- Limit on total number of simultaneous runs.
- </description>
- </property>
- <property name="cleanerInterval" value="300">
- <description>
- Time between trying to delete expired runs, in seconds.
- </description>
- </property>
- </bean>
-
- <bean id="runFactory" class="org.taverna.server.master.mocks.ExampleRun$Builder">
- <constructor-arg type="int" value="10" /> <!-- "initialLifetimeMinutes" -->
- </bean>
-
- <bean id="runCatalog" scope="singleton"
- class="org.taverna.server.master.mocks.SimpleNonpersistentRunStore">
- <property name="policy" ref="policy" />
- </bean>
-
- <bean id="listenerFactory" class="org.taverna.server.master.mocks.SimpleListenerFactory">
- <property name="builders">
- <description>
- This map describes how to build each type of supported
- event listener that is not installed by default. Any site policy for
- a listeners should be installed using its properties, as shown. The
- "key" is the type, the "class" is the builder for actual instances
- (which must be an instance of
- org.taverna.server.master.factories.SimpleListenerFactory.Builder)
- and any policies and installation-specific configurations are
- characterised by properties such as "sitePolicy" below.
- </description>
- <map>
- <!-- <entry key="exampleListener">-->
- <!--
- <bean
- class="org.taverna.server.master.example.ExampleListener$Builder">
- -->
- <!-- <property name="sitePolicy">-->
- <!-- <value>Just an example!</value>-->
- <!-- </property>-->
- <!-- </bean>-->
- <!-- </entry>-->
- </map>
- </property>
- </bean>
-</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/test/resources/log4j.properties b/server-webapp/src/test/resources/log4j.properties
deleted file mode 100644
index 6707f55..0000000
--- a/server-webapp/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-log4j.rootLogger=info, R
-log4j.appender.R=org.apache.log4j.ConsoleAppender
-log4j.appender.R.layout=org.apache.log4j.PatternLayout
-log4j.appender.R.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/pom.xml
----------------------------------------------------------------------
diff --git a/server-worker/pom.xml b/server-worker/pom.xml
deleted file mode 100644
index 8006c6d..0000000
--- a/server-worker/pom.xml
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-worker</artifactId>
- <name>Apache Taverna Server Workflow Executor/File System Access Process Implementation</name>
- <description>This is the implementation of the factory process that is started up by the web application to manage executing Taverna Workflow executeworkflow.sh calls. Also provides per-user access to filestore.</description>
-
- <properties>
- <workerMainClass>org.taverna.server.localworker.impl.TavernaRunManager</workerMainClass>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-runinterface</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
- <dependency>
- <groupId>commons-collections</groupId>
- <artifactId>commons-collections</artifactId>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-usagerecord</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.taverna.language</groupId>
- <artifactId>taverna-scufl2-api</artifactId>
- <version>${taverna.language.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.taverna.language</groupId>
- <artifactId>taverna-scufl2-t2flow</artifactId>
- <version>${taverna.language.version}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.taverna.language</groupId>
- <artifactId>taverna-scufl2-wfbundle</artifactId>
- <version>${taverna.language.version}</version>
- <scope>runtime</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
- <manifest>
- <mainClass>${workerMainClass}</mainClass>
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <versionRange>[2.0,)</versionRange>
- <goals>
- <goal>single</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute />
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/META-INF/MANIFEST.MF b/server-worker/src/main/java/META-INF/MANIFEST.MF
deleted file mode 100644
index 5e94951..0000000
--- a/server-worker/src/main/java/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Class-Path:
-
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java b/server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java
deleted file mode 100644
index 600913a..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.api;
-
-import static java.nio.charset.Charset.defaultCharset;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * The defaults associated with this worker, together with various other
- * constants.
- *
- * @author Donal Fellows
- */
-public abstract class Constants {
- /**
- * Subdirectories of the working directory to create by default.
- */
- public static final String[] SUBDIR_LIST = { "conf", "externaltool", "feed",
- "interactions", "lib", "logs", "plugins", "repository", "var" };
-
- /** The name of the default encoding for characters on this machine. */
- public static final String SYSTEM_ENCODING = defaultCharset().name();
-
- /**
- * Password to use to encrypt security information. This default is <7 chars
- * to work even without Unlimited Strength JCE.
- */
- public static final char[] KEYSTORE_PASSWORD = { 'c', 'h', 'a', 'n', 'g', 'e' };
-
- /**
- * The name of the directory (in the home directory) where security settings
- * will be written.
- */
- public static final String SECURITY_DIR_NAME = ".taverna-server-security";
-
- /** The name of the file that will be the created keystore. */
- public static final String KEYSTORE_FILE = "t2keystore.ubr";
-
- /** The name of the file that will be the created truststore. */
- public static final String TRUSTSTORE_FILE = "t2truststore.ubr";
-
- /**
- * The name of the file that contains the password to unlock the keystore
- * and truststore.
- */
- public static final String PASSWORD_FILE = "password.txt";
-
- // --------- UNUSED ---------
- // /**
- // * The name of the file that contains the mapping from URIs to keystore
- // * aliases.
- // */
- // public static final String URI_ALIAS_MAP = "urlmap.txt";
-
- /**
- * Used to instruct the Taverna credential manager to use a non-default
- * location for user credentials.
- */
- public static final String CREDENTIAL_MANAGER_DIRECTORY = "-cmdir";
-
- /**
- * Used to instruct the Taverna credential manager to take its master
- * password from standard input.
- */
- public static final String CREDENTIAL_MANAGER_PASSWORD = "-cmpassword";
-
- /**
- * Name of environment variable used to pass HELIO security tokens to
- * workflows.
- */
- // This technique is known to be insecure; bite me.
- public static final String HELIO_TOKEN_NAME = "HELIO_CIS_TOKEN";
-
- /**
- * The name of the standard listener, which is installed by default.
- */
- public static final String DEFAULT_LISTENER_NAME = "io";
-
- /**
- * Time to wait for the subprocess to wait, in milliseconds.
- */
- public static final int START_WAIT_TIME = 1500;
-
- /**
- * Time to wait for success or failure of a death-causing activity (i.e.,
- * sending a signal).
- */
- public static final int DEATH_TIME = 333;
-
- /**
- * The name of the file (in this code's resources) that provides the default
- * security policy that we use.
- */
- public static final String SECURITY_POLICY_FILE = "security.policy";
-
- /**
- * The Java property holding security policy info.
- */
- public static final String SEC_POLICY_PROP = "java.security.policy";
- /**
- * The Java property to set to make this code not try to enforce security
- * policy.
- */
- public static final String UNSECURE_PROP = "taverna.suppressrestrictions.rmi";
- /**
- * The Java property that holds the name of the host name to enforce.
- */
- public static final String RMI_HOST_PROP = "java.rmi.server.hostname";
- /**
- * The default hostname to require in secure mode. This is the
- * <i>resolved</i> version of "localhost".
- */
- public static final String LOCALHOST;
- static {
- String h = "127.0.0.1"; // fallback
- try {
- h = InetAddress.getByName("localhost").getHostAddress();
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } finally {
- LOCALHOST = h;
- }
- }
-
- /**
- * Time to wait during closing down this process. In milliseconds.
- */
- public static final int DEATH_DELAY = 500;
- /**
- * The name of the property describing where shared directories should be
- * located.
- */
- public static final String SHARED_DIR_PROP = "taverna.sharedDirectory";
-
- public static final String TIME = "/usr/bin/time";
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java b/server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java
deleted file mode 100644
index 3896c06..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.api;
-
-/**
- *
- * @author Donal Fellows
- */
-public interface RunAccounting {
- /**
- * Logs that a run has started executing.
- */
- void runStarted();
-
- /**
- * Logs that a run has finished executing.
- */
- void runCeased();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java b/server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java
deleted file mode 100644
index c513ed8..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.api;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-import org.taverna.server.localworker.impl.LocalWorker;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-/**
- * The interface between the connectivity layer and the thunk to the
- * subprocesses.
- *
- * @author Donal Fellows
- */
-public interface Worker {
- /**
- * Fire up the workflow. This causes a transition into the operating state.
- *
- * @param local
- * The reference to the factory class for this worker.
- * @param executeWorkflowCommand
- * The command to run to execute the workflow.
- * @param workflow
- * The workflow document to execute.
- * @param workingDir
- * What directory to use as the working directory.
- * @param inputBaclavaFile
- * The baclava file to use for inputs, or <tt>null</tt> to use
- * the other <b>input*</b> arguments' values.
- * @param inputRealFiles
- * A mapping of input names to files that supply them. Note that
- * we assume that nothing mapped here will be mapped in
- * <b>inputValues</b>.
- * @param inputValues
- * A mapping of input names to values to supply to them. Note
- * that we assume that nothing mapped here will be mapped in
- * <b>inputFiles</b>.
- * @param inputDelimiters
- * A mapping of input names to characters used to split them into
- * lists.
- * @param outputBaclavaFile
- * What baclava file to write the output from the workflow into,
- * or <tt>null</tt> to have it written into the <tt>out</tt>
- * subdirectory.
- * @param contextDirectory
- * The directory containing the keystore and truststore. <i>Must
- * not be <tt>null</tt>.</i>
- * @param keystorePassword
- * The password to the keystore and truststore. <i>Must not be
- * <tt>null</tt>.</i>
- * @param generateProvenance
- * Whether to generate a run bundle containing provenance data.
- * @param environment
- * Any environment variables that need to be added to the
- * invokation.
- * @param masterToken
- * The internal name of the workflow run.
- * @param runtimeSettings
- * List of configuration details for the forked runtime.
- * @return Whether a successful start happened.
- * @throws Exception
- * If any of quite a large number of things goes wrong.
- */
- boolean initWorker(LocalWorker local, String executeWorkflowCommand,
- byte[] workflow, File workingDir, File inputBaclavaFile,
- Map<String, File> inputRealFiles, Map<String, String> inputValues,
- Map<String, String> inputDelimiters, File outputBaclavaFile,
- File contextDirectory, char[] keystorePassword,
- boolean generateProvenance, Map<String, String> environment,
- String masterToken, List<String> runtimeSettings) throws Exception;
-
- /**
- * Kills off the subprocess if it exists and is alive.
- *
- * @throws Exception
- * if anything goes badly wrong when the worker is being killed
- * off.
- */
- void killWorker() throws Exception;
-
- /**
- * Move the worker out of the stopped state and back to operating.
- *
- * @throws Exception
- * if it fails (which it always does; operation currently
- * unsupported).
- */
- void startWorker() throws Exception;
-
- /**
- * Move the worker into the stopped state from the operating state.
- *
- * @throws Exception
- * if it fails (which it always does; operation currently
- * unsupported).
- */
- void stopWorker() throws Exception;
-
- /**
- * @return The status of the workflow run. Note that this can be an
- * expensive operation.
- */
- RemoteStatus getWorkerStatus();
-
- /**
- * @return The listener that is registered by default, in addition to all
- * those that are explicitly registered by the user.
- */
- RemoteListener getDefaultListener();
-
- /**
- * @param receiver
- * The destination where any final usage records are to be
- * written in order to log them back to the server.
- */
- void setURReceiver(UsageRecordReceiver receiver);
-
- /**
- * Arrange for the deletion of any resources created during worker process
- * construction. Guaranteed to be the last thing done before finalization.
- *
- * @throws ImplementationException
- * If anything goes wrong.
- */
- void deleteLocalResources() throws ImplementationException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java b/server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java
deleted file mode 100644
index 4ce13a7..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.taverna.server.localworker.api;
-
-
-/**
- * Class that manufactures instances of {@link Worker}.
- *
- * @author Donal Fellows
- */
-public interface WorkerFactory {
- /**
- * Create an instance of the low-level worker class.
- *
- * @return The worker object.
- * @throws Exception
- * If anything goes wrong.
- */
- Worker makeInstance() throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java
deleted file mode 100644
index 1692856..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static org.apache.commons.io.FileUtils.forceDelete;
-import static org.apache.commons.io.FileUtils.forceMkdir;
-import static org.apache.commons.io.FileUtils.touch;
-import static org.taverna.server.localworker.impl.utils.FilenameVerifier.getValidatedNewFile;
-
-import java.io.File;
-import java.io.IOException;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-import org.apache.commons.collections.MapIterator;
-import org.apache.commons.collections.map.ReferenceMap;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteDirectoryEntry;
-import org.taverna.server.localworker.remote.RemoteFile;
-
-/**
- * This class acts as a remote-aware delegate for the workflow run's working
- * directory and its subdirectories.
- *
- * @author Donal Fellows
- * @see FileDelegate
- */
-@SuppressWarnings("serial")
-public class DirectoryDelegate extends UnicastRemoteObject implements
- RemoteDirectory {
- private File dir;
- private DirectoryDelegate parent;
- private ReferenceMap localCache;
-
- /**
- * @param dir
- * @param parent
- * @throws RemoteException
- * If registration of the directory fails.
- */
- public DirectoryDelegate(@Nonnull File dir,
- @Nonnull DirectoryDelegate parent) throws RemoteException {
- super();
- this.localCache = new ReferenceMap();
- this.dir = dir;
- this.parent = parent;
- }
-
- @Override
- public Collection<RemoteDirectoryEntry> getContents()
- throws RemoteException {
- List<RemoteDirectoryEntry> result = new ArrayList<>();
- for (String s : dir.list()) {
- if (s.equals(".") || s.equals(".."))
- continue;
- File f = new File(dir, s);
- RemoteDirectoryEntry entry;
- synchronized (localCache) {
- entry = (RemoteDirectoryEntry) localCache.get(s);
- if (f.isDirectory()) {
- if (entry == null || !(entry instanceof DirectoryDelegate)) {
- entry = new DirectoryDelegate(f, this);
- localCache.put(s, entry);
- }
- } else if (f.isFile()) {
- if (entry == null || !(entry instanceof FileDelegate)) {
- entry = new FileDelegate(f, this);
- localCache.put(s, entry);
- }
- } else {
- // not file or dir; skip...
- continue;
- }
- }
- result.add(entry);
- }
- return result;
- }
-
- @Override
- public RemoteFile makeEmptyFile(String name) throws IOException {
- File f = getValidatedNewFile(dir, name);
- touch(f);
- FileDelegate delegate = new FileDelegate(f, this);
- synchronized (localCache) {
- localCache.put(name, delegate);
- }
- return delegate;
- }
-
- @Override
- public RemoteDirectory makeSubdirectory(String name) throws IOException {
- File f = getValidatedNewFile(dir, name);
- forceMkdir(f);
- DirectoryDelegate delegate = new DirectoryDelegate(f, this);
- synchronized (localCache) {
- localCache.put(name, delegate);
- }
- return delegate;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public void destroy() throws IOException {
- if (parent == null)
- throw new IOException("tried to destroy main job working directory");
- Collection<RemoteDirectoryEntry> values;
- synchronized (localCache) {
- values = new ArrayList<>(localCache.values());
- }
- for (RemoteDirectoryEntry obj : values) {
- if (obj == null)
- continue;
- try {
- obj.destroy();
- } catch (IOException e) {
- }
- }
- forceDelete(dir);
- parent.forgetEntry(this);
- }
-
- @Override
- public RemoteDirectory getContainingDirectory() {
- return parent;
- }
-
- void forgetEntry(@Nonnull RemoteDirectoryEntry entry) {
- synchronized (localCache) {
- MapIterator i = localCache.mapIterator();
- while (i.hasNext()) {
- Object key = i.next();
- if (entry == i.getValue()) {
- localCache.remove(key);
- break;
- }
- }
- }
- }
-
- @Override
- public String getName() {
- if (parent == null)
- return "";
- return dir.getName();
- }
-
- @Override
- public Date getModificationDate() throws RemoteException {
- return new Date(dir.lastModified());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java
deleted file mode 100644
index 7e47af9..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.lang.System.arraycopy;
-import static java.net.InetAddress.getLocalHost;
-import static org.apache.commons.io.FileUtils.copyFile;
-import static org.apache.commons.io.FileUtils.forceDelete;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.Date;
-
-import javax.annotation.Nonnull;
-
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteFile;
-
-/**
- * This class acts as a remote-aware delegate for the files in a workflow run's
- * working directory and its subdirectories.
- *
- * @author Donal Fellows
- * @see DirectoryDelegate
- */
-@java.lang.SuppressWarnings("serial")
-public class FileDelegate extends UnicastRemoteObject implements RemoteFile {
- private File file;
- private DirectoryDelegate parent;
-
- /**
- * @param file
- * @param parent
- * @throws RemoteException
- * If registration of the file fails.
- */
- public FileDelegate(@Nonnull File file, @Nonnull DirectoryDelegate parent)
- throws RemoteException {
- super();
- this.file = file;
- this.parent = parent;
- }
-
- @Override
- public byte[] getContents(int offset, int length) throws IOException {
- if (length == -1)
- length = (int) (file.length() - offset);
- if (length < 0 || length > 1024 * 64)
- length = 1024 * 64;
- byte[] buffer = new byte[length];
- int read;
- try (FileInputStream fis = new FileInputStream(file)) {
- if (offset > 0 && fis.skip(offset) != offset)
- throw new IOException("did not move to correct offset in file");
- read = fis.read(buffer);
- }
- if (read <= 0)
- return new byte[0];
- if (read < buffer.length) {
- byte[] shortened = new byte[read];
- arraycopy(buffer, 0, shortened, 0, read);
- return shortened;
- }
- return buffer;
- }
-
- @Override
- public long getSize() {
- return file.length();
- }
-
- @Override
- public void setContents(byte[] data) throws IOException {
- try (FileOutputStream fos = new FileOutputStream(file)) {
- fos.write(data);
- }
- }
-
- @Override
- public void appendContents(byte[] data) throws IOException {
- try (FileOutputStream fos = new FileOutputStream(file, true)) {
- fos.write(data);
- }
- }
-
- @Override
- public void destroy() throws IOException {
- forceDelete(file);
- parent.forgetEntry(this);
- parent = null;
- }
-
- @Override
- public RemoteDirectory getContainingDirectory() {
- return parent;
- }
-
- @Override
- public String getName() {
- return file.getName();
- }
-
- @Override
- public void copy(RemoteFile sourceFile) throws RemoteException, IOException {
- String sourceHost = sourceFile.getNativeHost();
- if (!getNativeHost().equals(sourceHost)) {
- throw new IOException(
- "cross-system copy not implemented; cannot copy from "
- + sourceHost + " to " + getNativeHost());
- }
- // Must copy; cannot count on other file to stay unmodified
- copyFile(new File(sourceFile.getNativeName()), file);
- }
-
- @Override
- public String getNativeName() {
- return file.getAbsolutePath();
- }
-
- @Override
- public String getNativeHost() {
- try {
- return getLocalHost().getHostAddress();
- } catch (UnknownHostException e) {
- throw new RuntimeException(
- "unexpected failure to resolve local host address", e);
- }
- }
-
- @Override
- public Date getModificationDate() throws RemoteException {
- return new Date(file.lastModified());
- }
-}
[44/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java b/server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
deleted file mode 100644
index 48969fa..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
-import static javax.ws.rs.core.Response.created;
-import static javax.ws.rs.core.Response.noContent;
-import static javax.ws.rs.core.Response.ok;
-import static javax.ws.rs.core.Response.seeOther;
-import static javax.ws.rs.core.Response.status;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
-import static org.taverna.server.master.api.ContentTypes.DIRECTORY_VARIANTS;
-import static org.taverna.server.master.api.ContentTypes.INITIAL_FILE_VARIANTS;
-import static org.taverna.server.master.common.Roles.SELF;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.common.Uri.secure;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.security.RolesAllowed;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.PathSegment;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.core.Variant;
-import javax.xml.ws.Holder;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.api.DirectoryBean;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.rest.DirectoryContents;
-import org.taverna.server.master.rest.FileSegment;
-import org.taverna.server.master.rest.MakeOrUpdateDirEntry;
-import org.taverna.server.master.rest.MakeOrUpdateDirEntry.MakeDirectory;
-import org.taverna.server.master.rest.TavernaServerDirectoryREST;
-import org.taverna.server.master.utils.FilenameUtils;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * RESTful access to the filesystem.
- *
- * @author Donal Fellows
- */
-class DirectoryREST implements TavernaServerDirectoryREST, DirectoryBean {
- private Log log = getLog("Taverna.Server.Webapp");
- private TavernaServerSupport support;
- private TavernaRun run;
- private FilenameUtils fileUtils;
-
- @Override
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- @Required
- public void setFileUtils(FilenameUtils fileUtils) {
- this.fileUtils = fileUtils;
- }
-
- @Override
- public DirectoryREST connect(TavernaRun run) {
- this.run = run;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Response destroyDirectoryEntry(List<PathSegment> path)
- throws NoUpdateException, FilesystemAccessException,
- NoDirectoryEntryException {
- support.permitUpdate(run);
- fileUtils.getDirEntry(run, path).destroy();
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public DirectoryContents getDescription(UriInfo ui)
- throws FilesystemAccessException {
- return new DirectoryContents(ui, run.getWorkingDirectory()
- .getContents());
- }
-
- @Override
- @CallCounted
- public Response options(List<PathSegment> path) {
- return opt("PUT", "POST", "DELETE");
- }
-
- /*
- * // Nasty! This can have several different responses...
- *
- * @Override @CallCounted private Response
- * getDirectoryOrFileContents(List<PathSegment> path, UriInfo ui, Request
- * req) throws FilesystemAccessException, NoDirectoryEntryException {
- *
- * DirectoryEntry de = fileUtils.getDirEntry(run, path);
- *
- * // How did the user want the result?
- *
- * List<Variant> variants = getVariants(de); Variant v =
- * req.selectVariant(variants); if (v == null) return
- * notAcceptable(variants).type(TEXT_PLAIN)
- * .entity("Do not know what type of response to produce.") .build();
- *
- * // Produce the content to deliver up
- *
- * Object result; if
- * (v.getMediaType().equals(APPLICATION_OCTET_STREAM_TYPE))
- *
- * // Only for files...
- *
- * result = de; else if (v.getMediaType().equals(APPLICATION_ZIP_TYPE))
- *
- * // Only for directories...
- *
- * result = ((Directory) de).getContentsAsZip(); else
- *
- * // Only for directories... // XML or JSON; let CXF pick what to do
- *
- * result = new DirectoryContents(ui, ((Directory) de).getContents());
- * return ok(result).type(v.getMediaType()).build();
- *
- * }
- */
-
- private boolean matchType(MediaType a, MediaType b) {
- if (log.isDebugEnabled())
- log.debug("comparing " + a.getType() + "/" + a.getSubtype()
- + " and " + b.getType() + "/" + b.getSubtype());
- return (a.isWildcardType() || b.isWildcardType() || a.getType().equals(
- b.getType()))
- && (a.isWildcardSubtype() || b.isWildcardSubtype() || a
- .getSubtype().equals(b.getSubtype()));
- }
-
- /**
- * What are we willing to serve up a directory or file as?
- *
- * @param de
- * The reference to the object to serve.
- * @return The variants we can serve it as.
- * @throws FilesystemAccessException
- * If we fail to read data necessary to detection of its media
- * type.
- */
- private List<Variant> getVariants(DirectoryEntry de)
- throws FilesystemAccessException {
- if (de instanceof Directory)
- return DIRECTORY_VARIANTS;
- else if (!(de instanceof File))
- throw new FilesystemAccessException("not a directory or file!");
- File f = (File) de;
- List<Variant> variants = new ArrayList<>(INITIAL_FILE_VARIANTS);
- String contentType = support.getEstimatedContentType(f);
- if (!contentType.equals(APPLICATION_OCTET_STREAM)) {
- String[] ct = contentType.split("/");
- variants.add(0,
- new Variant(new MediaType(ct[0], ct[1]), (String) null, null));
- }
- return variants;
- }
-
- /** How did the user want the result? */
- private MediaType pickType(HttpHeaders headers, DirectoryEntry de)
- throws FilesystemAccessException, NegotiationFailedException {
- List<Variant> variants = getVariants(de);
- // Manual content negotiation!!! Ugh!
- for (MediaType mt : headers.getAcceptableMediaTypes())
- for (Variant v : variants)
- if (matchType(mt, v.getMediaType()))
- return v.getMediaType();
- throw new NegotiationFailedException(
- "Do not know what type of response to produce.", variants);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Response getDirectoryOrFileContents(List<PathSegment> path,
- UriInfo ui, HttpHeaders headers) throws FilesystemAccessException,
- NoDirectoryEntryException, NegotiationFailedException {
- DirectoryEntry de = fileUtils.getDirEntry(run, path);
-
- // How did the user want the result?
- MediaType wanted = pickType(headers, de);
-
- log.info("producing content of type " + wanted);
- // Produce the content to deliver up
- Object result;
- if (de instanceof File) {
- // Only for files...
- result = de;
- List<String> range = headers.getRequestHeader("Range");
- if (range != null && range.size() == 1)
- return new FileSegment((File) de, range.get(0))
- .toResponse(wanted);
- } else {
- // Only for directories...
- Directory d = (Directory) de;
- if (wanted.getType().equals(APPLICATION_ZIP_TYPE.getType())
- && wanted.getSubtype().equals(
- APPLICATION_ZIP_TYPE.getSubtype()))
- result = d.getContentsAsZip();
- else
- // XML or JSON; let CXF pick what to do
- result = new DirectoryContents(ui, d.getContents());
- }
- return ok(result).type(wanted).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Response makeDirectoryOrUpdateFile(List<PathSegment> parent,
- MakeOrUpdateDirEntry op, UriInfo ui) throws NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException {
- support.permitUpdate(run);
- DirectoryEntry container = fileUtils.getDirEntry(run, parent);
- if (!(container instanceof Directory))
- throw new FilesystemAccessException("You may not "
- + ((op instanceof MakeDirectory) ? "make a subdirectory of"
- : "place a file in") + " a file.");
- if (op.name == null || op.name.length() == 0)
- throw new FilesystemAccessException("missing name attribute");
- Directory d = (Directory) container;
- UriBuilder ub = secure(ui).path("{name}");
-
- // Make a directory in the context directory
-
- if (op instanceof MakeDirectory) {
- Directory target = d.makeSubdirectory(support.getPrincipal(),
- op.name);
- return created(ub.build(target.getName())).build();
- }
-
- // Make or set the contents of a file
-
- File f = null;
- for (DirectoryEntry e : d.getContents()) {
- if (e.getName().equals(op.name)) {
- if (e instanceof Directory)
- throw new FilesystemAccessException(
- "You may not overwrite a directory with a file.");
- f = (File) e;
- break;
- }
- }
- if (f == null) {
- f = d.makeEmptyFile(support.getPrincipal(), op.name);
- f.setContents(op.contents);
- return created(ub.build(f.getName())).build();
- }
- f.setContents(op.contents);
- return seeOther(ub.build(f.getName())).build();
- }
-
- private File getFileForWrite(List<PathSegment> filePath,
- Holder<Boolean> isNew) throws FilesystemAccessException,
- NoDirectoryEntryException, NoUpdateException {
- support.permitUpdate(run);
- if (filePath == null || filePath.size() == 0)
- throw new FilesystemAccessException(
- "Cannot create a file that is not in a directory.");
-
- List<PathSegment> dirPath = new ArrayList<>(filePath);
- String name = dirPath.remove(dirPath.size() - 1).getPath();
- DirectoryEntry de = fileUtils.getDirEntry(run, dirPath);
- if (!(de instanceof Directory)) {
- throw new FilesystemAccessException(
- "Cannot create a file that is not in a directory.");
- }
- Directory d = (Directory) de;
-
- File f = null;
- isNew.value = false;
- for (DirectoryEntry e : d.getContents())
- if (e.getName().equals(name)) {
- if (e instanceof File) {
- f = (File) e;
- break;
- }
- throw new FilesystemAccessException(
- "Cannot create a file that is not in a directory.");
- }
-
- if (f == null) {
- f = d.makeEmptyFile(support.getPrincipal(), name);
- isNew.value = true;
- } else
- f.setContents(new byte[0]);
- return f;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Response setFileContents(List<PathSegment> filePath,
- InputStream contents, UriInfo ui) throws NoDirectoryEntryException,
- NoUpdateException, FilesystemAccessException {
- Holder<Boolean> isNew = new Holder<>(true);
- support.copyStreamToFile(contents, getFileForWrite(filePath, isNew));
-
- if (isNew.value)
- return created(ui.getAbsolutePath()).build();
- else
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response setFileContentsFromURL(List<PathSegment> filePath,
- List<URI> referenceList, UriInfo ui)
- throws NoDirectoryEntryException, NoUpdateException,
- FilesystemAccessException {
- support.permitUpdate(run);
- if (referenceList.isEmpty() || referenceList.size() > 1)
- return status(422).entity("URI list must have single URI in it")
- .build();
- URI uri = referenceList.get(0);
- try {
- uri.toURL();
- } catch (MalformedURLException e) {
- return status(422).entity("URI list must have value URL in it")
- .build();
- }
- Holder<Boolean> isNew = new Holder<>(true);
- File f = getFileForWrite(filePath, isNew);
-
- try {
- support.copyDataToFile(uri, f);
- } catch (MalformedURLException ex) {
- // Should not happen; called uri.toURL() successfully above
- throw new NoUpdateException("failed to parse URI", ex);
- } catch (IOException ex) {
- throw new FilesystemAccessException(
- "failed to transfer data from URI", ex);
- }
-
- if (isNew.value)
- return created(ui.getAbsolutePath()).build();
- else
- return noContent().build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java b/server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
deleted file mode 100644
index 3893b3d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.taverna.server.master;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.interfaces.File;
-
-/**
- * Simple concatenation of files.
- *
- * @author Donal Fellows
- */
-public class FileConcatenation implements Iterable<File> {
- private List<File> files = new ArrayList<>();
-
- public void add(File f) {
- files.add(f);
- }
-
- public boolean isEmpty() {
- return files.isEmpty();
- }
-
- /**
- * @return The total length of the files, or -1 if this cannot be
- * determined.
- */
- public long size() {
- long size = 0;
- for (File f : files)
- try {
- size += f.getSize();
- } catch (FilesystemAccessException e) {
- // Ignore; shouldn't happen but can't guarantee
- }
- return (size == 0 && !files.isEmpty() ? -1 : size);
- }
-
- /**
- * Get the concatenated files.
- *
- * @param encoding
- * The encoding to use.
- * @return The concatenated files.
- * @throws UnsupportedEncodingException
- * If the encoding doesn't exist.
- */
- public String get(String encoding) throws UnsupportedEncodingException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for (File f : files)
- try {
- baos.write(f.getContents(0, -1));
- } catch (FilesystemAccessException | IOException e) {
- continue;
- }
- return baos.toString(encoding);
- }
-
- @Override
- public Iterator<File> iterator() {
- return files.iterator();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/InputREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/InputREST.java b/server-webapp/src/main/java/org/taverna/server/master/InputREST.java
deleted file mode 100644
index 0f48207..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/InputREST.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static java.util.UUID.randomUUID;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.util.Date;
-
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import org.apache.cxf.jaxrs.impl.MetadataMap;
-import org.apache.cxf.jaxrs.model.URITemplate;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.api.InputBean;
-import org.taverna.server.master.common.DirEntryReference;
-import org.taverna.server.master.exceptions.BadInputPortNameException;
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-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.NoUpdateException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.rest.TavernaServerInputREST;
-import org.taverna.server.master.rest.TavernaServerInputREST.InDesc.AbstractContents;
-import org.taverna.server.master.rest.TavernaServerInputREST.InDesc.Reference;
-import org.taverna.server.master.utils.FilenameUtils;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-import org.taverna.server.port_description.InputDescription;
-
-/**
- * RESTful interface to the input descriptor of a single workflow run.
- *
- * @author Donal Fellows
- */
-class InputREST implements TavernaServerInputREST, InputBean {
- private UriInfo ui;
- private TavernaServerSupport support;
- private TavernaRun run;
- private ContentsDescriptorBuilder cdBuilder;
- private FilenameUtils fileUtils;
-
- @Override
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- @Required
- public void setCdBuilder(ContentsDescriptorBuilder cdBuilder) {
- this.cdBuilder = cdBuilder;
- }
-
- @Override
- @Required
- public void setFileUtils(FilenameUtils fileUtils) {
- this.fileUtils = fileUtils;
- }
-
- @Override
- public InputREST connect(TavernaRun run, UriInfo ui) {
- this.run = run;
- this.ui = ui;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public InputsDescriptor get() {
- return new InputsDescriptor(ui, run);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public InputDescription getExpected() {
- return cdBuilder.makeInputDescriptor(run, ui);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String getBaclavaFile() {
- String i = run.getInputBaclavaFile();
- return i == null ? "" : i;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public InDesc getInput(String name, UriInfo ui) throws BadInputPortNameException {
- Input i = support.getInput(run, name);
- if (i == null)
- throw new BadInputPortNameException("unknown input port name");
- return new InDesc(i, ui);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String setBaclavaFile(String filename) throws NoUpdateException,
- BadStateChangeException, FilesystemAccessException {
- support.permitUpdate(run);
- run.setInputBaclavaFile(filename);
- String i = run.getInputBaclavaFile();
- return i == null ? "" : i;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public InDesc setInput(String name, InDesc inputDescriptor, UriInfo ui)
- throws NoUpdateException, BadStateChangeException,
- FilesystemAccessException, BadInputPortNameException,
- BadPropertyValueException {
- inputDescriptor.descriptorRef = null;
- AbstractContents ac = inputDescriptor.assignment;
- if (name == null || name.isEmpty())
- throw new BadInputPortNameException("bad input name");
- if (ac == null)
- throw new BadPropertyValueException("no content!");
- if (inputDescriptor.delimiter != null
- && inputDescriptor.delimiter.isEmpty())
- inputDescriptor.delimiter = null;
- if (ac instanceof InDesc.Reference)
- return setRemoteInput(name, (InDesc.Reference) ac,
- inputDescriptor.delimiter, ui);
- if (!(ac instanceof InDesc.File || ac instanceof InDesc.Value))
- throw new BadPropertyValueException("unknown content type");
- support.permitUpdate(run);
- Input i = support.getInput(run, name);
- if (i == null)
- i = run.makeInput(name);
- if (ac instanceof InDesc.File)
- i.setFile(ac.contents);
- else
- i.setValue(ac.contents);
- i.setDelimiter(inputDescriptor.delimiter);
- return new InDesc(i, ui);
- }
-
- private InDesc setRemoteInput(String name, Reference ref, String delimiter,
- UriInfo ui) throws BadStateChangeException,
- BadPropertyValueException, FilesystemAccessException {
- URITemplate tmpl = new URITemplate(ui.getBaseUri()
- + "/runs/{runName}/wd/{path:.+}");
- MultivaluedMap<String, String> mvm = new MetadataMap<>();
- if (!tmpl.match(ref.contents, mvm)) {
- throw new BadPropertyValueException(
- "URI in reference does not refer to local disk resource");
- }
- try {
- File from = fileUtils.getFile(
- support.getRun(mvm.get("runName").get(0)),
- SyntheticDirectoryEntry.make(mvm.get("path").get(0)));
- File to = run.getWorkingDirectory().makeEmptyFile(
- support.getPrincipal(), randomUUID().toString());
-
- to.copy(from);
-
- Input i = support.getInput(run, name);
- if (i == null)
- i = run.makeInput(name);
- i.setFile(to.getFullName());
- i.setDelimiter(delimiter);
- return new InDesc(i, ui);
- } catch (UnknownRunException e) {
- throw new BadStateChangeException("may not copy from that run", e);
- } catch (NoDirectoryEntryException e) {
- throw new BadStateChangeException("source does not exist", e);
- }
- }
-
- @Override
- @CallCounted
- public Response options() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response expectedOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response baclavaOptions() {
- return opt("PUT");
- }
-
- @Override
- @CallCounted
- public Response inputOptions(@PathParam("name") String name) {
- return opt("PUT");
- }
-}
-
-/**
- * A way to create synthetic directory entries, used during deletion.
- *
- * @author Donal Fellows
- */
-class SyntheticDirectoryEntry implements DirectoryEntry {
- public static DirEntryReference make(String path) {
- return DirEntryReference.newInstance(new SyntheticDirectoryEntry(path));
- }
-
- private SyntheticDirectoryEntry(String p) {
- this.p = p;
- this.d = new Date();
- }
-
- private String p;
- private Date d;
-
- @Override
- public String getName() {
- return null;
- }
-
- @Override
- public String getFullName() {
- return p;
- }
-
- @Override
- public void destroy() {
- }
-
- @Override
- public int compareTo(DirectoryEntry o) {
- return p.compareTo(o.getFullName());
- }
-
- @Override
- public Date getModificationDate() {
- return d;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java b/server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
deleted file mode 100644
index b686491..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static org.taverna.server.master.common.Roles.SELF;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-import javax.annotation.security.RolesAllowed;
-import javax.ws.rs.core.Response;
-
-import org.apache.abdera.model.Entry;
-import org.apache.abdera.model.Feed;
-import org.taverna.server.master.api.FeedBean;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interaction.InteractionFeedSupport;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.rest.InteractionFeedREST;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * How to connect an interaction feed to the webapp.
- *
- * @author Donal Fellows
- */
-public class InteractionFeed implements InteractionFeedREST, FeedBean {
- private InteractionFeedSupport interactionFeed;
- private TavernaRun run;
-
- @Override
- public void setInteractionFeedSupport(InteractionFeedSupport feed) {
- this.interactionFeed = feed;
- }
-
- InteractionFeed connect(TavernaRun run) {
- this.run = run;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Feed getFeed() throws FilesystemAccessException,
- NoDirectoryEntryException {
- return interactionFeed.getRunFeed(run);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Response addEntry(Entry entry) throws MalformedURLException,
- FilesystemAccessException, NoDirectoryEntryException,
- NoUpdateException {
- Entry realEntry = interactionFeed.addRunFeedEntry(run, entry);
- URI location;
- try {
- location = realEntry.getSelfLink().getHref().toURI();
- } catch (URISyntaxException e) {
- throw new RuntimeException("failed to make URI from link?!", e);
- }
- return Response.created(location).entity(realEntry)
- .type("application/atom+xml;type=entry").build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public Entry getEntry(String id) throws FilesystemAccessException,
- NoDirectoryEntryException {
- return interactionFeed.getRunFeedEntry(run, id);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public String deleteEntry(String id) throws FilesystemAccessException,
- NoDirectoryEntryException, NoUpdateException {
- interactionFeed.removeRunFeedEntry(run, id);
- return "entry successfully deleted";
- }
-
- @Override
- @CallCounted
- public Response feedOptions() {
- return opt("POST");
- }
-
- @Override
- @CallCounted
- public Response entryOptions(String id) {
- return opt("DELETE");
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java b/server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java
deleted file mode 100644
index 3e983a9..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import javax.ws.rs.core.Response;
-
-import org.apache.commons.logging.Log;
-import org.taverna.server.master.api.ListenerPropertyBean;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.rest.TavernaServerListenersREST;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * RESTful interface to a single property of a workflow run.
- *
- * @author Donal Fellows
- */
-class ListenerPropertyREST implements TavernaServerListenersREST.Property,
- ListenerPropertyBean {
- private Log log = getLog("Taverna.Server.Webapp");
- private TavernaServerSupport support;
- private Listener listen;
- private String propertyName;
- private TavernaRun run;
-
- @Override
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- public ListenerPropertyREST connect(Listener listen, TavernaRun run,
- String propertyName) {
- this.listen = listen;
- this.propertyName = propertyName;
- this.run = run;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String getValue() {
- try {
- return listen.getProperty(propertyName);
- } catch (NoListenerException e) {
- log.error("unexpected exception; property \"" + propertyName
- + "\" should exist", e);
- return null;
- }
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String setValue(String value) throws NoUpdateException,
- NoListenerException {
- support.permitUpdate(run);
- listen.setProperty(propertyName, value);
- return listen.getProperty(propertyName);
- }
-
- @Override
- @CallCounted
- public Response options() {
- return opt("PUT");
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java b/server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java
deleted file mode 100644
index 4b7d7f3..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static javax.ws.rs.core.Response.created;
-import static javax.ws.rs.core.UriBuilder.fromUri;
-import static org.taverna.server.master.common.Uri.secure;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-import org.taverna.server.master.api.ListenersBean;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.rest.ListenerDefinition;
-import org.taverna.server.master.rest.TavernaServerListenersREST;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * RESTful interface to a single workflow run's event listeners.
- *
- * @author Donal Fellows
- */
-abstract class ListenersREST implements TavernaServerListenersREST,
- ListenersBean {
- private TavernaRun run;
- private TavernaServerSupport support;
-
- @Override
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- public ListenersREST connect(TavernaRun run) {
- this.run = run;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response addListener(ListenerDefinition typeAndConfiguration,
- UriInfo ui) throws NoUpdateException, NoListenerException {
- String name = support.makeListener(run, typeAndConfiguration.type,
- typeAndConfiguration.configuration).getName();
- return created(secure(ui).path("{listenerName}").build(name)).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public TavernaServerListenerREST getListener(String name)
- throws NoListenerException {
- Listener l = support.getListener(run, name);
- if (l == null)
- throw new NoListenerException();
- return makeListenerInterface().connect(l, run);
- }
-
- @Nonnull
- protected abstract SingleListenerREST makeListenerInterface();
-
- @Override
- @CallCounted
- @PerfLogged
- public Listeners getDescription(UriInfo ui) {
- List<ListenerDescription> result = new ArrayList<>();
- UriBuilder ub = secure(ui).path("{name}");
- for (Listener l : run.getListeners())
- result.add(new ListenerDescription(l,
- fromUri(ub.build(l.getName()))));
- return new Listeners(result, ub);
- }
-
- @Override
- @CallCounted
- public Response listenersOptions() {
- return opt();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/ManagementState.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/ManagementState.java b/server-webapp/src/main/java/org/taverna/server/master/ManagementState.java
deleted file mode 100644
index 9d4a651..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/ManagementState.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import javax.annotation.PostConstruct;
-import javax.jdo.Query;
-import javax.jdo.annotations.PersistenceAware;
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.PrimaryKey;
-
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.api.ManagementModel;
-import org.taverna.server.master.utils.JDOSupport;
-
-/** The persistent, manageable state of the Taverna Server web application. */
-@PersistenceAware
-class ManagementState extends JDOSupport<WebappState> implements
- ManagementModel {
- public ManagementState() {
- super(WebappState.class);
- }
-
- /** Whether we should log all workflows sent to us. */
- private boolean logIncomingWorkflows = false;
-
- /** Whether we allow the creation of new workflow runs. */
- private boolean allowNewWorkflowRuns = true;
-
- /**
- * Whether outgoing exceptions should be logged before being converted to
- * responses.
- */
- private boolean logOutgoingExceptions = false;
-
- /**
- * The file that all usage records should be appended to, or <tt>null</tt>
- * if they should be just dropped.
- */
- private String usageRecordLogFile = null;
-
- @Override
- public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
- this.logIncomingWorkflows = logIncomingWorkflows;
- if (loadedState)
- self.store();
- }
-
- @Override
- public boolean getLogIncomingWorkflows() {
- self.load();
- return logIncomingWorkflows;
- }
-
- @Override
- public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
- this.allowNewWorkflowRuns = allowNewWorkflowRuns;
- if (loadedState)
- self.store();
- }
-
- @Override
- public boolean getAllowNewWorkflowRuns() {
- self.load();
- return allowNewWorkflowRuns;
- }
-
- @Override
- public void setLogOutgoingExceptions(boolean logOutgoingExceptions) {
- this.logOutgoingExceptions = logOutgoingExceptions;
- if (loadedState)
- self.store();
- }
-
- @Override
- public boolean getLogOutgoingExceptions() {
- self.load();
- return logOutgoingExceptions || true;
- }
-
- @Override
- public String getUsageRecordLogFile() {
- self.load();
- return usageRecordLogFile;
- }
-
- @Override
- public void setUsageRecordLogFile(String usageRecordLogFile) {
- this.usageRecordLogFile = usageRecordLogFile;
- if (loadedState)
- self.store();
- }
-
- private static final int KEY = 42; // whatever
-
- private WebappState get() {
- Query q = query("id == " + KEY);
- q.setUnique(true);
- return (WebappState) q.execute();
- }
-
- private boolean loadedState;
- private ManagementState self;
-
- @Required
- public void setSelf(ManagementState self) {
- this.self = self;
- }
-
- @PostConstruct
- @WithinSingleTransaction
- public void load() {
- if (loadedState || !isPersistent())
- return;
- WebappState state = get();
- if (state == null)
- return;
- allowNewWorkflowRuns = state.getAllowNewWorkflowRuns();
- logIncomingWorkflows = state.getLogIncomingWorkflows();
- logOutgoingExceptions = state.getLogOutgoingExceptions();
- usageRecordLogFile = state.getUsageRecordLogFile();
- loadedState = true;
- }
-
- @WithinSingleTransaction
- public void store() {
- if (!isPersistent())
- return;
- WebappState state = get();
- if (state == null) {
- state = new WebappState();
- // save state
- state.id = KEY; // whatever...
- state = persist(state);
- }
- state.setAllowNewWorkflowRuns(allowNewWorkflowRuns);
- state.setLogIncomingWorkflows(logIncomingWorkflows);
- state.setLogOutgoingExceptions(logOutgoingExceptions);
- state.setUsageRecordLogFile(usageRecordLogFile);
- loadedState = true;
- }
-}
-
-// WARNING! If you change the name of this class, update persistence.xml as
-// well!
-@PersistenceCapable(table = "MANAGEMENTSTATE__WEBAPPSTATE")
-class WebappState implements ManagementModel {
- public WebappState() {
- }
-
- @PrimaryKey
- protected int id;
-
- /** Whether we should log all workflows sent to us. */
- @Persistent
- private boolean logIncomingWorkflows;
-
- /** Whether we allow the creation of new workflow runs. */
- @Persistent
- private boolean allowNewWorkflowRuns;
-
- /**
- * Whether outgoing exceptions should be logged before being converted to
- * responses.
- */
- @Persistent
- private boolean logOutgoingExceptions;
-
- /** Where to write usage records. */
- @Persistent
- private String usageRecordLogFile;
-
- @Override
- public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
- this.logIncomingWorkflows = logIncomingWorkflows;
- }
-
- @Override
- public boolean getLogIncomingWorkflows() {
- return logIncomingWorkflows;
- }
-
- @Override
- public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
- this.allowNewWorkflowRuns = allowNewWorkflowRuns;
- }
-
- @Override
- public boolean getAllowNewWorkflowRuns() {
- return allowNewWorkflowRuns;
- }
-
- @Override
- public void setLogOutgoingExceptions(boolean logOutgoingExceptions) {
- this.logOutgoingExceptions = logOutgoingExceptions;
- }
-
- @Override
- public boolean getLogOutgoingExceptions() {
- return logOutgoingExceptions;
- }
-
- @Override
- public String getUsageRecordLogFile() {
- return usageRecordLogFile;
- }
-
- @Override
- public void setUsageRecordLogFile(String usageRecordLogFile) {
- this.usageRecordLogFile = usageRecordLogFile;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/RunREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/RunREST.java b/server-webapp/src/main/java/org/taverna/server/master/RunREST.java
deleted file mode 100644
index 563a822..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/RunREST.java
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-import static javax.ws.rs.core.Response.noContent;
-import static javax.ws.rs.core.Response.ok;
-import static javax.ws.rs.core.Response.status;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.joda.time.format.ISODateTimeFormat.dateTime;
-import static org.joda.time.format.ISODateTimeFormat.dateTimeParser;
-import static org.taverna.server.master.common.Roles.SELF;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.common.Status.Initialized;
-import static org.taverna.server.master.common.Status.Operating;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.util.Date;
-
-import javax.annotation.security.RolesAllowed;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import javax.xml.bind.JAXBException;
-
-import org.apache.commons.logging.Log;
-import org.joda.time.DateTime;
-import org.ogf.usage.JobUsageRecord;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.api.RunBean;
-import org.taverna.server.master.common.ProfileList;
-import org.taverna.server.master.common.Status;
-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.exceptions.OverloadedException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.rest.InteractionFeedREST;
-import org.taverna.server.master.rest.TavernaServerInputREST;
-import org.taverna.server.master.rest.TavernaServerListenersREST;
-import org.taverna.server.master.rest.TavernaServerRunREST;
-import org.taverna.server.master.rest.TavernaServerSecurityREST;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-import org.taverna.server.port_description.OutputDescription;
-
-/**
- * RESTful interface to a single workflow run.
- *
- * @author Donal Fellows
- */
-abstract class RunREST implements TavernaServerRunREST, RunBean {
- private Log log = getLog("Taverna.Server.Webapp");
- private String runName;
- private TavernaRun run;
- private TavernaServerSupport support;
- private ContentsDescriptorBuilder cdBuilder;
-
- @Override
- @Required
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- @Required
- public void setCdBuilder(ContentsDescriptorBuilder cdBuilder) {
- this.cdBuilder = cdBuilder;
- }
-
- @Override
- public void setRunName(String runName) {
- this.runName = runName;
- }
-
- @Override
- public void setRun(TavernaRun run) {
- this.run = run;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public RunDescription getDescription(UriInfo ui) {
- return new RunDescription(run, ui);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response destroy() throws NoUpdateException {
- try {
- support.unregisterRun(runName, run);
- } catch (UnknownRunException e) {
- log.fatal("can't happen", e);
- }
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public TavernaServerListenersREST getListeners() {
- return makeListenersInterface().connect(run);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public TavernaServerSecurityREST getSecurity() throws NotOwnerException {
- TavernaSecurityContext secContext = run.getSecurityContext();
- if (!support.getPrincipal().equals(secContext.getOwner()))
- throw new NotOwnerException();
-
- // context.getBean("run.security", run, secContext);
- return makeSecurityInterface().connect(secContext, run);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getExpiryTime() {
- return dateTime().print(new DateTime(run.getExpiry()));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getCreateTime() {
- return dateTime().print(new DateTime(run.getCreationTimestamp()));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getFinishTime() {
- Date f = run.getFinishTimestamp();
- return f == null ? "" : dateTime().print(new DateTime(f));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getStartTime() {
- Date f = run.getStartTimestamp();
- return f == null ? "" : dateTime().print(new DateTime(f));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getStatus() {
- return run.getStatus().toString();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Workflow getWorkflow() {
- return run.getWorkflow();
- }
-
- @Override
- @CallCounted
- public String getMainProfileName() {
- String name = run.getWorkflow().getMainProfileName();
- return (name == null ? "" : name);
- }
-
- @Override
- @CallCounted
- public ProfileList getProfiles() {
- return support.getProfileDescriptor(run.getWorkflow());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public DirectoryREST getWorkingDirectory() {
- return makeDirectoryInterface().connect(run);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String setExpiryTime(String expiry) throws NoUpdateException,
- IllegalArgumentException {
- DateTime wanted = dateTimeParser().parseDateTime(expiry.trim());
- Date achieved = support.updateExpiry(run, wanted.toDate());
- return dateTime().print(new DateTime(achieved));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response setStatus(String status) throws NoUpdateException {
- Status newStatus = Status.valueOf(status.trim());
- support.permitUpdate(run);
- if (newStatus == Operating && run.getStatus() == Initialized) {
- if (!support.getAllowStartWorkflowRuns())
- throw new OverloadedException();
- String issue = run.setStatus(newStatus);
- if (issue == null)
- issue = "starting run...";
- return status(202).entity(issue).type("text/plain").build();
- }
- run.setStatus(newStatus); // Ignore the result
- return ok(run.getStatus().toString()).type("text/plain").build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public TavernaServerInputREST getInputs(UriInfo ui) {
- return makeInputInterface().connect(run, ui);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getOutputFile() {
- String o = run.getOutputBaclavaFile();
- return o == null ? "" : o;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String setOutputFile(String filename) throws NoUpdateException,
- FilesystemAccessException, BadStateChangeException {
- support.permitUpdate(run);
- if (filename != null && filename.length() == 0)
- filename = null;
- run.setOutputBaclavaFile(filename);
- String o = run.getOutputBaclavaFile();
- return o == null ? "" : o;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public OutputDescription getOutputDescription(UriInfo ui)
- throws BadStateChangeException, FilesystemAccessException,
- NoDirectoryEntryException {
- if (run.getStatus() == Initialized)
- throw new BadStateChangeException(
- "may not get output description in initial state");
- return cdBuilder.makeOutputDescriptor(run, ui);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed({ USER, SELF })
- public InteractionFeedREST getInteractionFeed() {
- return makeInteractionFeed().connect(run);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getName() {
- return run.getName();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String setName(String name) throws NoUpdateException {
- support.permitUpdate(run);
- run.setName(name);
- return run.getName();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getStdout() throws NoListenerException {
- return support.getProperty(run, "io", "stdout");
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public String getStderr() throws NoListenerException {
- return support.getProperty(run, "io", "stderr");
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response getUsage() throws NoListenerException, JAXBException {
- String ur = support.getProperty(run, "io", "usageRecord");
- if (ur.isEmpty())
- return noContent().build();
- return ok(JobUsageRecord.unmarshal(ur), APPLICATION_XML).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response getLogContents() {
- FileConcatenation fc = support.getLogs(run);
- if (fc.isEmpty())
- return Response.noContent().build();
- return Response.ok(fc, TEXT_PLAIN).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public Response getRunBundle() {
- FileConcatenation fc = support.getProv(run);
- if (fc.isEmpty())
- return Response.status(404).entity("no provenance currently available").build();
- return Response.ok(fc, "application/vnd.wf4ever.robundle+zip").build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public boolean getGenerateProvenance() {
- return run.getGenerateProvenance();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- @RolesAllowed(USER)
- public boolean setGenerateProvenance(boolean newValue) throws NoUpdateException {
- support.permitUpdate(run);
- run.setGenerateProvenance(newValue);
- return run.getGenerateProvenance();
- }
-
- /**
- * Construct a RESTful interface to a run's filestore.
- *
- * @return The handle to the interface, as decorated by Spring.
- */
- protected abstract DirectoryREST makeDirectoryInterface();
-
- /**
- * Construct a RESTful interface to a run's input descriptors.
- *
- * @return The handle to the interface, as decorated by Spring.
- */
- protected abstract InputREST makeInputInterface();
-
- /**
- * Construct a RESTful interface to a run's listeners.
- *
- * @return The handle to the interface, as decorated by Spring.
- */
- protected abstract ListenersREST makeListenersInterface();
-
- /**
- * Construct a RESTful interface to a run's security.
- *
- * @return The handle to the interface, as decorated by Spring.
- */
- protected abstract RunSecurityREST makeSecurityInterface();
-
- /**
- * Construct a RESTful interface to a run's interaction feed.
- *
- * @return The handle to the interaface, as decorated by Spring.
- */
- protected abstract InteractionFeed makeInteractionFeed();
-
- @Override
- @CallCounted
- public Response runOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response workflowOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response profileOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response expiryOptions() {
- return opt("PUT");
- }
-
- @Override
- @CallCounted
- public Response createTimeOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response startTimeOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response finishTimeOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response statusOptions() {
- return opt("PUT");
- }
-
- @Override
- @CallCounted
- public Response outputOptions() {
- return opt("PUT");
- }
-
- @Override
- @CallCounted
- public Response nameOptions() {
- return opt("PUT");
- }
-
- @Override
- @CallCounted
- public Response stdoutOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response stderrOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response usageOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response logOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response runBundleOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response generateProvenanceOptions() {
- return opt("PUT");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java b/server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java
deleted file mode 100644
index 5a366b2..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static java.util.UUID.randomUUID;
-import static javax.ws.rs.core.Response.created;
-import static javax.ws.rs.core.Response.noContent;
-import static org.taverna.server.master.common.Status.Initialized;
-import static org.taverna.server.master.common.Uri.secure;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.net.URI;
-import java.util.Map;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import org.taverna.server.master.api.SecurityBean;
-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.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.InvalidCredentialException;
-import org.taverna.server.master.exceptions.NoCredentialException;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.rest.TavernaServerSecurityREST;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * RESTful interface to a single workflow run's security settings.
- *
- * @author Donal Fellows
- */
-class RunSecurityREST implements TavernaServerSecurityREST, SecurityBean {
- private TavernaServerSupport support;
- private TavernaSecurityContext context;
- private TavernaRun run;
-
- @Override
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- @Override
- public RunSecurityREST connect(TavernaSecurityContext context,
- TavernaRun run) {
- this.context = context;
- this.run = run;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Descriptor describe(UriInfo ui) {
- return new Descriptor(secure(ui).path("{element}"), context.getOwner()
- .getName(), context.getCredentials(), context.getTrusted());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String getOwner() {
- return context.getOwner().getName();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public CredentialList listCredentials() {
- return new CredentialList(context.getCredentials());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public CredentialHolder getParticularCredential(String id)
- throws NoCredentialException {
- for (Credential c : context.getCredentials())
- if (c.id.equals(id))
- return new CredentialHolder(c);
- throw new NoCredentialException();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public CredentialHolder setParticularCredential(String id,
- CredentialHolder cred, UriInfo ui)
- throws InvalidCredentialException, BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- Credential c = cred.credential;
- c.id = id;
- c.href = ui.getAbsolutePath().toString();
- context.validateCredential(c);
- context.deleteCredential(c);
- context.addCredential(c);
- return new CredentialHolder(c);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response addCredential(CredentialHolder cred, UriInfo ui)
- throws InvalidCredentialException, BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- Credential c = cred.credential;
- c.id = randomUUID().toString();
- URI uri = secure(ui).path("{id}").build(c.id);
- c.href = uri.toString();
- context.validateCredential(c);
- context.addCredential(c);
- return created(uri).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response deleteAllCredentials(UriInfo ui)
- throws BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- for (Credential c : context.getCredentials())
- context.deleteCredential(c);
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response deleteCredential(String id, UriInfo ui)
- throws BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- context.deleteCredential(new Credential.Dummy(id));
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public TrustList listTrusted() {
- return new TrustList(context.getTrusted());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Trust getParticularTrust(String id) throws NoCredentialException {
- for (Trust t : context.getTrusted())
- if (t.id.equals(id))
- return t;
- throw new NoCredentialException();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Trust setParticularTrust(String id, Trust t, UriInfo ui)
- throws InvalidCredentialException, BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- t.id = id;
- t.href = ui.getAbsolutePath().toString();
- context.validateTrusted(t);
- context.deleteTrusted(t);
- context.addTrusted(t);
- return t;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response addTrust(Trust t, UriInfo ui)
- throws InvalidCredentialException, BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- t.id = randomUUID().toString();
- URI uri = secure(ui).path("{id}").build(t.id);
- t.href = uri.toString();
- context.validateTrusted(t);
- context.addTrusted(t);
- return created(uri).build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response deleteAllTrusts(UriInfo ui) throws BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- for (Trust t : context.getTrusted())
- context.deleteTrusted(t);
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response deleteTrust(String id, UriInfo ui)
- throws BadStateChangeException {
- if (run.getStatus() != Initialized)
- throw new BadStateChangeException();
- Trust toDelete = new Trust();
- toDelete.id = id;
- context.deleteTrusted(toDelete);
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public PermissionsDescription describePermissions(UriInfo ui) {
- Map<String, Permission> perm = support.getPermissionMap(context);
- return new PermissionsDescription(secure(ui).path("{id}"), perm);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Permission describePermission(String id) {
- return support.getPermission(context, id);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Permission setPermission(String id, Permission perm) {
- support.setPermission(context, id, perm);
- return support.getPermission(context, id);
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response deletePermission(String id, UriInfo ui) {
- support.setPermission(context, id, Permission.None);
- return noContent().build();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public Response makePermission(PermissionDescription desc, UriInfo ui) {
- support.setPermission(context, desc.userName, desc.permission);
- return created(secure(ui).path("{user}").build(desc.userName)).build();
- }
-
- @Override
- @CallCounted
- public Response descriptionOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response ownerOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response credentialsOptions() {
- return opt("POST", "DELETE");
- }
-
- @Override
- @CallCounted
- public Response credentialOptions(String id) {
- return opt("PUT", "DELETE");
- }
-
- @Override
- @CallCounted
- public Response trustsOptions() {
- return opt("POST", "DELETE");
- }
-
- @Override
- @CallCounted
- public Response trustOptions(String id) {
- return opt("PUT", "DELETE");
- }
-
- @Override
- @CallCounted
- public Response permissionsOptions() {
- return opt("POST");
- }
-
- @Override
- @CallCounted
- public Response permissionOptions(String id) {
- return opt("PUT", "DELETE");
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java b/server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java
deleted file mode 100644
index 6c9e8d8..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static java.util.Arrays.asList;
-import static org.taverna.server.master.common.Uri.secure;
-import static org.taverna.server.master.utils.RestUtils.opt;
-
-import java.util.List;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-
-import org.taverna.server.master.api.OneListenerBean;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.rest.TavernaServerListenersREST;
-import org.taverna.server.master.rest.TavernaServerListenersREST.ListenerDescription;
-import org.taverna.server.master.rest.TavernaServerListenersREST.TavernaServerListenerREST;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * RESTful interface to a single listener attached to a workflow run.
- *
- * @author Donal Fellows
- */
-abstract class SingleListenerREST implements TavernaServerListenerREST,
- OneListenerBean {
- private Listener listen;
- private TavernaRun run;
-
- @Override
- public SingleListenerREST connect(Listener listen, TavernaRun run) {
- this.listen = listen;
- this.run = run;
- return this;
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public String getConfiguration() {
- return listen.getConfiguration();
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public ListenerDescription getDescription(UriInfo ui) {
- return new ListenerDescription(listen, secure(ui));
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public TavernaServerListenersREST.Properties getProperties(UriInfo ui) {
- return new TavernaServerListenersREST.Properties(secure(ui).path(
- "{prop}"), listen.listProperties());
- }
-
- @Override
- @CallCounted
- @PerfLogged
- public TavernaServerListenersREST.Property getProperty(
- final String propertyName) throws NoListenerException {
- List<String> p = asList(listen.listProperties());
- if (p.contains(propertyName)) {
- return makePropertyInterface().connect(listen, run, propertyName);
- }
- throw new NoListenerException("no such property");
- }
-
- protected abstract ListenerPropertyREST makePropertyInterface();
-
- @Override
- @CallCounted
- public Response listenerOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response configurationOptions() {
- return opt();
- }
-
- @Override
- @CallCounted
- public Response propertiesOptions() {
- return opt();
- }
-}
[23/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-client/src/main/wadl/tavserv.wadl
----------------------------------------------------------------------
diff --git a/taverna-server-client/src/main/wadl/tavserv.wadl b/taverna-server-client/src/main/wadl/tavserv.wadl
new file mode 100644
index 0000000..2ba8fbe
--- /dev/null
+++ b/taverna-server-client/src/main/wadl/tavserv.wadl
@@ -0,0 +1,591 @@
+<application xmlns="http://wadl.dev.java.net/2009/02"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:prefix1="http://ns.taverna.org.uk/2010/xml/server/rest/"
+ xmlns:prefix3="http://ns.taverna.org.uk/2010/xml/server/"
+ xmlns:prefix10="http://ns.taverna.org.uk/2010/port/" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" jxb:version="2.1">
+<grammars>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:admin="http://ns.taverna.org.uk/2010/xml/server/admin/" xmlns:feed="http://ns.taverna.org.uk/2010/xml/server/feed/" xmlns:port="http://ns.taverna.org.uk/2010/port/" xmlns:tns="http://ns.taverna.org.uk/2010/xml/server/rest/" xmlns:ts="http://ns.taverna.org.uk/2010/xml/server/" xmlns:ts-rest="http://ns.taverna.org.uk/2010/xml/server/rest/" xmlns:ts-soap="http://ns.taverna.org.uk/2010/xml/server/soap/" xmlns:xlink="http://www.w3.org/1999/xlink" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ns.taverna.org.uk/2010/xml/server/rest/" jxb:version="2.1">
+ <xs:annotation>
+ <xs:appinfo>
+ <jxb:schemaBindings>
+ <jxb:package name="uk.org.taverna.server.client.rest" />
+ </jxb:schemaBindings>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:import namespace="http://ns.taverna.org.uk/2010/xml/server/"/>
+ <xs:import namespace="http://www.w3.org/1999/xlink"/>
+ <xs:element name="capabilities">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="capability" type="ts:Capability"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="credential" type="ts-rest:Credential"/>
+ <xs:element name="credentials" type="ts-rest:credentialList"/>
+ <xs:element name="directoryContents" type="ts-rest:DirectoryContents"/>
+ <xs:element name="enabledNotificationFabrics">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="notifier" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="filesystemOperation" type="ts-rest:FilesystemCreationOperation"/>
+ <xs:element name="listenerDefinition" type="ts-rest:ListenerDefinition"/>
+ <xs:element name="listenerDescription" type="ts-rest:ListenerDescription"/>
+ <xs:element name="listeners">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="listener" type="ts-rest:ListenerDescription"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="mkdir" type="ts-rest:MakeDirectory"/>
+ <xs:element name="permissionUpdate" type="ts-rest:permissionDescription"/>
+ <xs:element name="permissionsDescriptor" type="ts-rest:permissionsDescription"/>
+ <xs:element name="permittedListeners">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="type" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="permittedWorkflows">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="workflow" type="xs:string"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="policyDescription">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="runLimit" type="ts:Location"/>
+ <xs:element minOccurs="0" name="operatingLimit" type="ts:Location"/>
+ <xs:element minOccurs="0" name="permittedWorkflows" type="ts:Location"/>
+ <xs:element minOccurs="0" name="permittedListenerTypes" type="ts:Location"/>
+ <xs:element minOccurs="0" name="enabledNotificationFabrics" type="ts:Location"/>
+ <xs:element minOccurs="0" name="capabilities" type="ts:Location"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="properties">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="property" type="ts-rest:PropertyDescription"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="runDescription">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="expiry">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute ref="xlink:href"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element minOccurs="0" name="creationWorkflow" type="ts:Location"/>
+ <xs:element minOccurs="0" name="createTime" type="ts:Location"/>
+ <xs:element minOccurs="0" name="startTime" type="ts:Location"/>
+ <xs:element minOccurs="0" name="finishTime" type="ts:Location"/>
+ <xs:element minOccurs="0" name="status" type="ts:Location"/>
+ <xs:element minOccurs="0" name="workingDirectory" type="ts:Location"/>
+ <xs:element minOccurs="0" name="inputs" type="ts:Location"/>
+ <xs:element minOccurs="0" name="output" type="ts:Location"/>
+ <xs:element minOccurs="0" name="securityContext" type="ts:Location"/>
+ <xs:element minOccurs="0" name="listeners">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="ts:Location">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="listener" nillable="true" type="ts:Location"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element minOccurs="0" name="interaction" type="ts:Location"/>
+ <xs:element minOccurs="0" name="name" type="ts:Location"/>
+ <xs:element minOccurs="0" name="stdout" type="ts:Location"/>
+ <xs:element minOccurs="0" name="stderr" type="ts:Location"/>
+ <xs:element minOccurs="0" name="usage" type="ts:Location"/>
+ <xs:element minOccurs="0" name="log" type="ts:Location"/>
+ <xs:element minOccurs="0" name="run-bundle" type="ts:Location"/>
+ <xs:element minOccurs="0" name="generate-provenance" type="ts:Location"/>
+ </xs:sequence>
+ <xs:attribute ref="ts-rest:owner"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="runInput" type="ts-rest:InputDescription"/>
+ <xs:element name="runInputs" type="ts-rest:TavernaRunInputs"/>
+ <xs:element name="runList">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="run" type="ts:TavernaRun"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="securityDescriptor" type="ts-rest:SecurityDescriptor"/>
+ <xs:element name="serverDescription">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="runs" type="ts:Location"/>
+ <xs:element minOccurs="0" name="policy" type="ts:Location"/>
+ <xs:element minOccurs="0" name="feed" type="ts:Location"/>
+ <xs:element minOccurs="0" name="interactionFeed" type="ts:Location"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="trustedIdentities" type="ts-rest:trustList"/>
+ <xs:element name="upload" type="ts-rest:UploadFile"/>
+ <xs:element name="userPermission" type="ts-rest:linkedPermissionDescription"/>
+ <xs:complexType name="InputDescription">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:choice minOccurs="0">
+ <xs:element name="file">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="ts-rest:InputContents"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="reference">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="ts-rest:InputContents"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="value">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="ts-rest:InputContents"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute ref="ts-rest:name"/>
+ <xs:attribute ref="ts-rest:descriptorRef"/>
+ <xs:attribute ref="ts-rest:listDelimiter"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:simpleType name="InputContents">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+ <xs:complexType name="ListenerDescription">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="configuration" type="ts:Location"/>
+ <xs:element minOccurs="0" name="properties">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="property" type="ts-rest:PropertyDescription"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute ref="xlink:href"/>
+ <xs:attribute ref="ts-rest:name"/>
+ <xs:attribute ref="ts-rest:type"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="PropertyDescription">
+ <xs:complexContent>
+ <xs:extension base="ts:Location">
+ <xs:sequence/>
+ <xs:attribute ref="ts-rest:name"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="TavernaRunInputs">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="expected" type="ts:Location"/>
+ <xs:element minOccurs="0" name="baclava" type="ts:Location"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="input" nillable="true" type="ts:Location"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="Credential">
+ <xs:choice>
+ <xs:element ref="ts:keypair"/>
+ <xs:element ref="ts:userpass"/>
+ </xs:choice>
+ </xs:complexType>
+ <xs:complexType name="DirectoryContents">
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element ref="ts:dir"/>
+ <xs:element ref="ts:file"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="FilesystemCreationOperation">
+ <xs:simpleContent>
+ <xs:extension base="xs:base64Binary">
+ <xs:attribute ref="ts-rest:name"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="MakeDirectory">
+ <xs:simpleContent>
+ <xs:extension base="ts-rest:FilesystemCreationOperation"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="UploadFile">
+ <xs:simpleContent>
+ <xs:extension base="ts-rest:FilesystemCreationOperation"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="permissionsDescription">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="permission" type="ts-rest:linkedPermissionDescription"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="linkedPermissionDescription">
+ <xs:complexContent>
+ <xs:extension base="ts:Location">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="userName" type="xs:string"/>
+ <xs:element minOccurs="0" name="permission" type="ts:Permission"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="trustList">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="trust" type="ts:TrustDescriptor"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="permissionDescription">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="userName" type="xs:string"/>
+ <xs:element minOccurs="0" name="permission" type="ts:Permission"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="SecurityDescriptor">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="owner" type="xs:string"/>
+ <xs:element minOccurs="0" name="permissions" type="ts:Location"/>
+ <xs:element minOccurs="0" name="credentials" type="ts-rest:CredentialCollection"/>
+ <xs:element minOccurs="0" name="trusts" type="ts-rest:TrustCollection"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="CredentialCollection">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" ref="ts-rest:credential"/>
+ </xs:sequence>
+ <xs:attribute ref="xlink:href"/>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="TrustCollection">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="trust" type="ts:TrustDescriptor"/>
+ </xs:sequence>
+ <xs:attribute ref="xlink:href"/>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="credentialList">
+ <xs:complexContent>
+ <xs:extension base="ts:VersionedElement">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" ref="ts-rest:credential"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="ListenerDefinition">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute ref="ts-rest:type"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:attribute name="descriptorRef" type="xs:anyURI"/>
+ <xs:attribute name="listDelimiter" type="xs:string"/>
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="owner" type="xs:string"/>
+ <xs:attribute name="type" type="xs:string"/>
+</xs:schema>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/1999/xlink" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://www.w3.org/1999/xlink" jxb:version="2.1">
+ <xs:attribute name="href" type="xs:string"/>
+</xs:schema>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:port="http://ns.taverna.org.uk/2010/port/" xmlns:run="http://ns.taverna.org.uk/2010/run/" xmlns:tns="http://ns.taverna.org.uk/2010/port/" xmlns:xlink="http://www.w3.org/1999/xlink" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ns.taverna.org.uk/2010/port/" jxb:version="2.1">
+ <xs:annotation>
+ <xs:appinfo>
+ <jxb:schemaBindings>
+ <jxb:package name="uk.org.taverna.server.client.generic.port" />
+ </jxb:schemaBindings>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:import namespace="http://www.w3.org/1999/xlink"/>
+ <xs:element name="inputDescription" type="port:inputDescription"/>
+ <xs:element name="workflowOutputs" type="port:outputDescription"/>
+ <xs:complexType name="outputDescription">
+ <xs:complexContent>
+ <xs:extension base="port:PortDescription">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="output" type="port:OutputPort"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType abstract="true" name="PortDescription">
+ <xs:sequence/>
+ <xs:attribute ref="port:workflowId"/>
+ <xs:attribute ref="port:workflowRun"/>
+ <xs:attribute ref="port:workflowRunId"/>
+ </xs:complexType>
+ <xs:complexType name="OutputPort">
+ <xs:complexContent>
+ <xs:extension base="port:Port">
+ <xs:choice>
+ <xs:element name="value" type="port:LeafValue"/>
+ <xs:element name="list" type="port:ListValue"/>
+ <xs:element name="error" type="port:ErrorValue"/>
+ <xs:element name="absent" type="port:AbsentValue"/>
+ </xs:choice>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="Port">
+ <xs:sequence/>
+ <xs:attribute ref="port:name" use="required"/>
+ <xs:attribute ref="port:depth"/>
+ </xs:complexType>
+ <xs:complexType name="LeafValue">
+ <xs:complexContent>
+ <xs:extension base="port:Value">
+ <xs:sequence/>
+ <xs:attribute ref="port:contentFile"/>
+ <xs:attribute ref="port:contentType"/>
+ <xs:attribute ref="port:contentByteLength"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType abstract="true" name="Value">
+ <xs:sequence/>
+ <xs:attribute ref="xlink:href"/>
+ </xs:complexType>
+ <xs:complexType name="ErrorValue">
+ <xs:complexContent>
+ <xs:extension base="port:Value">
+ <xs:sequence/>
+ <xs:attribute ref="port:depth"/>
+ <xs:attribute ref="port:errorFile"/>
+ <xs:attribute ref="port:errorByteLength"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="ListValue">
+ <xs:complexContent>
+ <xs:extension base="port:Value">
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element name="value" type="port:LeafValue"/>
+ <xs:element name="list" type="port:ListValue"/>
+ <xs:element name="error" type="port:ErrorValue"/>
+ <xs:element name="absent" type="port:AbsentValue"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute ref="port:length"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="AbsentValue">
+ <xs:complexContent>
+ <xs:extension base="port:Value">
+ <xs:sequence/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="inputDescription">
+ <xs:complexContent>
+ <xs:extension base="port:PortDescription">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="input" type="port:InputPort"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="InputPort">
+ <xs:complexContent>
+ <xs:extension base="port:Port">
+ <xs:sequence/>
+ <xs:attribute ref="xlink:href"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:attribute name="contentByteLength" type="xs:long"/>
+ <xs:attribute name="contentFile" type="xs:string"/>
+ <xs:attribute name="contentType" type="xs:string"/>
+ <xs:attribute name="depth" type="xs:int"/>
+ <xs:attribute name="errorByteLength" type="xs:long"/>
+ <xs:attribute name="errorFile" type="xs:string"/>
+ <xs:attribute name="length" type="xs:int"/>
+ <xs:attribute name="name" type="xs:ID"/>
+ <xs:attribute name="workflowId" type="xs:string"/>
+ <xs:attribute name="workflowRun" type="xs:anyURI"/>
+ <xs:attribute name="workflowRunId" type="xs:string"/>
+</xs:schema>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:admin="http://ns.taverna.org.uk/2010/xml/server/admin/" xmlns:feed="http://ns.taverna.org.uk/2010/xml/server/feed/" xmlns:tns="http://ns.taverna.org.uk/2010/xml/server/" xmlns:ts="http://ns.taverna.org.uk/2010/xml/server/" xmlns:ts-rest="http://ns.taverna.org.uk/2010/xml/server/rest/" xmlns:ts-soap="http://ns.taverna.org.uk/2010/xml/server/soap/" xmlns:xlink="http://www.w3.org/1999/xlink" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ns.taverna.org.uk/2010/xml/server/" jxb:version="2.1">
+ <xs:annotation>
+ <xs:appinfo>
+ <jxb:schemaBindings>
+ <jxb:package name="uk.org.taverna.server.client.generic" />
+ </jxb:schemaBindings>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:import namespace="http://www.w3.org/1999/xlink"/>
+ <xs:element name="capability" type="ts:Capability"/>
+ <xs:element name="dir" type="ts:DirectoryReference"/>
+ <xs:element name="file" type="ts:FileReference"/>
+ <xs:element name="keypair" type="ts:KeyPairCredential"/>
+ <xs:element name="runReference" type="ts:TavernaRun"/>
+ <xs:element name="trustedIdentity" type="ts:TrustDescriptor"/>
+ <xs:element name="userpass" type="ts:PasswordCredential"/>
+ <xs:element name="workflow" type="ts:Workflow"/>
+ <xs:complexType abstract="true" name="VersionedElement">
+ <xs:sequence/>
+ <xs:attribute ref="ts:serverVersion"/>
+ <xs:attribute ref="ts:serverRevision"/>
+ <xs:attribute ref="ts:serverBuildTimestamp"/>
+ </xs:complexType>
+ <xs:complexType name="Location">
+ <xs:sequence/>
+ <xs:attribute ref="xlink:href"/>
+ </xs:complexType>
+ <xs:complexType name="Capability">
+ <xs:sequence/>
+ <xs:attribute ref="ts:capability"/>
+ <xs:attribute ref="ts:version"/>
+ </xs:complexType>
+ <xs:complexType name="KeyPairCredential">
+ <xs:complexContent>
+ <xs:extension base="ts:CredentialDescriptor">
+ <xs:sequence>
+ <xs:element name="credentialName" type="xs:string"/>
+ <xs:element minOccurs="0" name="credentialFile" type="xs:string"/>
+ <xs:element minOccurs="0" name="fileType" type="xs:string"/>
+ <xs:element minOccurs="0" name="unlockPassword" type="xs:string"/>
+ <xs:element minOccurs="0" name="credentialBytes" type="xs:base64Binary"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType abstract="true" name="CredentialDescriptor">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="serviceURI" type="xs:anyURI"/>
+ </xs:sequence>
+ <xs:attribute ref="xlink:href"/>
+ </xs:complexType>
+ <xs:complexType name="PasswordCredential">
+ <xs:complexContent>
+ <xs:extension base="ts:CredentialDescriptor">
+ <xs:sequence>
+ <xs:element name="username" type="xs:string"/>
+ <xs:element name="password" type="xs:string"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="DirectoryEntry">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute ref="xlink:href"/>
+ <xs:attribute ref="ts:name"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="DirectoryReference">
+ <xs:simpleContent>
+ <xs:extension base="ts:DirectoryEntry"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="FileReference">
+ <xs:simpleContent>
+ <xs:extension base="ts:DirectoryEntry"/>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="TavernaRun">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute ref="xlink:href"/>
+ <xs:attribute ref="ts:serverVersion"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:complexType name="Workflow">
+ <xs:sequence>
+ <xs:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType final="extension restriction" name="TrustDescriptor">
+ <xs:sequence>
+ <xs:element minOccurs="0" name="certificateFile" type="xs:string"/>
+ <xs:element minOccurs="0" name="fileType" type="xs:string"/>
+ <xs:element minOccurs="0" name="certificateBytes" type="xs:base64Binary"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="serverName" type="xs:string"/>
+ </xs:sequence>
+ <xs:attribute ref="xlink:href"/>
+ </xs:complexType>
+ <xs:simpleType name="Permission">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="read"/>
+ <xs:enumeration value="update"/>
+ <xs:enumeration value="destroy"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:attribute name="capability" type="xs:anyURI"/>
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="serverBuildTimestamp" type="xs:string"/>
+ <xs:attribute name="serverRevision" type="xs:string"/>
+ <xs:attribute name="serverVersion" type="xs:string"/>
+ <xs:attribute name="version" type="xs:string"/>
+</xs:schema>
+</grammars><resources base="http://example.com/taverna/rest"><resource path="/"><method name="GET"><doc>Produces the description of the service.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:serverDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the service.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="runs"><method name="GET"><doc>Produces a list of all runs visible to the user.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:runList"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the operations on the collection of runs.</doc><response><representation mediaType="application/octet-stream"><
/representation></response></method><method name="POST"><doc>Accepts (or not) a request to create a new run executing the given workflow.</doc><request><representation mediaType="application/vnd.taverna.t2flow+xml" element="prefix3:workflow"><doc>Accepts (or not) a request to create a new run executing the given workflow.</doc></representation><representation mediaType="application/xml" element="prefix3:workflow"><doc>Accepts (or not) a request to create a new run executing the given workflow.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Accepts a URL to a workflow to download and run. The URL must be hosted on a publicly-accessible service.</doc><request><representation mediaType="text/uri-list"><doc>Accepts a URL to a workflow to download and run. The URL must be hosted on a publicly-accessible service.</doc></representation></request><response><representation mediaType=
"application/octet-stream"></representation></response></method></resource><resource path="/policy"><method name="GET"><doc>Describe the parts of this policy.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:policyDescription"></representation><representation mediaType="application/json"></representation></response></method><resource path="/capabilities"><method name="GET"><doc>Gets a description of the capabilities supported by this installation of Taverna Server.</doc><response><representation mediaType="application/xml" element="prefix1:capabilities"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/enabledNotificationFabrics"><method name="GET"><doc>Gets the list of supported, enabled notification fabrics. Each corresponds (approximately) to a protocol, e.g., email.</doc><response><representation mediaType="application/xml" element="prefix1:enabledNotificati
onFabrics"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/operatingLimit"><method name="GET"><doc>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.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:int"><doc>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.</doc></param></representation></response></method></resource><resource path="/permittedListenerTypes"><method name="GET"><doc>Gets the list of permitted event listener types.</doc><response><representation mediaType="application/xml" element="prefix1:
permittedListeners"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/permittedWorkflows"><method name="GET"><doc>Gets the list of permitted workflows.</doc><response><representation mediaType="application/xml" element="prefix1:permittedWorkflows"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/runLimit"><method name="GET"><doc>Gets the maximum number of simultaneous runs in any state that the user may create.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:int"><doc>Gets the maximum number of simultaneous runs in any state that the user may create.</doc></param></representation></response></method></resource></resource><resource path="/runs/{runName}"><doc>This represents how a Taverna Server workflow run looks to a RESTful API.</doc><param name="runName" style="template" type="x
s:string"/><method name="DELETE"><doc>Deletes a workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Describes a workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:runDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/createTime"><method name="GET"><doc>Gives the time when the workflow run was first submitted to the server.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the time when the workflow run was first submitted to the server.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the d
escription of the run create time.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/expiry"><method name="GET"><doc>Gives the time when the workflow run becomes eligible for automatic deletion.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the time when the workflow run becomes eligible for automatic deletion.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run expiry.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the time when the workflow run becomes eligible for automatic deletion.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Sets the time when the workflow run becomes eligible for automatic deletion.</doc></param><
/representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Sets the time when the workflow run becomes eligible for automatic deletion.</doc></param></representation></response></method></resource><resource path="/finishTime"><method name="GET"><doc>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).</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>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).</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run finish time.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="
/generate-provenance"><method name="GET"><doc>Whether to create the run bundle for the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:boolean"><doc>Whether to create the run bundle for the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Whether to create the run bundle for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Whether to create the run bundle for the workflow run.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:boolean"><doc>Whether to create the run bundle for the workflow run.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:boolean"><doc>Whether to create the run bundle for the workflow run.</doc></param></representation></response></
method></resource><resource path="/log"><method name="GET"><doc>Return the log for the workflow run.</doc><response><representation mediaType="text/plain"></representation></response></method><method name="OPTIONS"><doc>Return the log for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/name"><method name="GET"><doc>Gives the descriptive name of the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the descriptive name of the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the operations on the run's descriptive name.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Set the descriptive name of the workflow run. Note that this value may be arbitraril
y truncated by the implementation.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Set the descriptive name of the workflow run. Note that this value may be arbitrarily truncated by the implementation.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Set the descriptive name of the workflow run. Note that this value may be arbitrarily truncated by the implementation.</doc></param></representation></response></method></resource><resource path="/output"><method name="GET"><doc>Gives the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc></param></repre
sentation></response></method><method name="GET"><doc>Gives a description of the outputs, as currently understood</doc><request></request><response><representation mediaType="application/xml" element="prefix10:workflowOutputs"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run output.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Sets the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:st
ring"><doc>Sets the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc></param></representation></response></method></resource><resource path="/run-bundle"><method name="GET"><doc>Return the run bundle for the workflow run.</doc><response><representation mediaType="application/vnd.wf4ever.robundle+zip"></representation></response></method><method name="OPTIONS"><doc>Return the run bundle for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/startTime"><method name="GET"><doc>Gives the time when the workflow run was started, or an empty string if the run has not yet started.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the time when the workflow run was started, or an empty string if the run has not yet started.</doc></param></representation></response></met
hod><method name="OPTIONS"><doc>Produces the description of the run start time.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/status"><method name="GET"><doc>Gives the current status of the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the current status of the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run status.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Attempts to update the status of the workflow run.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Attempts to update the status of the workflow run.</doc></param></representation></request><response><representation mediaType="text/pla
in"></representation></response></method></resource><resource path="/stderr"><method name="GET"><doc>Return the stderr for the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Return the stderr for the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Return the stderr for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/stdout"><method name="GET"><doc>Return the stdout for the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Return the stdout for the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Return the stdout for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resour
ce><resource path="/usage"><method name="GET"><doc>Return the usage record for the workflow run.</doc><response><representation mediaType="application/xml"></representation></response></method><method name="OPTIONS"><doc>Return the usage record for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/workflow"><method name="GET"><doc>Gives the workflow document used to create the workflow run.</doc><response><representation mediaType="application/vnd.taverna.t2flow+xml" element="prefix3:workflow"></representation><representation mediaType="application/xml" element="prefix3:workflow"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run workflow.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/inp
ut"><doc>This represents how a Taverna Server workflow run's inputs looks to a RESTful API.</doc><method name="GET"><doc>Describe the sub-URIs of this resource.</doc><response><representation mediaType="application/xml" element="prefix1:runInputs"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run's inputs' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/baclava"><method name="GET"><doc>Gives the Baclava file describing the inputs, or empty if individual files are used.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the Baclava file describing the inputs, or empty if individual files are used.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the inp
uts' baclava operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the Baclava file describing the inputs.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Sets the Baclava file describing the inputs.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Sets the Baclava file describing the inputs.</doc></param></representation></response></method></resource><resource path="/expected"><method name="GET"><doc>Describe the expected inputs of this workflow run.</doc><response><representation mediaType="application/xml" element="prefix10:inputDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the expected inputs' operati
ons.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/input/{name}"><param name="name" style="template" type="xs:string"/><method name="GET"><doc>Gives a description of what is used to supply a particular input.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:runInput"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the one input's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the source for a particular input port.</doc><request><representation mediaType="application/xml" element="prefix1:runInput"><doc>Sets the source for a particular input port.</doc></representation><representation mediaType="application/json"><doc>Sets the
source for a particular input port.</doc></representation></request><response><representation mediaType="application/xml" element="prefix1:runInput"></representation><representation mediaType="application/json"></representation></response></method></resource></resource><resource path="/interaction"><method name="GET"><doc>Get the feed document for this ATOM feed.</doc><response><representation mediaType="application/atom+xml"></representation></response></method><method name="OPTIONS"><doc>Describes what HTTP operations are supported on the feed.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Adds an entry to this ATOM feed.</doc><request><representation mediaType="application/atom+xml"><doc>Adds an entry to this ATOM feed.</doc></representation></request><response><representation mediaType="application/atom+xml"></representation></response></method><resource path="/{id}"><param name="id" style="temp
late" type="xs:string"/><method name="DELETE"><doc>Deletes an entry from this ATOM feed.</doc><request></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Deletes an entry from this ATOM feed.</doc></param></representation></response></method><method name="GET"><doc>Get the entry with a particular ID within this ATOM feed.</doc><request></request><response><representation mediaType="application/atom+xml"></representation></response></method><method name="OPTIONS"><doc>Describes what HTTP operations are supported on an entry.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource></resource><resource path="/listeners"><doc>This represents all the event listeners attached to a workflow run.</doc><method name="GET"><doc>Get the listeners installed in the workflow run.</doc><request></request><response><representation mediaType="application/xml"
element="prefix1:listeners"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run listeners' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Add a new event listener to the named workflow run.</doc><request><representation mediaType="application/xml" element="prefix1:listenerDefinition"><doc>Add a new event listener to the named workflow run.</doc></representation><representation mediaType="application/json"><doc>Add a new event listener to the named workflow run.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/{name}"><doc>This represents a single event listener attached to a workflow run.</doc><param name="name" style="template" type="xs:string"/><method name="GET"><doc>Get th
e description of this listener.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:listenerDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/configuration"><method name="GET"><doc>Get the configuration for the given event listener that is attached to a workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Get the configuration for the given event listener that is attached to a workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's configuration's operations.</doc><response><representation mediaType="applica
tion/octet-stream"></representation></response></method></resource><resource path="/properties"><method name="GET"><doc>Get the list of properties supported by a given event listener attached to a workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:properties"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's properties' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/properties/{propertyName}"><doc>This represents a single property attached of an event listener.</doc><param name="propertyName" style="template" type="xs:string"/><method name="GET"><doc>Get the value of the particular property of an event listener attached to a workflow run.</doc><response><representation mediaType="text/plain"><param
name="result" style="plain" type="xs:string"><doc>Get the value of the particular property of an event listener attached to a workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's property's operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Set the value of the particular property of an event listener attached to a workflow run.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Set the value of the particular property of an event listener attached to a workflow run.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Set the value of the particular property of an event listener attached to a workflow run.</doc></param></representation></response><
/method></resource></resource></resource><resource path="/security"><doc>Manages the security of the workflow run. In general, only the owner of a run may access this resource.</doc><method name="GET"><doc>Gives a description of the security information supported by the workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:securityDescriptor"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run security.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/credentials"><method name="DELETE"><doc>Deletes all credentials.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Gives a list of credentials supplied to this workflow run.</doc><response><representation
mediaType="application/xml" element="prefix1:credentials"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run credentials' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Creates a new credential.</doc><request><representation mediaType="application/xml" element="prefix1:credential"><doc>Creates a new credential.</doc></representation><representation mediaType="application/json"><doc>Creates a new credential.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/credentials/{id}"><param name="id" style="template" type="xs:string"/><method name="DELETE"><doc>Deletes a particular credential.</doc><request></request><response><representation mediaType="application/octet-stre
am"></representation></response></method><method name="GET"><doc>Describes a particular credential.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:credential"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run credential's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Updates a particular credential.</doc><request><representation mediaType="application/xml" element="prefix1:credential"><doc>Updates a particular credential.</doc></representation><representation mediaType="application/json"><doc>Updates a particular credential.</doc></representation></request><response><representation mediaType="application/xml" element="prefix1:credential"></representation><representation mediaType="application/json"></represe
ntation></response></method></resource><resource path="/owner"><method name="GET"><doc>Gives the identity of who owns the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the identity of who owns the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run owner.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/permissions"><method name="GET"><doc>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.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:permissionsDescriptor"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Pro
duces the description of the run permissions' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Creates a new assignment of permissions to a particular user.</doc><request><representation mediaType="application/xml" element="prefix1:permissionUpdate"><doc>Creates a new assignment of permissions to a particular user.</doc></representation><representation mediaType="application/json"><doc>Creates a new assignment of permissions to a particular user.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/permissions/{id}"><param name="id" style="template" type="xs:string"/><method name="DELETE"><doc>Deletes (by resetting to default) the permissions associated with a particular user.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></
response></method><method name="GET"><doc>Describes the permission granted to a particular user.</doc><request></request><response><representation mediaType="text/plain"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run permission's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Updates the permissions granted to a particular user.</doc><request><representation mediaType="text/plain"><doc>Updates the permissions granted to a particular user.</doc></representation></request><response><representation mediaType="text/plain"></representation></response></method></resource><resource path="/trusts"><method name="DELETE"><doc>Deletes all trusted identities.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Gives a list of trust
ed identities supplied to this workflow run.</doc><response><representation mediaType="application/xml" element="prefix1:trustedIdentities"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run trusted certificates' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Adds a new trusted identity.</doc><request><representation mediaType="application/xml" element="prefix3:trustedIdentity"><doc>Adds a new trusted identity.</doc></representation><representation mediaType="application/json"><doc>Adds a new trusted identity.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/trusts/{id}"><param name="id" style="template" type="xs:string"/><method name="DELETE"><doc>Deletes a particu
lar trusted identity.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Describes a particular trusted identity.</doc><request></request><response><representation mediaType="application/xml" element="prefix3:trustedIdentity"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run trusted certificate's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Updates a particular trusted identity.</doc><request><representation mediaType="application/xml" element="prefix3:trustedIdentity"><doc>Updates a particular trusted identity.</doc></representation><representation mediaType="application/json"><doc>Updates a particular trusted identity.</doc></representation></request><respo
nse><representation mediaType="application/xml" element="prefix3:trustedIdentity"></representation><representation mediaType="application/json"></representation></response></method></resource></resource><resource path="/wd"><doc>Representation of how a workflow run's working directory tree looks.</doc><method name="GET"><doc>Describes the working directory of the workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:directoryContents"></representation><representation mediaType="application/json"></representation></response></method><resource path="/{path:(.*)}"><param name="path" style="template" repeating="true"/><method name="POST"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run with the contents of a publicly readable URL.</doc><request><representation mediaType="text/uri-list"><doc>Creates or updates a file in a particular location beneath the working directory o
f the workflow run with the contents of a publicly readable URL.</doc></representation></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method><method name="PUT"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run.</doc><request><representation mediaType="application/octet-stream"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run.</doc></representation><representation mediaType="*/*"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run.</doc></representation></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/{path:.*}"><param name="path" style="template" repeating="true"/><method
name="DELETE"><doc>Deletes a file or directory that is in or below the working directory of a workflow run.</doc><request></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the files/directories' baclava operations.</doc><request></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method><method name="POST"><doc>Creates a directory in the filesystem beneath the working directory of the workflow run, or creates or updates a file's contents, where that file is in or below the working directory of a workflow run.</doc><request><representation mediaType="application/xml" element="prefix1:filesystemOperation"><doc>Creates a directory in the filesystem beneath the working directory of the workflow run, or create
s or updates a file's contents, where that file is in or below the working directory of a workflow run.</doc></representation><representation mediaType="application/json"><doc>Creates a directory in the filesystem beneath the working directory of the workflow run, or creates or updates a file's contents, where that file is in or below the working directory of a workflow run.</doc></representation></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/{path:.+}"><param name="path" style="template" repeating="true"/><method name="GET"><doc>Gives a description of the named entity in or beneath the working directory of the workflow run (either a Directory or File).</doc><request></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation><representation mediaTyp
e="application/octet-stream"></representation><representation mediaType="application/zip"></representation><representation mediaType="*/*"></representation></response></method></resource></resource></resource></resource></resources></application>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-distribution/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-distribution/pom.xml b/taverna-server-distribution/pom.xml
new file mode 100644
index 0000000..8939dbf
--- /dev/null
+++ b/taverna-server-distribution/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-distribution</artifactId>
+ <name>Apache Taverna Server Distribution Packaging</name>
+ <packaging>pom</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.version}</groupId>
+ <artifactId>taverna-server-webapp</artifactId>
+ <version>${project.parent.version}</version>
+ <type>war</type>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>TavernaServer-${project.parent.version}</finalName>
+ <descriptors>
+ <descriptor>src/assemble/dist.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-t2server-distribution</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>default</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.4</version>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <!-- Only generate the index, nothing else. -->
+ <report>index</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8</version>
+ <reportSets>
+ <reportSet />
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-changelog-plugin</artifactId>
+ <version>2.2</version>
+ <reportSets>
+ <reportSet />
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-changes-plugin</artifactId>
+ <version>2.6</version>
+ <reportSets>
+ <reportSet />
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.7</version>
+ <reportSets>
+ <reportSet />
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>2.5</version>
+ <reportSets>
+ <reportSet />
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.9</version>
+ <reportSets>
+ <reportSet />
+ </reportSets>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-distribution/src/assemble/dist.xml
----------------------------------------------------------------------
diff --git a/taverna-server-distribution/src/assemble/dist.xml b/taverna-server-distribution/src/assemble/dist.xml
new file mode 100644
index 0000000..a77883c
--- /dev/null
+++ b/taverna-server-distribution/src/assemble/dist.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>distribution</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+<!--
+ <dependencySets>
+ <dependencySet>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ <useProjectArtifact>false</useProjectArtifact>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ <fileMode>0644</fileMode>
+ </dependencySet>
+ </dependencySets>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>*.html</include>
+ <include>*.xml</include>
+ <include>*.txt</include>
+ <include>*.pdf</include>
+ </includes>
+ <excludes>
+ <exclude>pom.xml</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+-->
+ <fileSets>
+ <fileSet>
+ <directory>${project.parent.basedir}</directory>
+ <includes>
+ <include>*.xml</include>
+ <include>*.txt</include>
+ <include>*.pdf</include>
+ </includes>
+ <excludes>
+ <exclude>pom.xml</exclude>
+ </excludes>
+ <fileMode>0644</fileMode>
+ <outputDirectory>.</outputDirectory>
+ </fileSet>
+ <fileSet>
+ <directory>${project.parent.basedir}/server-webapp/target</directory>
+ <includes>
+ <include>*.war</include>
+ </includes>
+ <outputDirectory>.</outputDirectory>
+ <fileMode>0644</fileMode>
+ </fileSet>
+ </fileSets>
+<!--
+ <moduleSets>
+ <moduleSet>
+ <includes>
+ <include>uk.org.taverna.server:server</include>
+ </includes>
+ <sources>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>*.html</include>
+ <include>*.txt</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </sources>
+ </moduleSet>
+ <moduleSet>
+ <includes>
+ <include>uk.org.taverna.server:server-webapp</include>
+ </includes>
+ <binaries />
+ </moduleSet>
+ </moduleSets>
+-->
+</assembly>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-execution-delegate/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-execution-delegate/pom.xml b/taverna-server-execution-delegate/pom.xml
new file mode 100644
index 0000000..59c8aff
--- /dev/null
+++ b/taverna-server-execution-delegate/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-execution-delegate</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Taverna Server Reporting Probe</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.taverna.engine</groupId>
+ <artifactId>taverna-execution-api</artifactId>
+ <version>${taverna.engine.version}</version>
+ <type>bundle</type>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java
----------------------------------------------------------------------
diff --git a/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java b/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java
new file mode 100644
index 0000000..7ea9998
--- /dev/null
+++ b/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java
@@ -0,0 +1,172 @@
+package org.taverna.server.execution_delegate;
+
+import java.net.URI;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Map;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.taverna.server.execution_delegate.RemoteExecution.ProcessorReportDocument.Property;
+
+import uk.org.taverna.platform.data.api.Data;
+import uk.org.taverna.platform.data.api.DataLocation;
+import uk.org.taverna.platform.execution.api.Execution;
+import uk.org.taverna.platform.report.ActivityReport;
+import uk.org.taverna.platform.report.ProcessorReport;
+import uk.org.taverna.platform.report.StatusReport;
+import uk.org.taverna.platform.report.WorkflowReport;
+import uk.org.taverna.scufl2.api.common.AbstractNamed;
+
+public class ExecutionDelegate extends UnicastRemoteObject implements
+ RemoteExecution {
+ private Execution delegated;
+ private DatatypeFactory dtf;
+
+ public ExecutionDelegate(Execution execution) throws RemoteException,
+ DatatypeConfigurationException {
+ super();
+ delegated = execution;
+ dtf = DatatypeFactory.newInstance();
+ }
+
+ @Override
+ public String getID() {
+ return delegated.getID();
+ }
+
+ @Override
+ public void delete() {
+ delegated.delete();
+ }
+
+ @Override
+ public void start() {
+ delegated.start();
+ }
+
+ @Override
+ public void pause() {
+ delegated.pause();
+ }
+
+ @Override
+ public void resume() {
+ delegated.resume();
+ }
+
+ @Override
+ public void cancel() {
+ delegated.cancel();
+ }
+
+ private XMLGregorianCalendar date(Date d) {
+ if (d == null)
+ return null;
+ GregorianCalendar c = new GregorianCalendar();
+ c.setTime(d);
+ return dtf.newXMLGregorianCalendar(c);
+ }
+
+ private <R extends ReportDocument, T extends AbstractNamed> R init(
+ R snapshot, StatusReport<T, ?, ?> report) {
+ snapshot.created = date(report.getCreatedDate());
+ snapshot.completed = date(report.getCompletedDate());
+ snapshot.cancelled = date(report.getCancelledDate());
+ snapshot.failed = date(report.getFailedDate());
+ snapshot.started = date(report.getStartedDate());
+ for (Date d : report.getPausedDates())
+ snapshot.paused.add(date(d));
+ for (Date d : report.getResumedDates())
+ snapshot.resumed.add(date(d));
+ snapshot.subject = report.getSubject().getName();
+ snapshot.state = report.getState().toString();
+ return snapshot;
+ }
+
+ private WorkflowReportDocument getReport(WorkflowReport report) {
+ WorkflowReportDocument snapshot = init(new WorkflowReportDocument(),
+ report);
+ for (ProcessorReport pr : report.getChildReports())
+ snapshot.processor.add(getReport(pr));
+ initMap(snapshot.inputs, report.getInputs());
+ initMap(snapshot.outputs, report.getOutputs());
+ return snapshot;
+ }
+
+ private void initMap(ArrayList<PortMapping> snapshot, Map<String, ?> report) {
+ for (String port : report.keySet())
+ snapshot.add(data(port, report.get(port)));
+ }
+
+ private static final String DEFAULT_PROPERTY_STRING = "";
+
+ private PortMapping data(String name, Object o) {
+ String loc;
+ if (o instanceof DataLocation) {
+ DataLocation d = (DataLocation) o;
+ loc = d.getDataServiceURI() + "#" + d.getDataID();
+ } else {
+ Data d = (Data) o;
+ loc = null;
+ if (d.hasReferences()) {
+ try {
+ loc = d.getReferences().iterator().next().getURI()
+ .toString();
+ } catch (Exception e) {
+ }
+ }
+ if (loc == null) {
+ DataLocation dl = d.getDataService().getDataLocation(d);
+ loc = dl.getDataServiceURI() + "#" + dl.getDataID();
+ }
+ }
+ return new PortMapping(name, URI.create(loc));
+ }
+
+ private ProcessorReportDocument getReport(ProcessorReport report) {
+ ProcessorReportDocument snapshot = init(new ProcessorReportDocument(),
+ report);
+ for (ActivityReport pr : report.getChildReports())
+ snapshot.activity.add(getReport(pr));
+ snapshot.jobsQueued = report.getJobsStarted();
+ snapshot.jobsStarted = report.getJobsStarted();
+ snapshot.jobsCompleted = report.getJobsCompleted();
+ snapshot.jobsErrored = report.getJobsCompletedWithErrors();
+ for (String key : report.getPropertyKeys()) {
+ Object value = report.getProperty(key);
+ if (value instanceof String || value instanceof Number)
+ snapshot.properties.add(new Property(key, value.toString()));
+ else
+ snapshot.properties.add(new Property(key,
+ DEFAULT_PROPERTY_STRING));
+ }
+ return snapshot;
+ }
+
+ private ActivityReportDocument getReport(ActivityReport report) {
+ ActivityReportDocument snapshot = init(new ActivityReportDocument(),
+ report);
+ for (WorkflowReport pr : report.getChildReports())
+ snapshot.workflow.add(getReport(pr));
+ initMap(snapshot.inputs, report.getInputs());
+ initMap(snapshot.outputs, report.getOutputs());
+ return snapshot;
+ }
+
+ @Override
+ public WorkflowReportDocument getWorkflowReport() {
+ return getReport(delegated.getWorkflowReport());
+ }
+}
+
+// ExecutionDelegate.java:[96,2]
+// initMap(java.util.ArrayList<org.taverna.server.execution_delegate.RemoteExecution.PortMapping>,java.util.Map<java.lang.String,uk.org.taverna.platform.data.api.Data>)
+// in org.taverna.server.execution_delegate.ExecutionDelegate cannot be applied
+// to
+// (java.util.ArrayList<org.taverna.server.execution_delegate.RemoteExecution.PortMapping>,java.util.Map<java.lang.String,uk.org.taverna.platform.data.api.DataLocation>)
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java
----------------------------------------------------------------------
diff --git a/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java b/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java
new file mode 100644
index 0000000..b8510df
--- /dev/null
+++ b/taverna-server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java
@@ -0,0 +1,188 @@
+package org.taverna.server.execution_delegate;
+
+import static javax.xml.bind.annotation.XmlAccessType.NONE;
+
+import java.net.URI;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessorType;
+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.XmlSeeAlso;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * Interface for a single execution of a Taverna workflow in a remote process.
+ *
+ * @author David Withers
+ */
+public interface RemoteExecution extends Remote {
+
+ /**
+ * Returns the identifier for this execution.
+ *
+ * @return the identifier for this execution
+ */
+ String getID() throws RemoteException;
+
+ /**
+ * Returns the <code>WorkflowReport</code> for the execution.
+ *
+ * @return the <code>WorkflowReport</code> for the execution
+ */
+ WorkflowReportDocument getWorkflowReport() throws RemoteException;
+
+ /**
+ * Deletes the execution.
+ */
+ void delete() throws RemoteException;
+
+ /**
+ * Starts the execution.
+ */
+ void start() throws RemoteException;
+
+ /**
+ * Pauses the execution.
+ */
+ void pause() throws RemoteException;
+
+ /**
+ * Resumes a paused execution.
+ */
+ void resume() throws RemoteException;
+
+ /**
+ * Cancels the execution.
+ */
+ void cancel() throws RemoteException;
+
+ @XmlType(name = "Report", propOrder = { "state", "created", "started",
+ "completed", "failed", "cancelled", "paused", "resumed" })
+ @XmlSeeAlso({ WorkflowReportDocument.class, ProcessorReportDocument.class,
+ ActivityReportDocument.class })
+ @XmlAccessorType(NONE)
+ public static abstract class ReportDocument {
+ @XmlAttribute
+ public String subject;
+ @XmlElement
+ public String state;
+ @XmlElement(required = true)
+ @XmlSchemaType(name = "dateTime")
+ public XMLGregorianCalendar created;
+ @XmlElement
+ @XmlSchemaType(name = "dateTime")
+ public XMLGregorianCalendar started;
+ @XmlElement
+ @XmlSchemaType(name = "dateTime")
+ public XMLGregorianCalendar completed;
+ @XmlElement
+ @XmlSchemaType(name = "dateTime")
+ public XMLGregorianCalendar failed;
+ @XmlElement
+ @XmlSchemaType(name = "dateTime")
+ public XMLGregorianCalendar cancelled;
+ @XmlElement
+ @XmlSchemaType(name = "dateTime")
+ public List<XMLGregorianCalendar> paused;
+ @XmlElement
+ @XmlSchemaType(name = "dateTime")
+ public List<XMLGregorianCalendar> resumed;
+ }
+
+ @XmlType(name = "WorkflowReport", propOrder = { "processor", "inputs",
+ "outputs" })
+ @XmlRootElement(name = "workflowReport")
+ @XmlAccessorType(NONE)
+ public static class WorkflowReportDocument extends ReportDocument {
+ @XmlElement(name = "processor")
+ public ArrayList<ProcessorReportDocument> processor = new ArrayList<ProcessorReportDocument>();
+ @XmlElement(name = "input")
+ public ArrayList<PortMapping> inputs = new ArrayList<PortMapping>();
+ @XmlElement(name = "output")
+ public ArrayList<PortMapping> outputs = new ArrayList<PortMapping>();
+ }
+
+ @XmlType(name = "ProcessorReport", propOrder = { "jobsQueued",
+ "jobsStarted", "jobsCompleted", "jobsErrored", "properties",
+ "activity" })
+ @XmlAccessorType(NONE)
+ public static class ProcessorReportDocument extends ReportDocument {
+ @XmlElement(name = "jobsQueued", required = true)
+ public int jobsQueued;
+ @XmlElement(name = "jobsStarted", required = true)
+ public int jobsStarted;
+ @XmlElement(name = "jobsCompleted", required = true)
+ public int jobsCompleted;
+ @XmlElement(name = "jobsErrored", required = true)
+ public int jobsErrored;
+ @XmlElement(name = "property")
+ @XmlElementWrapper(name = "properties")
+ public ArrayList<Property> properties = new ArrayList<Property>();
+ @XmlElement(name = "activity")
+ public ArrayList<ActivityReportDocument> activity = new ArrayList<ActivityReportDocument>();
+
+ @XmlType(name = "ProcessorProperty")
+ @XmlAccessorType(NONE)
+ public static class Property {
+ @XmlAttribute(name = "key", required = true)
+ String key;
+ @XmlValue
+ String value;
+
+ public Property() {
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ Property(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+ }
+ }
+
+ @XmlType(name = "ActivityReport", propOrder = { "workflow", "inputs",
+ "outputs" })
+ @XmlAccessorType(NONE)
+ public static class ActivityReportDocument extends ReportDocument {
+ @XmlElement(name = "workflow")
+ public ArrayList<WorkflowReportDocument> workflow = new ArrayList<WorkflowReportDocument>();
+ @XmlElement(name = "input")
+ public ArrayList<PortMapping> inputs = new ArrayList<PortMapping>();
+ @XmlElement(name = "output")
+ public ArrayList<PortMapping> outputs = new ArrayList<PortMapping>();
+ }
+
+ @XmlType(name = "PortMapping")
+ @XmlAccessorType(NONE)
+ public static class PortMapping {
+ public PortMapping() {
+ }
+
+ PortMapping(String port, URI data) {
+ this.name = port;
+ this.reference = data;
+ }
+
+ @XmlAttribute(name = "name")
+ public String name;
+ @XmlAttribute(name = "ref")
+ @XmlSchemaType(name = "anyURI")
+ public URI reference;
+ }
+}
[19/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java
new file mode 100644
index 0000000..0f98da6
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServer.java
@@ -0,0 +1,1425 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static java.lang.Math.min;
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.sort;
+import static java.util.UUID.randomUUID;
+import static javax.ws.rs.core.Response.created;
+import static javax.ws.rs.core.UriBuilder.fromUri;
+import static javax.xml.ws.handler.MessageContext.HTTP_REQUEST_HEADERS;
+import static javax.xml.ws.handler.MessageContext.PATH_INFO;
+import static org.apache.commons.io.IOUtils.toByteArray;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.TavernaServerSupport.PROV_BUNDLE;
+import static org.taverna.server.master.common.DirEntryReference.newInstance;
+import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
+import static org.taverna.server.master.common.Roles.ADMIN;
+import static org.taverna.server.master.common.Roles.SELF;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.common.Status.Initialized;
+import static org.taverna.server.master.common.Uri.secure;
+import static org.taverna.server.master.soap.DirEntry.convert;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import javax.annotation.security.DeclareRoles;
+import javax.annotation.security.RolesAllowed;
+import javax.jws.WebService;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+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.ws.WebServiceContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.cxf.annotations.WSDLDocumentation;
+import org.ogf.usage.JobUsageRecord;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.api.SupportAware;
+import org.taverna.server.master.api.TavernaServerBean;
+import org.taverna.server.master.common.Capability;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.DirEntryReference;
+import org.taverna.server.master.common.InputDescription;
+import org.taverna.server.master.common.Permission;
+import org.taverna.server.master.common.ProfileList;
+import org.taverna.server.master.common.RunReference;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.common.version.Version;
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoCredentialException;
+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.exceptions.OverloadedException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.factories.ListenerFactory;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.Input;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.RunStore;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+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.rest.TavernaServerREST.EnabledNotificationFabrics;
+import org.taverna.server.master.rest.TavernaServerREST.PermittedListeners;
+import org.taverna.server.master.rest.TavernaServerREST.PermittedWorkflows;
+import org.taverna.server.master.rest.TavernaServerREST.PolicyView;
+import org.taverna.server.master.rest.TavernaServerRunREST;
+import org.taverna.server.master.soap.DirEntry;
+import org.taverna.server.master.soap.FileContents;
+import org.taverna.server.master.soap.PermissionList;
+import org.taverna.server.master.soap.TavernaServerSOAP;
+import org.taverna.server.master.soap.WrappedWorkflow;
+import org.taverna.server.master.soap.ZippedDirectory;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.FilenameUtils;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+import org.taverna.server.port_description.OutputDescription;
+
+/**
+ * The core implementation of the web application.
+ *
+ * @author Donal Fellows
+ */
+@Path("/")
+@DeclareRoles({ USER, ADMIN })
+@WebService(endpointInterface = "org.taverna.server.master.soap.TavernaServerSOAP", serviceName = "TavernaServer", targetNamespace = SERVER_SOAP)
+@WSDLDocumentation("An instance of Taverna " + Version.JAVA + " Server.")
+public abstract class TavernaServer implements TavernaServerSOAP,
+ TavernaServerREST, TavernaServerBean {
+ /**
+ * The root of descriptions of the server in JMX.
+ */
+ public static final String JMX_ROOT = "Taverna:group=Server-"
+ + Version.JAVA + ",name=";
+
+ /** The logger for the server framework. */
+ public Log log = getLog("Taverna.Server.Webapp");
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // CONNECTIONS TO JMX, SPRING AND CXF
+
+ @Resource
+ WebServiceContext jaxws;
+ @Context
+ private HttpHeaders jaxrsHeaders;
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // STATE VARIABLES AND SPRING SETTERS
+
+ /**
+ * For building descriptions of the expected inputs and actual outputs of a
+ * workflow.
+ */
+ private ContentsDescriptorBuilder cdBuilder;
+ /**
+ * Utilities for accessing files on the local-worker.
+ */
+ private FilenameUtils fileUtils;
+ /** How notifications are dispatched. */
+ private NotificationEngine notificationEngine;
+ /** Main support class. */
+ private TavernaServerSupport support;
+ /** A storage facility for workflow runs. */
+ private RunStore runStore;
+ /** Encapsulates the policies applied by this server. */
+ private Policy policy;
+ /** Where Atom events come from. */
+ EventDAO eventSource;
+ /** Reference to the main interaction feed. */
+ private String interactionFeed;
+
+ @Override
+ @Required
+ public void setFileUtils(FilenameUtils converter) {
+ this.fileUtils = converter;
+ }
+
+ @Override
+ @Required
+ public void setContentsDescriptorBuilder(ContentsDescriptorBuilder cdBuilder) {
+ this.cdBuilder = cdBuilder;
+ }
+
+ @Override
+ @Required
+ public void setNotificationEngine(NotificationEngine notificationEngine) {
+ this.notificationEngine = notificationEngine;
+ }
+
+ /**
+ * @param support
+ * the support to set
+ */
+ @Override
+ @Required
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ @Required
+ public void setRunStore(RunStore runStore) {
+ this.runStore = runStore;
+ }
+
+ @Override
+ @Required
+ public void setPolicy(Policy policy) {
+ this.policy = policy;
+ }
+
+ @Override
+ @Required
+ public void setEventSource(EventDAO eventSource) {
+ this.eventSource = eventSource;
+ }
+
+ /**
+ * The location of a service-wide interaction feed, derived from a
+ * properties file. Expected to be <i>actually</i> not set (to a real
+ * value).
+ *
+ * @param interactionFeed
+ * The URL, which will be resolved relative to the location of
+ * the webapp, or the string "<tt>none</tt>" (which corresponds
+ * to a <tt>null</tt>).
+ */
+ public void setInteractionFeed(String interactionFeed) {
+ if ("none".equals(interactionFeed))
+ interactionFeed = null;
+ else if (interactionFeed != null && interactionFeed.startsWith("${"))
+ interactionFeed = null;
+ this.interactionFeed = interactionFeed;
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // REST INTERFACE
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public ServerDescription describeService(UriInfo ui) {
+ jaxrsUriInfo.set(new WeakReference<>(ui));
+ return new ServerDescription(ui, resolve(interactionFeed));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public RunList listUsersRuns(UriInfo ui) {
+ jaxrsUriInfo.set(new WeakReference<>(ui));
+ return new RunList(runs(), secure(ui).path("{name}"));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response submitWorkflow(Workflow workflow, UriInfo ui)
+ throws NoUpdateException {
+ jaxrsUriInfo.set(new WeakReference<>(ui));
+ checkCreatePolicy(workflow);
+ String name = support.buildWorkflow(workflow);
+ return created(secure(ui).path("{uuid}").build(name)).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response submitWorkflowByURL(List<URI> referenceList, UriInfo ui)
+ throws NoCreateException {
+ jaxrsUriInfo.set(new WeakReference<>(ui));
+ if (referenceList == null || referenceList.size() == 0)
+ throw new NoCreateException("no workflow URI supplied");
+ URI workflowURI = referenceList.get(0);
+ checkCreatePolicy(workflowURI);
+ Workflow workflow;
+ try {
+ workflow = support.getWorkflowDocumentFromURI(workflowURI);
+ } catch (IOException e) {
+ throw new NoCreateException("could not read workflow", e);
+ }
+ String name = support.buildWorkflow(workflow);
+ return created(secure(ui).path("{uuid}").build(name)).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public int getServerMaxRuns() {
+ return support.getMaxSimultaneousRuns();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public TavernaServerRunREST getRunResource(String runName, UriInfo ui)
+ throws UnknownRunException {
+ jaxrsUriInfo.set(new WeakReference<>(ui));
+ RunREST rr = makeRunInterface();
+ rr.setRun(support.getRun(runName));
+ rr.setRunName(runName);
+ return rr;
+ }
+
+ private ThreadLocal<Reference<UriInfo>> jaxrsUriInfo = new InheritableThreadLocal<>();
+
+ private UriInfo getUriInfo() {
+ if (jaxrsUriInfo.get() == null)
+ return null;
+ return jaxrsUriInfo.get().get();
+ }
+
+ @Override
+ @CallCounted
+ public abstract PolicyView getPolicyDescription();
+
+ @Override
+ @CallCounted
+ public Response serviceOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response runsOptions() {
+ return opt("POST");
+ }
+
+ /**
+ * Construct a RESTful interface to a run.
+ *
+ * @return The handle to the interface, as decorated by Spring.
+ */
+ protected abstract RunREST makeRunInterface();
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // SOAP INTERFACE
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public RunReference[] listRuns() {
+ ArrayList<RunReference> ws = new ArrayList<>();
+ UriBuilder ub = getRunUriBuilder();
+ for (String runName : runs().keySet())
+ ws.add(new RunReference(runName, ub));
+ return ws.toArray(new RunReference[ws.size()]);
+ }
+
+ private void checkCreatePolicy(Workflow workflow) throws NoCreateException {
+ List<URI> pwu = policy
+ .listPermittedWorkflowURIs(support.getPrincipal());
+ if (pwu == null || pwu.size() == 0)
+ return;
+ throw new NoCreateException("server policy: will only start "
+ + "workflows sourced from permitted URI list");
+ }
+
+ private void checkCreatePolicy(URI workflowURI) throws NoCreateException {
+ List<URI> pwu = policy
+ .listPermittedWorkflowURIs(support.getPrincipal());
+ if (pwu == null || pwu.size() == 0 || pwu.contains(workflowURI))
+ return;
+ throw new NoCreateException("workflow URI not on permitted list");
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public RunReference submitWorkflow(Workflow workflow)
+ throws NoUpdateException {
+ checkCreatePolicy(workflow);
+ String name = support.buildWorkflow(workflow);
+ return new RunReference(name, getRunUriBuilder());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public RunReference submitWorkflowMTOM(WrappedWorkflow workflow)
+ throws NoUpdateException {
+ Workflow wf;
+ try {
+ wf = workflow.getWorkflow();
+ } catch (IOException e) {
+ throw new NoCreateException(e.getMessage(), e);
+ }
+ checkCreatePolicy(wf);
+ String name = support.buildWorkflow(wf);
+ return new RunReference(name, getRunUriBuilder());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public RunReference submitWorkflowByURI(URI workflowURI)
+ throws NoCreateException {
+ checkCreatePolicy(workflowURI);
+ Workflow workflow;
+ try {
+ workflow = support.getWorkflowDocumentFromURI(workflowURI);
+ } catch (IOException e) {
+ throw new NoCreateException("could not read workflow", e);
+ }
+ String name = support.buildWorkflow(workflow);
+ return new RunReference(name, getRunUriBuilder());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public URI[] getServerWorkflows() {
+ return support.getPermittedWorkflowURIs();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String[] getServerListeners() {
+ List<String> types = support.getListenerTypes();
+ return types.toArray(new String[types.size()]);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String[] getServerNotifiers() {
+ List<String> dispatchers = notificationEngine
+ .listAvailableDispatchers();
+ return dispatchers.toArray(new String[dispatchers.size()]);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public List<Capability> getServerCapabilities() {
+ return support.getCapabilities();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void destroyRun(String runName) throws UnknownRunException,
+ NoUpdateException {
+ support.unregisterRun(runName, null);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunDescriptiveName(String runName)
+ throws UnknownRunException {
+ return support.getRun(runName).getName();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunDescriptiveName(String runName, String descriptiveName)
+ throws UnknownRunException, NoUpdateException {
+ TavernaRun run = support.getRun(runName);
+ support.permitUpdate(run);
+ run.setName(descriptiveName);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Workflow getRunWorkflow(String runName) throws UnknownRunException {
+ return support.getRun(runName).getWorkflow();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public WrappedWorkflow getRunWorkflowMTOM(String runName)
+ throws UnknownRunException {
+ WrappedWorkflow ww = new WrappedWorkflow();
+ ww.setWorkflow(support.getRun(runName).getWorkflow());
+ return ww;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public ProfileList getRunWorkflowProfiles(String runName)
+ throws UnknownRunException {
+ return support.getProfileDescriptor(support.getRun(runName)
+ .getWorkflow());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Date getRunExpiry(String runName) throws UnknownRunException {
+ return support.getRun(runName).getExpiry();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunExpiry(String runName, Date d)
+ throws UnknownRunException, NoUpdateException {
+ support.updateExpiry(support.getRun(runName), d);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Date getRunCreationTime(String runName) throws UnknownRunException {
+ return support.getRun(runName).getCreationTimestamp();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Date getRunFinishTime(String runName) throws UnknownRunException {
+ return support.getRun(runName).getFinishTimestamp();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Date getRunStartTime(String runName) throws UnknownRunException {
+ return support.getRun(runName).getStartTimestamp();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Status getRunStatus(String runName) throws UnknownRunException {
+ return support.getRun(runName).getStatus();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String setRunStatus(String runName, Status s)
+ throws UnknownRunException, NoUpdateException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ if (s == Status.Operating && w.getStatus() == Status.Initialized) {
+ if (!support.getAllowStartWorkflowRuns())
+ throw new OverloadedException();
+ try {
+ String issue = w.setStatus(s);
+ if (issue == null)
+ return "";
+ if (issue.isEmpty())
+ return "unknown reason for partial change";
+ return issue;
+ } catch (RuntimeException | NoUpdateException e) {
+ log.info("failed to start run " + runName, e);
+ throw e;
+ }
+ } else {
+ w.setStatus(s);
+ return "";
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunStdout(String runName) throws UnknownRunException {
+ try {
+ return support.getProperty(runName, "io", "stdout");
+ } catch (NoListenerException e) {
+ return "";
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunStderr(String runName) throws UnknownRunException {
+ try {
+ return support.getProperty(runName, "io", "stderr");
+ } catch (NoListenerException e) {
+ return "";
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public JobUsageRecord getRunUsageRecord(String runName)
+ throws UnknownRunException {
+ try {
+ String ur = support.getProperty(runName, "io", "usageRecord");
+ if (ur.isEmpty())
+ return null;
+ return JobUsageRecord.unmarshal(ur);
+ } catch (NoListenerException e) {
+ return null;
+ } catch (JAXBException e) {
+ log.info("failed to deserialize non-empty usage record", e);
+ return null;
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunLog(String runName) throws UnknownRunException {
+ try {
+ return support.getLogs(support.getRun(runName)).get("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ log.warn("unexpected encoding problem", e);
+ return "";
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public FileContents getRunBundle(String runName)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ File f = fileUtils.getFile(support.getRun(runName), PROV_BUNDLE);
+ FileContents fc = new FileContents();
+ // We *know* the content type, by definition
+ fc.setFile(f, "application/vnd.wf4ever.robundle+zip");
+ return fc;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public boolean getRunGenerateProvenance(String runName)
+ throws UnknownRunException {
+ return support.getRun(runName).getGenerateProvenance();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunGenerateProvenance(String runName, boolean generate)
+ throws UnknownRunException, NoUpdateException {
+ TavernaRun run = support.getRun(runName);
+ support.permitUpdate(run);
+ run.setGenerateProvenance(generate);
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // SOAP INTERFACE - Security
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunOwner(String runName) throws UnknownRunException {
+ return support.getRun(runName).getSecurityContext().getOwner()
+ .getName();
+ }
+
+ /**
+ * Look up a security context, applying access control rules for access to
+ * the parts of the context that are only open to the owner.
+ *
+ * @param runName
+ * The name of the workflow run.
+ * @param initialOnly
+ * Whether to check if we're in the initial state.
+ * @return The security context. Never <tt>null</tt>.
+ * @throws UnknownRunException
+ * @throws NotOwnerException
+ * @throws BadStateChangeException
+ */
+ private TavernaSecurityContext getRunSecurityContext(String runName,
+ boolean initialOnly) throws UnknownRunException, NotOwnerException,
+ BadStateChangeException {
+ TavernaRun run = support.getRun(runName);
+ TavernaSecurityContext c = run.getSecurityContext();
+ if (!c.getOwner().equals(support.getPrincipal()))
+ throw new NotOwnerException();
+ if (initialOnly && run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ return c;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Credential[] getRunCredentials(String runName)
+ throws UnknownRunException, NotOwnerException {
+ try {
+ return getRunSecurityContext(runName, false).getCredentials();
+ } catch (BadStateChangeException e) {
+ Error e2 = new Error("impossible");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ private Credential findCredential(TavernaSecurityContext c, String id)
+ throws NoCredentialException {
+ for (Credential t : c.getCredentials())
+ if (t.id.equals(id))
+ return t;
+ throw new NoCredentialException();
+ }
+
+ private Trust findTrust(TavernaSecurityContext c, String id)
+ throws NoCredentialException {
+ for (Trust t : c.getTrusted())
+ if (t.id.equals(id))
+ return t;
+ throw new NoCredentialException();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String setRunCredential(String runName, String credentialID,
+ Credential credential) throws UnknownRunException,
+ NotOwnerException, InvalidCredentialException,
+ NoCredentialException, BadStateChangeException {
+ TavernaSecurityContext c = getRunSecurityContext(runName, true);
+ if (credentialID == null || credentialID.isEmpty()) {
+ credential.id = randomUUID().toString();
+ } else {
+ credential.id = findCredential(c, credentialID).id;
+ }
+ URI uri = getRunUriBuilder().path("security/credentials/{credid}")
+ .build(runName, credential.id);
+ credential.href = uri.toString();
+ c.validateCredential(credential);
+ c.addCredential(credential);
+ return credential.id;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void deleteRunCredential(String runName, String credentialID)
+ throws UnknownRunException, NotOwnerException,
+ NoCredentialException, BadStateChangeException {
+ getRunSecurityContext(runName, true).deleteCredential(
+ new Credential.Dummy(credentialID));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Trust[] getRunCertificates(String runName)
+ throws UnknownRunException, NotOwnerException {
+ try {
+ return getRunSecurityContext(runName, false).getTrusted();
+ } catch (BadStateChangeException e) {
+ Error e2 = new Error("impossible");
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String setRunCertificates(String runName, String certificateID,
+ Trust certificate) throws UnknownRunException, NotOwnerException,
+ InvalidCredentialException, NoCredentialException,
+ BadStateChangeException {
+ TavernaSecurityContext c = getRunSecurityContext(runName, true);
+ if (certificateID == null || certificateID.isEmpty()) {
+ certificate.id = randomUUID().toString();
+ } else {
+ certificate.id = findTrust(c, certificateID).id;
+ }
+ URI uri = getRunUriBuilder().path("security/trusts/{certid}").build(
+ runName, certificate.id);
+ certificate.href = uri.toString();
+ c.validateTrusted(certificate);
+ c.addTrusted(certificate);
+ return certificate.id;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void deleteRunCertificates(String runName, String certificateID)
+ throws UnknownRunException, NotOwnerException,
+ NoCredentialException, BadStateChangeException {
+ TavernaSecurityContext c = getRunSecurityContext(runName, true);
+ Trust toDelete = new Trust();
+ toDelete.id = certificateID;
+ c.deleteTrusted(toDelete);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public PermissionList listRunPermissions(String runName)
+ throws UnknownRunException, NotOwnerException {
+ PermissionList pl = new PermissionList();
+ pl.permission = new ArrayList<>();
+ Map<String, Permission> perm;
+ try {
+ perm = support.getPermissionMap(getRunSecurityContext(runName,
+ false));
+ } catch (BadStateChangeException e) {
+ log.error("unexpected error from internal API", e);
+ perm = emptyMap();
+ }
+ List<String> users = new ArrayList<>(perm.keySet());
+ sort(users);
+ for (String user : users)
+ pl.permission.add(new PermissionList.SinglePermissionMapping(user,
+ perm.get(user)));
+ return pl;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunPermission(String runName, String userName,
+ Permission permission) throws UnknownRunException,
+ NotOwnerException {
+ try {
+ support.setPermission(getRunSecurityContext(runName, false),
+ userName, permission);
+ } catch (BadStateChangeException e) {
+ log.error("unexpected error from internal API", e);
+ }
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // SOAP INTERFACE - Filesystem connection
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public OutputDescription getRunOutputDescription(String runName)
+ throws UnknownRunException, BadStateChangeException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun run = support.getRun(runName);
+ if (run.getStatus() == Initialized)
+ throw new BadStateChangeException(
+ "may not get output description in initial state");
+ return cdBuilder.makeOutputDescriptor(run, null);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public DirEntry[] getRunDirectoryContents(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ List<DirEntry> result = new ArrayList<>();
+ for (DirectoryEntry e : fileUtils.getDirectory(support.getRun(runName),
+ convert(d)).getContents())
+ result.add(convert(newInstance(null, e)));
+ return result.toArray(new DirEntry[result.size()]);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public byte[] getRunDirectoryAsZip(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ try {
+ return toByteArray(fileUtils.getDirectory(support.getRun(runName),
+ convert(d)).getContentsAsZip());
+ } catch (IOException e) {
+ throw new FilesystemAccessException("problem serializing ZIP data",
+ e);
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public ZippedDirectory getRunDirectoryAsZipMTOM(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ return new ZippedDirectory(fileUtils.getDirectory(
+ support.getRun(runName), convert(d)));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public DirEntry makeRunDirectory(String runName, DirEntry parent,
+ String name) throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ Directory dir = fileUtils.getDirectory(w, convert(parent))
+ .makeSubdirectory(support.getPrincipal(), name);
+ return convert(newInstance(null, dir));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public DirEntry makeRunFile(String runName, DirEntry parent, String name)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ File f = fileUtils.getDirectory(w, convert(parent)).makeEmptyFile(
+ support.getPrincipal(), name);
+ return convert(newInstance(null, f));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void destroyRunDirectoryEntry(String runName, DirEntry d)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ fileUtils.getDirEntry(w, convert(d)).destroy();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public byte[] getRunFileContents(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ File f = fileUtils.getFile(support.getRun(runName), convert(d));
+ return f.getContents(0, -1);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunFileContents(String runName, DirEntry d,
+ byte[] newContents) throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ fileUtils.getFile(w, convert(d)).setContents(newContents);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public FileContents getRunFileContentsMTOM(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ File f = fileUtils.getFile(support.getRun(runName), convert(d));
+ FileContents fc = new FileContents();
+ fc.setFile(f, support.getEstimatedContentType(f));
+ return fc;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunFileContentsFromURI(String runName,
+ DirEntryReference file, URI reference)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun run = support.getRun(runName);
+ support.permitUpdate(run);
+ File f = fileUtils.getFile(run, file);
+ try {
+ support.copyDataToFile(reference, f);
+ } catch (IOException e) {
+ throw new FilesystemAccessException(
+ "problem transferring data from URI", e);
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunFileContentsMTOM(String runName, FileContents newContents)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ TavernaRun run = support.getRun(runName);
+ support.permitUpdate(run);
+ File f = fileUtils.getFile(run, newContents.name);
+ f.setContents(new byte[0]);
+ support.copyDataToFile(newContents.fileData, f);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunFileType(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ return support.getEstimatedContentType(fileUtils.getFile(
+ support.getRun(runName), convert(d)));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public long getRunFileLength(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ return fileUtils.getFile(support.getRun(runName), convert(d)).getSize();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Date getRunFileModified(String runName, DirEntry d)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ return fileUtils.getFile(support.getRun(runName), convert(d))
+ .getModificationDate();
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // SOAP INTERFACE - Run listeners
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String[] getRunListeners(String runName) throws UnknownRunException {
+ TavernaRun w = support.getRun(runName);
+ List<String> result = new ArrayList<>();
+ for (Listener l : w.getListeners())
+ result.add(l.getName());
+ return result.toArray(new String[result.size()]);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String addRunListener(String runName, String listenerType,
+ String configuration) throws UnknownRunException,
+ NoUpdateException, NoListenerException {
+ return support.makeListener(support.getRun(runName), listenerType,
+ configuration).getName();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunListenerConfiguration(String runName,
+ String listenerName) throws UnknownRunException,
+ NoListenerException {
+ return support.getListener(runName, listenerName).getConfiguration();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String[] getRunListenerProperties(String runName, String listenerName)
+ throws UnknownRunException, NoListenerException {
+ return support.getListener(runName, listenerName).listProperties()
+ .clone();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunListenerProperty(String runName, String listenerName,
+ String propName) throws UnknownRunException, NoListenerException {
+ return support.getListener(runName, listenerName).getProperty(propName);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunListenerProperty(String runName, String listenerName,
+ String propName, String value) throws UnknownRunException,
+ NoUpdateException, NoListenerException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ Listener l = support.getListener(w, listenerName);
+ try {
+ l.getProperty(propName); // sanity check!
+ l.setProperty(propName, value);
+ } catch (RuntimeException e) {
+ throw new NoListenerException("problem setting property: "
+ + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public InputDescription getRunInputs(String runName)
+ throws UnknownRunException {
+ return new InputDescription(support.getRun(runName));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getRunOutputBaclavaFile(String runName)
+ throws UnknownRunException {
+ return support.getRun(runName).getOutputBaclavaFile();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunInputBaclavaFile(String runName, String fileName)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, BadStateChangeException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ w.setInputBaclavaFile(fileName);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunInputPortFile(String runName, String portName,
+ String portFilename) throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, BadStateChangeException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ Input i = support.getInput(w, portName);
+ if (i == null)
+ i = w.makeInput(portName);
+ i.setFile(portFilename);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunInputPortValue(String runName, String portName,
+ String portValue) throws UnknownRunException, NoUpdateException,
+ BadStateChangeException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ Input i = support.getInput(w, portName);
+ if (i == null)
+ i = w.makeInput(portName);
+ i.setValue(portValue);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunInputPortListDelimiter(String runName, String portName,
+ String delimiter) throws UnknownRunException, NoUpdateException,
+ BadStateChangeException, BadPropertyValueException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ Input i = support.getInput(w, portName);
+ if (i == null)
+ i = w.makeInput(portName);
+ if (delimiter != null && delimiter.isEmpty())
+ delimiter = null;
+ if (delimiter != null) {
+ if (delimiter.length() > 1)
+ throw new BadPropertyValueException("delimiter too long");
+ if (delimiter.charAt(0) < 1 || delimiter.charAt(0) > 127)
+ throw new BadPropertyValueException(
+ "delimiter character must be non-NUL ASCII");
+ }
+ i.setDelimiter(delimiter);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public void setRunOutputBaclavaFile(String runName, String outputFile)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, BadStateChangeException {
+ TavernaRun w = support.getRun(runName);
+ support.permitUpdate(w);
+ w.setOutputBaclavaFile(outputFile);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public org.taverna.server.port_description.InputDescription getRunInputDescriptor(
+ String runName) throws UnknownRunException {
+ return cdBuilder.makeInputDescriptor(support.getRun(runName), null);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getServerStatus() {
+ return support.getAllowNewWorkflowRuns() ? "operational" : "suspended";
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ // SUPPORT METHODS
+
+ @Override
+ public boolean initObsoleteSOAPSecurity(TavernaSecurityContext c) {
+ try {
+ javax.xml.ws.handler.MessageContext msgCtxt = (jaxws == null ? null
+ : jaxws.getMessageContext());
+ if (msgCtxt == null)
+ return true;
+ c.initializeSecurityFromSOAPContext(msgCtxt);
+ return false;
+ } catch (IllegalStateException e) {
+ /* ignore; not much we can do */
+ return true;
+ }
+ }
+
+ @Override
+ public boolean initObsoleteRESTSecurity(TavernaSecurityContext c) {
+ if (jaxrsHeaders == null)
+ return true;
+ c.initializeSecurityFromRESTContext(jaxrsHeaders);
+ return false;
+ }
+
+ /**
+ * A creator of substitute {@link URI} builders.
+ *
+ * @return A URI builder configured so that it takes a path parameter that
+ * corresponds to the run ID (but with no such ID applied).
+ */
+ UriBuilder getRunUriBuilder() {
+ return getBaseUriBuilder().path("runs/{uuid}");
+ }
+
+ @Override
+ public UriBuilder getRunUriBuilder(TavernaRun run) {
+ return fromUri(getRunUriBuilder().build(run.getId()));
+ }
+
+ private final String DEFAULT_HOST = "localhost:8080"; // Crappy default
+
+ private String getHostLocation() {
+ @java.lang.SuppressWarnings("unchecked")
+ Map<String, List<String>> headers = (Map<String, List<String>>) jaxws
+ .getMessageContext().get(HTTP_REQUEST_HEADERS);
+ if (headers != null) {
+ List<String> host = headers.get("HOST");
+ if (host != null && !host.isEmpty())
+ return host.get(0);
+ }
+ return DEFAULT_HOST;
+ }
+
+ @Nonnull
+ private URI getPossiblyInsecureBaseUri() {
+ // See if JAX-RS can supply the info
+ UriInfo ui = getUriInfo();
+ if (ui != null && ui.getBaseUri() != null)
+ return ui.getBaseUri();
+ // See if JAX-WS *cannot* supply the info
+ if (jaxws == null || jaxws.getMessageContext() == null)
+ // Hack to make the test suite work
+ return URI.create("http://" + DEFAULT_HOST
+ + "/taverna-server/rest/");
+ String pathInfo = (String) jaxws.getMessageContext().get(PATH_INFO);
+ pathInfo = pathInfo.replaceFirst("/soap$", "/rest/");
+ pathInfo = pathInfo.replaceFirst("/rest/.+$", "/rest/");
+ return URI.create("http://" + getHostLocation() + pathInfo);
+ }
+
+ @Override
+ public UriBuilder getBaseUriBuilder() {
+ return secure(fromUri(getPossiblyInsecureBaseUri()));
+ }
+
+ @Override
+ @Nullable
+ public String resolve(@Nullable String uri) {
+ if (uri == null)
+ return null;
+ return secure(getPossiblyInsecureBaseUri(), uri).toString();
+ }
+
+ private Map<String, TavernaRun> runs() {
+ return runStore.listRuns(support.getPrincipal(), policy);
+ }
+}
+
+/**
+ * RESTful interface to the policies of a Taverna Server installation.
+ *
+ * @author Donal Fellows
+ */
+class PolicyREST implements PolicyView, SupportAware {
+ private TavernaServerSupport support;
+ private Policy policy;
+ private ListenerFactory listenerFactory;
+ private NotificationEngine notificationEngine;
+
+ @Override
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Required
+ public void setPolicy(Policy policy) {
+ this.policy = policy;
+ }
+
+ @Required
+ public void setListenerFactory(ListenerFactory listenerFactory) {
+ this.listenerFactory = listenerFactory;
+ }
+
+ @Required
+ public void setNotificationEngine(NotificationEngine notificationEngine) {
+ this.notificationEngine = notificationEngine;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public PolicyDescription getDescription(UriInfo ui) {
+ return new PolicyDescription(ui);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public int getMaxSimultaneousRuns() {
+ Integer limit = policy.getMaxRuns(support.getPrincipal());
+ if (limit == null)
+ return policy.getMaxRuns();
+ return min(limit.intValue(), policy.getMaxRuns());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public PermittedListeners getPermittedListeners() {
+ return new PermittedListeners(
+ listenerFactory.getSupportedListenerTypes());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public PermittedWorkflows getPermittedWorkflows() {
+ return new PermittedWorkflows(policy.listPermittedWorkflowURIs(support
+ .getPrincipal()));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public EnabledNotificationFabrics getEnabledNotifiers() {
+ return new EnabledNotificationFabrics(
+ notificationEngine.listAvailableDispatchers());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public int getMaxOperatingRuns() {
+ return policy.getOperatingLimit();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public CapabilityList getCapabilities() {
+ CapabilityList cl = new CapabilityList();
+ cl.capability.addAll(support.getCapabilities());
+ return cl;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java
new file mode 100644
index 0000000..ce36bd3
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/TavernaServerSupport.java
@@ -0,0 +1,957 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static eu.medsea.util.MimeUtil.UNKNOWN_MIME_TYPE;
+import static eu.medsea.util.MimeUtil.getExtensionMimeTypes;
+import static eu.medsea.util.MimeUtil.getMimeType;
+import static java.lang.Math.min;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.springframework.jmx.support.MetricType.COUNTER;
+import static org.springframework.jmx.support.MetricType.GAUGE;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+import static org.taverna.server.master.common.Roles.ADMIN;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.activation.DataHandler;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.PreDestroy;
+import javax.ws.rs.WebApplicationException;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedMetric;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.taverna.server.master.api.ManagementModel;
+import org.taverna.server.master.api.TavernaServerBean;
+import org.taverna.server.master.common.Capability;
+import org.taverna.server.master.common.Permission;
+import org.taverna.server.master.common.ProfileList;
+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.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoDestroyException;
+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.UnknownRunException;
+import org.taverna.server.master.factories.ListenerFactory;
+import org.taverna.server.master.factories.RunFactory;
+import org.taverna.server.master.identity.WorkflowInternalAuthProvider.WorkflowSelfAuthority;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.Input;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.LocalIdentityMapper;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.RunStore;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.rest.handler.T2FlowDocumentHandler;
+import org.taverna.server.master.utils.CapabilityLister;
+import org.taverna.server.master.utils.FilenameUtils;
+import org.taverna.server.master.utils.InvocationCounter;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+import uk.org.taverna.scufl2.api.profiles.Profile;
+
+/**
+ * Web application support utilities.
+ *
+ * @author Donal Fellows
+ */
+@ManagedResource(objectName = JMX_ROOT + "Webapp", description = "The main Taverna Server "
+ + Version.JAVA + " web-application interface.")
+public class TavernaServerSupport {
+ /** The main webapp log. */
+ private Log log = getLog("Taverna.Server.Webapp");
+ private Log accessLog = getLog("Taverna.Server.Webapp.Access");;
+ /** Bean used to log counts of external calls. */
+ private InvocationCounter counter;
+ /** A storage facility for workflow runs. */
+ private RunStore runStore;
+ /** Encapsulates the policies applied by this server. */
+ private Policy policy;
+ /** Connection to the persistent state of this service. */
+ private ManagementModel stateModel;
+ /** A factory for event listeners to attach to workflow runs. */
+ private ListenerFactory listenerFactory;
+ /** A factory for workflow runs. */
+ private RunFactory runFactory;
+ /** How to map the user ID to who to run as. */
+ private LocalIdentityMapper idMapper;
+ /** The code that is coupled to CXF. */
+ private TavernaServerBean webapp;
+ /** How to handle files. */
+ private FilenameUtils fileUtils;
+ /** How to get the server capabilities. */
+ private CapabilityLister capabilitySource;
+ /**
+ * Whether to log failures during principal retrieval. Should be normally on
+ * as it indicates a serious problem, but can be switched off for testing.
+ */
+ private boolean logGetPrincipalFailures = true;
+ private Map<String, String> contentTypeMap;
+ /** Number of bytes to read when guessing the MIME type. */
+ private static final int SAMPLE_SIZE = 1024;
+ /** Number of bytes to ask for when copying a stream to a file. */
+ private static final int TRANSFER_SIZE = 32768;
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ /**
+ * @return Count of the number of external calls into this webapp.
+ */
+ @ManagedMetric(description = "Count of the number of external calls into this webapp.", metricType = COUNTER, category = "throughput")
+ public int getInvocationCount() {
+ return counter.getCount();
+ }
+
+ /**
+ * @return Current number of runs.
+ */
+ @ManagedMetric(description = "Current number of runs.", metricType = GAUGE, category = "utilization")
+ public int getCurrentRunCount() {
+ return runStore.listRuns(null, policy).size();
+ }
+
+ /**
+ * @return Whether to write submitted workflows to the log.
+ */
+ @ManagedAttribute(description = "Whether to write submitted workflows to the log.")
+ public boolean getLogIncomingWorkflows() {
+ return stateModel.getLogIncomingWorkflows();
+ }
+
+ /**
+ * @param logIncomingWorkflows
+ * Whether to write submitted workflows to the log.
+ */
+ @ManagedAttribute(description = "Whether to write submitted workflows to the log.")
+ public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
+ stateModel.setLogIncomingWorkflows(logIncomingWorkflows);
+ }
+
+ /**
+ * @return Whether outgoing exceptions should be logged before being
+ * converted to responses.
+ */
+ @ManagedAttribute(description = "Whether outgoing exceptions should be logged before being converted to responses.")
+ public boolean getLogOutgoingExceptions() {
+ return stateModel.getLogOutgoingExceptions();
+ }
+
+ /**
+ * @param logOutgoing
+ * Whether outgoing exceptions should be logged before being
+ * converted to responses.
+ */
+ @ManagedAttribute(description = "Whether outgoing exceptions should be logged before being converted to responses.")
+ public void setLogOutgoingExceptions(boolean logOutgoing) {
+ stateModel.setLogOutgoingExceptions(logOutgoing);
+ }
+
+ /**
+ * @return Whether to permit any new workflow runs to be created.
+ */
+ @ManagedAttribute(description = "Whether to permit any new workflow runs to be created; has no effect on existing runs.")
+ public boolean getAllowNewWorkflowRuns() {
+ return stateModel.getAllowNewWorkflowRuns();
+ }
+
+ /**
+ * @param allowNewWorkflowRuns
+ * Whether to permit any new workflow runs to be created.
+ */
+ @ManagedAttribute(description = "Whether to permit any new workflow runs to be created; has no effect on existing runs.")
+ public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
+ stateModel.setAllowNewWorkflowRuns(allowNewWorkflowRuns);
+ }
+
+ /**
+ * @return The server's version identifier.
+ */
+ @ManagedAttribute(description = "The installed version of the server.")
+ public String getServerVersion() {
+ return VersionedElement.VERSION + " " + VersionedElement.REVISION + " "
+ + VersionedElement.TIMESTAMP;
+ }
+
+ @ManagedAttribute(description = "The URIs of the workfows that this server will allow to be instantiated.")
+ public URI[] getPermittedWorkflowURIs() {
+ List<URI> pw = policy.listPermittedWorkflowURIs(null);
+ if (pw == null)
+ return new URI[0];
+ return pw.toArray(new URI[pw.size()]);
+ }
+
+ @ManagedAttribute(description = "The URIs of the workfows that this server will allow to be instantiated.")
+ public void setPermittedWorkflowURIs(URI[] pw) {
+ if (pw == null)
+ policy.setPermittedWorkflowURIs(null, new ArrayList<URI>());
+ else
+ policy.setPermittedWorkflowURIs(null, Arrays.asList(pw));
+ }
+
+ public int getMaxSimultaneousRuns() {
+ Integer limit = policy.getMaxRuns(getPrincipal());
+ if (limit == null)
+ return policy.getMaxRuns();
+ return min(limit.intValue(), policy.getMaxRuns());
+ }
+
+ @Autowired
+ private T2FlowDocumentHandler t2flowHandler;
+
+ public Workflow getWorkflowDocumentFromURI(URI uri)
+ throws WebApplicationException, IOException {
+ URLConnection conn = uri.toURL().openConnection();
+ conn.setRequestProperty("Accept", T2FLOW);
+ conn.connect();
+ // Tricky point: we know the reader part of the handler only cares
+ // about the stream argument.
+ return t2flowHandler.readFrom(null, null, null, null, null,
+ conn.getInputStream());
+ }
+
+ public List<String> getListenerTypes() {
+ return listenerFactory.getSupportedListenerTypes();
+ }
+
+ /**
+ * @param policy
+ * The policy being installed by Spring.
+ */
+ @Required
+ public void setPolicy(Policy policy) {
+ this.policy = policy;
+ }
+
+ /**
+ * @param listenerFactory
+ * The listener factory being installed by Spring.
+ */
+ @Required
+ public void setListenerFactory(ListenerFactory listenerFactory) {
+ this.listenerFactory = listenerFactory;
+ }
+
+ /**
+ * @param runFactory
+ * The run factory being installed by Spring.
+ */
+ @Required
+ public void setRunFactory(RunFactory runFactory) {
+ this.runFactory = runFactory;
+ }
+
+ /**
+ * @param runStore
+ * The run store being installed by Spring.
+ */
+ @Required
+ public void setRunStore(RunStore runStore) {
+ this.runStore = runStore;
+ }
+
+ /**
+ * @param stateModel
+ * The state model engine being installed by Spring.
+ */
+ @Required
+ public void setStateModel(ManagementModel stateModel) {
+ this.stateModel = stateModel;
+ }
+
+ /**
+ * @param mapper
+ * The identity mapper being installed by Spring.
+ */
+ @Required
+ public void setIdMapper(LocalIdentityMapper mapper) {
+ this.idMapper = mapper;
+ }
+
+ /**
+ * @param counter
+ * The object whose job it is to manage the counting of
+ * invocations. Installed by Spring.
+ */
+ @Required
+ public void setInvocationCounter(InvocationCounter counter) {
+ this.counter = counter;
+ }
+
+ /**
+ * @param webapp
+ * The web-app being installed by Spring.
+ */
+ @Required
+ public void setWebapp(TavernaServerBean webapp) {
+ this.webapp = webapp;
+ }
+
+ /**
+ * @param fileUtils
+ * The file handling utilities.
+ */
+ @Required
+ public void setFileUtils(FilenameUtils fileUtils) {
+ this.fileUtils = fileUtils;
+ }
+
+ /**
+ * @param logthem
+ * Whether to log failures relating to principals.
+ */
+ public void setLogGetPrincipalFailures(boolean logthem) {
+ logGetPrincipalFailures = logthem;
+ }
+
+ public Map<String, String> getContentTypeMap() {
+ return contentTypeMap;
+ }
+
+ /**
+ * Mapping from filename suffixes (e.g., "baclava") to content types.
+ *
+ * @param contentTypeMap
+ * The mapping to install.
+ */
+ @Required
+ public void setContentTypeMap(Map<String, String> contentTypeMap) {
+ this.contentTypeMap = contentTypeMap;
+ }
+
+ @Required
+ public void setCapabilitySource(CapabilityLister capabilitySource) {
+ this.capabilitySource = capabilitySource;
+ }
+
+ /**
+ * Test whether the current user can do updates to the given run.
+ *
+ * @param run
+ * The workflow run to do the test on.
+ * @throws NoUpdateException
+ * If the current user is not permitted to update the run.
+ */
+ public void permitUpdate(@Nonnull TavernaRun run) throws NoUpdateException {
+ if (isSuperUser()) {
+ accessLog
+ .warn("check for admin powers passed; elevated access rights granted for update");
+ return; // Superusers are fully authorized to access others things
+ }
+ if (getSelfAuthority() != null) {
+ // At this point, must already be accessing self as that is checked
+ // in getRun().
+ return;
+ }
+ policy.permitUpdate(getPrincipal(), run);
+ }
+
+ /**
+ * Test whether the current user can destroy or control the lifespan of the
+ * given run.
+ *
+ * @param run
+ * The workflow run to do the test on.
+ * @throws NoDestroyException
+ * If the current user is not permitted to destroy the run.
+ */
+ public void permitDestroy(TavernaRun run) throws NoDestroyException {
+ if (isSuperUser()) {
+ accessLog
+ .warn("check for admin powers passed; elevated access rights granted for destroy");
+ return; // Superusers are fully authorized to access others things
+ }
+ if (getSelfAuthority() != null)
+ throw new NoDestroyException();
+ policy.permitDestroy(getPrincipal(), run);
+ }
+
+ /**
+ * Gets the identity of the user currently accessing the webapp, which is
+ * stored in a thread-safe way in the webapp's container's context.
+ *
+ * @return The identity of the user accessing the webapp.
+ */
+ @Nonnull
+ public UsernamePrincipal getPrincipal() {
+ try {
+ Authentication auth = SecurityContextHolder.getContext()
+ .getAuthentication();
+ if (auth == null || !auth.isAuthenticated()) {
+ if (logGetPrincipalFailures)
+ log.warn("failed to get auth; going with <NOBODY>");
+ return new UsernamePrincipal("<NOBODY>");
+ }
+ return new UsernamePrincipal(auth);
+ } catch (RuntimeException e) {
+ if (logGetPrincipalFailures)
+ log.info("failed to map principal", e);
+ throw e;
+ }
+ }
+
+ private WorkflowSelfAuthority getSelfAuthority() {
+ try {
+ Authentication a = SecurityContextHolder.getContext()
+ .getAuthentication();
+ for (GrantedAuthority ga : a.getAuthorities())
+ if (ga instanceof WorkflowSelfAuthority)
+ return (WorkflowSelfAuthority) ga;
+ } catch (RuntimeException e) {
+ }
+ return null;
+ }
+
+ /**
+ * Obtain the workflow run with a particular name.
+ *
+ * @param name
+ * The name of the run to look up.
+ * @return A workflow run handle that the current user has at least
+ * permission to read.
+ * @throws UnknownRunException
+ * If the workflow run doesn't exist or the current user doesn't
+ * have permission to see it.
+ */
+ @Nonnull
+ public TavernaRun getRun(@Nonnull String name) throws UnknownRunException {
+ if (isSuperUser()) {
+ accessLog
+ .info("check for admin powers passed; elevated access rights granted for read");
+ return runStore.getRun(name);
+ }
+ WorkflowSelfAuthority wsa = getSelfAuthority();
+ if (wsa != null) {
+ if (wsa.getWorkflowID().equals(name))
+ return runStore.getRun(name);
+ throw new UnknownRunException();
+ }
+ return runStore.getRun(getPrincipal(), policy, name);
+ }
+
+ /**
+ * Construct a listener attached to the given run.
+ *
+ * @param run
+ * The workflow run to attach the listener to.
+ * @param type
+ * The name of the type of run to create.
+ * @param configuration
+ * The configuration description to pass into the listener. The
+ * format of this string is up to the listener to define.
+ * @return A handle to the listener which can be used to further configure
+ * any properties.
+ * @throws NoListenerException
+ * If the listener type is unrecognized or the configuration is
+ * invalid.
+ * @throws NoUpdateException
+ * If the run does not permit the current user to add listeners
+ * (or perform other types of update).
+ */
+ @Nonnull
+ public Listener makeListener(@Nonnull TavernaRun run, @Nonnull String type,
+ @Nonnull String configuration) throws NoListenerException,
+ NoUpdateException {
+ permitUpdate(run);
+ return listenerFactory.makeListener(run, type, configuration);
+ }
+
+ /**
+ * Obtain a listener that is already attached to a workflow run.
+ *
+ * @param run
+ * The workflow run to search.
+ * @param listenerName
+ * The name of the listener to look up.
+ * @return The listener instance interface.
+ * @throws NoListenerException
+ * If no listener with that name exists.
+ */
+ @Nonnull
+ public Listener getListener(TavernaRun run, String listenerName)
+ throws NoListenerException {
+ for (Listener l : run.getListeners())
+ if (l.getName().equals(listenerName))
+ return l;
+ throw new NoListenerException();
+ }
+
+ /**
+ * Obtain a property from a listener that is already attached to a workflow
+ * run.
+ *
+ * @param runName
+ * The ID of the workflow run to search.
+ * @param listenerName
+ * The name of the listener to look up in.
+ * @param propertyName
+ * The name of the property to fetch.
+ * @return The property value.
+ * @throws NoListenerException
+ * If no listener with that name exists, or no property with
+ * that name exists.
+ * @throws UnknownRunException
+ * If no run with that name exists.
+ */
+ @Nonnull
+ public String getProperty(String runName, String listenerName,
+ String propertyName) throws NoListenerException,
+ UnknownRunException {
+ return getListener(runName, listenerName).getProperty(propertyName);
+ }
+
+ /**
+ * Obtain a property from a listener that is already attached to a workflow
+ * run.
+ *
+ * @param run
+ * The workflow run to search.
+ * @param listenerName
+ * The name of the listener to look up in.
+ * @param propertyName
+ * The name of the property to fetch.
+ * @return The property value.
+ * @throws NoListenerException
+ * If no listener with that name exists, or no property with
+ * that name exists.
+ */
+ @Nonnull
+ public String getProperty(TavernaRun run, String listenerName,
+ String propertyName) throws NoListenerException {
+ return getListener(run, listenerName).getProperty(propertyName);
+ }
+
+ /**
+ * Get the permission description for the given user.
+ *
+ * @param context
+ * A security context associated with a particular workflow run.
+ * Note that only the owner of a workflow run may get the
+ * security context in the first place.
+ * @param userName
+ * The name of the user to look up the permission for.
+ * @return A permission description.
+ */
+ @Nonnull
+ public Permission getPermission(@Nonnull TavernaSecurityContext context,
+ @Nonnull String userName) {
+ if (context.getPermittedDestroyers().contains(userName))
+ return Permission.Destroy;
+ if (context.getPermittedUpdaters().contains(userName))
+ return Permission.Update;
+ if (context.getPermittedReaders().contains(userName))
+ return Permission.Read;
+ return Permission.None;
+ }
+
+ /**
+ * Set the permissions for the given user.
+ *
+ * @param context
+ * A security context associated with a particular workflow run.
+ * Note that only the owner of a workflow run may get the
+ * security context in the first place.
+ * @param userName
+ * The name of the user to set the permission for.
+ * @param permission
+ * The description of the permission to grant. Note that the
+ * owner of a workflow run always has the equivalent of
+ * {@link Permission#Destroy}; this is always enforced before
+ * checking for other permissions.
+ */
+ public void setPermission(TavernaSecurityContext context, String userName,
+ Permission permission) {
+ Set<String> permSet;
+ boolean doRead = false, doWrite = false, doKill = false;
+
+ switch (permission) {
+ case Destroy:
+ doKill = true;
+ case Update:
+ doWrite = true;
+ case Read:
+ doRead = true;
+ default:
+ break;
+ }
+
+ permSet = context.getPermittedReaders();
+ if (doRead) {
+ if (!permSet.contains(userName)) {
+ permSet = new HashSet<>(permSet);
+ permSet.add(userName);
+ context.setPermittedReaders(permSet);
+ }
+ } else if (permSet.contains(userName)) {
+ permSet = new HashSet<>(permSet);
+ permSet.remove(userName);
+ context.setPermittedReaders(permSet);
+ }
+
+ permSet = context.getPermittedUpdaters();
+ if (doWrite) {
+ if (!permSet.contains(userName)) {
+ permSet = new HashSet<>(permSet);
+ permSet.add(userName);
+ context.setPermittedUpdaters(permSet);
+ }
+ } else if (permSet.contains(userName)) {
+ permSet = new HashSet<>(permSet);
+ permSet.remove(userName);
+ context.setPermittedUpdaters(permSet);
+ }
+
+ permSet = context.getPermittedDestroyers();
+ if (doKill) {
+ if (!permSet.contains(userName)) {
+ permSet = new HashSet<>(permSet);
+ permSet.add(userName);
+ context.setPermittedDestroyers(permSet);
+ }
+ } else if (permSet.contains(userName)) {
+ permSet = new HashSet<>(permSet);
+ permSet.remove(userName);
+ context.setPermittedDestroyers(permSet);
+ }
+ }
+
+ public Map<String, Permission> getPermissionMap(
+ TavernaSecurityContext context) {
+ Map<String, Permission> perm = new HashMap<>();
+ for (String u : context.getPermittedReaders())
+ perm.put(u, Permission.Read);
+ for (String u : context.getPermittedUpdaters())
+ perm.put(u, Permission.Update);
+ for (String u : context.getPermittedDestroyers())
+ perm.put(u, Permission.Destroy);
+ return perm;
+ }
+
+ /**
+ * Stops a run from being possible to be looked up and destroys it.
+ *
+ * @param runName
+ * The name of the run.
+ * @param run
+ * The workflow run. <i>Must</i> correspond to the name.
+ * @throws NoDestroyException
+ * If the user is not permitted to destroy the workflow run.
+ * @throws UnknownRunException
+ * If the run is unknown (e.g., because it is already
+ * destroyed).
+ */
+ public void unregisterRun(@Nonnull String runName, @Nonnull TavernaRun run)
+ throws NoDestroyException, UnknownRunException {
+ if (run == null)
+ run = getRun(runName);
+ permitDestroy(run);
+ runStore.unregisterRun(runName);
+ run.destroy();
+ }
+
+ /**
+ * Changes the expiry date of a workflow run. The expiry date is when the
+ * workflow run becomes eligible for automated destruction.
+ *
+ * @param run
+ * The handle to the workflow run.
+ * @param date
+ * When the workflow run should be expired.
+ * @return When the workflow run will actually be expired.
+ * @throws NoDestroyException
+ * If the user is not permitted to destroy the workflow run.
+ * (Note that lifespan management requires the ability to
+ * destroy.)
+ */
+ @Nonnull
+ public Date updateExpiry(@Nonnull TavernaRun run, @Nonnull Date date)
+ throws NoDestroyException {
+ permitDestroy(run);
+ run.setExpiry(date);
+ return run.getExpiry();
+ }
+
+ /**
+ * Manufacture a workflow run instance.
+ *
+ * @param workflow
+ * The workflow document (t2flow, scufl2?) to instantiate.
+ * @return The ID of the created workflow run.
+ * @throws NoCreateException
+ * If the user is not permitted to create workflows.
+ */
+ public String buildWorkflow(Workflow workflow) throws NoCreateException {
+ UsernamePrincipal p = getPrincipal();
+ if (getSelfAuthority() != null)
+ throw new NoCreateException(
+ "runs may not create workflows on their host server");
+ if (!stateModel.getAllowNewWorkflowRuns())
+ throw new NoCreateException("run creation not currently enabled");
+ try {
+ if (stateModel.getLogIncomingWorkflows()) {
+ log.info(workflow.marshal());
+ }
+ } catch (JAXBException e) {
+ log.warn("problem when logging workflow", e);
+ }
+
+ // Security checks
+ policy.permitCreate(p, workflow);
+ if (idMapper != null && idMapper.getUsernameForPrincipal(p) == null) {
+ log.error("cannot map principal to local user id");
+ throw new NoCreateException(
+ "failed to map security token to local user id");
+ }
+
+ TavernaRun run;
+ try {
+ run = runFactory.create(p, workflow);
+ TavernaSecurityContext c = run.getSecurityContext();
+ c.initializeSecurityFromContext(SecurityContextHolder.getContext());
+ /*
+ * These next pieces of security initialisation are (hopefully)
+ * obsolete now that we use Spring Security, but we keep them Just
+ * In Case.
+ */
+ boolean doRESTinit = webapp.initObsoleteSOAPSecurity(c);
+ if (doRESTinit)
+ webapp.initObsoleteRESTSecurity(c);
+ } catch (Exception e) {
+ log.error("failed to build workflow run worker", e);
+ throw new NoCreateException("failed to build workflow run worker");
+ }
+
+ return runStore.registerRun(run);
+ }
+
+ private boolean isSuperUser() {
+ try {
+ Authentication auth = SecurityContextHolder.getContext()
+ .getAuthentication();
+ if (auth == null || !auth.isAuthenticated())
+ return false;
+ UserDetails details = (UserDetails) auth.getPrincipal();
+ if (log.isDebugEnabled())
+ log.debug("checking for admin role for user <" + auth.getName()
+ + "> in collection " + details.getAuthorities());
+ return details.getAuthorities().contains(ADMIN);
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Get a particular input to a workflow run.
+ *
+ * @param run
+ * The workflow run to search.
+ * @param portName
+ * The name of the input.
+ * @return The handle of the input, or <tt>null</tt> if no such handle
+ * exists.
+ */
+ @Nullable
+ public Input getInput(TavernaRun run, String portName) {
+ for (Input i : run.getInputs())
+ if (i.getName().equals(portName))
+ return i;
+ return null;
+ }
+
+ /**
+ * Get a listener attached to a run.
+ *
+ * @param runName
+ * The name of the run to look up
+ * @param listenerName
+ * The name of the listener.
+ * @return The handle of the listener.
+ * @throws NoListenerException
+ * If no such listener exists.
+ * @throws UnknownRunException
+ * If no such workflow run exists, or if the user does not have
+ * permission to access it.
+ */
+ public Listener getListener(String runName, String listenerName)
+ throws NoListenerException, UnknownRunException {
+ return getListener(getRun(runName), listenerName);
+ }
+
+ /**
+ * Given a file, produce a guess at its content type. This uses the content
+ * type map property, and if that search fails it falls back on the Medsea
+ * mime type library.
+ *
+ * @param f
+ * The file handle.
+ * @return The content type. If all else fails, produces good old
+ * "application/octet-stream".
+ */
+ @Nonnull
+ public String getEstimatedContentType(@Nonnull File f) {
+ String name = f.getName();
+ for (int idx = name.indexOf('.'); idx != -1; idx = name.indexOf('.',
+ idx + 1)) {
+ String mt = contentTypeMap.get(name.substring(idx + 1));
+ if (mt != null)
+ return mt;
+ }
+ @Nonnull
+ String type = getExtensionMimeTypes(name);
+ if (!type.equals(UNKNOWN_MIME_TYPE))
+ return type;
+ try {
+ return getMimeType(new ByteArrayInputStream(f.getContents(0,
+ SAMPLE_SIZE)));
+ } catch (FilesystemAccessException e) {
+ return type;
+ }
+ }
+
+ public void copyDataToFile(DataHandler handler, File file)
+ throws FilesystemAccessException {
+ try {
+ copyStreamToFile(handler.getInputStream(), file);
+ } catch (IOException e) {
+ throw new FilesystemAccessException(
+ "problem constructing stream from data source", e);
+ }
+ }
+
+ public void copyDataToFile(URI uri, File file)
+ throws MalformedURLException, FilesystemAccessException,
+ IOException {
+ copyStreamToFile(uri.toURL().openStream(), file);
+ }
+
+ public void copyStreamToFile(InputStream stream, File file)
+ throws FilesystemAccessException {
+ String name = file.getFullName();
+ long total = 0;
+ try {
+ byte[] buffer = new byte[TRANSFER_SIZE];
+ boolean first = true;
+ while (true) {
+ int len = stream.read(buffer);
+ if (len < 0)
+ break;
+ total += len;
+ if (log.isDebugEnabled())
+ log.debug("read " + len
+ + " bytes from source stream (total: " + total
+ + ") bound for " + name);
+ if (len == buffer.length) {
+ if (first)
+ file.setContents(buffer);
+ else
+ file.appendContents(buffer);
+ } else {
+ byte[] newBuf = new byte[len];
+ System.arraycopy(buffer, 0, newBuf, 0, len);
+ if (first)
+ file.setContents(newBuf);
+ else
+ file.appendContents(newBuf);
+ }
+ first = false;
+ }
+ } catch (IOException exn) {
+ throw new FilesystemAccessException("failed to transfer bytes", exn);
+ }
+ }
+
+ /**
+ * Build a description of the profiles supported by a workflow. Note that we
+ * expect the set of profiles to be fairly small.
+ *
+ * @param workflow
+ * The workflow to describe the profiles of.
+ * @return The descriptor (which might be empty).
+ */
+ public ProfileList getProfileDescriptor(Workflow workflow) {
+ ProfileList result = new ProfileList();
+ String main = workflow.getMainProfileName();
+ for (Profile p : workflow.getProfiles()) {
+ ProfileList.Info i = new ProfileList.Info();
+ i.name = p.getName();
+ if (main != null && main.equals(i.name))
+ i.main = true;
+ result.profile.add(i);
+ }
+ return result;
+ }
+
+ public boolean getAllowStartWorkflowRuns() {
+ return runFactory.isAllowingRunsToStart();
+ }
+
+ /**
+ * The list of filenames that logs may occupy.
+ */
+ private static final String[] LOGS = { "logs/detail.log.4",
+ "logs/detail.log.3", "logs/detail.log.2", "logs/detail.log.1",
+ "logs/detail.log" };
+
+ public FileConcatenation getLogs(TavernaRun run) {
+ FileConcatenation fc = new FileConcatenation();
+ for (String name : LOGS) {
+ try {
+ fc.add(fileUtils.getFile(run, name));
+ } catch (FilesystemAccessException | NoDirectoryEntryException e) {
+ // Ignore
+ }
+ }
+ return fc;
+ }
+
+ @Nonnull
+ public List<Capability> getCapabilities() {
+ return capabilitySource.getCapabilities();
+ }
+
+ static final String PROV_BUNDLE = "out.bundle.zip";
+
+ public FileConcatenation getProv(TavernaRun run) {
+ FileConcatenation fc = new FileConcatenation();
+ try {
+ fc.add(fileUtils.getFile(run, PROV_BUNDLE));
+ } catch (FilesystemAccessException | NoDirectoryEntryException e) {
+ // Ignore
+ }
+ return fc;
+ }
+}
[38/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java
deleted file mode 100644
index c8d7ef6..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.joda.time.DateTime;
-import org.taverna.server.master.interfaces.MessageDispatcher;
-import org.taverna.server.master.interfaces.TavernaRun;
-
-/**
- * Rate-limiting support. Some message fabrics simply should not be used to send
- * a lot of messages.
- *
- * @author Donal Fellows
- */
-public abstract class RateLimitedDispatcher implements MessageDispatcher {
- /** Pre-configured logger. */
- protected Log log = LogFactory.getLog("Taverna.Server.Notification");
- private int cooldownSeconds;
- private Map<String, DateTime> lastSend = new HashMap<>();
-
- String valid(String value, String def) {
- if (value == null || value.trim().isEmpty()
- || value.trim().startsWith("${"))
- return def;
- else
- return value.trim();
- }
-
- /**
- * Set how long must elapse between updates to the status of any particular
- * user. Calls before that time are just silently dropped.
- *
- * @param cooldownSeconds
- * Time to elapse, in seconds.
- */
- public void setCooldownSeconds(int cooldownSeconds) {
- this.cooldownSeconds = cooldownSeconds;
- }
-
- /**
- * Test whether the rate limiter allows the given user to send a message.
- *
- * @param who
- * Who wants to send the message?
- * @return <tt>true</tt> iff they are permitted.
- */
- protected boolean isSendAllowed(String who) {
- DateTime now = new DateTime();
- synchronized (lastSend) {
- DateTime last = lastSend.get(who);
- if (last != null) {
- if (!now.isAfter(last.plusSeconds(cooldownSeconds)))
- return false;
- }
- lastSend.put(who, now);
- }
- return true;
- }
-
- @Override
- public void dispatch(TavernaRun ignored, String messageSubject,
- String messageContent, String target) throws Exception {
- if (isSendAllowed(target))
- dispatch(messageSubject, messageContent, target);
- }
-
- /**
- * Dispatch a message to a recipient that doesn't care what produced it.
- *
- * @param messageSubject
- * The subject of the message to send.
- * @param messageContent
- * The plain-text content of the message to send.
- * @param target
- * A description of where it is to go.
- * @throws Exception
- * If anything goes wrong.
- */
- public abstract void dispatch(String messageSubject, String messageContent,
- String target) throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java
deleted file mode 100644
index 5553141..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification;
-
-import static org.taverna.server.master.defaults.Default.SMS_GATEWAY_URL;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.message.BasicNameValuePair;
-import org.springframework.beans.factory.annotation.Required;
-
-/**
- * Dispatch termination messages via SMS.
- *
- * @author Donal Fellows
- */
-public class SMSDispatcher extends RateLimitedDispatcher {
- @Override
- public String getName() {
- return "sms";
- }
-
- private CloseableHttpClient client;
- private URI service;
- private String user = "", pass = "";
- private String usernameField = "username", passwordField = "password",
- destinationField = "to", messageField = "text";
-
- /**
- * @param usernameField
- * The name of the field that conveys the sending username; this
- * is the <i>server</i>'s identity.
- */
- @Required
- public void setUsernameField(String usernameField) {
- this.usernameField = usernameField;
- }
-
- /**
- * @param passwordField
- * The field holding the password to authenticate the server to
- * the SMS gateway.
- */
- @Required
- public void setPasswordField(String passwordField) {
- this.passwordField = passwordField;
- }
-
- /**
- * @param destinationField
- * The field holding the number to send the SMS to.
- */
- @Required
- public void setDestinationField(String destinationField) {
- this.destinationField = destinationField;
- }
-
- /**
- * @param messageField
- * The field holding the plain-text message to send.
- */
- @Required
- public void setMessageField(String messageField) {
- this.messageField = messageField;
- }
-
- public void setService(String serviceURL) {
- String s = valid(serviceURL, "");
- if (s.isEmpty()) {
- log.warn("did not get sms.service from servlet config; using default ("
- + SMS_GATEWAY_URL + ")");
- s = SMS_GATEWAY_URL;
- }
- try {
- service = new URI(s);
- } catch (URISyntaxException e) {
- service = null;
- }
- }
-
- public void setUser(String user) {
- this.user = valid(user, "");
- }
-
- public void setPassword(String pass) {
- this.pass = valid(pass, "");
- }
-
- @PostConstruct
- void init() {
- client = HttpClientBuilder.create().build();
- }
-
- @PreDestroy
- void close() throws IOException {
- try {
- if (client != null)
- client.close();
- } finally {
- client = null;
- }
- }
-
- @Override
- public boolean isAvailable() {
- return service != null && !user.isEmpty() && !pass.isEmpty();
- }
-
- @Override
- public void dispatch(String messageSubject, String messageContent,
- String targetParameter) throws Exception {
- // Sanity check
- if (!targetParameter.matches("[^0-9]+"))
- throw new Exception("invalid phone number");
-
- if (!isSendAllowed("anyone"))
- return;
-
- // Build the message to send
- List<NameValuePair> params = new ArrayList<>();
- params.add(new BasicNameValuePair(usernameField, user));
- params.add(new BasicNameValuePair(passwordField, pass));
- params.add(new BasicNameValuePair(destinationField, targetParameter));
- params.add(new BasicNameValuePair(messageField, messageContent));
-
- // Send the message
- HttpPost post = new HttpPost(service);
- post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
- HttpResponse response = client.execute(post);
-
- // Log the response
- HttpEntity entity = response.getEntity();
- if (entity != null)
- try (BufferedReader e = new BufferedReader(new InputStreamReader(
- entity.getContent()))) {
- log.info(e.readLine());
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java
deleted file mode 100644
index 8ee4815..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification;
-
-import java.util.Properties;
-
-import twitter4j.Twitter;
-import twitter4j.TwitterFactory;
-import twitter4j.conf.Configuration;
-import twitter4j.conf.PropertyConfiguration;
-import twitter4j.auth.AuthorizationFactory;
-
-/**
- * Super simple-minded twitter dispatcher. You need to tell it your consumer key
- * and secret as part of the connection parameters, for example via a dispatcher
- * URN of "<tt>twitter:fred:bloggs</tt>" where <tt>fred</tt> is the key and
- * <tt>bloggs</tt> is the secret.
- *
- * @author Donal Fellows
- */
-public class TwitterDispatcher extends RateLimitedDispatcher {
- @Override
- public String getName() {
- return "twitter";
- }
-
- public static final int MAX_MESSAGE_LENGTH = 140;
- public static final char ELLIPSIS = '\u2026';
-
- private String token = "";
- private String secret = "";
-
- public void setAccessToken(String token) {
- this.token = valid(token, "");
- }
-
- public void setAccessSecret(String secret) {
- this.secret = valid(secret, "");
- }
-
- private Properties getConfig() throws NotConfiguredException {
- if (token.isEmpty() || secret.isEmpty())
- throw new NotConfiguredException();
- Properties p = new Properties();
- p.setProperty(ACCESS_TOKEN_PROP, token);
- p.setProperty(ACCESS_SECRET_PROP, secret);
- return p;
- }
-
- public static final String ACCESS_TOKEN_PROP = "oauth.accessToken";
- public static final String ACCESS_SECRET_PROP = "oauth.accessTokenSecret";
-
- private Twitter getTwitter(String key, String secret) throws Exception {
- if (key.isEmpty() || secret.isEmpty())
- throw new NoCredentialsException();
-
- Properties p = getConfig();
- p.setProperty("oauth.consumerKey", key);
- p.setProperty("oauth.consumerSecret", secret);
-
- Configuration config = new PropertyConfiguration(p);
- TwitterFactory factory = new TwitterFactory(config);
- Twitter t = factory.getInstance(AuthorizationFactory
- .getInstance(config));
- // Verify that we can connect!
- t.getOAuthAccessToken();
- return t;
- }
-
- // TODO: Get secret from credential manager
- @Override
- public void dispatch(String messageSubject, String messageContent,
- String targetParameter) throws Exception {
- // messageSubject ignored
- String[] target = targetParameter.split(":", 2);
- if (target == null || target.length != 2)
- throw new Exception("missing consumer key or secret");
- String who = target[0];
- if (!isSendAllowed(who))
- return;
- Twitter twitter = getTwitter(who, target[1]);
-
- if (messageContent.length() > MAX_MESSAGE_LENGTH)
- messageContent = messageContent
- .substring(0, MAX_MESSAGE_LENGTH - 1) + ELLIPSIS;
- twitter.updateStatus(messageContent);
- }
-
- @Override
- public boolean isAvailable() {
- try {
- // Try to create the configuration and push it through as far as
- // confirming that we can build an access object (even if it isn't
- // bound to a user)
- new TwitterFactory(new PropertyConfiguration(getConfig()))
- .getInstance();
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-
- /**
- * Indicates that the dispatcher has not been configured with service
- * credentials.
- *
- * @author Donal Fellows
- */
- @SuppressWarnings("serial")
- public static class NotConfiguredException extends Exception {
- NotConfiguredException() {
- super("not configured with xAuth key and secret; "
- + "dispatch not possible");
- }
- }
-
- /**
- * Indicates that the user did not supply their credentials.
- *
- * @author Donal Fellows
- */
- @SuppressWarnings("serial")
- public static class NoCredentialsException extends Exception {
- NoCredentialsException() {
- super("no consumer key and secret present; "
- + "dispatch not possible");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java
deleted file mode 100644
index e5beaeb..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification.atom;
-
-import static java.lang.String.format;
-import static java.util.UUID.randomUUID;
-import static javax.ws.rs.core.UriBuilder.fromUri;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.common.Uri.secure;
-
-import java.net.URI;
-import java.util.Date;
-
-import javax.annotation.security.RolesAllowed;
-import javax.servlet.ServletContext;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-import org.apache.abdera.Abdera;
-import org.apache.abdera.model.Entry;
-import org.apache.abdera.model.Feed;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.web.context.ServletContextAware;
-import org.taverna.server.master.TavernaServerSupport;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-import org.taverna.server.master.rest.TavernaServerREST.EventFeed;
-import org.taverna.server.master.utils.InvocationCounter.CallCounted;
-
-/**
- * Simple REST handler that allows an Atom feed to be served up of events
- * generated by workflow runs.
- *
- * @author Donal Fellows
- */
-public class AtomFeed implements EventFeed, UriBuilderFactory,
- ServletContextAware {
- /**
- * The name of a parameter that states what address we should claim that the
- * feed's internally-generated URIs are relative to. If not set, a default
- * will be guessed.
- */
- public static final String PREFERRED_URI_PARAM = "taverna.preferredUserUri";
- private EventDAO eventSource;
- private TavernaServerSupport support;
- private URI baseURI;
- private Abdera abdera;
- private String feedLanguage = "en";
- private String uuid = randomUUID().toString();
-
- @Required
- public void setEventSource(EventDAO eventSource) {
- this.eventSource = eventSource;
- }
-
- @Required
- public void setSupport(TavernaServerSupport support) {
- this.support = support;
- }
-
- public void setFeedLanguage(String language) {
- this.feedLanguage = language;
- }
-
- public String getFeedLanguage() {
- return feedLanguage;
- }
-
- @Required
- public void setAbdera(Abdera abdera) {
- this.abdera = abdera;
- }
-
- @Override
- @CallCounted
- @RolesAllowed(USER)
- public Feed getFeed(UriInfo ui) {
- Feed feed = abdera.getFactory().newFeed();
- feed.setTitle("events relating to workflow runs").setLanguage(
- feedLanguage);
- String user = support.getPrincipal().toString()
- .replaceAll("[^A-Za-z0-9]+", "");
- feed.setId(format("urn:taverna-server:%s:%s", uuid, user));
- org.joda.time.DateTime modification = null;
- for (Event e : eventSource.getEvents(support.getPrincipal())) {
- if (modification == null || e.getPublished().isAfter(modification))
- modification = e.getPublished();
- feed.addEntry(e.getEntry(abdera, feedLanguage));
- }
- if (modification == null)
- feed.setUpdated(new Date());
- else
- feed.setUpdated(modification.toDate());
- feed.addLink(ui.getAbsolutePath().toASCIIString(), "self");
- return feed;
- }
-
- @Override
- @CallCounted
- @RolesAllowed(USER)
- public Entry getEvent(String id) {
- return eventSource.getEvent(support.getPrincipal(), id).getEntry(
- abdera, feedLanguage);
- }
-
- @Override
- public UriBuilder getRunUriBuilder(TavernaRun run) {
- return secure(fromUri(getBaseUriBuilder().path("runs/{uuid}").build(
- run.getId())));
- }
-
- @Override
- public UriBuilder getBaseUriBuilder() {
- return secure(fromUri(baseURI));
- }
-
- @Override
- public String resolve(String uri) {
- if (uri == null)
- return null;
- return secure(baseURI, uri).toString();
- }
-
- @Override
- public void setServletContext(ServletContext servletContext) {
- String base = servletContext.getInitParameter(PREFERRED_URI_PARAM);
- if (base == null)
- base = servletContext.getContextPath() + "/rest";
- baseURI = URI.create(base);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java
deleted file mode 100644
index 825029d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification.atom;
-
-import static java.util.UUID.randomUUID;
-
-import java.io.Serializable;
-import java.net.URI;
-import java.util.Date;
-
-import javax.jdo.annotations.Column;
-import javax.jdo.annotations.Index;
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.Queries;
-import javax.jdo.annotations.Query;
-
-import org.apache.abdera.Abdera;
-import org.apache.abdera.model.Entry;
-import org.joda.time.DateTime;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Parent class of all events that may appear on the feed for a workflow run.
- *
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-@PersistenceCapable(schema = "ATOM", table = "EVENTS")
-@Queries({
- @Query(name = "eventsForUser", language = "SQL", value = "SELECT id FROM ATOM.EVENTS WHERE owner = ? ORDER BY published DESC", resultClass = String.class),
- @Query(name = "eventForUserAndId", language = "SQL", value = "SELECT id FROM ATOM.EVENTS WHERE owner = ? AND id = ?", resultClass = String.class),
- @Query(name = "eventsFromBefore", language = "SQL", value = "SELECT id FROM ATOM.EVENTS where published < ?", resultClass = String.class) })
-public class Event implements Serializable {
- @Persistent(primaryKey = "true")
- @Column(length = 48)
- private String id;
- @Persistent
- private String owner;
- @Persistent
- @Index
- private Date published;
- @Persistent
- private String message;
- @Persistent
- private String title;
- @Persistent
- private String link;
-
- Event() {
- }
-
- /**
- * Initialise the identity of this event and the point at which it was
- * published.
- *
- * @param idPrefix
- * A prefix for the identity of this event.
- * @param owner
- * Who is the owner of this event.
- */
- Event(String idPrefix, URI workflowLink, UsernamePrincipal owner,
- String title, String message) {
- id = idPrefix + "." + randomUUID().toString();
- published = new Date();
- this.owner = owner.getName();
- this.title = title;
- this.message = message;
- this.link = workflowLink.toASCIIString();
- }
-
- public final String getId() {
- return id;
- }
-
- public final String getOwner() {
- return owner;
- }
-
- public final DateTime getPublished() {
- return new DateTime(published);
- }
-
- public String getMessage() {
- return message;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getLink() {
- return link;
- }
-
- public Entry getEntry(Abdera abdera, String language) {
- Entry entry = abdera.getFactory().newEntry();
- entry.setId(id);
- entry.setPublished(published);
- entry.addAuthor(owner).setLanguage(language);
- entry.setUpdated(published);
- entry.setTitle(title).setLanguage(language);
- entry.addLink(link, "related").setTitle("workflow run");
- entry.setContent(message).setLanguage(language);
- return entry;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java
deleted file mode 100644
index 56f25ff..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.notification.atom;
-
-import static java.lang.Thread.interrupted;
-import static java.lang.Thread.sleep;
-import static java.util.Arrays.asList;
-
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-
-import javax.annotation.Nonnull;
-import javax.annotation.PreDestroy;
-import javax.jdo.annotations.PersistenceAware;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.joda.time.DateTime;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.interfaces.MessageDispatcher;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-import org.taverna.server.master.utils.JDOSupport;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * The database interface that supports the event feed.
- *
- * @author Donal Fellows
- */
-@PersistenceAware
-public class EventDAO extends JDOSupport<Event> implements MessageDispatcher {
- public EventDAO() {
- super(Event.class);
- }
-
- @Override
- public String getName() {
- return "atom";
- }
-
- private Log log = LogFactory.getLog("Taverna.Server.Atom");
- private UriBuilderFactory ubf;
- private int expiryAgeDays;
-
- @Required
- public void setExpiryAgeDays(int expiryAgeDays) {
- this.expiryAgeDays = expiryAgeDays;
- }
-
- @Required
- public void setUriBuilderFactory(UriBuilderFactory ubf) {
- this.ubf = ubf;
- }
-
- /**
- * Get the given user's list of events.
- *
- * @param user
- * The identity of the user to get the events for.
- * @return A copy of the list of events currently known about.
- */
- @Nonnull
- @WithinSingleTransaction
- public List<Event> getEvents(@Nonnull UsernamePrincipal user) {
- @SuppressWarnings("unchecked")
- List<String> ids = (List<String>) namedQuery("eventsForUser").execute(
- user.getName());
- if (log.isDebugEnabled())
- log.debug("found " + ids.size() + " events for user " + user);
-
- List<Event> result = new ArrayList<>();
- for (String id : ids) {
- Event event = getById(id);
- result.add(detach(event));
- }
- return result;
- }
-
- /**
- * Get a particular event.
- *
- * @param user
- * The identity of the user to get the event for.
- * @param id
- * The handle of the event to look up.
- * @return A copy of the event.
- */
- @Nonnull
- @WithinSingleTransaction
- public Event getEvent(@Nonnull UsernamePrincipal user, @Nonnull String id) {
- @SuppressWarnings("unchecked")
- List<String> ids = (List<String>) namedQuery("eventForUserAndId")
- .execute(user.getName(), id);
- if (log.isDebugEnabled())
- log.debug("found " + ids.size() + " events for user " + user
- + " with id = " + id);
-
- if (ids.size() != 1)
- throw new IllegalArgumentException("no such id");
- return detach(getById(ids.get(0)));
- }
-
- /**
- * Delete a particular event.
- *
- * @param id
- * The identifier of the event to delete.
- */
- @WithinSingleTransaction
- public void deleteEventById(@Nonnull String id) {
- delete(getById(id));
- }
-
- /**
- * Delete all events that have expired.
- */
- @WithinSingleTransaction
- public void deleteExpiredEvents() {
- Date death = new DateTime().plusDays(-expiryAgeDays).toDate();
- death = new Timestamp(death.getTime()); // UGLY SQL HACK
-
- @SuppressWarnings("unchecked")
- List<String> ids = (List<String>) namedQuery("eventsFromBefore")
- .execute(death);
- if (log.isDebugEnabled() && !ids.isEmpty())
- log.debug("found " + ids.size()
- + " events to be squelched (older than " + death + ")");
-
- for (String id : ids)
- delete(getById(id));
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- private BlockingQueue<Event> insertQueue = new ArrayBlockingQueue<>(16);
-
- @Override
- public void dispatch(TavernaRun originator, String messageSubject,
- String messageContent, String targetParameter) throws Exception {
- insertQueue.put(new Event("finish", ubf.getRunUriBuilder(originator)
- .build(), originator.getSecurityContext().getOwner(),
- messageSubject, messageContent));
- }
-
- public void started(TavernaRun originator, String messageSubject,
- String messageContent) throws InterruptedException {
- insertQueue.put(new Event("start", ubf.getRunUriBuilder(originator)
- .build(), originator.getSecurityContext().getOwner(),
- messageSubject, messageContent));
- }
-
- private Thread eventDaemon;
- private boolean shuttingDown = false;
-
- @Required
- public void setSelf(final EventDAO dao) {
- eventDaemon = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- while (!shuttingDown && !interrupted()) {
- transferEvents(dao, new ArrayList<Event>(
- asList(insertQueue.take())));
- sleep(5000);
- }
- } catch (InterruptedException e) {
- } finally {
- transferEvents(dao, new ArrayList<Event>());
- }
- }
- }, "ATOM event daemon");
- eventDaemon.setContextClassLoader(null);
- eventDaemon.setDaemon(true);
- eventDaemon.start();
- }
-
- private void transferEvents(EventDAO dao, List<Event> e) {
- insertQueue.drainTo(e);
- dao.storeEvents(e);
- }
-
- @PreDestroy
- void stopDaemon() {
- shuttingDown = true;
- if (eventDaemon != null)
- eventDaemon.interrupt();
- }
-
- @WithinSingleTransaction
- protected void storeEvents(List<Event> events) {
- for (Event e : events)
- persist(e);
- log.info("stored " + events.size() + " notification events");
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java
deleted file mode 100644
index 9cc592d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains the Atom feed implementation within Taverna Server.
- * @author Donal Fellows
- */
-@XmlSchema(namespace = FEED, 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) })
-package org.taverna.server.master.notification.atom;
-
-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.XLINK;
-
-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/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java
deleted file mode 100644
index 979066a..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * The notification fabric and implementations of notification dispatchers
- * that support subscription.
- */
-package org.taverna.server.master.notification;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/package-info.java
deleted file mode 100644
index 17bfd03..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/package-info.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * The core of the implementation of Taverna Server, including the
- * implementations of the SOAP and REST interfaces.
- */
-package org.taverna.server.master;
-
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java b/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java
deleted file mode 100644
index b0819a5..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_ATOM_XML;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
-import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-
-/**
- * Miscellaneous content type constants.
- *
- * @author Donal Fellows
- */
-interface ContentTypes {
- static final String URI_LIST = "text/uri-list";
- static final String ZIP = "application/zip";
- static final String TEXT = TEXT_PLAIN;
- static final String XML = APPLICATION_XML;
- static final String JSON = APPLICATION_JSON;
- static final String BYTES = APPLICATION_OCTET_STREAM;
- static final String ATOM = APPLICATION_ATOM_XML;
- static final String ROBUNDLE = "application/vnd.wf4ever.robundle+zip";
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java b/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java
deleted file mode 100644
index e01d1c4..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.Uri.secure;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlSeeAlso;
-import javax.xml.bind.annotation.XmlType;
-
-import org.taverna.server.master.common.DirEntryReference;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-
-/**
- * The result of a RESTful operation to list the contents of a directory. Done
- * with JAXB.
- *
- * @author Donal Fellows
- */
-@XmlRootElement
-@XmlType(name = "DirectoryContents")
-@XmlSeeAlso(MakeOrUpdateDirEntry.class)
-public class DirectoryContents {
- /**
- * The contents of the directory.
- */
- @XmlElementRef
- public List<DirEntryReference> contents;
-
- /**
- * Make an empty directory description. Required for JAXB.
- */
- public DirectoryContents() {
- contents = new ArrayList<>();
- }
-
- /**
- * Make a directory description.
- *
- * @param ui
- * The factory for URIs.
- * @param collection
- * The real directory contents that we are to describe.
- */
- public DirectoryContents(UriInfo ui, Collection<DirectoryEntry> collection) {
- contents = new ArrayList<>();
- UriBuilder ub = secure(ui).path("{filename}");
- for (DirectoryEntry e : collection)
- contents.add(DirEntryReference.newInstance(ub, e));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java b/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java
deleted file mode 100644
index 74269c1..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest;
-
-import static javax.ws.rs.core.Response.ok;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.interfaces.File;
-
-/**
- * Representation of a segment of a file to be read by JAX-RS.
- *
- * @author Donal Fellows
- */
-public class FileSegment {
- /** The file to read a segment of. */
- public final File file;
- /** The offset of the first byte of the segment to read. */
- public Integer from;
- /** The offset of the first byte after the segment to read. */
- public Integer to;
-
- /**
- * Parse the HTTP Range header and determine what exact range of the file to
- * read.
- *
- * @param f
- * The file this refers to
- * @param range
- * The content of the Range header.
- * @throws FilesystemAccessException
- * If we can't determine the length of the file (shouldn't
- * happen).
- */
- public FileSegment(File f, String range) throws FilesystemAccessException {
- file = f;
- Matcher m = Pattern.compile("^\\s*bytes=(\\d*)-(\\d*)\\s*$").matcher(
- range);
- if (m.matches()) {
- if (!m.group(1).isEmpty())
- from = Integer.valueOf(m.group(1));
- if (!m.group(2).isEmpty())
- to = Integer.valueOf(m.group(2)) + 1;
- int size = (int) f.getSize();
- if (from == null) {
- from = size - to;
- to = size;
- } else if (to == null)
- to = size;
- else if (to > size)
- to = size;
- }
- }
-
- /**
- * Convert to a response, as per RFC 2616.
- *
- * @param type
- * The expected type of the data.
- * @return A JAX-RS response.
- */
- public Response toResponse(MediaType type) {
- if (from == null && to == null)
- return ok(file).type(type).build();
- if (from >= to)
- return ok("Requested range not satisfiable").status(416).build();
- return ok(this).status(206).type(type).build();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java
deleted file mode 100644
index b9b4718..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest;
-
-import static org.taverna.server.master.rest.ContentTypes.ATOM;
-
-import java.net.MalformedURLException;
-
-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.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Response;
-
-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.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-
-/**
- * A very stripped down ATOM feed for the interaction service.
- *
- * @author Donal Fellows
- */
-public interface InteractionFeedREST {
- /**
- * Get the feed document for this ATOM feed.
- *
- * @return The feed.
- * @throws FilesystemAccessException
- * If we can't read from the feed directory.
- * @throws NoDirectoryEntryException
- * If something changes things under our feet.
- */
- @GET
- @Path("/")
- @Produces(ATOM)
- @Description("Get the feed document for this ATOM feed.")
- Feed getFeed() throws FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Adds an entry to this ATOM feed.
- *
- * @param entry
- * The entry to create.
- * @return A redirect to the created entry.
- * @throws MalformedURLException
- * If we have problems generating the URI of the entry.
- * @throws FilesystemAccessException
- * If we can't create the feed entry file.
- * @throws NoDirectoryEntryException
- * If things get changed under our feet.
- * @throws NoUpdateException
- * If we don't have permission to change things relating to this
- * run.
- */
- @POST
- @Path("/")
- @Consumes(ATOM)
- @Produces(ATOM)
- @Description("Adds an entry to this ATOM feed.")
- Response addEntry(Entry entry) throws MalformedURLException,
- FilesystemAccessException, NoDirectoryEntryException,
- NoUpdateException;
-
- /** Handles the OPTIONS request. */
- @OPTIONS
- @Path("/")
- @Description("Describes what HTTP operations are supported on the feed.")
- Response feedOptions();
-
- /**
- * Gets the content of an entry in this ATOM feed.
- *
- * @param id
- * The ID of the entry to fetch.
- * @return The entry contents.
- * @throws FilesystemAccessException
- * If we have problems reading the entry.
- * @throws NoDirectoryEntryException
- * If we can't find the entry to read.
- */
- @GET
- @Path("{id}")
- @Produces(ATOM)
- @Description("Get the entry with a particular ID within this ATOM feed.")
- Entry getEntry(@PathParam("id") String id)
- throws FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Delete an entry from this ATOM feed.
- *
- * @param id
- * The ID of the entry to delete.
- * @return A simple message. Not very important!
- * @throws FilesystemAccessException
- * If we have problems deleting the entry.
- * @throws NoDirectoryEntryException
- * If we can't find the entry to delete.
- * @throws NoUpdateException
- * If we don't have permission to alter things relating to this
- * run.
- */
- @DELETE
- @Path("{id}")
- @Produces("text/plain")
- @Description("Deletes an entry from this ATOM feed.")
- String deleteEntry(@PathParam("id") String id)
- throws FilesystemAccessException, NoDirectoryEntryException,
- NoUpdateException;
-
- /** Handles the OPTIONS request. */
- @OPTIONS
- @Path("{id}")
- @Description("Describes what HTTP operations are supported on an entry.")
- Response entryOptions(@PathParam("{id}") String id);
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java b/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java
deleted file mode 100644
index 7a072be..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-/**
- * Description of what sort of event listener to create and attach to a workflow
- * run. Bound via JAXB.
- *
- * @author Donal Fellows
- */
-@XmlRootElement(name = "listenerDefinition")
-@XmlType(name="ListenerDefinition")
-public class ListenerDefinition {
- /**
- * The type of event listener to create.
- */
- @XmlAttribute
- public String type;
- /**
- * How the event listener should be configured.
- */
- @XmlValue
- public String configuration;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java b/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java
deleted file mode 100644
index 0138f88..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlSeeAlso;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-/**
- * The input to the REST interface for making directories and files, and
- * uploading file contents. Done with JAXB.
- *
- * @author Donal Fellows
- */
-@XmlRootElement(name = "filesystemOperation")
-@XmlType(name = "FilesystemCreationOperation")
-@XmlSeeAlso( { MakeOrUpdateDirEntry.MakeDirectory.class,
- MakeOrUpdateDirEntry.SetFileContents.class })
-public abstract class MakeOrUpdateDirEntry {
- /**
- * The name of the file or directory that the operation applies to.
- */
- @XmlAttribute
- public String name;
- /**
- * The contents of the file to upload.
- */
- @XmlValue
- public byte[] contents;
-
- /**
- * Create a directory, described with JAXB. Should leave the
- * {@link MakeOrUpdateDirEntry#contents contents} field empty.
- *
- * @author Donal Fellows
- */
- @XmlRootElement(name = "mkdir")
- @XmlType(name = "MakeDirectory")
- public static class MakeDirectory extends MakeOrUpdateDirEntry {
- }
-
- /**
- * Create a file or set its contents, described with JAXB.
- *
- * @author Donal Fellows
- */
- @XmlRootElement(name = "upload")
- @XmlType(name = "UploadFile")
- public static class SetFileContents extends MakeOrUpdateDirEntry {
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java
deleted file mode 100644
index ea2f776..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest;
-
-import static java.util.Collections.unmodifiableList;
-import static javax.ws.rs.core.MediaType.WILDCARD;
-import static org.taverna.server.master.common.Roles.USER;
-import static org.taverna.server.master.rest.ContentTypes.BYTES;
-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.ContentTypes.ZIP;
-
-import java.io.InputStream;
-import java.net.URI;
-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.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.HttpHeaders;
-import javax.ws.rs.core.PathSegment;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.core.Variant;
-
-import org.apache.cxf.jaxrs.model.wadl.Description;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.File;
-
-/**
- * Representation of how a workflow run's working directory tree looks.
- *
- * @author Donal Fellows
- */
-@RolesAllowed(USER)
-@Produces({ XML, JSON })
-@Consumes({ XML, JSON })
-@Description("Representation of how a workflow run's working directory tree looks.")
-public interface TavernaServerDirectoryREST {
- /**
- * Get the working directory of the workflow run.
- *
- * @param ui
- * About how this method was called.
- * @return A description of the working directory.
- * @throws FilesystemAccessException
- */
- @GET
- @Path("/")
- @Description("Describes the working directory of the workflow run.")
- @Nonnull
- DirectoryContents getDescription(@Nonnull @Context UriInfo ui)
- throws FilesystemAccessException;
-
- /** Get an outline of the operations supported. */
- @OPTIONS
- @Path("{path:.*}")
- @Description("Produces the description of the files/directories' baclava operations.")
- Response options(@PathParam("path") List<PathSegment> path);
-
- /**
- * Gets a description of the named entity in or beneath the working
- * directory of the workflow run, which may be either a {@link Directory} or
- * a {@link File}.
- *
- * @param path
- * The path to the thing to describe.
- * @param ui
- * About how this method was called.
- * @param headers
- * About what the caller was looking for.
- * @return An HTTP response containing a description of the named thing.
- * @throws NoDirectoryEntryException
- * If the name of the file or directory can't be looked up.
- * @throws FilesystemAccessException
- * If something went wrong during the filesystem operation.
- * @throws NegotiationFailedException
- * If the content type being downloaded isn't one that this
- * method can support.
- */
- @GET
- @Path("{path:.+}")
- @Produces({ XML, JSON, BYTES, ZIP, WILDCARD })
- @Description("Gives a description of the named entity in or beneath the "
- + "working directory of the workflow run (either a Directory or File).")
- @Nonnull
- Response getDirectoryOrFileContents(
- @Nonnull @PathParam("path") List<PathSegment> path,
- @Nonnull @Context UriInfo ui, @Nonnull @Context HttpHeaders headers)
- throws NoDirectoryEntryException, FilesystemAccessException,
- NegotiationFailedException;
-
- /**
- * Creates a directory in the filesystem beneath the working directory of
- * the workflow run, or creates or updates a file's contents, where that
- * file is in or below the working directory of a workflow run.
- *
- * @param parent
- * The directory to create the directory in.
- * @param operation
- * What to call the directory to create.
- * @param ui
- * About how this method was called.
- * @return An HTTP response indicating where the directory was actually made
- * or what file was created/updated.
- * @throws NoDirectoryEntryException
- * If the name of the containing directory can't be looked up.
- * @throws NoUpdateException
- * If the user is not permitted to update the run.
- * @throws FilesystemAccessException
- * If something went wrong during the filesystem operation.
- */
- @POST
- @Path("{path:.*}")
- @Description("Creates a directory in the filesystem beneath the working "
- + "directory of the workflow run, or creates or updates a file's "
- + "contents, where that file is in or below the working directory "
- + "of a workflow run.")
- @Nonnull
- Response makeDirectoryOrUpdateFile(
- @Nonnull @PathParam("path") List<PathSegment> parent,
- @Nonnull MakeOrUpdateDirEntry operation,
- @Nonnull @Context UriInfo ui) throws NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Creates or updates a file in a particular location beneath the working
- * directory of the workflow run.
- *
- * @param file
- * The path to the file to create or update.
- * @param referenceList
- * Location to get the file's contents from. Must be
- * <i>publicly</i> readable.
- * @param ui
- * About how this method was called.
- * @return An HTTP response indicating what file was created/updated.
- * @throws NoDirectoryEntryException
- * If the name of the containing directory can't be looked up.
- * @throws NoUpdateException
- * If the user is not permitted to update the run.
- * @throws FilesystemAccessException
- * If something went wrong during the filesystem operation.
- */
- @POST
- @Path("{path:(.*)}")
- @Consumes(URI_LIST)
- @Description("Creates or updates a file in a particular location beneath the "
- + "working directory of the workflow run with the contents of a "
- + "publicly readable URL.")
- @Nonnull
- Response setFileContentsFromURL(@PathParam("path") List<PathSegment> file,
- List<URI> referenceList, @Context UriInfo ui)
- throws NoDirectoryEntryException, NoUpdateException,
- FilesystemAccessException;
-
- /**
- * Creates or updates a file in a particular location beneath the working
- * directory of the workflow run.
- *
- * @param file
- * The path to the file to create or update.
- * @param contents
- * Stream of bytes to set the file's contents to.
- * @param ui
- * About how this method was called.
- * @return An HTTP response indicating what file was created/updated.
- * @throws NoDirectoryEntryException
- * If the name of the containing directory can't be looked up.
- * @throws NoUpdateException
- * If the user is not permitted to update the run.
- * @throws FilesystemAccessException
- * If something went wrong during the filesystem operation.
- */
- @PUT
- @Path("{path:(.*)}")
- @Consumes({ BYTES, WILDCARD })
- @Description("Creates or updates a file in a particular location beneath the "
- + "working directory of the workflow run.")
- @Nonnull
- Response setFileContents(@PathParam("path") List<PathSegment> file,
- InputStream contents, @Context UriInfo ui)
- throws NoDirectoryEntryException, NoUpdateException,
- FilesystemAccessException;
-
- /**
- * Deletes a file or directory that is in or below the working directory of
- * a workflow run.
- *
- * @param path
- * The path to the file or directory.
- * @return An HTTP response to the method.
- * @throws NoUpdateException
- * If the user is not permitted to update the run.
- * @throws FilesystemAccessException
- * If something went wrong during the filesystem operation.
- * @throws NoDirectoryEntryException
- * If the name of the file or directory can't be looked up.
- */
- @DELETE
- @Path("{path:.*}")
- @Description("Deletes a file or directory that is in or below the working "
- + "directory of a workflow run.")
- @Nonnull
- Response destroyDirectoryEntry(@PathParam("path") List<PathSegment> path)
- throws NoUpdateException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Exception thrown to indicate a failure by the client to provide an
- * acceptable content type.
- *
- * @author Donal Fellows
- */
- @SuppressWarnings("serial")
- public static class NegotiationFailedException extends Exception {
- public List<Variant> accepted;
-
- public NegotiationFailedException(String msg, List<Variant> accepted) {
- super(msg);
- this.accepted = unmodifiableList(accepted);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java
deleted file mode 100644
index faed19d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * 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.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.TavernaServerInputREST.PathNames.BACLAVA;
-import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.EXPECTED;
-import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.ONE_INPUT;
-
-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.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.PathSegment;
-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.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-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.BadInputPortNameException;
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-import org.taverna.server.master.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.port_description.InputDescription;
-
-/**
- * This represents how a Taverna Server workflow run's inputs looks to a RESTful
- * API.
- *
- * @author Donal Fellows.
- */
-@RolesAllowed(USER)
-@Description("This represents how a Taverna Server workflow run's inputs "
- + "looks to a RESTful API.")
-public interface TavernaServerInputREST {
- /**
- * @return A description of the various URIs to inputs associated with a
- * workflow run.
- */
- @GET
- @Path("/")
- @Produces({ XML, JSON })
- @Description("Describe the sub-URIs of this resource.")
- @Nonnull
- InputsDescriptor get();
-
- /** Get an outline of the operations supported. */
- @OPTIONS
- @Path("/")
- @Description("Produces the description of one run's inputs' operations.")
- Response options();
-
- /**
- * @return A description of the various URIs to inputs associated with a
- * workflow run.
- */
- @GET
- @Path(EXPECTED)
- @Produces({ XML, JSON })
- @Description("Describe the expected inputs of this workflow run.")
- @Nonnull
- InputDescription getExpected();
-
- /** Get an outline of the operations supported. */
- @OPTIONS
- @Path(EXPECTED)
- @Description("Produces the description of the expected inputs' operations.")
- Response expectedOptions();
-
- /**
- * @return The Baclava file that will supply all the inputs to the workflow
- * run, or empty to indicate that no such file is specified.
- */
- @GET
- @Path(BACLAVA)
- @Produces(TEXT)
- @Description("Gives the Baclava file describing the inputs, or empty if "
- + "individual files are used.")
- @Nonnull
- String getBaclavaFile();
-
- /**
- * Set the Baclava file that will supply all the inputs to the workflow run.
- *
- * @param filename
- * The filename to set.
- * @return The name of the Baclava file that was actually set.
- * @throws NoUpdateException
- * If the user can't update the run.
- * @throws BadStateChangeException
- * If the run is not Initialized.
- * @throws FilesystemAccessException
- * If the filename starts with a <tt>/</tt> or if it contains a
- * <tt>..</tt> segment.
- */
- @PUT
- @Path(BACLAVA)
- @Consumes(TEXT)
- @Produces(TEXT)
- @Description("Sets the Baclava file describing the inputs.")
- @Nonnull
- String setBaclavaFile(@Nonnull String filename) throws NoUpdateException,
- BadStateChangeException, FilesystemAccessException;
-
- /** Get an outline of the operations supported. */
- @OPTIONS
- @Path(BACLAVA)
- @Description("Produces the description of the inputs' baclava operations.")
- Response baclavaOptions();
-
- /**
- * Get what input is set for the specific input.
- *
- * @param name
- * The input to set.
- * @param uriInfo
- * About the URI used to access this resource.
- * @return A description of the input.
- * @throws BadInputPortNameException
- * If no input with that name exists.
- */
- @GET
- @Path(ONE_INPUT)
- @Produces({ XML, JSON })
- @Description("Gives a description of what is used to supply a particular "
- + "input.")
- @Nonnull
- InDesc getInput(@Nonnull @PathParam("name") String name,
- @Context UriInfo uriInfo) throws BadInputPortNameException;
-
- /**
- * Set what an input uses to provide data into the workflow run.
- *
- * @param name
- * The name of the input.
- * @param inputDescriptor
- * A description of the input
- * @param uriInfo
- * About the URI used to access this resource.
- * @return A description of the input.
- * @throws NoUpdateException
- * If the user can't update the run.
- * @throws BadStateChangeException
- * If the run is not Initialized.
- * @throws FilesystemAccessException
- * If a filename is being set and the filename starts with a
- * <tt>/</tt> or if it contains a <tt>..</tt> segment.
- * @throws BadInputPortNameException
- * If no input with that name exists.
- * @throws BadPropertyValueException
- * If some bad misconfiguration has happened.
- */
- @PUT
- @Path(ONE_INPUT)
- @Consumes({ XML, JSON })
- @Produces({ XML, JSON })
- @Description("Sets the source for a particular input port.")
- @Nonnull
- InDesc setInput(@Nonnull @PathParam("name") String name,
- @Nonnull InDesc inputDescriptor, @Context UriInfo uriInfo) throws NoUpdateException,
- BadStateChangeException, FilesystemAccessException,
- BadPropertyValueException, BadInputPortNameException;
-
- /** Get an outline of the operations supported. */
- @OPTIONS
- @Path(ONE_INPUT)
- @Description("Produces the description of the one input's operations.")
- Response inputOptions(@PathParam("name") String name);
-
- interface PathNames {
- final String EXPECTED = "expected";
- final String BACLAVA = "baclava";
- final String ONE_INPUT = "input/{name}";
- }
-
- /**
- * A description of the structure of inputs to a Taverna workflow run, done
- * with JAXB.
- *
- * @author Donal Fellows
- */
- @XmlRootElement(name = "runInputs")
- @XmlType(name = "TavernaRunInputs")
- public static class InputsDescriptor extends VersionedElement {
- /**
- * Where to find a description of the expected inputs to this workflow
- * run.
- */
- public Uri expected;
- /**
- * Where to find the overall Baclava document filename (if set).
- */
- public Uri baclava;
- /**
- * Where to find the details of inputs to particular ports (if set).
- */
- public List<Uri> input;
-
- /**
- * Make a blank description of the inputs.
- */
- public InputsDescriptor() {
- }
-
- /**
- * Make the description of the inputs.
- *
- * @param ui
- * Information about the URIs to generate.
- * @param run
- * The run whose inputs are to be described.
- */
- public InputsDescriptor(UriInfo ui, TavernaRun run) {
- super(true);
- expected = new Uri(ui, EXPECTED);
- baclava = new Uri(ui, BACLAVA);
- input = new ArrayList<>();
- for (Input i : run.getInputs())
- input.add(new Uri(ui, ONE_INPUT, i.getName()));
- }
- }
-
- /**
- * The Details of a particular input port's value assignment, done with
- * JAXB.
- *
- * @author Donal Fellows
- */
- @XmlRootElement(name = "runInput")
- @XmlType(name = "InputDescription")
- public static class InDesc extends VersionedElement {
- /** Make a blank description of an input port. */
- public InDesc() {
- }
-
- /**
- * Make a description of the given input port.
- *
- * @param inputPort
- */
- public InDesc(Input inputPort, UriInfo ui) {
- super(true);
- name = inputPort.getName();
- if (inputPort.getFile() != null) {
- assignment = new InDesc.File();
- assignment.contents = inputPort.getFile();
- } else {
- assignment = new InDesc.Value();
- assignment.contents = inputPort.getValue();
- }
- // .../runs/{id}/input/input/{name} ->
- // .../runs/{id}/input/expected#{name}
- UriBuilder ub = ui.getBaseUriBuilder();
- List<PathSegment> segments = ui.getPathSegments();
- for (PathSegment s : segments.subList(0, segments.size() - 2))
- ub.segment(s.getPath());
- ub.fragment(name);
- descriptorRef = new Uri(ub).ref;
- }
-
- /** The name of the port. */
- @XmlAttribute(required = false)
- public String name;
- /** Where the port is described. Ignored in user input. */
- @XmlAttribute(required = false)
- @XmlSchemaType(name = "anyURI")
- public URI descriptorRef;
- /** The character to use to split the input into a list. */
- @XmlAttribute(name = "listDelimiter", required = false)
- public String delimiter;
-
- /**
- * Either a filename or a literal string, used to provide input to a
- * workflow port.
- *
- * @author Donal Fellows
- */
- @XmlType(name = "InputContents")
- public static abstract class AbstractContents {
- /**
- * The contents of the description of the input port. Meaning not
- * defined.
- */
- @XmlValue
- public String contents;
- };
-
- /**
- * The name of a file that provides input to the port. The
- * {@link AbstractContents#contents contents} field is a filename.
- *
- * @author Donal Fellows
- */
- @XmlType(name = "")
- public static class File extends AbstractContents {
- }
-
- /**
- * The literal input to the port. The {@link AbstractContents#contents
- * contents} field is a literal input value.
- *
- * @author Donal Fellows
- */
- @XmlType(name = "")
- public static class Value extends AbstractContents {
- }
-
- /**
- * A reference to a file elsewhere <i>on this server</i>. The
- * {@link AbstractContents#contents contents} field is a URL to the file
- * (using the RESTful notation).
- *
- * @author Donal Fellows
- */
- @XmlType(name = "")
- public static class Reference extends AbstractContents {
- }
-
- /**
- * The assignment of input values to the port.
- */
- @XmlElements({ @XmlElement(name = "file", type = File.class),
- @XmlElement(name = "reference", type = Reference.class),
- @XmlElement(name = "value", type = Value.class) })
- public AbstractContents assignment;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java
deleted file mode 100644
index e9b067e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * 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));
- }
- }
-}
[07/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/admin.js
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/admin.js b/taverna-server-webapp/src/main/resources/static/admin.js
new file mode 100644
index 0000000..c2c41bf
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/static/admin.js
@@ -0,0 +1,549 @@
+// Wrappers round AJAX calls to simplify *most* of this stuff
+
+/** How to retrieve text asynchronously. */
+function getText(u, done) {
+ $.ajax({
+ type : "GET",
+ url : u,
+ async : true,
+ cache : false,
+ accept : "text/plain",
+ dataType : "text",
+ success : done
+ });
+}
+/** How to retrieve JSON asynchronously. */
+function getJSON(u, done) {
+ $.ajax({
+ type : "GET",
+ url : u,
+ async : true,
+ cache : false,
+ dataType : "json",
+ accept : "application/json",
+ success : done
+ });
+}
+/** How to send a PUT of text asynchronously. */
+function putText(u, val, done) {
+ $.ajax({
+ type : "PUT",
+ url : u,
+ async : false,
+ cache : false,
+ data : val,
+ contentType : "text/plain",
+ dataType : "text",
+ processData : false,
+ success : done,
+ error : function(jqXHR, textStatus, errorThrown) {
+ alert(errorThrown);
+ }
+ });
+}
+/** How to send a PUT of XML asynchronously. */
+function putXML(u, xml, done) {
+ $.ajax({
+ type : "PUT",
+ url : u,
+ async : false,
+ cache : false,
+ contentType : "application/xml",
+ data : new XMLSerializer().serializeToString(xml),
+ success : done,
+ error : function(jqXHR, textStatus, errorThrown) {
+ alert(errorThrown);
+ }
+ });
+}
+/** How to send a POST of XML asynchronously. */
+function postXML(u, xml, done) {
+ $.ajax({
+ type : "POST",
+ url : u,
+ async : false,
+ cache : false,
+ contentType : "application/xml",
+ data : new XMLSerializer().serializeToString(xml),
+ success : done,
+ error : function(jqXHR, textStatus, errorThrown) {
+ alert(errorThrown);
+ }
+ });
+}
+/** How to send a DELETE asynchronously. */
+function deleteUrl(u, done) {
+ $.ajax({
+ type : "DELETE",
+ url : u,
+ async : true,
+ cache : false,
+ success : done,
+ error : function(jqXHR, textStatus, errorThrown) {
+ alert(errorThrown);
+ }
+ });
+}
+
+/** Locates a URL with respect to the administrative REST interface. */
+function where(tail) {
+ return $("#admin")[0].href + "/" + tail;
+}
+
+// Make an XML element structure
+// Derived from hack on Stack Overflow, but with extra tinkering
+/** Function called to create a node in an XML structure. */
+var Node;
+/** Function called to create nodes in an XML structure from an array. */
+var NodeAll;
+(function() {
+ var doc = document.implementation.createDocument(null, null, null);
+ var adminNS = "http://ns.taverna.org.uk/2010/xml/server/admin/";
+ Node = function() {
+ var node = doc.createElementNS(adminNS, arguments[0]), child;
+ for ( var i = 1; i < arguments.length; i++) {
+ child = arguments[i];
+ if (child == undefined)
+ continue;
+ if (typeof child != 'object')
+ child = doc.createTextNode(child.toString());
+ node.appendChild(child);
+ }
+ return node;
+ };
+ NodeAll = function(wrapperElem, wrappedElem, elements) {
+ var node = doc.createElementNS(adminNS, wrapperElem);
+ for ( var i = 0; i < elements.length; i++) {
+ var child = doc.createElementNS(adminNS, wrappedElem);
+ var text = doc.createTextNode(elements[i]);
+ child.appendChild(text);
+ node.appendChild(child);
+ }
+ return node;
+ };
+})();
+
+/** The IDs of boolean-coupled buttons. */
+var buttonlist = [ "allowNew", "logFaults", "logWorkflows", "generateProvenance" ];
+/** The IDs of values that track server variables without setting things. */
+var readonlies = [ "invokationCount", "lastExitCode", "runCount", "startupTime", "operatingCount" ];
+/** The IDs of text/numeric-coupled entries. */
+var entries = [ "defaultLifetime", "executeWorkflowScript", "javaBinary",
+ "registrationPollMillis", "registrationWaitSeconds", "registryHost",
+ "registryPort", "runLimit", "runasPasswordFile", "serverForkerJar",
+ "serverWorkerJar", "usageRecordDumpFile", "operatingLimit",
+ "registryJar" ];
+/** Cached information about users. */
+var userinfo = [];
+/** Extra arguments to pass to the runtime. */
+var extraAry = [];
+
+/** How to update the read-only fields; will be called periodically */
+function updateRO() {
+ $.each(readonlies, function(idx, val) {
+ var widget = $("#" + val);
+ getText(where(val), function(data) {
+ widget.html(data);
+ });
+ });
+ getJSON(where("factoryProcessMapping"),
+ function(data) {
+ var ary = data.stringList.string;
+ var tbl = $("#factoryProcessMapping");
+ tbl.html("<tr><th>User<th>ID</tr>");
+ if (ary != undefined)
+ for ( var i = 0; i < ary.length - 1; i += 2)
+ tbl.append("<tr><td>" + ary[i] + "<td>" + ary[i + 1]
+ + "</tr>");
+ });
+}
+
+/**
+ * Generate a user row with suitable indices, but no content (it will be pushed
+ * into the row later).
+ */
+function userRowHTML(idx) {
+ // USER NAME
+ var content = "<td><span id='username" + idx
+ + "' title='The login name of the user.'></span></td>";
+ // SYSTEM ID MAPPING
+ content += "<td><input id='userlocal"
+ + idx
+ + "' title='The system username to run workflows as, or blank for default.' /></td>";
+ // ENABLED
+ content += "<td><label title='Is this user allowed to log in?' for='useron"
+ + idx + "'>Enabled</label>" + "<input type='checkbox' id='useron"
+ + idx + "' /></td>";
+ // ADMIN
+ content += "<td><label title='Is this user an admin (allowed to access this page)?' for='useradmin"
+ + idx
+ + "'>Admin</label>"
+ + "<input type='checkbox' id='useradmin"
+ + idx + "' /></td>";
+ // SET PASSWORD
+ content += "<td><button title='Set the password for this user.' id='userpass"
+ + idx + "'>Set Password</button></td>";
+ // DELETE
+ content += "<td><button title='Delete this user. Take care to not delete yourself!' id='userdel"
+ + idx + "'>Delete</button></td>";
+
+ return "<tr id='usersep" + idx + "' class='userrows'>"
+ + "<td colspan=6><hr></td></tr>" + "<tr id='userrow" + idx
+ + "' class='userrows'>" + content + "</tr>";
+}
+
+/** How to get the list of permitted workflows; called on demand */
+function refreshWorkflows() {
+ var wftable = $("#workflows"), wfbut = $("#saveWorkflows"), wfbut1 = $("#emptyWorkflows"), wfref = $("#refreshWorkflows");
+ wfbut.button("disable");
+ wfbut1.button("disable");
+ wfref.button("disable");
+ getJSON(where("permittedWorkflowURIs"), function(data) {
+ var s = "";
+ $.each(data.stringList.string || [], function(idx, str) {
+ s += $.trim(str) + "\n";
+ });
+ wftable.val($.trim(s));
+ wfbut.button("enable");
+ wfbut1.button("enable");
+ wfref.button("enable");
+ });
+}
+/** How to set the list of permitted workflows; called when the user clicks */
+function saveWorkflows() {
+ var wftable = $("#workflows"), wfbut = $("#saveWorkflows"), wfbut1 = $("#emptyWorkflows");
+ var xml = NodeAll("stringList", "string", wftable.val().split("\n"));
+ wfbut.button("disable");
+ wfbut1.button("disable");
+ putXML(where("permittedWorkflowURIs"), xml, function() {
+ refreshWorkflows();
+ });
+}
+
+/** How to empty the list of permitted workflows; called when the user clicks */
+function emptyWorkflows() {
+ var wftable = $("#workflows"), wfbut = $("#saveWorkflows"), wfbut1 = $("#emptyWorkflows");
+ var xml = NodeAll("stringList", "string", "");
+ wfbut.button("disable");
+ wfbut1.button("disable");
+ putXML(where("permittedWorkflowURIs"), xml, function() {
+ refreshWorkflows();
+ });
+}
+
+/** How to update the table of users; called on demand */
+function refreshUsers() {
+ var usertable = $("#userList");
+ getJSON(where("users"), function(data) {
+ $(".userrows").remove();
+ userinfo = [];
+ $.each(data.userList.user, function(idx, url) {
+ usertable.append(userRowHTML(idx));
+ var i = idx;
+ userinfo[i] = {
+ url : url
+ };
+ getJSON(url, function(data) {
+ var model = userinfo[i].model = data.userDesc;
+ $("#username" + i).html(model.username);
+ $("#userlocal" + i).val(model.localUserId).change(function() {
+ updateUser(i, "localUserId", $(this).val());
+ });
+ $("#useron" + i).button().attr("checked", model.enabled)
+ .button("refresh").click(
+ function() {
+ updateUser(i, "enabled", $(this).attr(
+ "checked") == "checked");
+ });
+ $("#useradmin" + i).button().attr("checked", model.admin)
+ .button("refresh").click(
+ function() {
+ updateUser(i, "admin", $(this).attr(
+ "checked") == "checked");
+ });
+ $("#userpass" + i).button({
+ icons : {
+ primary : "ui-icon-alert"
+ }
+ }).click(function() {
+ updatePasswordUser(i);
+ });
+ $("#userdel" + i).button({
+ icons : {
+ primary : "ui-icon-trash"
+ },
+ text : false
+ }).click(function() {
+ deleteUser(i);
+ });
+ });
+ return true;
+ });
+ });
+}
+
+/** How to delete a user by index (with dialog) */
+function deleteUser(idx) {
+ $("#dialog-confirm").dialog({
+ modal : true,
+ autoOpen : false,
+ buttons : {
+ "OK" : function() {
+ $(this).dialog("close");
+ deleteUrl(userinfo[idx].url, function() {
+ refreshUsers();
+ });
+ },
+ "Cancel" : function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ $("#dialog-confirm").dialog("open");
+}
+
+/** How to update a user's password by index (with dialog) */
+function updatePasswordUser(idx) {
+ $("#change-password").val("");
+ $("#change-password2").val("");
+ $("#dialog-password").dialog({
+ modal : true,
+ autoOpen : false,
+ buttons : {
+ "OK" : function() {
+ $(this).dialog("close");
+ var pass = $("#change-password").val();
+ var pass2 = $("#change-password2").val();
+ $("#change-password").val("");
+ $("#change-password2").val("");
+ if (pass.equals(pass2))
+ updateUser(idx, "password", pass);
+ },
+ "Cancel" : function() {
+ $(this).dialog("close");
+ $("#change-password").val("");
+ }
+ }
+ });
+ $("#dialog-password").dialog("open");
+}
+
+/** How to set a specific field of a user record */
+function updateUser(idx, field, value) {
+ var model = userinfo[idx].model;
+ var xml = Node("userDesc", Node("username", model.username),
+ field == "password" ? Node("password", value) : undefined,
+ field == "localUserId" ? Node("localUserId", value)
+ : model.localUserId == undefined ? undefined : Node(
+ "localUserId", model.localUserId), Node("enabled",
+ field == "enabled" ? value : model.enabled), Node("admin",
+ field == "admin" ? value : model.admin));
+ putXML(userinfo[idx].url, xml, function() {
+ refreshUsers();
+ });
+}
+
+/** How to configure all the buttons and entries */
+function connectButtonsAndEntries() {
+ $.each(buttonlist, function(idx, val) {
+ var widget = $("#" + val);
+ var u = where(val);
+ widget.button();
+ getText(u, function(data) {
+ widget.attr('checked', (data + "") != "false");
+ widget.button("refresh");
+ });
+ widget.change(function() {
+ putText(u, widget.attr("checked") == "checked", function(data) {
+ widget.attr('checked', (data + "") != "false");
+ widget.button("refresh");
+ return true;
+ });
+ });
+ });
+ $.each(entries, function(idx, val) {
+ var widget = $("#" + val);
+ var u = where(val);
+ getText(u, function(data) {
+ widget.val(data);
+ });
+ widget.change(function() {
+ putText(u, widget.val(), function(data) {
+ widget.val(data);
+ return true;
+ });
+ });
+ });
+}
+
+/** What happens when the user tries to make a new user */
+function makeNewUser() {
+ var sysid = $("#newSysID").val();
+ var newuserinfo = {
+ admin : $("#newAdmin").attr("checked") == "checked",
+ enabled : $("#newEnabled").attr("checked") == "checked",
+ username : $("#newUsername").val(),
+ password : $("#newPassword").val()
+ };
+ // Blank out the password immediately!
+ $("#newPassword").val("");
+ if (sysid.length > 0) {
+ newuserinfo.localUserId = sysid;
+ }
+ if (newuserinfo.username == "" || newuserinfo.password == "") {
+ alert("Won't create user; need a username and a password!");
+ return;
+ }
+ var xml = newuserinfo = Node("userDesc", Node("username",
+ newuserinfo.username), Node("password", newuserinfo.password),
+ newuserinfo.localUserId == undefined ? undefined : Node(
+ "localUserId", newuserinfo.localUserId), Node("enabled",
+ newuserinfo.enabled), Node("admin", newuserinfo.admin));
+ postXML(where("users"), xml, function() {
+ refreshUsers();
+ });
+}
+
+/** Handle the extra arguments */
+function loadExtraArgs() {
+ getJSON(where("extraArguments"),
+ function(data) {
+ var rows = data.stringList.string || [];
+ if ((typeof rows) == "string")
+ rows = [ rows ];
+ $(".extraargrow").remove();
+ extraAry = rows;
+ var i;
+ function row() {
+ var buf = "<tr class='extraargrow'>";
+ for ( var i = 1; i < arguments.length; i++)
+ buf += "<td>" + arguments[i] + "</td>";
+ return $(arguments[0]).append(buf + "</tr>");
+ }
+ function delbutn(id, what) {
+ return "<button id='" + id + "' title='Delete this " + what
+ + ".'>Del</button>";
+ }
+ for (i = 0; i < extraAry.length; i++) {
+ var rowid = "extradel" + i;
+ if (rows[i].match("^-D")) {
+ var m = rows[i].match("^-D([^=]*)=(.*)$");
+ row("#extraArguments-prop", delbutn(rowid,
+ "property assignment"), "<tt><b>-D</b>" + m[1]
+ + "<b>=</b>" + m[2] + "</tt>");
+ } else if (rows[i].match("-E")) {
+ var m = rows[i].match("^-E([^=]*)=(.*)$");
+ row("#extraArguments-env", delbutn(rowid,
+ "environment assignment"), "<tt><b>-E</b>"
+ + m[1] + "<b>=</b>" + m[2] + "</tt>");
+ } else {
+ var m = rows[i].match("^-J(.*)$");
+ row("#extraArguments-runtime", delbutn(rowid,
+ "runtime parameter"), "<tt><b>-J</b>" + m[1]
+ + "</tt>");
+ }
+ $("#" + rowid).button({
+ icons : {
+ primary : "ui-icon-trash"
+ },
+ text : false
+ }).click(
+ (function(row) {
+ return function() {
+ extraAry.splice(row, 1);
+ var xml = NodeAll("stringList", "string",
+ extraAry);
+ putXML(where("extraArguments"), xml,
+ function() {
+ loadExtraArgs();
+ });
+ };
+ })(i));
+ }
+ });
+}
+
+/** Run a dialog for creating an extra argument. */
+function addExtraArg(dialogId, prefix, part1id, part2id) {
+ $(dialogId).dialog({
+ modal : true,
+ autoOpen : false,
+ buttons : {
+ "OK" : function() {
+ $(this).dialog("close");
+ var str = prefix + $(part1id).val();
+ if (part2id != undefined)
+ str += "=" + $(part2id).val();
+ extraAry.push(str);
+ var xml = NodeAll("stringList", "string", extraAry);
+ putXML(where("extraArguments"), xml, function() {
+ loadExtraArgs();
+ });
+ },
+ "Cancel" : function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ $(dialogId).dialog("open");
+}
+
+/** Start everything going on page load */
+$(function() {
+ // Must be done in this order because the accordion is inside a tab
+ $("#a-worker").accordion({
+ collapsible : true,
+ fillSpace : true,
+ autoHeight : false
+ });
+ $("#body").tabs({
+ selected : 0
+ });
+ $("#saveWorkflows").button({
+ disabled : true
+ }).click(function(event) {
+ saveWorkflows();
+ event.preventDefault();
+ });
+ $("#refreshWorkflows").button({
+ disabled : true
+ }).click(function(event) {
+ refreshWorkflows();
+ event.preventDefault();
+ });
+ $("#emptyWorkflows").button({
+ disabled : true
+ }).click(function(event) {
+ emptyWorkflows();
+ event.preventDefault();
+ });
+
+ // Make the link to the list of usage records point correctly
+ // Original plan called for browsable table, but that's too slow
+ $("#ur").attr("href", where("usageRecords"));
+
+ connectButtonsAndEntries();
+ updateRO();
+ setInterval(updateRO, 30000);
+ refreshUsers();
+ refreshWorkflows();
+ $("#newEnabled").button();
+ $("#newAdmin").button({
+ icons : {
+ primary : "ui-icon-alert"
+ }
+ });
+ $("#makeNewUser").button().click(function() {
+ makeNewUser();
+ });
+ $("#extra-prop-add").button().click(function() {
+ addExtraArg("#dialog-property", "-D", "#prop-key", "#prop-value");
+ });
+ $("#extra-env-add").button().click(function() {
+ addExtraArg("#dialog-environment", "-E", "#env-key", "#env-value");
+ });
+ $("#extra-run-add").button().click(function() {
+ addExtraArg("#dialog-runtime", "-J", "#runtime-value");
+ });
+ loadExtraArgs();
+});
[09/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
new file mode 100644
index 0000000..22158d5
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
@@ -0,0 +1,967 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static java.lang.System.currentTimeMillis;
+import static java.util.Calendar.MINUTE;
+import static java.util.Collections.sort;
+import static java.util.Collections.unmodifiableSet;
+import static java.util.UUID.randomUUID;
+import static org.apache.commons.io.IOUtils.closeQuietly;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.worker.RemoteRunDelegate.checkBadFilename;
+import static org.taverna.server.master.worker.RunConnection.NAME_LENGTH;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PipedOutputStream;
+import java.rmi.MarshalledObject;
+import java.rmi.RemoteException;
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.annotation.Nonnull;
+
+import org.apache.commons.logging.Log;
+import org.taverna.server.localworker.remote.IllegalStateTransitionException;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.localworker.remote.RemoteDirectory;
+import org.taverna.server.localworker.remote.RemoteDirectoryEntry;
+import org.taverna.server.localworker.remote.RemoteFile;
+import org.taverna.server.localworker.remote.RemoteInput;
+import org.taverna.server.localworker.remote.RemoteListener;
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.localworker.remote.RemoteStatus;
+import org.taverna.server.localworker.remote.StillWorkingOnItException;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.OverloadedException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.Input;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.SecurityContextFactory;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Bridging shim between the WebApp world and the RMI world.
+ *
+ * @author Donal Fellows
+ */
+@SuppressWarnings("serial")
+public class RemoteRunDelegate implements TavernaRun {
+ private transient Log log = getLog("Taverna.Server.Worker");
+ transient TavernaSecurityContext secContext;
+ Date creationInstant;
+ Workflow workflow;
+ Date expiry;
+ HashSet<String> readers;
+ HashSet<String> writers;
+ HashSet<String> destroyers;
+ transient String id;
+ transient RemoteSingleRun run;
+ transient RunDBSupport db;
+ transient FactoryBean factory;
+ boolean doneTransitionToFinished;
+ boolean generateProvenance;// FIXME expose
+ String name;
+ private static final String ELLIPSIS = "...";
+
+ public RemoteRunDelegate(Date creationInstant, Workflow workflow,
+ RemoteSingleRun rsr, int defaultLifetime, RunDBSupport db, UUID id,
+ boolean generateProvenance, FactoryBean factory) {
+ if (rsr == null)
+ throw new IllegalArgumentException("remote run must not be null");
+ this.creationInstant = creationInstant;
+ this.workflow = workflow;
+ Calendar c = Calendar.getInstance();
+ c.add(MINUTE, defaultLifetime);
+ this.expiry = c.getTime();
+ this.run = rsr;
+ this.db = db;
+ this.generateProvenance = generateProvenance;
+ this.factory = factory;
+ try {
+ this.name = "";
+ String ci = " " + creationInstant;
+ String n = workflow.getName();
+ if (n.length() > NAME_LENGTH - ci.length())
+ n = n.substring(0,
+ NAME_LENGTH - ci.length() - ELLIPSIS.length())
+ + ELLIPSIS;
+ this.name = n + ci;
+ } catch (Exception e) {
+ // Ignore; it's just a name, not something important.
+ }
+ if (id != null)
+ this.id = id.toString();
+ }
+
+ RemoteRunDelegate() {
+ }
+
+ /**
+ * Get the types of listener supported by this run.
+ *
+ * @return A list of listener type names.
+ * @throws RemoteException
+ * If anything goes wrong.
+ */
+ public List<String> getListenerTypes() throws RemoteException {
+ return run.getListenerTypes();
+ }
+
+ @Override
+ public void addListener(Listener listener) {
+ if (listener instanceof ListenerDelegate)
+ try {
+ run.addListener(((ListenerDelegate) listener).getRemote());
+ } catch (RemoteException e) {
+ log.warn("communication problem adding listener", e);
+ } catch (ImplementationException e) {
+ log.warn("implementation problem adding listener", e);
+ }
+ else
+ log.fatal("bad listener " + listener.getClass()
+ + "; not applicable remotely!");
+ }
+
+ @Override
+ public String getId() {
+ if (id == null)
+ id = randomUUID().toString();
+ return id;
+ }
+
+ /**
+ * Attach a listener to a workflow run and return its local delegate.
+ *
+ * @param type
+ * The type of listener to create.
+ * @param config
+ * The configuration of the listener.
+ * @return The local delegate of the listener.
+ * @throws NoListenerException
+ * If anything goes wrong.
+ */
+ public Listener makeListener(String type, String config)
+ throws NoListenerException {
+ try {
+ return new ListenerDelegate(run.makeListener(type, config));
+ } catch (RemoteException e) {
+ throw new NoListenerException("failed to make listener", e);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ try {
+ run.destroy();
+ } catch (RemoteException | ImplementationException e) {
+ log.warn("failed to destroy run", e);
+ }
+ }
+
+ @Override
+ public Date getExpiry() {
+ return new Date(expiry.getTime());
+ }
+
+ @Override
+ public List<Listener> getListeners() {
+ List<Listener> listeners = new ArrayList<>();
+ try {
+ for (RemoteListener rl : run.getListeners())
+ listeners.add(new ListenerDelegate(rl));
+ } catch (RemoteException e) {
+ log.warn("failed to get listeners", e);
+ }
+ return listeners;
+ }
+
+ @Override
+ public TavernaSecurityContext getSecurityContext() {
+ return secContext;
+ }
+
+ @Override
+ public Status getStatus() {
+ try {
+ switch (run.getStatus()) {
+ case Initialized:
+ return Status.Initialized;
+ case Operating:
+ return Status.Operating;
+ case Stopped:
+ return Status.Stopped;
+ case Finished:
+ return Status.Finished;
+ }
+ } catch (RemoteException e) {
+ log.warn("problem getting remote status", e);
+ }
+ return Status.Finished;
+ }
+
+ @Override
+ public Workflow getWorkflow() {
+ return workflow;
+ }
+
+ @Override
+ public Directory getWorkingDirectory() throws FilesystemAccessException {
+ try {
+ return new DirectoryDelegate(run.getWorkingDirectory());
+ } catch (Throwable e) {
+ if (e.getCause() != null)
+ e = e.getCause();
+ throw new FilesystemAccessException(
+ "problem getting main working directory handle", e);
+ }
+ }
+
+ @Override
+ public void setExpiry(Date d) {
+ if (d.after(new Date()))
+ expiry = new Date(d.getTime());
+ db.flushToDisk(this);
+ }
+
+ @Override
+ public String setStatus(Status s) throws BadStateChangeException {
+ try {
+ log.info("setting status of run " + id + " to " + s);
+ switch (s) {
+ case Initialized:
+ run.setStatus(RemoteStatus.Initialized);
+ break;
+ case Operating:
+ if (run.getStatus() == RemoteStatus.Initialized) {
+ if (!factory.isAllowingRunsToStart())
+ throw new OverloadedException();
+ secContext.conveySecurity();
+ }
+ run.setGenerateProvenance(generateProvenance);
+ run.setStatus(RemoteStatus.Operating);
+ factory.getMasterEventFeed()
+ .started(
+ this,
+ "started run execution",
+ "The execution of run '" + getName()
+ + "' has started.");
+ break;
+ case Stopped:
+ run.setStatus(RemoteStatus.Stopped);
+ break;
+ case Finished:
+ run.setStatus(RemoteStatus.Finished);
+ break;
+ }
+ return null;
+ } catch (IllegalStateTransitionException e) {
+ throw new BadStateChangeException(e.getMessage());
+ } catch (RemoteException e) {
+ throw new BadStateChangeException(e.getMessage(), e.getCause());
+ } catch (GeneralSecurityException | IOException e) {
+ throw new BadStateChangeException(e.getMessage(), e);
+ } catch (ImplementationException e) {
+ if (e.getCause() != null)
+ throw new BadStateChangeException(e.getMessage(), e.getCause());
+ throw new BadStateChangeException(e.getMessage(), e);
+ } catch (StillWorkingOnItException e) {
+ log.info("still working on setting status of run " + id + " to "
+ + s, e);
+ return e.getMessage();
+ } catch (InterruptedException e) {
+ throw new BadStateChangeException(
+ "interrupted while waiting to insert notification into database");
+ }
+ }
+
+ static void checkBadFilename(String filename)
+ throws FilesystemAccessException {
+ if (filename.startsWith("/"))
+ throw new FilesystemAccessException("filename may not be absolute");
+ if (Arrays.asList(filename.split("/")).contains(".."))
+ throw new FilesystemAccessException(
+ "filename may not refer to parent");
+ }
+
+ @Override
+ public String getInputBaclavaFile() {
+ try {
+ return run.getInputBaclavaFile();
+ } catch (RemoteException e) {
+ log.warn("problem when fetching input baclava file", e);
+ return null;
+ }
+ }
+
+ @Override
+ public List<Input> getInputs() {
+ ArrayList<Input> inputs = new ArrayList<>();
+ try {
+ for (RemoteInput ri : run.getInputs())
+ inputs.add(new RunInput(ri));
+ } catch (RemoteException e) {
+ log.warn("problem when fetching list of workflow inputs", e);
+ }
+ return inputs;
+ }
+
+ @Override
+ public String getOutputBaclavaFile() {
+ try {
+ return run.getOutputBaclavaFile();
+ } catch (RemoteException e) {
+ log.warn("problem when fetching output baclava file", e);
+ return null;
+ }
+ }
+
+ @Override
+ public Input makeInput(String name) throws BadStateChangeException {
+ try {
+ return new RunInput(run.makeInput(name));
+ } catch (RemoteException e) {
+ throw new BadStateChangeException("failed to make input", e);
+ }
+ }
+
+ @Override
+ public void setInputBaclavaFile(String filename)
+ throws FilesystemAccessException, BadStateChangeException {
+ checkBadFilename(filename);
+ try {
+ run.setInputBaclavaFile(filename);
+ } catch (RemoteException e) {
+ throw new FilesystemAccessException(
+ "cannot set input baclava file name", e);
+ }
+ }
+
+ @Override
+ public void setOutputBaclavaFile(String filename)
+ throws FilesystemAccessException, BadStateChangeException {
+ checkBadFilename(filename);
+ try {
+ run.setOutputBaclavaFile(filename);
+ } catch (RemoteException e) {
+ throw new FilesystemAccessException(
+ "cannot set output baclava file name", e);
+ }
+ }
+
+ @Override
+ public Date getCreationTimestamp() {
+ return creationInstant == null ? null : new Date(
+ creationInstant.getTime());
+ }
+
+ @Override
+ public Date getFinishTimestamp() {
+ try {
+ return run.getFinishTimestamp();
+ } catch (RemoteException e) {
+ log.info("failed to get finish timestamp", e);
+ return null;
+ }
+ }
+
+ @Override
+ public Date getStartTimestamp() {
+ try {
+ return run.getStartTimestamp();
+ } catch (RemoteException e) {
+ log.info("failed to get finish timestamp", e);
+ return null;
+ }
+ }
+
+ /**
+ * @param readers
+ * the readers to set
+ */
+ public void setReaders(Set<String> readers) {
+ this.readers = new HashSet<>(readers);
+ db.flushToDisk(this);
+ }
+
+ /**
+ * @return the readers
+ */
+ public Set<String> getReaders() {
+ return readers == null ? new HashSet<String>()
+ : unmodifiableSet(readers);
+ }
+
+ /**
+ * @param writers
+ * the writers to set
+ */
+ public void setWriters(Set<String> writers) {
+ this.writers = new HashSet<>(writers);
+ db.flushToDisk(this);
+ }
+
+ /**
+ * @return the writers
+ */
+ public Set<String> getWriters() {
+ return writers == null ? new HashSet<String>()
+ : unmodifiableSet(writers);
+ }
+
+ /**
+ * @param destroyers
+ * the destroyers to set
+ */
+ public void setDestroyers(Set<String> destroyers) {
+ this.destroyers = new HashSet<>(destroyers);
+ db.flushToDisk(this);
+ }
+
+ /**
+ * @return the destroyers
+ */
+ public Set<String> getDestroyers() {
+ return destroyers == null ? new HashSet<String>()
+ : unmodifiableSet(destroyers);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ out.writeUTF(secContext.getOwner().getName());
+ out.writeObject(secContext.getFactory());
+ out.writeObject(new MarshalledObject<>(run));
+ }
+
+ @Override
+ public boolean getGenerateProvenance() {
+ return generateProvenance;
+ }
+
+ @Override
+ public void setGenerateProvenance(boolean generateProvenance) {
+ this.generateProvenance = generateProvenance;
+ db.flushToDisk(this);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ in.defaultReadObject();
+ if (log == null)
+ log = getLog("Taverna.Server.LocalWorker");
+ final String creatorName = in.readUTF();
+ SecurityContextFactory factory = (SecurityContextFactory) in
+ .readObject();
+ try {
+ secContext = factory.create(this,
+ new UsernamePrincipal(creatorName));
+ } catch (RuntimeException | IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SecurityContextReconstructionException(e);
+ }
+ run = ((MarshalledObject<RemoteSingleRun>) in.readObject()).get();
+ }
+
+ public void setSecurityContext(TavernaSecurityContext tavernaSecurityContext) {
+ secContext = tavernaSecurityContext;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void setName(@Nonnull String name) {
+ if (name.length() > RunConnection.NAME_LENGTH)
+ this.name = name.substring(0, RunConnection.NAME_LENGTH);
+ else
+ this.name = name;
+ db.flushToDisk(this);
+ }
+
+ @Override
+ public void ping() throws UnknownRunException {
+ try {
+ run.ping();
+ } catch (RemoteException e) {
+ throw new UnknownRunException(e);
+ }
+ }
+}
+
+abstract class DEDelegate implements DirectoryEntry {
+ Log log = getLog("Taverna.Server.Worker");
+ private RemoteDirectoryEntry entry;
+ private String name;
+ private String full;
+ private Date cacheModTime;
+ private long cacheQueryTime = 0L;
+
+ DEDelegate(RemoteDirectoryEntry entry) {
+ this.entry = entry;
+ }
+
+ @Override
+ public void destroy() throws FilesystemAccessException {
+ try {
+ entry.destroy();
+ } catch (IOException e) {
+ throw new FilesystemAccessException(
+ "failed to delete directory entry", e);
+ }
+ }
+
+ @Override
+ public String getFullName() {
+ if (full != null)
+ return full;
+ String n = getName();
+ RemoteDirectoryEntry re = entry;
+ try {
+ while (true) {
+ RemoteDirectory parent = re.getContainingDirectory();
+ if (parent == null)
+ break;
+ n = parent.getName() + "/" + n;
+ re = parent;
+ }
+ } catch (RemoteException e) {
+ log.warn("failed to generate full name", e);
+ }
+ return (full = n);
+ }
+
+ @Override
+ public String getName() {
+ if (name == null)
+ try {
+ name = entry.getName();
+ } catch (RemoteException e) {
+ log.error("failed to get name", e);
+ }
+ return name;
+ }
+
+ @Override
+ public Date getModificationDate() {
+ if (cacheModTime == null || currentTimeMillis() - cacheQueryTime < 5000)
+ try {
+ cacheModTime = entry.getModificationDate();
+ cacheQueryTime = currentTimeMillis();
+ } catch (RemoteException e) {
+ log.error("failed to get modification time", e);
+ }
+ return cacheModTime;
+ }
+
+ @Override
+ public int compareTo(DirectoryEntry de) {
+ return getFullName().compareTo(de.getFullName());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o != null && o instanceof DEDelegate
+ && getFullName().equals(((DEDelegate) o).getFullName());
+ }
+
+ @Override
+ public int hashCode() {
+ return getFullName().hashCode();
+ }
+}
+
+class DirectoryDelegate extends DEDelegate implements Directory {
+ RemoteDirectory rd;
+
+ DirectoryDelegate(RemoteDirectory dir) {
+ super(dir);
+ rd = dir;
+ }
+
+ @Override
+ public Collection<DirectoryEntry> getContents()
+ throws FilesystemAccessException {
+ ArrayList<DirectoryEntry> result = new ArrayList<>();
+ try {
+ for (RemoteDirectoryEntry rde : rd.getContents()) {
+ if (rde instanceof RemoteDirectory)
+ result.add(new DirectoryDelegate((RemoteDirectory) rde));
+ else
+ result.add(new FileDelegate((RemoteFile) rde));
+ }
+ } catch (IOException e) {
+ throw new FilesystemAccessException(
+ "failed to get directory contents", e);
+ }
+ return result;
+ }
+
+ @Override
+ public Collection<DirectoryEntry> getContentsByDate()
+ throws FilesystemAccessException {
+ ArrayList<DirectoryEntry> result = new ArrayList<>(getContents());
+ sort(result, new DateComparator());
+ return result;
+ }
+
+ static class DateComparator implements Comparator<DirectoryEntry> {
+ @Override
+ public int compare(DirectoryEntry a, DirectoryEntry b) {
+ return a.getModificationDate().compareTo(b.getModificationDate());
+ }
+ }
+
+ @Override
+ public File makeEmptyFile(Principal actor, String name)
+ throws FilesystemAccessException {
+ try {
+ return new FileDelegate(rd.makeEmptyFile(name));
+ } catch (IOException e) {
+ throw new FilesystemAccessException("failed to make empty file", e);
+ }
+ }
+
+ @Override
+ public Directory makeSubdirectory(Principal actor, String name)
+ throws FilesystemAccessException {
+ try {
+ return new DirectoryDelegate(rd.makeSubdirectory(name));
+ } catch (IOException e) {
+ throw new FilesystemAccessException("failed to make subdirectory",
+ e);
+ }
+ }
+
+ @Override
+ public ZipStream getContentsAsZip() throws FilesystemAccessException {
+ ZipStream zs = new ZipStream();
+
+ final ZipOutputStream zos;
+ try {
+ zos = new ZipOutputStream(new PipedOutputStream(zs));
+ } catch (IOException e) {
+ throw new FilesystemAccessException("problem building zip stream",
+ e);
+ }
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ zipDirectory(rd, null, zos);
+ } catch (IOException e) {
+ log.warn("problem when zipping directory", e);
+ } finally {
+ closeQuietly(zos);
+ }
+ }
+ });
+ t.setDaemon(true);
+ t.start();
+ return zs;
+ }
+
+ /**
+ * Compresses a directory tree into a ZIP.
+ *
+ * @param dir
+ * The directory to compress.
+ * @param base
+ * The base name of the directory (or <tt>null</tt> if this is
+ * the root directory of the ZIP).
+ * @param zos
+ * Where to write the compressed data.
+ * @throws RemoteException
+ * If some kind of problem happens with the remote delegates.
+ * @throws IOException
+ * If we run into problems with reading or writing data.
+ */
+ void zipDirectory(RemoteDirectory dir, String base, ZipOutputStream zos)
+ throws RemoteException, IOException {
+ for (RemoteDirectoryEntry rde : dir.getContents()) {
+ String name = rde.getName();
+ if (base != null)
+ name = base + "/" + name;
+ if (rde instanceof RemoteDirectory) {
+ RemoteDirectory rd = (RemoteDirectory) rde;
+ zipDirectory(rd, name, zos);
+ } else {
+ RemoteFile rf = (RemoteFile) rde;
+ zos.putNextEntry(new ZipEntry(name));
+ try {
+ int off = 0;
+ while (true) {
+ byte[] c = rf.getContents(off, 64 * 1024);
+ if (c == null || c.length == 0)
+ break;
+ zos.write(c);
+ off += c.length;
+ }
+ } finally {
+ zos.closeEntry();
+ }
+ }
+ }
+ }
+}
+
+class FileDelegate extends DEDelegate implements File {
+ RemoteFile rf;
+
+ FileDelegate(RemoteFile f) {
+ super(f);
+ this.rf = f;
+ }
+
+ @Override
+ public byte[] getContents(int offset, int length)
+ throws FilesystemAccessException {
+ try {
+ return rf.getContents(offset, length);
+ } catch (IOException e) {
+ throw new FilesystemAccessException("failed to read file contents",
+ e);
+ }
+ }
+
+ @Override
+ public long getSize() throws FilesystemAccessException {
+ try {
+ return rf.getSize();
+ } catch (IOException e) {
+ throw new FilesystemAccessException("failed to get file length", e);
+ }
+ }
+
+ @Override
+ public void setContents(byte[] data) throws FilesystemAccessException {
+ try {
+ rf.setContents(data);
+ } catch (IOException e) {
+ throw new FilesystemAccessException(
+ "failed to write file contents", e);
+ }
+ }
+
+ @Override
+ public void appendContents(byte[] data) throws FilesystemAccessException {
+ try {
+ rf.appendContents(data);
+ } catch (IOException e) {
+ throw new FilesystemAccessException(
+ "failed to write file contents", e);
+ }
+ }
+
+ @Override
+ public void copy(File from) throws FilesystemAccessException {
+ FileDelegate fromFile;
+ try {
+ fromFile = (FileDelegate) from;
+ } catch (ClassCastException e) {
+ throw new FilesystemAccessException("different types of File?!");
+ }
+
+ try {
+ rf.copy(fromFile.rf);
+ } catch (Exception e) {
+ throw new FilesystemAccessException("failed to copy file contents",
+ e);
+ }
+ return;
+ }
+}
+
+class ListenerDelegate implements Listener {
+ private Log log = getLog("Taverna.Server.Worker");
+ private RemoteListener r;
+ String conf;
+
+ ListenerDelegate(RemoteListener l) {
+ r = l;
+ }
+
+ RemoteListener getRemote() {
+ return r;
+ }
+
+ @Override
+ public String getConfiguration() {
+ try {
+ if (conf == null)
+ conf = r.getConfiguration();
+ } catch (RemoteException e) {
+ log.warn("failed to get configuration", e);
+ }
+ return conf;
+ }
+
+ @Override
+ public String getName() {
+ try {
+ return r.getName();
+ } catch (RemoteException e) {
+ log.warn("failed to get name", e);
+ return "UNKNOWN NAME";
+ }
+ }
+
+ @Override
+ public String getProperty(String propName) throws NoListenerException {
+ try {
+ return r.getProperty(propName);
+ } catch (RemoteException e) {
+ throw new NoListenerException("no such property: " + propName, e);
+ }
+ }
+
+ @Override
+ public String getType() {
+ try {
+ return r.getType();
+ } catch (RemoteException e) {
+ log.warn("failed to get type", e);
+ return "UNKNOWN TYPE";
+ }
+ }
+
+ @Override
+ public String[] listProperties() {
+ try {
+ return r.listProperties();
+ } catch (RemoteException e) {
+ log.warn("failed to list properties", e);
+ return new String[0];
+ }
+ }
+
+ @Override
+ public void setProperty(String propName, String value)
+ throws NoListenerException, BadPropertyValueException {
+ try {
+ r.setProperty(propName, value);
+ } catch (RemoteException e) {
+ log.warn("failed to set property", e);
+ if (e.getCause() != null
+ && e.getCause() instanceof RuntimeException)
+ throw new NoListenerException("failed to set property",
+ e.getCause());
+ if (e.getCause() != null && e.getCause() instanceof Exception)
+ throw new BadPropertyValueException("failed to set property",
+ e.getCause());
+ throw new BadPropertyValueException("failed to set property", e);
+ }
+ }
+}
+
+class RunInput implements Input {
+ private final RemoteInput i;
+
+ RunInput(RemoteInput remote) {
+ this.i = remote;
+ }
+
+ @Override
+ public String getFile() {
+ try {
+ return i.getFile();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String getName() {
+ try {
+ return i.getName();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String getValue() {
+ try {
+ return i.getValue();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void setFile(String file) throws FilesystemAccessException,
+ BadStateChangeException {
+ checkBadFilename(file);
+ try {
+ i.setFile(file);
+ } catch (RemoteException e) {
+ throw new FilesystemAccessException("cannot set file for input", e);
+ }
+ }
+
+ @Override
+ public void setValue(String value) throws BadStateChangeException {
+ try {
+ i.setValue(value);
+ } catch (RemoteException e) {
+ throw new BadStateChangeException(e);
+ }
+ }
+
+ @Override
+ public String getDelimiter() {
+ try {
+ return i.getDelimiter();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void setDelimiter(String delimiter) throws BadStateChangeException {
+ try {
+ if (delimiter != null)
+ delimiter = delimiter.substring(0, 1);
+ i.setDelimiter(delimiter);
+ } catch (RemoteException e) {
+ throw new BadStateChangeException(e);
+ }
+ }
+}
+
+@SuppressWarnings("serial")
+class SecurityContextReconstructionException extends RuntimeException {
+ public SecurityContextReconstructionException(Throwable t) {
+ super("failed to rebuild security context", t);
+ }
+}
\ 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/worker/RunConnection.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
new file mode 100644
index 0000000..cf55ea0
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.taverna.server.master.worker.RunConnection.COUNT_QUERY;
+import static org.taverna.server.master.worker.RunConnection.NAMES_QUERY;
+import static org.taverna.server.master.worker.RunConnection.SCHEMA;
+import static org.taverna.server.master.worker.RunConnection.TABLE;
+import static org.taverna.server.master.worker.RunConnection.TIMEOUT_QUERY;
+import static org.taverna.server.master.worker.RunConnection.UNTERMINATED_QUERY;
+
+import java.io.IOException;
+import java.rmi.MarshalledObject;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.jdo.annotations.Column;
+import javax.jdo.annotations.Join;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+import javax.jdo.annotations.Queries;
+import javax.jdo.annotations.Query;
+
+import org.taverna.server.localworker.remote.RemoteSingleRun;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.interfaces.SecurityContextFactory;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * The representation of the connections to the runs that actually participates
+ * in the persistence system.
+ *
+ * @author Donal Fellows
+ */
+@PersistenceCapable(table = TABLE, schema = SCHEMA)
+@Queries({
+ @Query(name = "count", language = "SQL", value = COUNT_QUERY, unique = "true", resultClass = Integer.class),
+ @Query(name = "names", language = "SQL", value = NAMES_QUERY, unique = "false", resultClass = String.class),
+ @Query(name = "unterminated", language = "SQL", value = UNTERMINATED_QUERY, unique = "false", resultClass = String.class),
+ @Query(name = "timedout", language = "SQL", value = TIMEOUT_QUERY, unique = "false", resultClass = String.class) })
+public class RunConnection {
+ static final String SCHEMA = "TAVERNA";
+ static final String TABLE = "RUN_CONNECTION";
+ private static final String FULL_NAME = SCHEMA + "." + TABLE;
+ static final String COUNT_QUERY = "SELECT count(*) FROM " + FULL_NAME;
+ static final String NAMES_QUERY = "SELECT ID FROM " + FULL_NAME;
+ static final String TIMEOUT_QUERY = "SELECT ID FROM " + FULL_NAME
+ + " WHERE expiry < CURRENT_TIMESTAMP";
+ static final String UNTERMINATED_QUERY = "SELECT ID FROM " + FULL_NAME
+ + " WHERE doneTransitionToFinished = 0";
+ static final int NAME_LENGTH = 48;
+
+ @PrimaryKey
+ @Column(length = 40)
+ private String id;
+
+ @Persistent(defaultFetchGroup = "true")
+ @Column(length = NAME_LENGTH)
+ private String name;
+
+ @Persistent(defaultFetchGroup = "true")
+ private Date creationInstant;
+
+ @Persistent(defaultFetchGroup = "true", serialized = "true")
+ @Column(jdbcType = "BLOB", sqlType = "BLOB")
+ private Workflow workflow;
+
+ @Persistent(defaultFetchGroup = "true")
+ private Date expiry;
+
+ @Persistent(defaultFetchGroup = "true")
+ @Join(table = TABLE + "_READERS", column = "ID")
+ private String[] readers;
+
+ @Persistent(defaultFetchGroup = "true")
+ @Join(table = TABLE + "_WRITERS", column = "ID")
+ private String[] writers;
+
+ @Persistent(defaultFetchGroup = "true")
+ @Join(table = TABLE + "_DESTROYERS", column = "ID")
+ private String[] destroyers;
+
+ @Persistent(defaultFetchGroup = "true", serialized = "true")
+ @Column(jdbcType = "BLOB", sqlType = "BLOB")
+ private MarshalledObject<RemoteSingleRun> run;
+
+ @Persistent(defaultFetchGroup = "true")
+ private int doneTransitionToFinished;
+
+ @Persistent(defaultFetchGroup = "true")
+ private int generateProvenance;
+
+ @Persistent(defaultFetchGroup = "true")
+ @Column(length = 128)
+ String owner;
+
+ @Persistent(defaultFetchGroup = "true")
+ @Column(length = 36)
+ private String securityToken;
+
+ @Persistent(defaultFetchGroup = "true", serialized = "true")
+ @Column(jdbcType = "BLOB", sqlType = "BLOB")
+ private SecurityContextFactory securityContextFactory;
+ @Persistent(defaultFetchGroup = "true", serialized = "true")
+ @Column(jdbcType = "BLOB", sqlType = "BLOB")
+ private Credential[] credentials;
+ @Persistent(defaultFetchGroup = "true", serialized = "true")
+ @Column(jdbcType = "BLOB", sqlType = "BLOB")
+ private Trust[] trust;
+
+ private static final String[] STRING_ARY = new String[0];
+
+ public String getId() {
+ return id;
+ }
+
+ public boolean isFinished() {
+ return doneTransitionToFinished != 0;
+ }
+
+ public void setFinished(boolean finished) {
+ doneTransitionToFinished = (finished ? 1 : 0);
+ }
+
+ public boolean isProvenanceGenerated() {
+ return generateProvenance != 0;
+ }
+
+ public void setProvenanceGenerated(boolean generate) {
+ generateProvenance = (generate ? 1 : 0);
+ }
+
+ /**
+ * Manufacture a persistent representation of the given workflow run. Must
+ * be called within the context of a transaction.
+ *
+ * @param rrd
+ * The remote delegate of the workflow run.
+ * @return The persistent object.
+ * @throws IOException
+ * If serialisation fails.
+ */
+ @Nonnull
+ public static RunConnection toDBform(@Nonnull RemoteRunDelegate rrd)
+ throws IOException {
+ RunConnection rc = new RunConnection();
+ rc.id = rrd.id;
+ rc.makeChanges(rrd);
+ return rc;
+ }
+
+ private static List<String> list(String[] ary) {
+ if (ary == null)
+ return emptyList();
+ return asList(ary);
+ }
+
+ /**
+ * Get the remote run delegate for a particular persistent connection. Must
+ * be called within the context of a transaction.
+ *
+ * @param db
+ * The database facade.
+ * @return The delegate object.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ @Nonnull
+ public RemoteRunDelegate fromDBform(@Nonnull RunDBSupport db)
+ throws Exception {
+ RemoteRunDelegate rrd = new RemoteRunDelegate();
+ rrd.id = getId();
+ rrd.creationInstant = creationInstant;
+ rrd.workflow = workflow;
+ rrd.expiry = expiry;
+ rrd.readers = new HashSet<>(list(readers));
+ rrd.writers = new HashSet<>(list(writers));
+ rrd.destroyers = new HashSet<>(list(destroyers));
+ rrd.run = run.get();
+ rrd.doneTransitionToFinished = isFinished();
+ rrd.generateProvenance = isProvenanceGenerated();
+ rrd.secContext = securityContextFactory.create(rrd,
+ new UsernamePrincipal(owner));
+ ((SecurityContextDelegate)rrd.secContext).setCredentialsAndTrust(credentials,trust);
+ rrd.db = db;
+ rrd.factory = db.getFactory();
+ rrd.name = name;
+ return rrd;
+ }
+
+ /**
+ * Flush changes from a remote run delegate to the database. Must be called
+ * within the context of a transaction.
+ *
+ * @param rrd
+ * The remote run delegate object that has potential changes.
+ * @throws IOException
+ * If anything goes wrong in serialization.
+ */
+ public void makeChanges(@Nonnull RemoteRunDelegate rrd) throws IOException {
+ // Properties that are set exactly once
+ if (creationInstant == null) {
+ creationInstant = rrd.getCreationTimestamp();
+ workflow = rrd.getWorkflow();
+ run = new MarshalledObject<>(rrd.run);
+ securityContextFactory = rrd.getSecurityContext().getFactory();
+ owner = rrd.getSecurityContext().getOwner().getName();
+ securityToken = ((org.taverna.server.master.worker.SecurityContextFactory) securityContextFactory)
+ .issueNewPassword();
+ }
+ // Properties that are set multiple times
+ expiry = rrd.getExpiry();
+ readers = rrd.getReaders().toArray(STRING_ARY);
+ writers = rrd.getWriters().toArray(STRING_ARY);
+ destroyers = rrd.getDestroyers().toArray(STRING_ARY);
+ credentials = rrd.getSecurityContext().getCredentials();
+ trust = rrd.getSecurityContext().getTrusted();
+ if (rrd.name.length() > NAME_LENGTH)
+ this.name = rrd.name.substring(0, NAME_LENGTH);
+ else
+ this.name = rrd.name;
+ setFinished(rrd.doneTransitionToFinished);
+ setProvenanceGenerated(rrd.generateProvenance);
+ }
+
+ public String getSecurityToken() {
+ return securityToken;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
new file mode 100644
index 0000000..2aa7ed1
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.taverna.server.master.notification.NotificationEngine;
+
+/**
+ * The interface to the database of runs.
+ *
+ * @author Donal Fellows
+ */
+public interface RunDBSupport {
+ /**
+ * Scan each run to see if it has finished yet and issue registered
+ * notifications if it has.
+ */
+ void checkForFinishNow();
+
+ /**
+ * Remove currently-expired runs from this database.
+ */
+ void cleanNow();
+
+ /**
+ * How many runs are stored in the database.
+ *
+ * @return The current size of the run table.
+ */
+ int countRuns();
+
+ /**
+ * Ensure that a run gets persisted in the database. It is assumed that the
+ * value is already in there.
+ *
+ * @param run
+ * The run to persist.
+ */
+ void flushToDisk(@Nonnull RemoteRunDelegate run);
+
+ /**
+ * Select an arbitrary representative run.
+ *
+ * @return The selected run.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ @Nullable
+ RemoteRunDelegate pickArbitraryRun() throws Exception;
+
+ /**
+ * Get a list of all the run names.
+ *
+ * @return The names (i.e., UUIDs) of all the runs.
+ */
+ @Nonnull
+ List<String> listRunNames();
+
+ /**
+ * @param notificationEngine
+ * A reference to the notification fabric bean.
+ */
+ void setNotificationEngine(NotificationEngine notificationEngine);
+
+ /**
+ * @param notifier
+ * A reference to the bean that creates messages about workflow
+ * run termination.
+ */
+ void setNotifier(CompletionNotifier notifier);
+
+ /**
+ * @return A reference to the actual factory for remote runs.
+ */
+ FactoryBean getFactory();
+}
\ 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/worker/RunDatabase.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
new file mode 100644
index 0000000..cedb4b5
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static java.lang.Integer.parseInt;
+import static java.util.UUID.randomUUID;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.RunStore;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.notification.NotificationEngine;
+import org.taverna.server.master.notification.NotificationEngine.Message;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * The main facade bean that interfaces to the database of runs.
+ *
+ * @author Donal Fellows
+ */
+public class RunDatabase implements RunStore, RunDBSupport {
+ private Log log = LogFactory.getLog("Taverna.Server.Worker.RunDB");
+ RunDatabaseDAO dao;
+ CompletionNotifier backupNotifier;
+ Map<String, CompletionNotifier> typedNotifiers;
+ private NotificationEngine notificationEngine;
+ @Autowired
+ private FactoryBean factory;
+ private Map<String, TavernaRun> cache = new HashMap<>();
+
+ @Override
+ @Required
+ public void setNotifier(CompletionNotifier n) {
+ backupNotifier = n;
+ }
+
+ public void setTypeNotifiers(List<CompletionNotifier> notifiers) {
+ typedNotifiers = new HashMap<>();
+ for (CompletionNotifier n : notifiers)
+ typedNotifiers.put(n.getName(), n);
+ }
+
+ @Required
+ @Override
+ public void setNotificationEngine(NotificationEngine notificationEngine) {
+ this.notificationEngine = notificationEngine;
+ }
+
+ @Required
+ public void setDao(RunDatabaseDAO dao) {
+ this.dao = dao;
+ }
+
+ @Override
+ public void checkForFinishNow() {
+ /*
+ * Get which runs are actually newly finished; this requires getting the
+ * candidates from the database and *then* doing the expensive requests
+ * to the back end to find out the status.
+ */
+ Map<String, RemoteRunDelegate> notifiable = new HashMap<>();
+ for (RemoteRunDelegate p : dao.getPotentiallyNotifiable())
+ if (p.getStatus() == Status.Finished)
+ notifiable.put(p.getId(), p);
+
+ // Check if there's nothing more to do
+ if (notifiable.isEmpty())
+ return;
+
+ /*
+ * Tell the database about the ones we've got.
+ */
+ dao.markFinished(notifiable.keySet());
+
+ /*
+ * Send out the notifications. The notification addresses are stored in
+ * the back-end engine, so this is *another* thing that can take time.
+ */
+ for (RemoteRunDelegate rrd : notifiable.values())
+ for (Listener l : rrd.getListeners())
+ if (l.getName().equals("io")) {
+ try {
+ notifyFinished(rrd.id, l, rrd);
+ } catch (Exception e) {
+ log.warn("failed to do notification of completion", e);
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void cleanNow() {
+ List<String> cleaned;
+ try {
+ cleaned = dao.doClean();
+ } catch (Exception e) {
+ log.warn("failure during deletion of expired runs", e);
+ return;
+ }
+ synchronized (cache) {
+ for (String id : cleaned)
+ cache.remove(id);
+ }
+ }
+
+ @Override
+ public int countRuns() {
+ return dao.countRuns();
+ }
+
+ @Override
+ public void flushToDisk(RemoteRunDelegate run) {
+ try {
+ dao.flushToDisk(run);
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "unexpected problem when persisting run record in database",
+ e);
+ }
+ }
+
+ @Override
+ public RemoteRunDelegate pickArbitraryRun() throws Exception {
+ return dao.pickArbitraryRun();
+ }
+
+ @Override
+ public List<String> listRunNames() {
+ return dao.listRunNames();
+ }
+
+ @Nullable
+ private TavernaRun get(String uuid) {
+ TavernaRun run = null;
+ synchronized (cache) {
+ run = cache.get(uuid);
+ }
+ try {
+ if (run != null)
+ run.ping();
+ } catch (UnknownRunException e) {
+ if (log.isDebugEnabled())
+ log.debug("stale mapping in cache?", e);
+ // Don't need to flush the cache; this happens when cleaning anyway
+ run = null;
+ }
+ if (run == null)
+ run = dao.get(uuid);
+ return run;
+ }
+
+ @Override
+ public TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
+ throws UnknownRunException {
+ // Check first to see if the 'uuid' actually looks like a UUID; if
+ // not, throw it out immediately without logging an exception.
+ try {
+ UUID.fromString(uuid);
+ } catch (IllegalArgumentException e) {
+ if (log.isDebugEnabled())
+ log.debug("run ID does not look like UUID; rejecting...");
+ throw new UnknownRunException();
+ }
+ TavernaRun run = get(uuid);
+ if (run != null && (user == null || p.permitAccess(user, run)))
+ return run;
+ throw new UnknownRunException();
+ }
+
+ @Override
+ public TavernaRun getRun(String uuid) throws UnknownRunException {
+ TavernaRun run = get(uuid);
+ if (run != null)
+ return run;
+ throw new UnknownRunException();
+ }
+
+ @Override
+ public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
+ synchronized (cache) {
+ Map<String, TavernaRun> cached = new HashMap<>();
+ for (Entry<String, TavernaRun> e : cache.entrySet()) {
+ TavernaRun r = e.getValue();
+ if (p.permitAccess(user, r))
+ cached.put(e.getKey(), r);
+ }
+ if (!cached.isEmpty())
+ return cached;
+ }
+ return dao.listRuns(user, p);
+ }
+
+ private void logLength(String message, Object obj) {
+ if (!log.isDebugEnabled())
+ return;
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ oos.writeObject(obj);
+ }
+ log.debug(message + ": " + baos.size());
+ } catch (Exception e) {
+ log.warn("oops", e);
+ }
+ }
+
+ @Override
+ public String registerRun(TavernaRun run) {
+ if (!(run instanceof RemoteRunDelegate))
+ throw new IllegalArgumentException(
+ "run must be created by localworker package");
+ RemoteRunDelegate rrd = (RemoteRunDelegate) run;
+ if (rrd.id == null)
+ rrd.id = randomUUID().toString();
+ logLength("RemoteRunDelegate serialized length", rrd);
+ try {
+ dao.persistRun(rrd);
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "unexpected problem when persisting run record in database",
+ e);
+ }
+ synchronized (cache) {
+ cache.put(rrd.getId(), run);
+ }
+ return rrd.getId();
+ }
+
+ @Override
+ public void unregisterRun(String uuid) {
+ try {
+ if (dao.unpersistRun(uuid))
+ synchronized (cache) {
+ cache.remove(uuid);
+ }
+ } catch (RuntimeException e) {
+ if (log.isDebugEnabled())
+ log.debug("problem persisting the deletion of the run " + uuid,
+ e);
+ }
+ }
+
+ /**
+ * Process the event that a run has finished.
+ *
+ * @param name
+ * The name of the run.
+ * @param io
+ * The io listener of the run (used to get information about the
+ * run).
+ * @param run
+ * The handle to the run.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ private void notifyFinished(final String name, Listener io,
+ final RemoteRunDelegate run) throws Exception {
+ String to = io.getProperty("notificationAddress");
+ final int code;
+ try {
+ code = parseInt(io.getProperty("exitcode"));
+ } catch (NumberFormatException nfe) {
+ // Ignore; not much we can do here...
+ return;
+ }
+
+ notificationEngine.dispatchMessage(run, to, new Message() {
+ private CompletionNotifier getNotifier(String type) {
+ CompletionNotifier n = typedNotifiers.get(type);
+ if (n == null)
+ n = backupNotifier;
+ return n;
+ }
+
+ @Override
+ public String getContent(String type) {
+ return getNotifier(type).makeCompletionMessage(name, run, code);
+ }
+
+ @Override
+ public String getTitle(String type) {
+ return getNotifier(type).makeMessageSubject(name, run, code);
+ }
+ });
+ }
+
+ @Override
+ public FactoryBean getFactory() {
+ return factory;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java
new file mode 100644
index 0000000..51931c0
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static org.taverna.server.master.worker.RunConnection.toDBform;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jdo.annotations.PersistenceAware;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.JDOSupport;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * This handles storing runs, interfacing with the underlying state engine as
+ * necessary.
+ *
+ * @author Donal Fellows
+ */
+@PersistenceAware
+public class RunDatabaseDAO extends JDOSupport<RunConnection> {
+ public RunDatabaseDAO() {
+ super(RunConnection.class);
+ }
+
+ private Log log = LogFactory.getLog("Taverna.Server.Worker.RunDB");
+ private RunDatabase facade;
+
+ @Required
+ public void setFacade(RunDatabase facade) {
+ this.facade = facade;
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+ @SuppressWarnings("unchecked")
+ private List<String> nameRuns() {
+ if (log.isDebugEnabled())
+ log.debug("fetching all run names");
+ return (List<String>) namedQuery("names").execute();
+ }
+
+ /**
+ * @return The number of workflow runs in the database.
+ */
+ @WithinSingleTransaction
+ public int countRuns() {
+ if (log.isDebugEnabled())
+ log.debug("counting the number of runs");
+ return (Integer) namedQuery("count").execute();
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<String> expiredRuns() {
+ return (List<String>) namedQuery("timedout").execute();
+ }
+
+ @SuppressWarnings("unchecked")
+ private List<String> unterminatedRuns() {
+ return (List<String>) namedQuery("unterminated").execute();
+ }
+
+ @Nullable
+ private RunConnection pickRun(@Nonnull String name) {
+ if (log.isDebugEnabled())
+ log.debug("fetching the run called " + name);
+ try {
+ RunConnection rc = getById(name);
+ if (rc == null)
+ log.warn("no result for " + name);
+ return rc;
+ } catch (RuntimeException e) {
+ log.warn("problem in fetch", e);
+ throw e;
+ }
+ }
+
+ @Nullable
+ @WithinSingleTransaction
+ public String getSecurityToken(@Nonnull String name) {
+ RunConnection rc = getById(name);
+ if (rc == null)
+ return null;
+ return rc.getSecurityToken();
+ }
+
+ private void persist(@Nonnull RemoteRunDelegate rrd) throws IOException {
+ persist(toDBform(rrd));
+ }
+
+ @Nonnull
+ private List<RunConnection> allRuns() {
+ try {
+ List<RunConnection> rcs = new ArrayList<>();
+ List<String> names = nameRuns();
+ for (String id : names) {
+ try {
+ if (id != null)
+ rcs.add(pickRun(id));
+ } catch (RuntimeException e) {
+ continue;
+ }
+ }
+ return rcs;
+ } catch (RuntimeException e) {
+ log.warn("problem in fetch", e);
+ throw e;
+ }
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+ /**
+ * Obtain a workflow run handle.
+ *
+ * @param name
+ * The identifier of the run.
+ * @return The run handle, or <tt>null</tt> if there is no such run.
+ */
+ @Nullable
+ @WithinSingleTransaction
+ public TavernaRun get(String name) {
+ try {
+ RunConnection rc = pickRun(name);
+ return (rc == null) ? null : rc.fromDBform(facade);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Get the runs that a user can read things from.
+ *
+ * @param user
+ * Who is asking?
+ * @param p
+ * The policy that determines what they can see.
+ * @return A mapping from run IDs to run handles.
+ */
+ @Nonnull
+ @WithinSingleTransaction
+ public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
+ Map<String, TavernaRun> result = new HashMap<>();
+ for (String id : nameRuns())
+ try {
+ RemoteRunDelegate rrd = pickRun(id).fromDBform(facade);
+ if (p.permitAccess(user, rrd))
+ result.put(id, rrd);
+ } catch (Exception e) {
+ continue;
+ }
+ return result;
+ }
+
+ /**
+ * @return A list of the IDs for all workflow runs.
+ */
+ @Nonnull
+ @WithinSingleTransaction
+ public List<String> listRunNames() {
+ List<String> runNames = new ArrayList<>();
+ for (RunConnection rc : allRuns())
+ if (rc.getId() != null)
+ runNames.add(rc.getId());
+ return runNames;
+ }
+
+ /**
+ * @return An arbitrary, representative workflow run.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ @Nullable
+ @WithinSingleTransaction
+ public RemoteRunDelegate pickArbitraryRun() throws Exception {
+ for (RunConnection rc : allRuns()) {
+ if (rc.getId() == null)
+ continue;
+ return rc.fromDBform(facade);
+ }
+ return null;
+ }
+
+ /**
+ * Make a workflow run persistent. Must only be called once per workflow
+ * run.
+ *
+ * @param rrd
+ * The workflow run to persist.
+ * @throws IOException
+ * If anything goes wrong with serialisation of the run.
+ */
+ @WithinSingleTransaction
+ public void persistRun(@Nonnull RemoteRunDelegate rrd) throws IOException {
+ persist(rrd);
+ }
+
+ /**
+ * Stop a workflow run from being persistent.
+ *
+ * @param name
+ * The ID of the run.
+ * @return Whether a deletion happened.
+ */
+ @WithinSingleTransaction
+ public boolean unpersistRun(String name) {
+ RunConnection rc = pickRun(name);
+ if (rc != null)
+ delete(rc);
+ return rc != null;
+ }
+
+ /**
+ * Ensure that the given workflow run is synchronized with the database.
+ *
+ * @param run
+ * The run to synchronise.
+ * @throws IOException
+ * If serialization of anything fails.
+ */
+ @WithinSingleTransaction
+ public void flushToDisk(@Nonnull RemoteRunDelegate run) throws IOException {
+ getById(run.id).makeChanges(run);
+ }
+
+ /**
+ * Remove all workflow runs that have expired.
+ *
+ * @return The ids of the deleted runs.
+ */
+ @Nonnull
+ @PerfLogged
+ @WithinSingleTransaction
+ public List<String> doClean() {
+ if (log.isDebugEnabled())
+ log.debug("deleting runs that timed out before " + new Date());
+ List<String> toDelete = expiredRuns();
+ if (log.isDebugEnabled())
+ log.debug("found " + toDelete.size() + " runs to delete");
+ for (String id : toDelete) {
+ RunConnection rc = getById(id);
+ try {
+ rc.fromDBform(facade).run.destroy();
+ } catch (Exception e) {
+ if (log.isDebugEnabled())
+ log.debug("failed to delete execution resource for " + id,
+ e);
+ }
+ delete(rc);
+ }
+ return toDelete;
+ }
+
+ /**
+ * @return A list of workflow runs that are candidates for doing
+ * notification of termination.
+ */
+ @Nonnull
+ @PerfLogged
+ @WithinSingleTransaction
+ public List<RemoteRunDelegate> getPotentiallyNotifiable() {
+ List<RemoteRunDelegate> toNotify = new ArrayList<>();
+ for (String id : unterminatedRuns())
+ try {
+ RunConnection rc = getById(id);
+ toNotify.add(rc.fromDBform(facade));
+ } catch (Exception e) {
+ log.warn("failed to fetch connection token"
+ + "for notification of completion check", e);
+ }
+ return toNotify;
+ }
+
+ @PerfLogged
+ @WithinSingleTransaction
+ public void markFinished(@Nonnull Set<String> terminated) {
+ for (String id : terminated) {
+ RunConnection rc = getById(id);
+ if (rc == null)
+ continue;
+ try {
+ rc.fromDBform(facade).doneTransitionToFinished = true;
+ rc.setFinished(true);
+ } catch (Exception e) {
+ log.warn("failed to note termination", e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java
new file mode 100644
index 0000000..29ac884
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java
@@ -0,0 +1,395 @@
+package org.taverna.server.master.worker;
+
+import static org.springframework.jmx.support.MetricType.COUNTER;
+import static org.springframework.jmx.support.MetricType.GAUGE;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.PreDestroy;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedMetric;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.taverna.server.master.factories.ConfigurableRunFactory;
+import org.taverna.server.master.localworker.LocalWorkerState;
+
+@ManagedResource(objectName = JMX_ROOT + "Factory", description = "The factory for runs.")
+public abstract class RunFactoryConfiguration implements ConfigurableRunFactory {
+ protected Log log = LogFactory.getLog("Taverna.Server.Worker");
+ protected LocalWorkerState state;
+ protected RunDBSupport runDB;
+ private int totalRuns = 0;
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ @Autowired(required = true)
+ @Order(0)
+ void setState(LocalWorkerState state) {
+ this.state = state;
+ }
+
+ @Autowired(required = true)
+ @Order(0)
+ void setRunDB(RunDBSupport runDB) {
+ this.runDB = runDB;
+ }
+
+ /**
+ * Drop any current references to the registry of runs, and kill off that
+ * process.
+ */
+ protected abstract void reinitRegistry();
+
+ /**
+ * Drop any current references to the run factory subprocess and kill it
+ * off.
+ */
+ protected abstract void reinitFactory();
+
+ /** Count the number of operating runs. */
+ protected abstract int operatingCount() throws Exception;
+
+ protected final synchronized void incrementRunCount() {
+ totalRuns++;
+ }
+
+ @Override
+ @ManagedAttribute(description = "Whether it is allowed to start a run executing.", currencyTimeLimit = 30)
+ public final boolean isAllowingRunsToStart() {
+ try {
+ return state.getOperatingLimit() > getOperatingCount();
+ } catch (Exception e) {
+ log.info("failed to get operating run count", e);
+ return false;
+ }
+ }
+
+ @Override
+ @ManagedAttribute(description = "The host holding the RMI registry to communicate via.")
+ public final String getRegistryHost() {
+ return state.getRegistryHost();
+ }
+
+ @Override
+ @ManagedAttribute(description = "The host holding the RMI registry to communicate via.")
+ public final void setRegistryHost(String host) {
+ state.setRegistryHost(host);
+ reinitRegistry();
+ reinitFactory();
+ }
+
+ @Override
+ @ManagedAttribute(description = "The port number of the RMI registry. Should not normally be set.")
+ public final int getRegistryPort() {
+ return state.getRegistryPort();
+ }
+
+ @Override
+ @ManagedAttribute(description = "The port number of the RMI registry. Should not normally be set.")
+ public final void setRegistryPort(int port) {
+ state.setRegistryPort(port);
+ reinitRegistry();
+ reinitFactory();
+ }
+
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "What JAR do we use to start the RMI registry process?")
+ public final String getRmiRegistryJar() {
+ return state.getRegistryJar();
+ }
+
+ @Override
+ @ManagedAttribute(description = "What JAR do we use to start the RMI registry process?")
+ public final void setRmiRegistryJar(String rmiRegistryJar) {
+ state.setRegistryJar(rmiRegistryJar);
+ reinitRegistry();
+ reinitFactory();
+ }
+
+ @Override
+ @ManagedAttribute(description = "The maximum number of simultaneous runs supported by the server.", currencyTimeLimit = 300)
+ public final int getMaxRuns() {
+ return state.getMaxRuns();
+ }
+
+ @Override
+ @ManagedAttribute(description = "The maximum number of simultaneous runs supported by the server.", currencyTimeLimit = 300)
+ public final void setMaxRuns(int maxRuns) {
+ state.setMaxRuns(maxRuns);
+ }
+
+ /** @return How many minutes should a workflow live by default? */
+ @Override
+ @ManagedAttribute(description = "How many minutes should a workflow live by default?", currencyTimeLimit = 300)
+ public final int getDefaultLifetime() {
+ return state.getDefaultLifetime();
+ }
+
+ /**
+ * Set how long a workflow should live by default.
+ *
+ * @param defaultLifetime
+ * Default lifetime, in minutes.
+ */
+ @Override
+ @ManagedAttribute(description = "How many minutes should a workflow live by default?", currencyTimeLimit = 300)
+ public final void setDefaultLifetime(int defaultLifetime) {
+ state.setDefaultLifetime(defaultLifetime);
+ }
+
+ /**
+ * @return How many milliseconds to wait between checks to see if a worker
+ * process has registered.
+ */
+ @Override
+ @ManagedAttribute(description = "How many milliseconds to wait between checks to see if a worker process has registered.", currencyTimeLimit = 300)
+ public final int getSleepTime() {
+ return state.getSleepMS();
+ }
+
+ /**
+ * @param sleepTime
+ * How many milliseconds to wait between checks to see if a
+ * worker process has registered.
+ */
+ @Override
+ @ManagedAttribute(description = "How many milliseconds to wait between checks to see if a worker process has registered.", currencyTimeLimit = 300)
+ public final void setSleepTime(int sleepTime) {
+ state.setSleepMS(sleepTime);
+ }
+
+ /**
+ * @return How many seconds to wait for a worker process to register itself.
+ */
+ @Override
+ @ManagedAttribute(description = "How many seconds to wait for a worker process to register itself.", currencyTimeLimit = 300)
+ public final int getWaitSeconds() {
+ return state.getWaitSeconds();
+ }
+
+ /**
+ * @param seconds
+ * How many seconds to wait for a worker process to register
+ * itself.
+ */
+ @Override
+ @ManagedAttribute(description = "How many seconds to wait for a worker process to register itself.", currencyTimeLimit = 300)
+ public final void setWaitSeconds(int seconds) {
+ state.setWaitSeconds(seconds);
+ }
+
+ /** @return The script to run to start running a workflow. */
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "The script to run to start running a workflow.", currencyTimeLimit = 300)
+ public final String getExecuteWorkflowScript() {
+ return state.getExecuteWorkflowScript();
+ }
+
+ /**
+ * @param executeWorkflowScript
+ * The script to run to start running a workflow.
+ */
+ @Override
+ @ManagedAttribute(description = "The script to run to start running a workflow.", currencyTimeLimit = 300)
+ public final void setExecuteWorkflowScript(String executeWorkflowScript) {
+ state.setExecuteWorkflowScript(executeWorkflowScript);
+ reinitFactory();
+ }
+
+ /** @return The location of the JAR implementing the server worker processes. */
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "The location of the JAR implementing the server worker processes.")
+ public final String getServerWorkerJar() {
+ return state.getServerWorkerJar();
+ }
+
+ /**
+ * @param serverWorkerJar
+ * The location of the JAR implementing the server worker
+ * processes.
+ */
+ @Override
+ @ManagedAttribute(description = "The location of the JAR implementing the server worker processes.")
+ public final void setServerWorkerJar(String serverWorkerJar) {
+ state.setServerWorkerJar(serverWorkerJar);
+ reinitFactory();
+ }
+
+ /** @return The list of additional arguments used to make a worker process. */
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "The list of additional arguments used to make a worker process.", currencyTimeLimit = 300)
+ public final String[] getExtraArguments() {
+ return state.getExtraArgs();
+ }
+
+ /**
+ * @param extraArguments
+ * The list of additional arguments used to make a worker
+ * process.
+ */
+ @Override
+ @ManagedAttribute(description = "The list of additional arguments used to make a worker process.", currencyTimeLimit = 300)
+ public final void setExtraArguments(@Nonnull String[] extraArguments) {
+ state.setExtraArgs(extraArguments);
+ reinitFactory();
+ }
+
+ /** @return Which java executable to run. */
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "Which java executable to run.", currencyTimeLimit = 300)
+ public final String getJavaBinary() {
+ return state.getJavaBinary();
+ }
+
+ /**
+ * @param javaBinary
+ * Which java executable to run.
+ */
+ @Override
+ @ManagedAttribute(description = "Which java executable to run.", currencyTimeLimit = 300)
+ public final void setJavaBinary(@Nonnull String javaBinary) {
+ state.setJavaBinary(javaBinary);
+ reinitFactory();
+ }
+
+ /**
+ * @return A file containing a password to use when running a program as
+ * another user (e.g., with sudo).
+ */
+ @Nullable
+ @Override
+ @ManagedAttribute(description = "A file containing a password to use when running a program as another user (e.g., with sudo).", currencyTimeLimit = 300)
+ public final String getPasswordFile() {
+ return state.getPasswordFile();
+ }
+
+ /**
+ * @param passwordFile
+ * A file containing a password to use when running a program as
+ * another user (e.g., with sudo).
+ */
+ @Override
+ @ManagedAttribute(description = "A file containing a password to use when running a program as another user (e.g., with sudo).", currencyTimeLimit = 300)
+ public final void setPasswordFile(@Nullable String passwordFile) {
+ state.setPasswordFile(passwordFile);
+ reinitFactory();
+ }
+
+ /**
+ * @return The location of the JAR implementing the secure-fork process.
+ */
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "The location of the JAR implementing the secure-fork process.", currencyTimeLimit = 300)
+ public final String getServerForkerJar() {
+ return state.getServerForkerJar();
+ }
+
+ /**
+ * @param serverForkerJar
+ * The location of the JAR implementing the secure-fork process.
+ */
+ @Override
+ @ManagedAttribute(description = "The location of the JAR implementing the secure-fork process.", currencyTimeLimit = 300)
+ public final void setServerForkerJar(String forkerJarFilename) {
+ state.setServerForkerJar(forkerJarFilename);
+ reinitFactory();
+ }
+
+ /**
+ * @return How many times has a workflow run been spawned by this engine.
+ * Restarts reset this counter.
+ */
+ @Override
+ @ManagedMetric(description = "How many times has a workflow run been spawned by this engine.", currencyTimeLimit = 10, metricType = COUNTER, category = "throughput")
+ public final synchronized int getTotalRuns() {
+ return totalRuns;
+ }
+
+ /**
+ * @return How many checks were done for the worker process the last time a
+ * spawn was tried.
+ */
+ @Override
+ @ManagedAttribute(description = "How many checks were done for the worker process the last time a spawn was tried.", currencyTimeLimit = 60)
+ public abstract int getLastStartupCheckCount();
+
+ @Nonnull
+ @Override
+ @ManagedAttribute(description = "The names of the current runs.", currencyTimeLimit = 5)
+ public final String[] getCurrentRunNames() {
+ List<String> names = runDB.listRunNames();
+ return names.toArray(new String[names.size()]);
+ }
+
+ @Override
+ @ManagedAttribute(description = "What the factory subprocess's main RMI interface is registered as.", currencyTimeLimit = 60)
+ public abstract String getFactoryProcessName();
+
+ /**
+ * @return What was the exit code from the last time the factory subprocess
+ * was killed?
+ */
+ @Override
+ @ManagedAttribute(description = "What was the exit code from the last time the factory subprocess was killed?")
+ public abstract Integer getLastExitCode();
+
+ /**
+ * @return The mapping of user names to RMI factory IDs.
+ */
+ @Override
+ @ManagedAttribute(description = "The mapping of user names to RMI factory IDs.", currencyTimeLimit = 60)
+ public abstract String[] getFactoryProcessMapping();
+
+ @Override
+ @ManagedAttribute(description = "The maximum number of simultaneous operating runs supported by the server.", currencyTimeLimit = 300)
+ public final void setOperatingLimit(int operatingLimit) {
+ state.setOperatingLimit(operatingLimit);
+ }
+
+ @Override
+ @ManagedAttribute(description = "The maximum number of simultaneous operating runs supported by the server.", currencyTimeLimit = 300)
+ public final int getOperatingLimit() {
+ return state.getOperatingLimit();
+ }
+
+ /**
+ * @return A count of the number of runs believed to actually be in the
+ * {@linkplain uk.org.taverna.server.master.common.Status#Operating
+ * operating} state.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ @Override
+ @ManagedMetric(description = "How many workflow runs are currently actually executing.", currencyTimeLimit = 10, metricType = GAUGE, category = "throughput")
+ public final int getOperatingCount() throws Exception {
+ return operatingCount();
+ }
+
+ @Override
+ @ManagedAttribute(description="Whether to tell a workflow to generate provenance bundles by default.")
+ public final void setGenerateProvenance(boolean genProv) {
+ state.setGenerateProvenance(genProv);
+ }
+
+ @Override
+ @ManagedAttribute(description="Whether to tell a workflow to generate provenance bundles by default.")
+ public final boolean getGenerateProvenance() {
+ return state.getGenerateProvenance();
+ }
+}
[21/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
----------------------------------------------------------------------
diff --git a/taverna-server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java b/taverna-server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
new file mode 100644
index 0000000..d12d3d8
--- /dev/null
+++ b/taverna-server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.ogf.usage;
+
+import static java.util.UUID.randomUUID;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.transform.dom.DOMSource;
+
+import org.ogf.usage.v1_0.Charge;
+import org.ogf.usage.v1_0.ConsumableResourceType;
+import org.ogf.usage.v1_0.CpuDuration;
+import org.ogf.usage.v1_0.Disk;
+import org.ogf.usage.v1_0.EndTime;
+import org.ogf.usage.v1_0.Host;
+import org.ogf.usage.v1_0.JobName;
+import org.ogf.usage.v1_0.MachineName;
+import org.ogf.usage.v1_0.Memory;
+import org.ogf.usage.v1_0.Network;
+import org.ogf.usage.v1_0.NodeCount;
+import org.ogf.usage.v1_0.Processors;
+import org.ogf.usage.v1_0.ProjectName;
+import org.ogf.usage.v1_0.Queue;
+import org.ogf.usage.v1_0.RecordIdentity;
+import org.ogf.usage.v1_0.ResourceType;
+import org.ogf.usage.v1_0.ServiceLevel;
+import org.ogf.usage.v1_0.StartTime;
+import org.ogf.usage.v1_0.Status;
+import org.ogf.usage.v1_0.SubmitHost;
+import org.ogf.usage.v1_0.Swap;
+import org.ogf.usage.v1_0.TimeDuration;
+import org.ogf.usage.v1_0.TimeInstant;
+import org.ogf.usage.v1_0.UserIdentity;
+import org.ogf.usage.v1_0.WallDuration;
+import org.w3c.dom.Element;
+
+@XmlRootElement(name = "UsageRecord", namespace = "http://schema.ogf.org/urf/2003/09/urf")
+public class JobUsageRecord extends org.ogf.usage.v1_0.UsageRecordType {
+ /**
+ * Create a new usage record with a random UUID as its identity.
+ *
+ * @throws DatatypeConfigurationException
+ * If the factory for XML-relevant datatypes fails to build; not
+ * expected.
+ */
+ public JobUsageRecord() throws DatatypeConfigurationException {
+ datatypeFactory = DatatypeFactory.newInstance();
+ RecordIdentity recid = new RecordIdentity();
+ recid.setRecordId(randomUUID().toString());
+ recid.setCreateTime(datatypeFactory
+ .newXMLGregorianCalendar(new GregorianCalendar()));
+ setRecordIdentity(recid);
+ }
+
+ /**
+ * Create a new usage record with a random UUID as its identity.
+ *
+ * @param name
+ * The name of the job to which this record pertains.
+ * @throws DatatypeConfigurationException
+ * If the factory for XML-relevant datatypes fails to build; not
+ * expected.
+ */
+ public JobUsageRecord(String name) throws DatatypeConfigurationException {
+ this();
+ setJobName(name);
+ }
+
+ @XmlTransient
+ private DatatypeFactory datatypeFactory;
+
+ public Status setStatus(String status) {
+ Status s = new Status();
+ s.setValue(status);
+ setStatus(s);
+ return s;
+ }
+
+ public WallDuration addWallDuration(long millis) {
+ WallDuration wall = new WallDuration();
+ wall.setValue(datatypeFactory.newDuration(millis));
+ getWallDurationOrCpuDurationOrNodeCount().add(wall);
+ return wall;
+ }
+
+ public CpuDuration addCpuDuration(long millis) {
+ CpuDuration cpu = new CpuDuration();
+ cpu.setValue(datatypeFactory.newDuration(millis));
+ getWallDurationOrCpuDurationOrNodeCount().add(cpu);
+ return cpu;
+ }
+
+ public NodeCount addNodeCount(int nodes) {
+ NodeCount nc = new NodeCount();
+ nc.setValue(BigInteger.valueOf(nodes));
+ getWallDurationOrCpuDurationOrNodeCount().add(nc);
+ return nc;
+ }
+
+ public Processors addProcessors(int processors) {
+ Processors pc = new Processors();
+ pc.setValue(BigInteger.valueOf(processors));
+ getWallDurationOrCpuDurationOrNodeCount().add(pc);
+ return pc;
+ }
+
+ public SubmitHost addSubmitHost(String host) {
+ SubmitHost sh = new SubmitHost();
+ sh.setValue(host);
+ getWallDurationOrCpuDurationOrNodeCount().add(sh);
+ return sh;
+ }
+
+ public Host addHost(String host) {
+ Host h = new Host();
+ h.setValue(host);
+ getWallDurationOrCpuDurationOrNodeCount().add(h);
+ return h;
+ }
+
+ public MachineName addMachine(String host) {
+ MachineName machine = new MachineName();
+ machine.setValue(host);
+ getWallDurationOrCpuDurationOrNodeCount().add(machine);
+ return machine;
+ }
+
+ public ProjectName addProject(String project) {
+ ProjectName p = new ProjectName();
+ p.setValue(project);
+ getWallDurationOrCpuDurationOrNodeCount().add(p);
+ return p;
+ }
+
+ public void addStartAndEnd(Date start, Date end) {
+ GregorianCalendar gc;
+
+ gc = new GregorianCalendar();
+ gc.setTime(start);
+ StartTime st = new StartTime();
+ st.setValue(datatypeFactory.newXMLGregorianCalendar(gc));
+ getWallDurationOrCpuDurationOrNodeCount().add(st);
+
+ gc = new GregorianCalendar();
+ gc.setTime(end);
+ EndTime et = new EndTime();
+ et.setValue(datatypeFactory.newXMLGregorianCalendar(gc));
+ getWallDurationOrCpuDurationOrNodeCount().add(et);
+ }
+
+ public Queue addQueue(String queue) {
+ Queue q = new Queue();
+ q.setValue(queue);
+ getWallDurationOrCpuDurationOrNodeCount().add(q);
+ return q;
+ }
+
+ public void addResource(ConsumableResourceType consumable) {
+ getWallDurationOrCpuDurationOrNodeCount().add(consumable);
+ }
+
+ public ResourceType addResource(ResourceType resource) {
+ getWallDurationOrCpuDurationOrNodeCount().add(resource);
+ return resource;
+ }
+
+ public ResourceType addResource(String description, String value) {
+ ResourceType resource = new ResourceType();
+ resource.setDescription(description);
+ resource.setValue(value);
+ getWallDurationOrCpuDurationOrNodeCount().add(resource);
+ return resource;
+ }
+
+ public ServiceLevel addServiceLevel(String service) {
+ ServiceLevel sl = new ServiceLevel();
+ sl.setValue(service);
+ getDiskOrMemoryOrSwap().add(sl);
+ return sl;
+ }
+
+ public Memory addMemory(long memory) {
+ Memory mem = new Memory();
+ mem.setValue(BigInteger.valueOf(memory));
+ getDiskOrMemoryOrSwap().add(mem);
+ return mem;
+ }
+
+ public TimeInstant addTimestamp(Date timestamp, String type) {
+ TimeInstant instant = new TimeInstant();
+ GregorianCalendar gc = new GregorianCalendar();
+ gc.setTime(timestamp);
+ instant.setValue(datatypeFactory.newXMLGregorianCalendar(gc));
+ instant.setType(type);
+ getDiskOrMemoryOrSwap().add(instant);
+ return instant;
+ }
+
+ public TimeDuration addDuration(long millis, String type) {
+ TimeDuration duration = new TimeDuration();
+ duration.setValue(datatypeFactory.newDuration(millis));
+ duration.setType(type);
+ getDiskOrMemoryOrSwap().add(duration);
+ return duration;
+ }
+
+ public Network addNetwork(long value) {
+ Network net = new Network();
+ net.setValue(BigInteger.valueOf(value));
+ getDiskOrMemoryOrSwap().add(net);
+ return net;
+ }
+
+ public Disk addDisk(long value) {
+ Disk disk = new Disk();
+ disk.setValue(BigInteger.valueOf(value));
+ getDiskOrMemoryOrSwap().add(disk);
+ return disk;
+ }
+
+ public Swap addSwap(long value) {
+ Swap net = new Swap();
+ net.setValue(BigInteger.valueOf(value));
+ getDiskOrMemoryOrSwap().add(net);
+ return net;
+ }
+
+ public UserIdentity addUser(String localUID, String globalName) {
+ UserIdentity user = new UserIdentity();
+ user.setLocalUserId(localUID);
+ user.setGlobalUserName(globalName);
+ getUserIdentity().add(user);
+ return user;
+ }
+
+ public JobName setJobName(String name) {
+ JobName jn = new JobName();
+ jn.setValue(name);
+ this.setJobName(jn);
+ return jn;
+ }
+
+ public Charge addCharge(float value) {
+ Charge c = new Charge();
+ c.setValue(value);
+ this.setCharge(c);
+ return c;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getOfType(Class<T> clazz) {
+ for (Object o : getWallDurationOrCpuDurationOrNodeCount())
+ if (clazz.isInstance(o))
+ return (T) o;
+ for (Object o : getDiskOrMemoryOrSwap())
+ if (clazz.isInstance(o))
+ return (T) o;
+ return null;
+ }
+
+ public String marshal() throws JAXBException {
+ StringWriter writer = new StringWriter();
+ JAXBContext.newInstance(getClass()).createMarshaller()
+ .marshal(this, writer);
+ return writer.toString();
+ }
+
+ private static JAXBContext context;
+ static {
+ try {
+ context = JAXBContext.newInstance(JobUsageRecord.class);
+ } catch (JAXBException e) {
+ throw new RuntimeException("failed to handle JAXB annotated class",
+ e);
+ }
+ }
+
+ public static JobUsageRecord unmarshal(String s) throws JAXBException {
+ return (JobUsageRecord) context.createUnmarshaller().unmarshal(
+ new StringReader(s));
+ }
+
+ public static JobUsageRecord unmarshal(Element elem) throws JAXBException {
+ return context.createUnmarshaller()
+ .unmarshal(new DOMSource(elem), JobUsageRecord.class)
+ .getValue();
+ }
+
+ // TODO: Add signing support
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-usagerecord/src/main/xsd/ur.xsd
----------------------------------------------------------------------
diff --git a/taverna-server-usagerecord/src/main/xsd/ur.xsd b/taverna-server-usagerecord/src/main/xsd/ur.xsd
new file mode 100644
index 0000000..16344a7
--- /dev/null
+++ b/taverna-server-usagerecord/src/main/xsd/ur.xsd
@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema attributeFormDefault="qualified" jaxb:version="2.1"
+ elementFormDefault="qualified" targetNamespace="http://schema.ogf.org/urf/2003/09/urf"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:urf="http://schema.ogf.org/urf/2003/09/urf"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd">
+ <xsd:annotation>
+ <!-- Copyright (c) 2003-2008 Open Grid Forum -->
+ <xsd:documentation xml:lang="en">Usage Record Working Group XML Schema definition</xsd:documentation>
+ <xsd:appinfo>
+ <jaxb:schemaBindings>
+ <jaxb:package name="org.ogf.usage.v1_0" />
+ </jaxb:schemaBindings>
+ </xsd:appinfo>
+ </xsd:annotation>
+ <xsd:import namespace="http://www.w3.org/2000/09/xmldsig#"
+ schemaLocation="xmlds.xsd" /> <!-- http://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd -->
+ <xsd:complexType name="UsageRecordType">
+ <xsd:sequence>
+ <xsd:element ref="urf:RecordIdentity" />
+ <xsd:element minOccurs="0" ref="urf:JobIdentity" />
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:UserIdentity" />
+ <xsd:element minOccurs="0" ref="urf:JobName" />
+ <xsd:element minOccurs="0" ref="urf:Charge" />
+ <xsd:element ref="urf:Status" />
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The elements grouped together in this choice may be represented
+ within a usage record multiple times. Each of these appearances
+ must be differentiated by the metric and/or type associated with
+ the element.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:element ref="urf:Disk" />
+ <xsd:element ref="urf:Memory" />
+ <xsd:element ref="urf:Swap" />
+ <xsd:element ref="urf:Network" />
+ <xsd:element ref="urf:TimeDuration" />
+ <xsd:element ref="urf:TimeInstant" />
+ <xsd:element ref="urf:ServiceLevel" />
+ </xsd:choice>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element minOccurs="0" ref="urf:WallDuration" />
+ <xsd:sequence minOccurs="0">
+ <xsd:element maxOccurs="2" minOccurs="0" ref="urf:CpuDuration" />
+ </xsd:sequence>
+ <xsd:element minOccurs="0" ref="urf:NodeCount" />
+ <xsd:element minOccurs="0" ref="urf:Processors" />
+ <xsd:element minOccurs="0" ref="urf:EndTime" />
+ <xsd:element minOccurs="0" ref="urf:StartTime" />
+ <xsd:element minOccurs="0" ref="urf:MachineName" />
+ <xsd:element minOccurs="0" ref="urf:SubmitHost" />
+ <xsd:element minOccurs="0" ref="urf:Queue" />
+ <xsd:sequence minOccurs="0">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:ProjectName" />
+ </xsd:sequence>
+ <xsd:sequence minOccurs="0">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:Host" />
+ </xsd:sequence>
+ <xsd:sequence minOccurs="0">
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="urf:PhaseResource" />
+ <xsd:element ref="urf:VolumeResource" />
+ <xsd:element ref="urf:Resource" />
+ <xsd:element ref="urf:ConsumableResource" />
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:element abstract="true" name="Usage" type="urf:UsageRecordType" />
+ <xsd:element name="UsageRecord" substitutionGroup="urf:Usage"
+ type="urf:UsageRecordType" />
+ <xsd:element name="JobUsageRecord" substitutionGroup="urf:Usage">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="urf:UsageRecordType" />
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="UsageRecords">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:Usage" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Common properties that may be measured with several different metrics
+ within the same usage record -->
+ <xsd:element name="Network">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attributeGroup ref="urf:intervallicVolume" />
+ <xsd:attribute default="total" ref="urf:metric" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Disk">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attributeGroup ref="urf:intervallicVolume" />
+ <xsd:attribute default="total" ref="urf:metric" use="optional" />
+ <xsd:attribute ref="urf:type" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Memory">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attributeGroup ref="urf:intervallicVolume" />
+ <xsd:attribute default="total" ref="urf:metric" use="optional" />
+ <xsd:attribute ref="urf:type" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Swap">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attributeGroup ref="urf:intervallicVolume" />
+ <xsd:attribute default="total" ref="urf:metric" use="optional" />
+ <xsd:attribute ref="urf:type" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="NodeCount">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attribute default="total" ref="urf:metric" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Processors">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attribute ref="urf:metric" use="optional" />
+ <xsd:attribute name="consumptionRate" type="xsd:float"
+ use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="TimeDuration">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:duration">
+ <xsd:attribute ref="urf:type" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="TimeInstant">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:attribute ref="urf:type" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ServiceLevel">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:token">
+ <xsd:attribute ref="urf:type" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- This element should appear at most twice within a usage record, with
+ differing values for usageType for each appearance -->
+ <xsd:element name="CpuDuration">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:duration">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attribute name="usageType">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="user" />
+ <xsd:enumeration value="system" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- These common properties should appear at most once within a usage record,
+ rather that at most once per metric per usage record -->
+ <xsd:element name="WallDuration">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:duration">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="EndTime">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="StartTime">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:dateTime">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="MachineName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="urf:domainNameType">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="SubmitHost">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="urf:domainNameType">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Host">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="urf:domainNameType">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attribute default="false" name="primary" type="xsd:boolean" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Queue">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="JobName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ProjectName">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Status">
+ <xsd:annotation>
+ <xsd:documentation>
+ Minimum required set = {Aborted, Completed, Failed,
+ Held, Queued, Started, Suspended}
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:token">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="Charge">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:float">
+ <xsd:attribute ref="urf:description" use="optional" />
+ <xsd:attribute ref="urf:unit" use="optional" />
+ <xsd:attribute name="formula" type="xsd:string" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- identity elements -->
+ <xsd:element name="JobIdentity">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="GlobalJobId" type="xsd:string" />
+ <xsd:element minOccurs="0" name="LocalJobId" type="xsd:string" />
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" minOccurs="0"
+ name="ProcessId" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="UserIdentity">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="LocalUserId" type="xsd:string" />
+ <xsd:element minOccurs="0" name="GlobalUserName" type="xsd:string" />
+ <xsd:element minOccurs="0" ref="ds:KeyInfo" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="RecordIdentity">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0">
+ <xsd:element ref="ds:KeyInfo" />
+ </xsd:sequence>
+ <xsd:attribute name="recordId" type="xsd:token" use="required" />
+ <xsd:attribute name="createTime" type="xsd:dateTime" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Extensibility Framework -->
+ <xsd:element name="Resource" type="urf:ResourceType" />
+ <xsd:element name="ConsumableResource" type="urf:ConsumableResourceType" />
+ <xsd:element name="PhaseResource">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="urf:ConsumableResourceType">
+ <xsd:attribute ref="urf:phaseUnit" use="optional" />
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="VolumeResource">
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="urf:ConsumableResourceType">
+ <xsd:attribute ref="urf:storageUnit" use="optional" />
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Create a generic consumable resource. Carries the units attribute -->
+ <xsd:complexType name="ConsumableResourceType">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:float">
+ <xsd:attribute name="units" type="xsd:string" use="optional" />
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <!-- Create a generic resource type -->
+ <xsd:complexType name="ResourceType">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="urf:description" use="optional" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <!-- Global Attribute Definitions -->
+ <xsd:attribute name="description" type="xsd:string" />
+ <!-- Units of measure attribute definitions -->
+ <xsd:attribute name="unit" type="xsd:token" />
+ <xsd:attribute name="storageUnit">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="b" />
+ <xsd:enumeration value="B" />
+ <xsd:enumeration value="KB" />
+ <xsd:enumeration value="MB" />
+ <xsd:enumeration value="GB" />
+ <xsd:enumeration value="PB" />
+ <xsd:enumeration value="EB" />
+ <xsd:enumeration value="Kb" />
+ <xsd:enumeration value="Mb" />
+ <xsd:enumeration value="Gb" />
+ <xsd:enumeration value="Pb" />
+ <xsd:enumeration value="Eb" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="phaseUnit" type="xsd:duration" />
+ <xsd:attributeGroup name="intervallicVolume">
+ <xsd:attribute ref="urf:storageUnit" use="optional" />
+ <xsd:attribute ref="urf:phaseUnit" use="optional" />
+ </xsd:attributeGroup>
+ <!-- End units attributes -->
+ <xsd:attribute name="metric" type="xsd:token" />
+ <xsd:attribute name="type" type="xsd:token" />
+ <!-- Simple type definitions used to constrain values of attributes -->
+ <xsd:simpleType name="domainNameType">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern
+ value="([a-zA-Z0-9][a-zA-Z0-9'\-']*[a-zA-Z0-9]\.)*([a-zA-Z0-9][a-zA-Z0-9'\-']*[a-zA-Z0-9])?" />
+ <xsd:maxLength value="255" />
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-usagerecord/src/main/xsd/xmlds.xsd
----------------------------------------------------------------------
diff --git a/taverna-server-usagerecord/src/main/xsd/xmlds.xsd b/taverna-server-usagerecord/src/main/xsd/xmlds.xsd
new file mode 100644
index 0000000..c3421c4
--- /dev/null
+++ b/taverna-server-usagerecord/src/main/xsd/xmlds.xsd
@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE schema
+ PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
+ [
+ <!ATTLIST schema
+ xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
+ <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
+ <!ENTITY % p ''>
+ <!ENTITY % s ''>
+ ]>
+
+<!-- Schema for XML Signatures
+ http://www.w3.org/2000/09/xmldsig#
+ $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
+
+ Copyright 2001 The Internet Society and W3C (Massachusetts Institute
+ of Technology, Institut National de Recherche en Informatique et en
+ Automatique, Keio University). All Rights Reserved.
+ http://www.w3.org/Consortium/Legal/
+
+ This document is governed by the W3C Software License [1] as described
+ in the FAQ [2].
+
+ [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
+ [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
+-->
+
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ targetNamespace="http://www.w3.org/2000/09/xmldsig#"
+ version="0.1" elementFormDefault="qualified">
+
+<!-- Basic Types Defined for Signatures -->
+
+<simpleType name="CryptoBinary">
+ <restriction base="base64Binary">
+ </restriction>
+</simpleType>
+
+<!-- Start Signature -->
+
+<element name="Signature" type="ds:SignatureType"/>
+<complexType name="SignatureType">
+ <sequence>
+ <element ref="ds:SignedInfo"/>
+ <element ref="ds:SignatureValue"/>
+ <element ref="ds:KeyInfo" minOccurs="0"/>
+ <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+ <element name="SignatureValue" type="ds:SignatureValueType"/>
+ <complexType name="SignatureValueType">
+ <simpleContent>
+ <extension base="base64Binary">
+ <attribute name="Id" type="ID" use="optional"/>
+ </extension>
+ </simpleContent>
+ </complexType>
+
+<!-- Start SignedInfo -->
+
+<element name="SignedInfo" type="ds:SignedInfoType"/>
+<complexType name="SignedInfoType">
+ <sequence>
+ <element ref="ds:CanonicalizationMethod"/>
+ <element ref="ds:SignatureMethod"/>
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+ <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
+ <complexType name="CanonicalizationMethodType" mixed="true">
+ <sequence>
+ <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
+ <!-- (0,unbounded) elements from (1,1) namespace -->
+ </sequence>
+ <attribute name="Algorithm" type="anyURI" use="required"/>
+ </complexType>
+
+ <element name="SignatureMethod" type="ds:SignatureMethodType"/>
+ <complexType name="SignatureMethodType" mixed="true">
+ <sequence>
+ <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+ <!-- (0,unbounded) elements from (1,1) external namespace -->
+ </sequence>
+ <attribute name="Algorithm" type="anyURI" use="required"/>
+ </complexType>
+
+<!-- Start Reference -->
+
+<element name="Reference" type="ds:ReferenceType"/>
+<complexType name="ReferenceType">
+ <sequence>
+ <element ref="ds:Transforms" minOccurs="0"/>
+ <element ref="ds:DigestMethod"/>
+ <element ref="ds:DigestValue"/>
+ </sequence>
+ <attribute name="Id" type="ID" use="optional"/>
+ <attribute name="URI" type="anyURI" use="optional"/>
+ <attribute name="Type" type="anyURI" use="optional"/>
+</complexType>
+
+ <element name="Transforms" type="ds:TransformsType"/>
+ <complexType name="TransformsType">
+ <sequence>
+ <element ref="ds:Transform" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+
+ <element name="Transform" type="ds:TransformType"/>
+ <complexType name="TransformType" mixed="true">
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <any namespace="##other" processContents="lax"/>
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
+ <element name="XPath" type="string"/>
+ </choice>
+ <attribute name="Algorithm" type="anyURI" use="required"/>
+ </complexType>
+
+<!-- End Reference -->
+
+<element name="DigestMethod" type="ds:DigestMethodType"/>
+<complexType name="DigestMethodType" mixed="true">
+ <sequence>
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="Algorithm" type="anyURI" use="required"/>
+</complexType>
+
+<element name="DigestValue" type="ds:DigestValueType"/>
+<simpleType name="DigestValueType">
+ <restriction base="base64Binary"/>
+</simpleType>
+
+<!-- End SignedInfo -->
+
+<!-- Start KeyInfo -->
+
+<element name="KeyInfo" type="ds:KeyInfoType"/>
+<complexType name="KeyInfoType" mixed="true">
+ <choice maxOccurs="unbounded">
+ <element ref="ds:KeyName"/>
+ <element ref="ds:KeyValue"/>
+ <element ref="ds:RetrievalMethod"/>
+ <element ref="ds:X509Data"/>
+ <element ref="ds:PGPData"/>
+ <element ref="ds:SPKIData"/>
+ <element ref="ds:MgmtData"/>
+ <any processContents="lax" namespace="##other"/>
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
+ </choice>
+ <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+ <element name="KeyName" type="string"/>
+ <element name="MgmtData" type="string"/>
+
+ <element name="KeyValue" type="ds:KeyValueType"/>
+ <complexType name="KeyValueType" mixed="true">
+ <choice>
+ <element ref="ds:DSAKeyValue"/>
+ <element ref="ds:RSAKeyValue"/>
+ <any namespace="##other" processContents="lax"/>
+ </choice>
+ </complexType>
+
+ <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
+ <complexType name="RetrievalMethodType">
+ <sequence>
+ <element ref="ds:Transforms" minOccurs="0"/>
+ </sequence>
+ <attribute name="URI" type="anyURI"/>
+ <attribute name="Type" type="anyURI" use="optional"/>
+ </complexType>
+
+<!-- Start X509Data -->
+
+<element name="X509Data" type="ds:X509DataType"/>
+<complexType name="X509DataType">
+ <sequence maxOccurs="unbounded">
+ <choice>
+ <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+ <element name="X509SKI" type="base64Binary"/>
+ <element name="X509SubjectName" type="string"/>
+ <element name="X509Certificate" type="base64Binary"/>
+ <element name="X509CRL" type="base64Binary"/>
+ <any namespace="##other" processContents="lax"/>
+ </choice>
+ </sequence>
+</complexType>
+
+<complexType name="X509IssuerSerialType">
+ <sequence>
+ <element name="X509IssuerName" type="string"/>
+ <element name="X509SerialNumber" type="integer"/>
+ </sequence>
+</complexType>
+
+<!-- End X509Data -->
+
+<!-- Begin PGPData -->
+
+<element name="PGPData" type="ds:PGPDataType"/>
+<complexType name="PGPDataType">
+ <choice>
+ <sequence>
+ <element name="PGPKeyID" type="base64Binary"/>
+ <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
+ <any namespace="##other" processContents="lax" minOccurs="0"
+ maxOccurs="unbounded"/>
+ </sequence>
+ <sequence>
+ <element name="PGPKeyPacket" type="base64Binary"/>
+ <any namespace="##other" processContents="lax" minOccurs="0"
+ maxOccurs="unbounded"/>
+ </sequence>
+ </choice>
+</complexType>
+
+<!-- End PGPData -->
+
+<!-- Begin SPKIData -->
+
+<element name="SPKIData" type="ds:SPKIDataType"/>
+<complexType name="SPKIDataType">
+ <sequence maxOccurs="unbounded">
+ <element name="SPKISexp" type="base64Binary"/>
+ <any namespace="##other" processContents="lax" minOccurs="0"/>
+ </sequence>
+</complexType>
+
+<!-- End SPKIData -->
+
+<!-- End KeyInfo -->
+
+<!-- Start Object (Manifest, SignatureProperty) -->
+
+<element name="Object" type="ds:ObjectType"/>
+<complexType name="ObjectType" mixed="true">
+ <sequence minOccurs="0" maxOccurs="unbounded">
+ <any namespace="##any" processContents="lax"/>
+ </sequence>
+ <attribute name="Id" type="ID" use="optional"/>
+ <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
+ <attribute name="Encoding" type="anyURI" use="optional"/>
+</complexType>
+
+<element name="Manifest" type="ds:ManifestType"/>
+<complexType name="ManifestType">
+ <sequence>
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+<element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
+<complexType name="SignaturePropertiesType">
+ <sequence>
+ <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+ <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
+ <complexType name="SignaturePropertyType" mixed="true">
+ <choice maxOccurs="unbounded">
+ <any namespace="##other" processContents="lax"/>
+ <!-- (1,1) elements from (1,unbounded) namespaces -->
+ </choice>
+ <attribute name="Target" type="anyURI" use="required"/>
+ <attribute name="Id" type="ID" use="optional"/>
+ </complexType>
+
+<!-- End Object (Manifest, SignatureProperty) -->
+
+<!-- Start Algorithm Parameters -->
+
+<simpleType name="HMACOutputLengthType">
+ <restriction base="integer"/>
+</simpleType>
+
+<!-- Start KeyValue Element-types -->
+
+<element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
+<complexType name="DSAKeyValueType">
+ <sequence>
+ <sequence minOccurs="0">
+ <element name="P" type="ds:CryptoBinary"/>
+ <element name="Q" type="ds:CryptoBinary"/>
+ </sequence>
+ <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
+ <element name="Y" type="ds:CryptoBinary"/>
+ <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
+ <sequence minOccurs="0">
+ <element name="Seed" type="ds:CryptoBinary"/>
+ <element name="PgenCounter" type="ds:CryptoBinary"/>
+ </sequence>
+ </sequence>
+</complexType>
+
+<element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
+<complexType name="RSAKeyValueType">
+ <sequence>
+ <element name="Modulus" type="ds:CryptoBinary"/>
+ <element name="Exponent" type="ds:CryptoBinary"/>
+ </sequence>
+</complexType>
+
+<!-- End KeyValue Element-types -->
+
+<!-- End Signature -->
+
+</schema>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-usagerecord/src/test/java/TestUR.java
----------------------------------------------------------------------
diff --git a/taverna-server-usagerecord/src/test/java/TestUR.java b/taverna-server-usagerecord/src/test/java/TestUR.java
new file mode 100644
index 0000000..42e9000
--- /dev/null
+++ b/taverna-server-usagerecord/src/test/java/TestUR.java
@@ -0,0 +1,120 @@
+import static java.lang.Runtime.getRuntime;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.JAXBIntrospector;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.ogf.usage.JobUsageRecord;
+import org.ogf.usage.v1_0.Charge;
+import org.ogf.usage.v1_0.CpuDuration;
+import org.ogf.usage.v1_0.Disk;
+import org.ogf.usage.v1_0.EndTime;
+import org.ogf.usage.v1_0.Host;
+import org.ogf.usage.v1_0.JobIdentity;
+import org.ogf.usage.v1_0.JobName;
+import org.ogf.usage.v1_0.MachineName;
+import org.ogf.usage.v1_0.Memory;
+import org.ogf.usage.v1_0.Network;
+import org.ogf.usage.v1_0.NodeCount;
+import org.ogf.usage.v1_0.PhaseResource;
+import org.ogf.usage.v1_0.Processors;
+import org.ogf.usage.v1_0.ProjectName;
+import org.ogf.usage.v1_0.Queue;
+import org.ogf.usage.v1_0.RecordIdentity;
+import org.ogf.usage.v1_0.ServiceLevel;
+import org.ogf.usage.v1_0.StartTime;
+import org.ogf.usage.v1_0.Status;
+import org.ogf.usage.v1_0.SubmitHost;
+import org.ogf.usage.v1_0.Swap;
+import org.ogf.usage.v1_0.TimeDuration;
+import org.ogf.usage.v1_0.TimeInstant;
+import org.ogf.usage.v1_0.UserIdentity;
+import org.ogf.usage.v1_0.VolumeResource;
+import org.ogf.usage.v1_0.WallDuration;
+
+public class TestUR {
+ SchemaOutputResolver sink;
+ StringWriter writer;
+
+ String result() {
+ return writer.toString();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ writer = new StringWriter();
+ sink = new SchemaOutputResolver() {
+ @Override
+ public Result createOutput(String namespaceUri,
+ String suggestedFileName) throws IOException {
+ StreamResult sr = new StreamResult(writer);
+ sr.setSystemId("/dev/null");
+ return sr;
+ }
+ };
+ Assert.assertNull(null);// Shut up, Eclipse!
+ Assert.assertEquals("", result());
+ }
+
+ @Test
+ public void testSchema() throws JAXBException, IOException {
+ JAXBContext.newInstance(JobUsageRecord.class).generateSchema(sink);
+ Assert.assertNotSame("", result());
+ }
+
+ @Test
+ public void testSchemaCompleteness() throws JAXBException, DatatypeConfigurationException {
+ JAXBIntrospector info = JAXBContext.newInstance(JobUsageRecord.class).createJAXBIntrospector();
+ Assert.assertTrue(info.isElement(new Charge()));
+ Assert.assertTrue(info.isElement(new CpuDuration()));
+ Assert.assertTrue(info.isElement(new Disk()));
+ Assert.assertTrue(info.isElement(new EndTime()));
+ Assert.assertTrue(info.isElement(new Host()));
+ Assert.assertTrue(info.isElement(new JobIdentity()));
+ Assert.assertTrue(info.isElement(new JobName()));
+ Assert.assertTrue(info.isElement(new JobUsageRecord()));
+ Assert.assertTrue(info.isElement(new MachineName()));
+ Assert.assertTrue(info.isElement(new Memory()));
+ Assert.assertTrue(info.isElement(new Network()));
+ Assert.assertTrue(info.isElement(new NodeCount()));
+ Assert.assertTrue(info.isElement(new PhaseResource()));
+ Assert.assertTrue(info.isElement(new Processors()));
+ Assert.assertTrue(info.isElement(new ProjectName()));
+ Assert.assertTrue(info.isElement(new Queue()));
+ Assert.assertTrue(info.isElement(new RecordIdentity()));
+ Assert.assertTrue(info.isElement(new ServiceLevel()));
+ Assert.assertTrue(info.isElement(new StartTime()));
+ Assert.assertTrue(info.isElement(new Status()));
+ Assert.assertTrue(info.isElement(new SubmitHost()));
+ Assert.assertTrue(info.isElement(new Swap()));
+ Assert.assertTrue(info.isElement(new TimeDuration()));
+ Assert.assertTrue(info.isElement(new TimeInstant()));
+ Assert.assertTrue(info.isElement(new UserIdentity()));
+ Assert.assertTrue(info.isElement(new VolumeResource()));
+ Assert.assertTrue(info.isElement(new WallDuration()));
+ }
+
+ @Test
+ public void testGenerate() throws DatatypeConfigurationException,
+ JAXBException {
+ JobUsageRecord ur = new JobUsageRecord();
+ ur.setStatus("Completed");
+ ur.addWallDuration(1000 * 65);
+ ur.addHost("localhost");
+ ur.addMemory(getRuntime().totalMemory() - getRuntime().freeMemory()).setType("vm");
+
+ String record = ur.marshal();
+ Assert.assertNotSame("", record);
+ //System.out.println(record);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/.gitignore
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/.gitignore b/taverna-server-webapp/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/taverna-server-webapp/.gitignore
@@ -0,0 +1 @@
+/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/pom.xml b/taverna-server-webapp/pom.xml
new file mode 100644
index 0000000..f4cf0ef
--- /dev/null
+++ b/taverna-server-webapp/pom.xml
@@ -0,0 +1,889 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>Apache Taverna Server Web Application Core</name>
+ <description>This is the implementation of the web-app that provides the Taverna Server with its SOAP and REST faces. It relies on the worker process to handle the actual launching of workflow runs.</description>
+
+ <properties>
+ <version.cxf>2.7.7</version.cxf>
+ <version.spring>3.2.5.RELEASE</version.spring>
+ <version.spring-security>3.1.4.RELEASE</version.spring-security>
+ <version.asm>3.3.1</version.asm>
+ <version.smack>3.2.1</version.smack>
+ <version.jdoapi>3.0.1</version.jdoapi>
+ <forker.module>taverna-server-unix-forker</forker.module>
+ <util.dir>${project.build.directory}/${project.build.finalName}/WEB-INF/classes/util</util.dir>
+ <cmdline.dir>${util.dir}/taverna-commandline-${edition.commandline}-${version.commandline}</cmdline.dir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxws</artifactId>
+ <version>${version.cxf}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>jaxb-impl</artifactId>
+ <groupId>com.sun.xml.bind</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+ <version>${version.cxf}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-transports-http</artifactId>
+ <version>${version.cxf}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <version>${version.spring-security}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ <version>${version.spring-security}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-config</artifactId>
+ <version>${version.spring-security}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${version.spring}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId><!--$NO-MVN-MAN-VER$-->
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-port-description</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-runinterface</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-usagerecord</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-worker</artifactId>
+ <version>${project.parent.version}</version>
+ <classifier>jar-with-dependencies</classifier>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>${forker.module}</artifactId>
+ <version>${project.parent.version}</version>
+ <classifier>jar-with-dependencies</classifier>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-rmidaemon</artifactId>
+ <version>${project.parent.version}</version>
+ <classifier>jar-with-dependencies</classifier>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <!--
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-annotations</artifactId>
+ <version>3.4.0.GA</version>
+ <scope>compile</scope>
+ </dependency>
+ -->
+ <!--
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <version>4.0.2.GA</version>
+ <scope>compile</scope>
+ </dependency>
+ -->
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <version>10.10.1.1</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-dbcp</groupId>
+ <artifactId>commons-dbcp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.jdo</groupId>
+ <artifactId>jdo-api</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-api-jdo</artifactId>
+ <version>[3.2.0, 3.2.99)</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-core</artifactId>
+ <version>3.2.10</version>
+ </dependency>
+ <dependency>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-rdbms</artifactId>
+ <version>[3.2.0, 3.2.99)</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jdo</groupId>
+ <artifactId>jdo2-core</artifactId>
+ <version>2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.mime-util</groupId>
+ <artifactId>mime-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.twitter4j</groupId>
+ <artifactId>twitter4j-core</artifactId>
+ <version>[3.0,)</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>3.0</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjrt</artifactId>
+ <version>1.7.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.igniterealtime.smack</groupId>
+ <artifactId>smack</artifactId>
+ <version>${version.smack}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.igniterealtime.smack</groupId>
+ <artifactId>smackx</artifactId>
+ <version>${version.smack}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.abdera</groupId>
+ <artifactId>abdera-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.abdera</groupId>
+ <artifactId>abdera-parser</artifactId>
+ <version>1.1.3</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>xercesImpl</artifactId>
+ <groupId>xerces</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ <version>1.49</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>aspectjweaver</artifactId>
+ <version>1.7.4</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ <version>1.4.4</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.activation</groupId>
+ <artifactId>activation</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>1.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-extension-providers</artifactId>
+ <version>${version.cxf}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jettison</groupId>
+ <artifactId>jettison</artifactId>
+ <version>1.3.4</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.taverna.language</groupId>
+ <artifactId>taverna-scufl2-api</artifactId>
+ <version>${taverna.language.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.taverna.language</groupId>
+ <artifactId>taverna-scufl2-t2flow</artifactId>
+ <version>${taverna.language.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.taverna.language</groupId>
+ <artifactId>taverna-scufl2-wfbundle</artifactId>
+ <version>${taverna.language.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>1.4.1</version>
+ </dependency>
+ </dependencies>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-runinterface</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ <version>${version.asm}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ <version>2.2.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-expression</artifactId>
+ <version>${version.spring}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.abdera</groupId>
+ <artifactId>abdera-core</artifactId>
+ <version>1.1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>wstx-asl</artifactId>
+ <version>4.0.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-javamail_1.4_spec</artifactId>
+ <version>1.7.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>woodstox-core-asl</artifactId>
+ <version>4.2.0</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>jaxen</groupId>
+ <artifactId>jaxen</artifactId>
+ <version>1.1.4</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <finalName>TavernaServer.${project.parent.version}</finalName>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>tomcat-maven-plugin</artifactId>
+ <version>1.1</version>
+ <configuration>
+ <server>deployhost</server>
+ <path>/taverna-server</path>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <encoding>US-ASCII</encoding>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-maven-plugin</artifactId>
+ <version>3.3.0-release</version>
+ <configuration>
+ <jdkLogConfiguration>${project.basedir}/src/build/resources/datanucleus-log.properties</jdkLogConfiguration>
+ <log4jConfiguration>${project.basedir}/src/build/resources/datanucleus_log4j.properties</log4jConfiguration>
+ <verbose>true</verbose>
+ </configuration>
+ <dependencies>
+ <!-- Sucks that I have to say these explicitly -->
+ <dependency>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-core</artifactId>
+ <version>3.2.10</version>
+ </dependency>
+ <dependency>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-enhancer</artifactId>
+ <version>3.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-api-jdo</artifactId>
+ <version>3.2.5</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.jdo</groupId>
+ <artifactId>jdo-api</artifactId>
+ <version>${version.jdoapi}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <versionRange>[2.0,)</versionRange>
+ <goals>
+ <goal>copy-dependencies</goal>
+ <goal>unpack</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-maven-plugin</artifactId>
+ <versionRange>3.3.0-release</versionRange>
+ <goals>
+ <goal>enhance</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <versionRange>[2.1.4,)</versionRange>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-maven-plugin</artifactId>
+ <versionRange>3.3.0-release</versionRange>
+ <goals>
+ <goal>schema-create</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>yuicompressor-maven-plugin</artifactId>
+ <versionRange>[1.0.0,)</versionRange>
+ <goals>
+ <goal>compress</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute/>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
+ <defaultGoal>package</defaultGoal>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-executable-library-jars</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-worker</artifactId>
+ <version>${project.parent.version}</version>
+ <classifier>jar-with-dependencies</classifier>
+ <overWrite>false</overWrite>
+ <destFileName>server.worker.jar</destFileName>
+ </artifactItem>
+ <artifactItem>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>${forker.module}</artifactId>
+ <version>${project.parent.version}</version>
+ <classifier>jar-with-dependencies</classifier>
+ <overWrite>false</overWrite>
+ <destFileName>secure.fork.jar</destFileName>
+ </artifactItem>
+ <artifactItem>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-rmidaemon</artifactId>
+ <version>${project.parent.version}</version>
+ <classifier>jar-with-dependencies</classifier>
+ <overWrite>false</overWrite>
+ <destFileName>rmi.daemon.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${util.dir}</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <excludeTransitive>true</excludeTransitive>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-taverna-commandline</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.taverna.commandline</groupId>
+ <artifactId>taverna-commandline</artifactId>
+ <version>${taverna.commandline.version}</version>
+ <classifier>bin</classifier>
+ <type>zip</type>
+ <classifier>bin</classifier>
+ <outputDirectory>${util.dir}</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <excludeTransitive>true</excludeTransitive>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.datanucleus</groupId>
+ <artifactId>datanucleus-maven-plugin</artifactId>
+ <configuration>
+ <fork>false</fork>
+ <metadataIncludes>
+ org/taverna/server/master/*.class,
+ org/taverna/server/master/identity/*.class,
+ org/taverna/server/master/localworker/*.class,
+ org/taverna/server/master/notification/atom/*.class,
+ org/taverna/server/master/usage/*.class,
+ org/taverna/server/master/worker/*.class
+ </metadataIncludes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>enhance</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>enhance</goal>
+ </goals>
+ </execution>
+ <!--
+ <execution>
+ <id>gen-db-schema</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>schema-create</goal>
+ </goals>
+ <configuration>
+ <completeDdl>true</completeDdl>
+ <ddlFile>${util.dir}/schema.sql</ddlFile>
+ </configuration>
+ </execution>
+ -->
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <encoding>US-ASCII</encoding>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <version>2.1.4</version>
+ <executions>
+ <execution>
+ <id>buildinfo</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <dotGitDirectory>${project.basedir}/../.git</dotGitDirectory>
+ <prefix>git</prefix>
+ <verbose>true</verbose>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <webXml>src/main/webapp/WEB-INF/web-sec.xml</webXml>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <configuration>
+ <additionalProjectnatures>
+ <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
+ </additionalProjectnatures>
+ <additionalConfig>
+ <file>
+ <name>.springBeans</name>
+ <content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion>3.3.0.201307091516-RELEASE</pluginVersion>
+ <configSuffixes>
+ <configSuffix>xml</configSuffix>
+ </configSuffixes>
+ <enableImports>true</enableImports>
+ <configs>
+ <config>src/main/webapp/WEB-INF/partsecure.xml</config>
+ <config>src/main/webapp/WEB-INF/beans.xml</config>
+ <config>src/main/webapp/WEB-INF/insecure.xml</config>
+ <config>src/main/webapp/WEB-INF/providers.xml</config>
+ <config>src/main/webapp/WEB-INF/secure.xml</config>
+ <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
+ </configs>
+ <configSets>
+ <configSet>
+ <name>Secure Configuration</name>
+ <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
+ <incomplete>false</incomplete>
+ <configs>
+ <config>src/main/webapp/WEB-INF/beans.xml</config>
+ <config>src/main/webapp/WEB-INF/providers.xml</config>
+ <config>src/main/webapp/WEB-INF/secure.xml</config>
+ <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
+ </configs>
+ <profiles>
+ </profiles>
+ </configSet>
+ <configSet>
+ <name>Insecure Configuration</name>
+ <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
+ <incomplete>false</incomplete>
+ <configs>
+ <config>src/main/webapp/WEB-INF/beans.xml</config>
+ <config>src/main/webapp/WEB-INF/insecure.xml</config>
+ <config>src/main/webapp/WEB-INF/providers.xml</config>
+ <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
+ </configs>
+ <profiles>
+ </profiles>
+ </configSet>
+ <configSet>
+ <name>Semi-Secure Configuration</name>
+ <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
+ <incomplete>false</incomplete>
+ <configs>
+ <config>src/main/webapp/WEB-INF/beans.xml</config>
+ <config>src/main/webapp/WEB-INF/providers.xml</config>
+ <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
+ <config>src/main/webapp/WEB-INF/partsecure.xml</config>
+ </configs>
+ <profiles>
+ </profiles>
+ </configSet>
+ </configSets>
+</beansProjectDescription>]]></content>
+ </file>
+ </additionalConfig>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>yuicompressor-maven-plugin</artifactId>
+ <version>1.4.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compress</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <excludes>
+ <exclude>**/*.min.js</exclude>
+ </excludes>
+ <nosuffix>true</nosuffix>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>override-executeworkflow-scripts</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${cmdline.dir}</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/replacementscripts</directory>
+ <filtering>false</filtering>
+ </resource>
+ </resources>
+ <overwrite>true</overwrite>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <id>improve-registry-coverage</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <executable>/bin/sh</executable>
+ <workingDirectory>${cmdline.dir}</workingDirectory>
+ <environmentVariables>
+ <RAVEN_APPHOME>${cmdline.dir}</RAVEN_APPHOME>
+ </environmentVariables>
+ <arguments>
+ <argument>./executeworkflow.sh</argument>
+ <argument>-help</argument>
+ </arguments>
+ <outputFile>/dev/null</outputFile>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
+ <directory>src/main/webapp</directory>
+ <filtering>false</filtering>
+ </resource>
+ </resources>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>unix</id>
+ <properties>
+ <forker.module>taverna-server-unix-forker</forker.module>
+ </properties>
+ </profile>
+ <profile>
+ <id>win</id>
+ <properties>
+ <!-- This doesn't exist yet. -->
+ <forker.module>taverna-server-win-forker</forker.module>
+ </properties>
+ </profile>
+ <profile>
+ <id>nosec</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <webXml>src/main/webapp/WEB-INF/web-nosec.xml</webXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>partsec</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <webXml>src/main/webapp/WEB-INF/web-partsec.xml</webXml>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/build/resources/datanucleus_log4j.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/build/resources/datanucleus_log4j.properties b/taverna-server-webapp/src/build/resources/datanucleus_log4j.properties
new file mode 100644
index 0000000..6707f55
--- /dev/null
+++ b/taverna-server-webapp/src/build/resources/datanucleus_log4j.properties
@@ -0,0 +1,4 @@
+log4j.rootLogger=info, R
+log4j.appender.R=org.apache.log4j.ConsoleAppender
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
\ 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/ContentsDescriptorBuilder.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java
new file mode 100644
index 0000000..f5259bd
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static eu.medsea.util.MimeUtil.getMimeType;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
+import static javax.ws.rs.core.UriBuilder.fromUri;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.common.Uri.secure;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+import org.taverna.server.master.utils.FilenameUtils;
+import org.taverna.server.port_description.AbsentValue;
+import org.taverna.server.port_description.AbstractPortDescription;
+import org.taverna.server.port_description.AbstractValue;
+import org.taverna.server.port_description.ErrorValue;
+import org.taverna.server.port_description.InputDescription;
+import org.taverna.server.port_description.InputDescription.InputPort;
+import org.taverna.server.port_description.LeafValue;
+import org.taverna.server.port_description.ListValue;
+import org.taverna.server.port_description.OutputDescription;
+import org.taverna.server.port_description.OutputDescription.OutputPort;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+import uk.org.taverna.scufl2.api.core.Workflow;
+import uk.org.taverna.scufl2.api.port.InputWorkflowPort;
+import uk.org.taverna.scufl2.api.port.OutputWorkflowPort;
+
+/**
+ * A class that is used to build descriptions of the contents of a workflow
+ * run's filesystem.
+ *
+ * @author Donal Fellows
+ */
+public class ContentsDescriptorBuilder {
+ private Log log = getLog("Taverna.Server.Webapp");
+ private FilenameUtils fileUtils;
+ private UriBuilderFactory uriBuilderFactory;
+
+ @Required
+ public void setUriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
+ this.uriBuilderFactory = uriBuilderFactory;
+ }
+
+ @Required
+ public void setFileUtils(FilenameUtils fileUtils) {
+ this.fileUtils = fileUtils;
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ private Workflow fillInFromWorkflow(TavernaRun run, UriBuilder ub,
+ AbstractPortDescription portDesc) throws IOException {
+ WorkflowBundle bundle = run.getWorkflow().getScufl2Workflow();
+ bundle.getMainWorkflow().getInputPorts();
+ portDesc.fillInBaseData(bundle.getMainWorkflow()
+ .getWorkflowIdentifier().toString(), run.getId(), ub.build());
+ return bundle.getMainWorkflow();
+ }
+
+ /**
+ * Computes the depth of value in a descriptor.
+ *
+ * @param value
+ * The value description to characterise.
+ * @return Its depth (i.e., the depth of the port outputting the value) or
+ * <tt>null</tt> if that is impossible to determine.
+ */
+ private Integer computeDepth(AbstractValue value) {
+ if (value instanceof ListValue) {
+ int mv = 1;
+ for (AbstractValue v : ((ListValue) value).contents) {
+ Integer d = computeDepth(v);
+ if (d != null && mv <= d)
+ mv = d + 1;
+ }
+ return mv;
+ } else if (value instanceof LeafValue || value instanceof ErrorValue)
+ return 0;
+ else
+ return null;
+ }
+
+ /**
+ * Build a description of a leaf value.
+ *
+ * @param file
+ * The file representing the value.
+ * @return A value descriptor.
+ * @throws FilesystemAccessException
+ * If anything goes wrong.
+ */
+ private LeafValue constructLeafValue(File file)
+ throws FilesystemAccessException {
+ LeafValue v = new LeafValue();
+ v.fileName = file.getFullName();
+ v.byteLength = file.getSize();
+ try {
+ byte[] head = file.getContents(0, 1024);
+ v.contentType = getMimeType(new ByteArrayInputStream(head));
+ } catch (Exception e) {
+ v.contentType = APPLICATION_OCTET_STREAM_TYPE.toString();
+ }
+ return v;
+ }
+
+ /**
+ * Build a description of an error value.
+ *
+ * @param file
+ * The file representing the error.
+ * @return A value descriptor.
+ * @throws FilesystemAccessException
+ * If anything goes wrong.
+ */
+ private ErrorValue constructErrorValue(File file)
+ throws FilesystemAccessException {
+ ErrorValue v = new ErrorValue();
+ v.fileName = file.getFullName();
+ v.byteLength = file.getSize();
+ return v;
+ }
+
+ /**
+ * Build a description of a list value.
+ *
+ * @param dir
+ * The directory representing the list.
+ * @param ub
+ * The factory for URIs.
+ * @return A value descriptor.
+ * @throws FilesystemAccessException
+ * If anything goes wrong.
+ */
+ private ListValue constructListValue(Directory dir, UriBuilder ub)
+ throws FilesystemAccessException {
+ ListValue v = new ListValue();
+ v.length = 0;
+ Set<DirectoryEntry> contents = new HashSet<>(dir.getContents());
+ Iterator<DirectoryEntry> it = contents.iterator();
+ while (it.hasNext())
+ if (!it.next().getName().matches("^[0-9]+([.].*)?$"))
+ it.remove();
+ for (int i = 1; !contents.isEmpty(); i++) {
+ String exact = Integer.toString(i);
+ AbstractValue subval = constructValue(contents, ub, exact);
+ v.contents.add(subval);
+ if (!(subval instanceof AbsentValue)) {
+ v.length = i;
+ String pfx = i + ".";
+ for (DirectoryEntry de : contents)
+ if (de.getName().equals(exact)
+ || de.getName().startsWith(pfx)) {
+ contents.remove(de);
+ break;
+ }
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Build a value description.
+ *
+ * @param parentContents
+ * The contents of the parent directory.
+ * @param ub
+ * The factory for URIs.
+ * @param name
+ * The name of the value's file/directory representative.
+ * @return A value descriptor.
+ * @throws FilesystemAccessException
+ * If anything goes wrong.
+ */
+ private AbstractValue constructValue(
+ Collection<DirectoryEntry> parentContents, UriBuilder ub,
+ String name) throws FilesystemAccessException {
+ String error = name + ".error";
+ String prefix = name + ".";
+ for (DirectoryEntry entry : parentContents) {
+ AbstractValue av;
+ if (entry.getName().equals(error) && entry instanceof File) {
+ av = constructErrorValue((File) entry);
+ } else if (!entry.getName().equals(name)
+ && !entry.getName().startsWith(prefix))
+ continue;
+ else if (entry instanceof File)
+ av = constructLeafValue((File) entry);
+ else
+ av = constructListValue((Directory) entry, ub);
+ String fullPath = entry.getFullName().replaceFirst("^/", "");
+ av.href = ub.clone().path(fullPath).build();
+ return av;
+ }
+ return new AbsentValue();
+ }
+
+ /**
+ * Construct a description of the outputs of a workflow run.
+ *
+ * @param run
+ * The workflow run whose outputs are to be described.
+ * @param ui
+ * The origin for URIs.
+ * @return The description, which can be serialized to XML.
+ * @throws FilesystemAccessException
+ * If something goes wrong reading the directories.
+ * @throws NoDirectoryEntryException
+ * If something goes wrong reading the directories.
+ */
+ public OutputDescription makeOutputDescriptor(TavernaRun run, UriInfo ui)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ OutputDescription descriptor = new OutputDescription();
+ try {
+ UriBuilder ub = getRunUriBuilder(run, ui);
+ Workflow dataflow = fillInFromWorkflow(run, ub, descriptor);
+ Collection<DirectoryEntry> outs = null;
+ ub = ub.path("wd/{path}");
+ for (OutputWorkflowPort output : dataflow.getOutputPorts()) {
+ OutputPort p = descriptor.addPort(output.getName());
+ if (run.getOutputBaclavaFile() == null) {
+ if (outs == null)
+ outs = fileUtils.getDirectory(run, "out").getContents();
+ p.output = constructValue(outs, ub, p.name);
+ p.depth = computeDepth(p.output);
+ }
+ }
+ } catch (IOException e) {
+ log.info("failure in conversion to .scufl2", e);
+ }
+ return descriptor;
+ }
+
+ private UriBuilder getRunUriBuilder(TavernaRun run, UriInfo ui) {
+ if (ui == null)
+ return secure(uriBuilderFactory.getRunUriBuilder(run));
+ else
+ return secure(fromUri(ui.getAbsolutePath().toString()
+ .replaceAll("/(out|in)put/?$", "")));
+ }
+
+ /**
+ * Constructs input descriptions.
+ *
+ * @param run
+ * The run to build for.
+ * @param ui
+ * The mechanism for building URIs.
+ * @return The description of the <i>expected</i> inputs of the run.
+ */
+ public InputDescription makeInputDescriptor(TavernaRun run, UriInfo ui) {
+ InputDescription desc = new InputDescription();
+ try {
+ UriBuilder ub = getRunUriBuilder(run, ui);
+ Workflow workflow = fillInFromWorkflow(run, ub, desc);
+ ub = ub.path("input/{name}");
+ for (InputWorkflowPort port : workflow.getInputPorts()) {
+ InputPort in = desc.addPort(port.getName());
+ in.href = ub.build(in.name);
+ try {
+ in.depth = port.getDepth();
+ } catch (NumberFormatException ex) {
+ in.depth = null;
+ }
+ }
+ } catch (IOException e) {
+ log.info("failure in conversion to .scufl2", e);
+ }
+ return desc;
+ }
+}
[37/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java
deleted file mode 100644
index 62158bb..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerREST.java
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java
deleted file mode 100644
index 2b328fd..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerRunREST.java
+++ /dev/null
@@ -1,797 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java
deleted file mode 100644
index 73000e8..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerSecurityREST.java
+++ /dev/null
@@ -1,775 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java
deleted file mode 100644
index 8b9c75f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/AccessDeniedHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java
deleted file mode 100644
index 254382b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadInputPortNameHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java
deleted file mode 100644
index 6ded568..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadPropertyValueHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java
deleted file mode 100644
index 9501923..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/BadStateChangeHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java
deleted file mode 100644
index 20d9f56..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.taverna.server.master.rest.handler;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.singletonMap;
-import static javax.ws.rs.core.Response.notAcceptable;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Variant;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-import org.apache.abdera.Abdera;
-import org.apache.abdera.model.Document;
-import org.apache.abdera.model.Entry;
-import org.apache.abdera.parser.Parser;
-import org.apache.abdera.writer.Writer;
-import org.springframework.beans.factory.annotation.Required;
-
-@Provider
-@Produces({ "application/atom+xml", "application/atom+xml;type=entry" })
-@Consumes({ "application/atom+xml", "application/atom+xml;type=entry" })
-public class EntryHandler implements MessageBodyWriter<Entry>,
- MessageBodyReader<Entry> {
- private static final String ENC = "UTF-8";
- private static final MediaType ENTRY = new MediaType("application",
- "atom+xml", singletonMap("type", "entry"));
- private static final Variant VARIANT = new Variant(ENTRY, (String) null,
- ENC);
- private static final Charset UTF8 = Charset.forName(ENC);
-
- @Required
- public void setAbdera(Abdera abdera) {
- parser = abdera.getParser();
- writer = abdera.getWriterFactory().getWriter("prettyxml");
- }
-
- private Parser parser;
- private Writer writer;
-
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (!Entry.class.isAssignableFrom(type))
- return false;
- if (!ENTRY.isCompatible(mediaType))
- return false;
- if (mediaType.getParameters().containsKey("type"))
- return "entry".equalsIgnoreCase(mediaType.getParameters().get(
- "type"));
- return true;
- }
-
- @Override
- public Entry readFrom(Class<Entry> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
- Charset cs = UTF8;
- try {
- String charset = mediaType.getParameters().get("charset");
- if (charset != null)
- cs = Charset.forName(charset);
- } catch (IllegalCharsetNameException e) {
- throw new WebApplicationException(notAcceptable(asList(VARIANT))
- .entity("bad charset name").build());
- } catch (UnsupportedCharsetException e) {
- throw new WebApplicationException(notAcceptable(asList(VARIANT))
- .entity("unsupportd charset name").build());
- }
- try {
- Document<Entry> doc = parser.parse(new InputStreamReader(
- entityStream, cs));
- if (!Entry.class.isAssignableFrom(doc.getRoot().getClass())) {
- throw new WebApplicationException(
- notAcceptable(asList(VARIANT)).entity(
- "not really a feed entry").build());
- }
- return doc.getRoot();
- } catch (ClassCastException e) {
- throw new WebApplicationException(notAcceptable(asList(VARIANT))
- .entity("not really a feed entry").build());
-
- }
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (!Entry.class.isAssignableFrom(type))
- return false;
- if (!ENTRY.isCompatible(mediaType))
- return false;
- if (mediaType.getParameters().containsKey("type"))
- return "entry".equalsIgnoreCase(mediaType.getParameters().get(
- "type"));
- return true;
- }
-
- @Override
- public long getSize(Entry t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(Entry t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- httpHeaders.putSingle("Content-Type", ENTRY.toString() + ";charset="
- + ENC);
- writer.writeTo(t, new OutputStreamWriter(entityStream, UTF8));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java
deleted file mode 100644
index 7c17f5c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.taverna.server.master.rest.handler;
-
-import static java.util.Collections.singletonMap;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-import org.apache.abdera.Abdera;
-import org.apache.abdera.model.Feed;
-import org.apache.abdera.writer.Writer;
-import org.springframework.beans.factory.annotation.Required;
-
-@Provider
-@Produces({ "application/atom+xml", "application/atom+xml;type=feed" })
-public class FeedHandler implements MessageBodyWriter<Feed> {
- private static final MediaType FEED = new MediaType("application",
- "atom+xml", singletonMap("type", "feed"));
- private static final String ENC = "UTF-8";
-
- @Required
- public void setAbdera(Abdera abdera) {
- writer = abdera.getWriterFactory().getWriter("prettyxml");
- }
-
- private Writer writer;
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (!Feed.class.isAssignableFrom(type))
- return false;
- if (!FEED.isCompatible(mediaType))
- return false;
- if (mediaType.getParameters().containsKey("type"))
- return "feed".equalsIgnoreCase(mediaType.getParameters()
- .get("type"));
- return true;
- }
-
- @Override
- public long getSize(Feed t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(Feed t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- httpHeaders.putSingle("Content-Type", FEED.toString() + ";charset="
- + ENC);
- writer.writeTo(t, new OutputStreamWriter(entityStream, ENC));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java
deleted file mode 100644
index ab18d73..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package org.taverna.server.master.rest.handler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyWriter;
-
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.FileConcatenation;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.interfaces.File;
-
-public class FileConcatenationHandler implements
- MessageBodyWriter<FileConcatenation> {
- /** How much to pull from the worker in one read. */
- private int maxChunkSize;
-
- /**
- * @param maxChunkSize
- * How much to pull from the worker in one read.
- */
- @Required
- public void setMaxChunkSize(int maxChunkSize) {
- this.maxChunkSize = maxChunkSize;
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return type.isAssignableFrom(FileConcatenation.class);
- }
-
- @Override
- public long getSize(FileConcatenation fc, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return fc.size();
- }
-
- @Override
- public void writeTo(FileConcatenation fc, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException {
- for (File f : fc)
- try {
- byte[] buffer;
- for (int off = 0; true ; off += buffer.length) {
- buffer = f.getContents(off, maxChunkSize);
- if (buffer == null || buffer.length == 0)
- break;
- entityStream.write(buffer);
- }
- } catch (FilesystemAccessException e) {
- // Ignore/skip to next file
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java
deleted file mode 100644
index 0aeb816..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-import org.apache.commons.logging.Log;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.interfaces.File;
-
-/**
- * How to write out a File object with JAX-RS.
- *
- * @author Donal Fellows
- */
-@Provider
-public class FileMessageHandler implements MessageBodyWriter<File> {
- private Log log = getLog("Taverna.Server.Webapp");
- /** How much to pull from the worker in one read. */
- private int maxChunkSize;
-
- /**
- * @param maxChunkSize
- * How much to pull from the worker in one read.
- */
- public void setMaxChunkSize(int maxChunkSize) {
- this.maxChunkSize = maxChunkSize;
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return File.class.isAssignableFrom(type);
- }
-
- @Override
- public long getSize(File t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- try {
- return t.getSize(); // Is it really raw bytes?
- } catch (FilesystemAccessException e) {
- log.info("failed to get file length", e);
- return -1;
- }
- }
-
- @Override
- public void writeTo(File t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- try {
- int off = 0;
- while (true) {
- byte[] buffer = t.getContents(off, maxChunkSize);
- if (buffer == null || buffer.length == 0)
- break;
- entityStream.write(buffer);
- off += buffer.length;
- }
- } catch (FilesystemAccessException e) {
- throw new IOException("problem when reading file", e);
- }
- }
-}
[46/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-execution-delegate/src/test/java/SerializationTest.java
----------------------------------------------------------------------
diff --git a/server-execution-delegate/src/test/java/SerializationTest.java b/server-execution-delegate/src/test/java/SerializationTest.java
deleted file mode 100644
index c4bf0b9..0000000
--- a/server-execution-delegate/src/test/java/SerializationTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.transform.Result;
-import javax.xml.transform.stream.StreamResult;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.taverna.server.execution_delegate.RemoteExecution.WorkflowReportDocument;
-
-public class SerializationTest {
- private static final boolean PRINT = true;
- SchemaOutputResolver sink;
- StringWriter schema;
-
- String schema() {
- return schema.toString();
- }
-
- @Before
- public void init() {
- schema = new StringWriter();
- sink = new SchemaOutputResolver() {
- @Override
- public Result createOutput(String namespaceUri,
- String suggestedFileName) throws IOException {
- StreamResult sr = new StreamResult(schema);
- sr.setSystemId("/dev/null");
- return sr;
- }
- };
- assertEquals("", schema());
- }
-
- @Test
- public void testSchemaGeneration() throws JAXBException, IOException {
- JAXBContext.newInstance(WorkflowReportDocument.class).generateSchema(
- sink);
- assertFalse("generated schema must be non-empty", schema().isEmpty());
- assertTrue(
- "generated schema must define workflowReport element",
- schema().contains(
- "<xs:element name=\"workflowReport\" type=\"WorkflowReport\"/>\n"));
- if (PRINT)
- System.out.print(schema());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/.gitignore
----------------------------------------------------------------------
diff --git a/server-port-description/.gitignore b/server-port-description/.gitignore
deleted file mode 100644
index ea8c4bf..0000000
--- a/server-port-description/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/pom.xml
----------------------------------------------------------------------
diff --git a/server-port-description/pom.xml b/server-port-description/pom.xml
deleted file mode 100644
index 99582ed..0000000
--- a/server-port-description/pom.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-port-description</artifactId>
- <name>Apache Taverna Server Workflow Port Descriptor Types</name>
- <description>The structural types used to describe ports on workflows, as exported by Taverna Server.</description>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-eclipse-plugin</artifactId>
- <configuration>
- <projectNameTemplate>[artifactId]-[version]</projectNameTemplate>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java b/server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java
deleted file mode 100644
index 2ea392f..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/AbsentValue.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType(name = "AbsentValue")
-public class AbsentValue extends AbstractValue {
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java b/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java
deleted file mode 100644
index e57c4f9..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPort.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2011-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlID;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-
-import org.taverna.server.port_description.utils.IntAdapter;
-
-@XmlType(name = "Port")
-public class AbstractPort {
- @XmlID
- @XmlAttribute(required = true)
- public String name;
-
- @XmlAttribute
- @XmlSchemaType(name = "int")
- @XmlJavaTypeAdapter(IntAdapter.class)
- public Integer depth;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java b/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java
deleted file mode 100644
index 7c3fe9a..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/AbstractPortDescription.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import java.net.URI;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType(name = "PortDescription")
-public abstract class AbstractPortDescription {
- @XmlAttribute
- public String workflowId;
- @XmlAttribute
- @XmlSchemaType(name = "anyURI")
- public URI workflowRun;
- @XmlAttribute
- public String workflowRunId;
-
- public void fillInBaseData(String docId, String runId, URI runUrl) {
- this.workflowId = docId;
- this.workflowRun = runUrl;
- this.workflowRunId = runId;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java b/server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java
deleted file mode 100644
index 47232c2..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/AbstractValue.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import static org.taverna.server.port_description.Namespaces.XLINK;
-
-import java.net.URI;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlSeeAlso;
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType(name = "Value")
-@XmlSeeAlso( { ErrorValue.class, LeafValue.class, ListValue.class, AbsentValue.class })
-public abstract class AbstractValue {
- @XmlAttribute(namespace = XLINK)
- @XmlSchemaType(name = "anyURI")
- public URI href;
-
- public void setAddress(URI uri, String localAddress) {
- if (uri.getPath().endsWith("/")) {
- href = URI.create(uri + "wd/out/" + localAddress);
- } else {
- href = URI.create(uri + "/wd/out/" + localAddress);
- }
- //about = "out/" + localAddress;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java b/server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java
deleted file mode 100644
index 0bb07b4..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/ErrorValue.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-
-import org.taverna.server.port_description.utils.IntAdapter;
-
-@XmlType(name = "ErrorValue")
-public class ErrorValue extends AbstractValue {
- @XmlAttribute
- @XmlSchemaType(name = "int")
- @XmlJavaTypeAdapter(IntAdapter.class)
- public Integer depth;
- @XmlAttribute(name = "errorFile")
- public String fileName;
- @XmlAttribute(name = "errorByteLength")
- public Long byteLength;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java b/server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java
deleted file mode 100644
index 60b9353..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/InputDescription.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import static org.taverna.server.port_description.Namespaces.XLINK;
-
-import java.net.URI;
-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.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-
-/**
- * A description of the inputs of a workflow run, as they are currently known
- * about.
- *
- * @author Donal Fellows.
- */
-@XmlRootElement
-public class InputDescription extends AbstractPortDescription {
- @XmlElement
- public List<InputPort> input = new ArrayList<>();
-
- @XmlType(name = "InputPort")
- public static class InputPort extends AbstractPort {
- @XmlAttribute(namespace = XLINK)
- @XmlSchemaType(name = "anyURI")
- public URI href;
- }
-
- /**
- * Add an input port to the list of ports.
- *
- * @param name
- * The name of the port to add.
- * @return The port (so that its details may be set);
- */
- public InputPort addPort(String name) {
- InputPort p = new InputPort();
- p.name = name;
- input.add(p);
- return p;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java b/server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java
deleted file mode 100644
index 052c0ef..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/LeafValue.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-@XmlType(name = "LeafValue")
-public class LeafValue extends AbstractValue {
- @XmlAttribute(name = "contentFile")
- public String fileName;
- @XmlAttribute(name = "contentType")
- public String contentType;
- @XmlAttribute(name = "contentByteLength")
- public Long byteLength;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java b/server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java
deleted file mode 100644
index b14cdf1..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/ListValue.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-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.XmlElements;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-
-import org.taverna.server.port_description.utils.IntAdapter;
-
-@XmlType(name = "ListValue")
-public class ListValue extends AbstractValue {
- @XmlAttribute
- @XmlSchemaType(name = "int")
- @XmlJavaTypeAdapter(IntAdapter.class)
- public Integer length;
- @XmlElements({
- @XmlElement(name = "value", type = LeafValue.class, nillable = false),
- @XmlElement(name = "list", type = ListValue.class, nillable = false),
- @XmlElement(name = "error", type = ErrorValue.class, nillable = false),
- @XmlElement(name = "absent", type = AbsentValue.class, nillable = false) })
- public List<AbstractValue> contents = new ArrayList<>();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java b/server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java
deleted file mode 100644
index 4003cdb..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/Namespaces.java
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-public interface Namespaces {
- static final String DATA = "http://ns.taverna.org.uk/2010/port/";
- static final String RUN = "http://ns.taverna.org.uk/2010/run/";
- static final String XLINK = "http://www.w3.org/1999/xlink";
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java b/server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java
deleted file mode 100644
index 0b94973..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/OutputDescription.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElements;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
-/**
- * A description of the outputs of a workflow run, as they are currently known
- * about.
- *
- * @author Donal Fellows
- */
-@XmlRootElement(name = "workflowOutputs")
-public class OutputDescription extends AbstractPortDescription {
- private static final AbsentValue ABSENT_VALUE = new AbsentValue();
- @XmlElement(name = "output")
- public List<OutputPort> ports = new ArrayList<>();
-
- @XmlType(name = "OutputPort")
- public static class OutputPort extends AbstractPort {
- @XmlElements({
- @XmlElement(name = "value", type = LeafValue.class, nillable = false, required = true),
- @XmlElement(name = "list", type = ListValue.class, nillable = false, required = true),
- @XmlElement(name = "error", type = ErrorValue.class, nillable = false, required = true),
- @XmlElement(name = "absent", type = AbsentValue.class, nillable = false, required = true) })
- public AbstractValue output;
- }
-
- /**
- * Add an output port to the list of ports.
- *
- * @param name
- * The name of the port to add.
- * @return The port (so that its value may be set);
- */
- public OutputPort addPort(String name) {
- OutputPort p = new OutputPort();
- p.name = name;
- p.output = ABSENT_VALUE;
- ports.add(p);
- return p;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/main/java/org/taverna/server/port_description/package-info.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/package-info.java b/server-port-description/src/main/java/org/taverna/server/port_description/package-info.java
deleted file mode 100644
index b1ac2c6..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/package-info.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-@XmlSchema(namespace = DATA, elementFormDefault = QUALIFIED, attributeFormDefault = QUALIFIED, xmlns = {
- @XmlNs(prefix = "port", namespaceURI = DATA),
- @XmlNs(prefix = "xlink", namespaceURI = XLINK),
- @XmlNs(prefix = "run", namespaceURI = RUN) })
-package org.taverna.server.port_description;
-
-import static javax.xml.bind.annotation.XmlNsForm.QUALIFIED;
-import static org.taverna.server.port_description.Namespaces.DATA;
-import static org.taverna.server.port_description.Namespaces.RUN;
-import static org.taverna.server.port_description.Namespaces.XLINK;
-
-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/server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java b/server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java
deleted file mode 100644
index 8764176..0000000
--- a/server-port-description/src/main/java/org/taverna/server/port_description/utils/IntAdapter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.port_description.utils;
-
-import static javax.xml.bind.DatatypeConverter.parseInt;
-import static javax.xml.bind.DatatypeConverter.printInt;
-
-import javax.xml.bind.annotation.adapters.XmlAdapter;
-
-/**
- * A type conversion utility for use with JAXB.
- *
- * @author Donal Fellows
- */
-public class IntAdapter extends XmlAdapter<String, Integer> {
- @Override
- public String marshal(Integer value) throws Exception {
- if (value == null)
- return null;
- return printInt(value);
- }
-
- @Override
- public Integer unmarshal(String value) throws Exception {
- if (value == null)
- return null;
- return parseInt(value);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java
----------------------------------------------------------------------
diff --git a/server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java b/server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java
deleted file mode 100644
index c952ec2..0000000
--- a/server-port-description/src/test/java/org/taverna/server/port_description/JaxbSanityTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.taverna.server.port_description;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.transform.Result;
-import javax.xml.transform.stream.StreamResult;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * This test file ensures that the JAXB bindings will work once deployed instead
- * of mysteriously failing in service.
- *
- * @author Donal Fellows
- */
-public class JaxbSanityTest {
- SchemaOutputResolver sink;
- StringWriter schema;
-
- String schema() {
- return schema.toString();
- }
-
- private String schemaTest(Class<?>... classes) throws IOException, JAXBException {
- Assert.assertTrue(schema().isEmpty());
- JAXBContext.newInstance(classes).generateSchema(sink);
- Assert.assertFalse(schema().isEmpty());
- return schema();
- }
-
- @Before
- public void init() {
- schema = new StringWriter();
- sink = new SchemaOutputResolver() {
- @Override
- public Result createOutput(String namespaceUri,
- String suggestedFileName) throws IOException {
- StreamResult sr = new StreamResult(schema);
- sr.setSystemId("/dev/null");
- return sr;
- }
- };
- }
-
- @Test
- public void testJAXBForInput() throws Exception {
- schemaTest(InputDescription.InputPort.class);
- }
-
- @Test
- public void testJAXBForInputDescription() throws Exception {
- schemaTest(InputDescription.class);
- }
-
- @Test
- public void testJAXBForAbsentValue() throws Exception {
- schemaTest(AbstractValue.class);
- }
-
- @Test
- public void testJAXBForAbstractValue() throws Exception {
- schemaTest(AbstractValue.class);
- }
-
- @Test
- public void testJAXBForErrorValue() throws Exception {
- schemaTest(ErrorValue.class);
- }
-
- @Test
- public void testJAXBForLeafValue() throws Exception {
- schemaTest(LeafValue.class);
- }
-
- @Test
- public void testJAXBForListValue() throws Exception {
- schemaTest(ListValue.class);
- }
-
- @Test
- public void testJAXBForOutputDescription() throws Exception {
- schemaTest(OutputDescription.class);
- }
-
- @Test
- public void testJAXBForEverythingAtOnce() throws Exception {
- schemaTest(AbsentValue.class, AbstractValue.class, ListValue.class,
- LeafValue.class, ErrorValue.class, OutputDescription.class,
- InputDescription.InputPort.class, InputDescription.class);
- // System.out.println(schema());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-rmidaemon/pom.xml
----------------------------------------------------------------------
diff --git a/server-rmidaemon/pom.xml b/server-rmidaemon/pom.xml
deleted file mode 100644
index 0e2a565..0000000
--- a/server-rmidaemon/pom.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
-
- <artifactId>taverna-server-rmidaemon</artifactId>
- <name>Apache Taverna Server RMI registry daemon</name>
- <description>Customised RMI registry that supports restricting to localhost.</description>
-
- <properties>
- <project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
- <mainClass>org.taverna.server.rmidaemon.Registry</mainClass>
- </properties>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
- <manifest>
- <mainClass>${mainClass}</mainClass>
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java
----------------------------------------------------------------------
diff --git a/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java b/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java
deleted file mode 100644
index 4be7579..0000000
--- a/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/Registry.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.taverna.server.rmidaemon;
-
-import static java.lang.System.setProperty;
-import static java.net.InetAddress.getLocalHost;
-import static java.rmi.registry.LocateRegistry.createRegistry;
-import static java.rmi.registry.Registry.REGISTRY_PORT;
-import static java.rmi.server.RMISocketFactory.getDefaultSocketFactory;
-
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.net.ServerSocket;
-import java.rmi.MarshalledObject;
-import java.rmi.server.RMIServerSocketFactory;
-
-/**
- * Special version of <tt>rmiregistry</tt>.
- *
- * @author Donal Fellows
- */
-public class Registry {
- /**
- * Run a registry. The first optional argument is the port for the registry
- * to listen on, and the second optional argument is whether the registry
- * should restrict itself to connections from localhost only.
- *
- * @param args
- * Arguments to the program.
- */
- public static void main(String... args) {
- try {
- if (args.length > 0)
- port = Integer.parseInt(args[0]);
- } catch (Exception e) {
- System.err.println("failed to parse port: " + e.getMessage());
- System.exit(2);
- }
- try {
- if (args.length > 1)
- localhostOnly = Boolean.parseBoolean(args[1]);
- } catch (Exception e) {
- System.err.println("failed to parse boolean localhost flag: "
- + e.getMessage());
- System.exit(2);
- }
- try {
- Object registryHandle = makeRegistry();
- try (ObjectOutputStream oos = new ObjectOutputStream(System.out)) {
- oos.writeObject(registryHandle);
- }
- } catch (Exception e) {
- System.err.println("problem creating registry: " + e.getMessage());
- System.exit(1);
- }
- }
-
- private static int port = REGISTRY_PORT;
- private static boolean localhostOnly = false;
-
- private static MarshalledObject<java.rmi.registry.Registry> makeRegistry() throws IOException {
- if (!localhostOnly)
- return new MarshalledObject<>(createRegistry(port));
- setProperty("java.rmi.server.hostname", "127.0.0.1");
- return new MarshalledObject<>(createRegistry(port,
- getDefaultSocketFactory(), new RMIServerSocketFactory() {
- @Override
- public ServerSocket createServerSocket(int port)
- throws IOException {
- return new ServerSocket(port, 0, getLocalHost());
- }
- }));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java
----------------------------------------------------------------------
diff --git a/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java b/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java
deleted file mode 100644
index 32144b5..0000000
--- a/server-rmidaemon/src/main/java/org/taverna/server/rmidaemon/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * RMI daemon implementation. A variation of an RMI registry.
- * @author Donal Fellows
- */
-package org.taverna.server.rmidaemon;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/.gitignore
----------------------------------------------------------------------
diff --git a/server-runinterface/.gitignore b/server-runinterface/.gitignore
deleted file mode 100644
index ea8c4bf..0000000
--- a/server-runinterface/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/pom.xml
----------------------------------------------------------------------
diff --git a/server-runinterface/pom.xml b/server-runinterface/pom.xml
deleted file mode 100644
index efd3763..0000000
--- a/server-runinterface/pom.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
-
- <artifactId>taverna-server-runinterface</artifactId>
- <name>Apache Taverna Server RMI Interface: Webapp <-> Worker</name>
- <description>This is the implementation of the RMI interface between the workflow run factory and the web-app service front-end.</description>
-
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/META-INF/MANIFEST.MF b/server-runinterface/src/main/java/META-INF/MANIFEST.MF
deleted file mode 100644
index 5e94951..0000000
--- a/server-runinterface/src/main/java/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Class-Path:
-
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java
deleted file mode 100644
index 9f4bf50..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/IllegalStateTransitionException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Exception that indicates where a change of a workflow run's status is
- * illegal.
- *
- * @author Donal Fellows
- * @see RemoteSingleRun#setStatus(RemoteStatus)
- */
-@WebFault(name = "IllegalStateTransitionFault", targetNamespace = "http://ns.taverna.org.uk/2010/xml/server/worker/")
-public class IllegalStateTransitionException extends Exception {
- private static final long serialVersionUID = 159673249162345L;
-
- public IllegalStateTransitionException() {
- this("illegal state transition");
- }
-
- public IllegalStateTransitionException(String message) {
- super(message);
- }
-
- public IllegalStateTransitionException(Throwable cause) {
- this("illegal state transition", cause);
- }
-
- public IllegalStateTransitionException(String message, Throwable cause) {
- super(message, cause);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java
deleted file mode 100644
index a47d112..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/ImplementationException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import javax.xml.ws.WebFault;
-
-/**
- * Exception that indicates that the implementation has gone wrong in some
- * unexpected way.
- *
- * @author Donal Fellows
- */
-@WebFault(name = "ImplementationFault", targetNamespace = "http://ns.taverna.org.uk/2010/xml/server/worker/")
-@SuppressWarnings("serial")
-public class ImplementationException extends Exception {
- public ImplementationException(String message) {
- super(message);
- }
-
- public ImplementationException(String message, Throwable cause) {
- super(message, cause);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java
deleted file mode 100644
index 395842a..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectory.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.io.IOException;
-import java.rmi.RemoteException;
-import java.util.Collection;
-
-import javax.annotation.Nonnull;
-
-/**
- * Represents a directory that is the working directory of a workflow run, or a
- * sub-directory of it.
- *
- * @author Donal Fellows
- * @see RemoteFile
- */
-public interface RemoteDirectory extends RemoteDirectoryEntry {
- /**
- * @return A list of the contents of the directory.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If anything goes wrong with listing the directory.
- */
- @Nonnull
- public Collection<RemoteDirectoryEntry> getContents()
- throws RemoteException, IOException;
-
- /**
- * Creates a sub-directory of this directory.
- *
- * @param name
- * The name of the sub-directory.
- * @return A handle to the newly-created directory.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If things go wrong with creating the subdirectory.
- */
- @Nonnull
- public RemoteDirectory makeSubdirectory(@Nonnull String name)
- throws RemoteException, IOException;
-
- /**
- * Creates an empty file in this directory.
- *
- * @param name
- * The name of the file to create.
- * @return A handle to the newly-created file.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If anything goes wrong with creating the file.
- */
- @Nonnull
- public RemoteFile makeEmptyFile(@Nonnull String name)
- throws RemoteException, IOException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java
deleted file mode 100644
index 1e04b44..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteDirectoryEntry.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.io.IOException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.Date;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-/**
- * An entry in a {@link RemoteDirectory} representing a file or sub-directory.
- *
- * @author Donal Fellows
- * @see RemoteDirectory
- * @see RemoteFile
- */
-public interface RemoteDirectoryEntry extends Remote {
- /**
- * @return The "local" name of the entry. This will never be "<tt>..</tt>"
- * or contain the character "<tt>/</tt>".
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public String getName() throws RemoteException;
-
- /**
- * @return The time when the entry was last modified.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public Date getModificationDate() throws RemoteException;
-
- /**
- * Gets the directory containing this directory entry.
- *
- * @return A directory handle, or <tt>null</tt> if called on the workflow
- * run's working directory.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- public RemoteDirectory getContainingDirectory() throws RemoteException;
-
- /**
- * Destroy this directory entry, deleting the file or sub-directory. The
- * workflow run's working directory can never be manually destroyed.
- *
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If things go wrong when deleting the directory entry.
- */
- public void destroy() throws RemoteException, IOException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java
deleted file mode 100644
index e09466d..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteFile.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.io.IOException;
-import java.rmi.RemoteException;
-
-import javax.annotation.Nonnull;
-
-/**
- * Represents a file in the working directory of a workflow instance run, or in
- * some sub-directory of it.
- *
- * @author Donal Fellows
- * @see RemoteDirectory
- */
-public interface RemoteFile extends RemoteDirectoryEntry {
- /**
- * Read from the file.
- *
- * @param offset
- * Where in the file to read the bytes from.
- * @param length
- * How much of the file to read; -1 for "to the end".
- * @return The literal byte contents of the given section of the file.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If things go wrong reading the file.
- */
- @Nonnull
- byte[] getContents(int offset, int length) throws RemoteException,
- IOException;
-
- /**
- * Write the data to the file, totally replacing what was there before.
- *
- * @param data
- * The literal bytes that will form the new contents of the file.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If things go wrong writing the contents.
- */
- void setContents(@Nonnull byte[] data) throws RemoteException, IOException;
-
- /**
- * Append the data to the file.
- *
- * @param data
- * The literal bytes that will be appended.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If things go wrong writing the contents.
- */
- void appendContents(@Nonnull byte[] data) throws RemoteException,
- IOException;
-
- /**
- * @return The length of the file, in bytes.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- long getSize() throws RemoteException;
-
- /**
- * Copy from another file to this one.
- *
- * @param sourceFile
- * The other file to copy from.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws IOException
- * If things go wrong during the copy.
- */
- void copy(@Nonnull RemoteFile sourceFile) throws RemoteException,
- IOException;
-
- /**
- * @return The full native OS name for the file.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- String getNativeName() throws RemoteException;
-
- /**
- * @return The host holding the file.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- String getNativeHost() throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java
deleted file mode 100644
index 7a7510c..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteInput.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-/**
- * This represents the assignment of inputs to input ports of the workflow. Note
- * that the <tt>file</tt> and <tt>value</tt> properties are never set at the
- * same time.
- *
- * @author Donal Fellows
- */
-public interface RemoteInput extends Remote {
- /**
- * @return The file currently assigned to this input port, or <tt>null</tt>
- * if no file is assigned.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- String getFile() throws RemoteException;
-
- /**
- * @return The name of this input port. This may not be changed.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- String getName() throws RemoteException;
-
- /**
- * @return The value currently assigned to this input port, or <tt>null</tt>
- * if no value is assigned.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- String getValue() throws RemoteException;
-
- /**
- * @return The delimiter currently used to split this input port's value
- * into a list, or <tt>null</tt> if no delimiter is to be used
- * (i.e., the value is a singleton).
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- String getDelimiter() throws RemoteException;
-
- /**
- * Sets the file to use for this input. This overrides the use of the
- * previous file and any set value.
- *
- * @param file
- * The filename to use. Must not start with a <tt>/</tt> or
- * contain any <tt>..</tt> segments. Will be interpreted relative
- * to the run's working directory.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void setFile(@Nonnull String file) throws RemoteException;
-
- /**
- * Sets the value to use for this input. This overrides the use of the
- * previous value and any set file.
- *
- * @param value
- * The value to use.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void setValue(@Nonnull String value) throws RemoteException;
-
- /**
- * Sets the delimiter used to split this input port's value into a list.
- *
- * @param delimiter
- * The delimiter character, or <tt>null</tt> if no delimiter is
- * to be used (i.e., the value is a singleton).
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void setDelimiter(@Nullable String delimiter) throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java
deleted file mode 100644
index 4001721..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteListener.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-import javax.annotation.Nonnull;
-
-/**
- * An event listener that is attached to a {@link RemoteSingleRun}.
- *
- * @author Donal Fellows
- */
-public interface RemoteListener extends Remote {
- /**
- * @return The name of the listener.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public String getName() throws RemoteException;
-
- /**
- * @return The type of the listener.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public String getType() throws RemoteException;
-
- /**
- * @return The configuration document for the listener.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public String getConfiguration() throws RemoteException;
-
- /**
- * @return The supported properties of the listener.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public String[] listProperties() throws RemoteException;
-
- /**
- * Get the value of a particular property, which should be listed in the
- * {@link #listProperties()} method.
- *
- * @param propName
- * The name of the property to read.
- * @return The value of the property.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public String getProperty(@Nonnull String propName) throws RemoteException;
-
- /**
- * Set the value of a particular property, which should be listed in the
- * {@link #listProperties()} method.
- *
- * @param propName
- * The name of the property to write.
- * @param value
- * The value to set the property to.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- public void setProperty(@Nonnull String propName, @Nonnull String value)
- throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java
deleted file mode 100644
index eec4ab5..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteRunFactory.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.UUID;
-
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-/**
- * The main RMI-enabled interface for creating runs.
- *
- * @author Donal Fellows
- */
-public interface RemoteRunFactory extends Remote {
- /**
- * Makes a workflow run that will process a particular workflow document.
- *
- * @param workflow
- * The (serialised) workflow to instantiate as a run.
- * @param creator
- * Who is this run created for?
- * @param usageRecordReceiver
- * Where to write any usage records. May be <tt>null</tt> to
- * cause them to not be written.
- * @param masterID
- * The UUID of the run to use, or <tt>null</tt> if the execution
- * engine is to manufacture a new one for itself.
- * @return A remote handle for the run.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- RemoteSingleRun make(@Nonnull byte[] workflow, @Nonnull String creator,
- @Nullable UsageRecordReceiver usageRecordReceiver,
- @Nullable UUID masterID) throws RemoteException;
-
- /**
- * Asks this factory to unregister itself from the registry and cease
- * operation.
- *
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void shutdown() throws RemoteException;
-
- /**
- * Configures the details to use when setting up the workflow run's
- * connnection to the interaction feed.
- *
- * @param host
- * The host where the feed is located.
- * @param port
- * The port where the feed is located.
- * @param webdavPath
- * The path used for pushing web pages into the feed.
- * @param feedPath
- * The path used for reading and writing notifications on the
- * feed.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void setInteractionServiceDetails(@Nonnull String host,
- @Nonnull String port, @Nonnull String webdavPath,
- @Nonnull String feedPath) throws RemoteException;
-
- /**
- * Gets a count of the number of {@linkplain RemoteSingleRun workflow runs}
- * that this factor knows about that are in the
- * {@link RemoteStatus#Operating Operating} state.
- *
- * @return A count of "running" workflow runs.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- int countOperatingRuns() throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java
deleted file mode 100644
index 35e6c09..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSecurityContext.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.net.URI;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-
-/**
- * Outline of the security context for a workflow run.
- *
- * @author Donal Fellows
- */
-public interface RemoteSecurityContext extends Remote {
- void setKeystore(@Nonnull byte[] keystore) throws RemoteException,
- ImplementationException;
-
- void setPassword(@Nonnull char[] password) throws RemoteException,
- ImplementationException;
-
- void setTruststore(@Nonnull byte[] truststore) throws RemoteException,
- ImplementationException;
-
- void setUriToAliasMap(@Nonnull Map<URI, String> uriToAliasMap)
- throws RemoteException;
-
- void setHelioToken(@Nonnull String helioToken) throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java
deleted file mode 100644
index fa68b81..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteSingleRun.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-import java.net.URL;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.Date;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-public interface RemoteSingleRun extends Remote {
- /**
- * @return The name of the Baclava file to use for all inputs, or
- * <tt>null</tt> if no Baclava file is set.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- public String getInputBaclavaFile() throws RemoteException;
-
- /**
- * Sets the Baclava file to use for all inputs. This overrides the use of
- * individual inputs.
- *
- * @param filename
- * The filename to use. Must not start with a <tt>/</tt> or
- * contain any <tt>..</tt> segments. Will be interpreted relative
- * to the run's working directory.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- public void setInputBaclavaFile(@Nonnull String filename)
- throws RemoteException;
-
- /**
- * @return The list of input assignments.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public List<RemoteInput> getInputs() throws RemoteException;
-
- /**
- * Create an input assignment.
- *
- * @param name
- * The name of the port that this will be an input for.
- * @return The assignment reference.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public RemoteInput makeInput(@Nonnull String name) throws RemoteException;
-
- /**
- * @return The file (relative to the working directory) to write the outputs
- * of the run to as a Baclava document, or <tt>null</tt> if they are
- * to be written to non-Baclava files in a directory called
- * <tt>out</tt>.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- public String getOutputBaclavaFile() throws RemoteException;
-
- /**
- * Sets where the output of the run is to be written to. This will cause the
- * output to be generated as a Baclava document, rather than a collection of
- * individual non-Baclava files in the subdirectory of the working directory
- * called <tt>out</tt>.
- *
- * @param filename
- * Where to write the Baclava file (or <tt>null</tt> to cause the
- * output to be written to individual files); overwrites any
- * previous setting of this value.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- public void setOutputBaclavaFile(@Nullable String filename)
- throws RemoteException;
-
- /**
- * @return The current status of the run.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public RemoteStatus getStatus() throws RemoteException;
-
- /**
- * Set the status of the run, which should cause it to move into the given
- * state. This may cause some significant changes.
- *
- * @param s
- * The state to try to change to.
- * @throws IllegalStateTransitionException
- * If the requested state change is impossible. (Note that it is
- * always legal to set the status to the current status.)
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws ImplementationException
- * If something goes horribly wrong on the back end.
- * @throws StillWorkingOnItException
- * If the startup time of the workflow implementation exceeds a
- * built-in threshold.
- */
- public void setStatus(@Nonnull RemoteStatus s)
- throws IllegalStateTransitionException, RemoteException,
- ImplementationException, StillWorkingOnItException;
-
- /**
- * @return When this workflow run was found to have finished, or
- * <tt>null</tt> if it has never finished (either still running or
- * never started).
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- public Date getFinishTimestamp() throws RemoteException;
-
- /**
- * @return When this workflow run was started, or <tt>null</tt> if it has
- * never been started.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nullable
- public Date getStartTimestamp() throws RemoteException;
-
- /**
- * @return Handle to the main working directory of the run.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public RemoteDirectory getWorkingDirectory() throws RemoteException;
-
- /**
- * @return The list of listener instances attached to the run.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public List<RemoteListener> getListeners() throws RemoteException;
-
- /**
- * Add a listener to the run.
- *
- * @param listener
- * The listener to add.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws ImplementationException
- * If something goes wrong when adding the listener.
- */
- public void addListener(@Nonnull RemoteListener listener)
- throws RemoteException, ImplementationException;
-
- /**
- * @return The security context structure for this run.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws ImplementationException
- * If something goes wrong when getting the context.
- */
- @Nonnull
- public RemoteSecurityContext getSecurityContext() throws RemoteException,
- ImplementationException;
-
- /**
- * Kill off this run, removing all resources which it consumes.
- *
- * @throws RemoteException
- * If anything goes wrong with the communication.
- * @throws ImplementationException
- * If something goes horribly wrong when destroying the run.
- */
- public void destroy() throws RemoteException, ImplementationException;
-
- /**
- * Get the types of listener supported by this run.
- *
- * @return A list of listener type names.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public List<String> getListenerTypes() throws RemoteException;
-
- /**
- * Create a listener that can be attached to this run.
- *
- * @param type
- * The type name of the listener to create; it must be one of the
- * names returned by the {@link #getListenerTypes()} operation.
- * @param configuration
- * The configuration document for this listener. The nature of
- * the contents of this are determined by the type.
- * @return A handle for the listener.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- @Nonnull
- public RemoteListener makeListener(@Nonnull String type,
- @Nonnull String configuration) throws RemoteException;
-
- /**
- * Configures the details to use when setting up the workflow run's
- * connnection to the interaction feed.
- *
- * @param interactionFeed
- * The location of the interaction feed. If <tt>null</tt>,
- * defaults from the factory will be used instead.
- * @param webdavPath
- * The location used for pushing web pages to support the feed.
- * If <tt>null</tt>, a default from the factory will be used
- * instead.
- * @param publishUrlBase
- * Where to <i>actually</i> publish to, if this needs to be
- * different from the location presented in the published HTML
- * and Feed entries. Necessary in complex network scenarios.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void setInteractionServiceDetails(@Nonnull URL interactionFeed,
- @Nonnull URL webdavPath, @Nullable URL publishUrlBase) throws RemoteException;
-
- /**
- * A do-nothing method, used to check the general reachability of the
- * workflow run.
- *
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void ping() throws RemoteException;
-
- /**
- * Sets whether we should generate provenance information from a run.
- *
- * @param generateProvenance
- * Boolean flag, true for do the generation. Must be set before
- * starting the run for this to have an effect.
- * @throws RemoteException
- * If anything goes wrong with the communication.
- */
- void setGenerateProvenance(boolean generateProvenance)
- throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java
deleted file mode 100644
index db039f0..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/RemoteStatus.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-/**
- * States of a workflow run. They are {@link RemoteStatus#Initialized
- * Initialized}, {@link RemoteStatus#Operating Operating},
- * {@link RemoteStatus#Stopped Stopped}, and {@link RemoteStatus#Finished
- * Finished}. Conceptually, there is also a <tt>Destroyed</tt> state, but the
- * workflow run does not exist (and hence can't have its state queried or set)
- * in that case.
- *
- * @author Donal Fellows
- */
-public enum RemoteStatus {
- /**
- * The workflow run has been created, but is not yet running. The run will
- * need to be manually moved to {@link #Operating} when ready.
- */
- Initialized,
- /**
- * The workflow run is going, reading input, generating output, etc. Will
- * eventually either move automatically to {@link #Finished} or can be moved
- * manually to {@link #Stopped} (where supported).
- */
- Operating,
- /**
- * The workflow run is paused, and will need to be moved back to
- * {@link #Operating} manually.
- */
- Stopped,
- /**
- * The workflow run has ceased; data files will continue to exist until the
- * run is destroyed (which may be manual or automatic).
- */
- Finished
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java
deleted file mode 100644
index 4643d5c..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/StillWorkingOnItException.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.remote;
-
-/**
- * Exception that indicates that the implementation is still working on
- * processing the operation. Note that though this is an exception, it is <i>not
- * a failure</i>.
- *
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-public class StillWorkingOnItException extends Exception {
- public StillWorkingOnItException(String string) {
- super(string);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java b/server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java
deleted file mode 100644
index 9880a3b..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/remote/package-info.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Interfaces exported by worker classes to the server.
- */
-package org.taverna.server.localworker.remote;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java b/server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java
deleted file mode 100644
index 89c29ae..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/server/UsageRecordReceiver.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.server;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-/**
- * Interface exported by (part of) the webapp to allow processes it creates to
- * push in usage records.
- *
- * @author Donal Fellows
- */
-public interface UsageRecordReceiver extends Remote {
- /**
- * Called to push in a usage record. Note that it is assumed that the usage
- * record already contains all the information required to locate and
- * process the job; there is no separate handle.
- *
- * @param usageRecord
- * The serialised XML of the usage record.
- * @throws RemoteException
- * if anything goes wrong.
- */
- void acceptUsageRecord(String usageRecord) throws RemoteException;
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java
----------------------------------------------------------------------
diff --git a/server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java b/server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java
deleted file mode 100644
index cdd592b..0000000
--- a/server-runinterface/src/main/java/org/taverna/server/localworker/server/package-info.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Interfaces exported by the server to worker classes.
- */
-package org.taverna.server.localworker.server;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-unix-forker/pom.xml
----------------------------------------------------------------------
diff --git a/server-unix-forker/pom.xml b/server-unix-forker/pom.xml
deleted file mode 100644
index a2beeb4..0000000
--- a/server-unix-forker/pom.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-unix-forker</artifactId>
- <name>Apache Taverna Server Impersonation Module (Unix)</name>
- <description>Manages the starting of the worker processes as different users. Unix-specific.</description>
-
- <properties>
- <project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
- <forkerMainClass>org.taverna.server.unixforker.Forker</forkerMainClass>
- </properties>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- <archive>
- <manifest>
- <mainClass>${forkerMainClass}</mainClass>
- </manifest>
- </archive>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java
----------------------------------------------------------------------
diff --git a/server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java b/server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java
deleted file mode 100644
index f9dc632..0000000
--- a/server-unix-forker/src/main/java/org/taverna/server/unixforker/Forker.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.unixforker;
-
-import static java.lang.System.err;
-import static java.lang.System.getProperty;
-import static java.lang.System.in;
-import static java.lang.System.out;
-import static java.util.Arrays.asList;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-
-/**
- * A simple class that forks off processes when asked to over its standard
- * input. The one complication is that it forks them off as other users, through
- * the use of the <tt>sudo</tt> utility. It is Unix-specific.
- *
- * @author Donal Fellows
- */
-public class Forker extends Thread {
- private static String password;
- private static BufferedReader br;
-
- /**
- * Helper to make reading a password from a file clearer. The password must
- * be the first line of the file.
- *
- * @param passwordFile
- * The file to load from.
- * @throws IOException
- * If anything goes wrong.
- */
- private static void loadPassword(@Nonnull File passwordFile)
- throws IOException {
- try {
- err.println("attempting to load password from " + passwordFile);
- try (FileReader fr = new FileReader(passwordFile)) {
- password = new BufferedReader(fr).readLine();
- }
- } catch (IOException e) {
- err.println("failed to read password from file " + passwordFile
- + "described in password.file property");
- throw e;
- }
- }
-
- /**
- * Initialization code, which runs before the main loop starts processing.
- *
- * @param args
- * The arguments to the program.
- * @throws Exception
- * If anything goes wrong.
- */
- public static void init(String[] args) throws Exception {
- if (args.length < 1)
- throw new IllegalArgumentException(
- "wrong # args: must be \"program ?argument ...?\"");
- if (getProperty("password.file") != null)
- loadPassword(new File(getProperty("password.file")));
- if (password == null)
- err.println("no password.file property or empty file; "
- + "assuming password-less sudo is configured");
- else
- err.println("password is of length " + password.length());
- br = new BufferedReader(new InputStreamReader(in));
- }
-
- /**
- * The body of the main loop of this program.
- *
- * @param args
- * The arguments to use when running the other program.
- * @return Whether to repeat the loop.
- * @throws Exception
- * If anything goes wrong. Note that the loop is repeated if an
- * exception occurs in it.
- */
- public static boolean mainLoopBody(String[] args) throws Exception {
- String line = br.readLine();
- if (line == null)
- return false;
- List<String> vals = asList(line.split("[ \t]+"));
- if (vals.size() != 2) {
- out.println("wrong # values: must be \"username UUID\"");
- return true;
- }
- ProcessBuilder pb = new ProcessBuilder();
- pb.command()
- .addAll(asList("sudo", "-u", vals.get(0), "-S", "-H", "--"));
- pb.command().addAll(asList(args));
- pb.command().add(vals.get(1));
- Forker f = new Forker(pb);
- f.setDaemon(true);
- f.start();
- return true;
- }
-
- /**
- * The main code for this class, which turns this into an executable
- * program. Runs the initialisation and then the main loop, in both cases
- * with appropriate error handling.
- *
- * @param args
- * Arguments to this program.
- */
- public static void main(String... args) {
- try {
- init(args);
- while (true) {
- try {
- if (!mainLoopBody(args))
- break;
- } catch (Exception e) {
- e.printStackTrace(err);
- out.println(e.getClass().getName() + ": " + e.getMessage());
- }
- }
- System.exit(0);
- } catch (Exception e) {
- e.printStackTrace(err);
- System.exit(1);
- }
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- public Forker(ProcessBuilder pb) throws IOException {
- out.println("Starting subprocess: " + pb.command());
- final Process p = pb.start();
- abstract class ProcessAttachedDaemon extends Thread {
- public ProcessAttachedDaemon() {
- setDaemon(true);
- start();
- }
-
- abstract void act() throws Exception;
-
- @Override
- public final void run() {
- try {
- act();
- p.waitFor();
- } catch (InterruptedException e) {
- // Just drop
- } catch (Exception e) {
- p.destroy();
- e.printStackTrace(err);
- }
- }
- }
- new ProcessAttachedDaemon() {
- @Override
- void act() throws Exception {
- copyFromSudo("Subprocess(out):", p.getInputStream());
- }
- };
- new ProcessAttachedDaemon() {
- @Override
- void act() throws Exception {
- copyFromSudo("Subprocess(err):", p.getErrorStream());
- }
- };
- new ProcessAttachedDaemon() {
- @Override
- void act() throws Exception {
- interactWithSudo(p.getOutputStream());
- }
- };
- }
-
- protected void interactWithSudo(OutputStream os) throws Exception {
- if (password != null) {
- OutputStreamWriter osw = new OutputStreamWriter(os);
- osw.write(password + "\n");
- osw.flush();
- }
- os.close();
- }
-
- protected void copyFromSudo(String header, InputStream sudoStream)
- throws Exception {
- int b = '\n';
- while (true) {
- if (b == '\n')
- out.print(header);
- b = sudoStream.read();
- if (b == -1)
- break;
- out.write(b);
- out.flush();
- }
- sudoStream.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-usagerecord/.gitignore
----------------------------------------------------------------------
diff --git a/server-usagerecord/.gitignore b/server-usagerecord/.gitignore
deleted file mode 100644
index ea8c4bf..0000000
--- a/server-usagerecord/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-usagerecord/pom.xml
----------------------------------------------------------------------
diff --git a/server-usagerecord/pom.xml b/server-usagerecord/pom.xml
deleted file mode 100644
index 47ab732..0000000
--- a/server-usagerecord/pom.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-usagerecord</artifactId>
- <name>Apache Taverna Server Usage Record Support</name>
- <description>Basic Java bindings for the OGF Usage Record Format, version 1.0, plus a simple wrapper to make working with it easier.</description>
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>jaxb2-maven-plugin</artifactId>
- <version>1.3.1</version>
- <executions>
- <execution>
- <id>xsd2java</id>
- <goals>
- <goal>xjc</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/generated-sources/xjc</outputDirectory>
- <schemaDirectory>${basedir}/src/main/xsd</schemaDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- </plugins>
- <pluginManagement>
- <plugins>
- <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>jaxb2-maven-plugin</artifactId>
- <versionRange>[1.3.1,)</versionRange>
- <goals>
- <goal>xjc</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute />
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-</project>
[20/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
new file mode 100644
index 0000000..48969fa
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static javax.ws.rs.core.Response.created;
+import static javax.ws.rs.core.Response.noContent;
+import static javax.ws.rs.core.Response.ok;
+import static javax.ws.rs.core.Response.seeOther;
+import static javax.ws.rs.core.Response.status;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
+import static org.taverna.server.master.api.ContentTypes.DIRECTORY_VARIANTS;
+import static org.taverna.server.master.api.ContentTypes.INITIAL_FILE_VARIANTS;
+import static org.taverna.server.master.common.Roles.SELF;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.common.Uri.secure;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.PathSegment;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.Variant;
+import javax.xml.ws.Holder;
+
+import org.apache.commons.logging.Log;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.api.DirectoryBean;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.rest.DirectoryContents;
+import org.taverna.server.master.rest.FileSegment;
+import org.taverna.server.master.rest.MakeOrUpdateDirEntry;
+import org.taverna.server.master.rest.MakeOrUpdateDirEntry.MakeDirectory;
+import org.taverna.server.master.rest.TavernaServerDirectoryREST;
+import org.taverna.server.master.utils.FilenameUtils;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * RESTful access to the filesystem.
+ *
+ * @author Donal Fellows
+ */
+class DirectoryREST implements TavernaServerDirectoryREST, DirectoryBean {
+ private Log log = getLog("Taverna.Server.Webapp");
+ private TavernaServerSupport support;
+ private TavernaRun run;
+ private FilenameUtils fileUtils;
+
+ @Override
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ @Required
+ public void setFileUtils(FilenameUtils fileUtils) {
+ this.fileUtils = fileUtils;
+ }
+
+ @Override
+ public DirectoryREST connect(TavernaRun run) {
+ this.run = run;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Response destroyDirectoryEntry(List<PathSegment> path)
+ throws NoUpdateException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ support.permitUpdate(run);
+ fileUtils.getDirEntry(run, path).destroy();
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public DirectoryContents getDescription(UriInfo ui)
+ throws FilesystemAccessException {
+ return new DirectoryContents(ui, run.getWorkingDirectory()
+ .getContents());
+ }
+
+ @Override
+ @CallCounted
+ public Response options(List<PathSegment> path) {
+ return opt("PUT", "POST", "DELETE");
+ }
+
+ /*
+ * // Nasty! This can have several different responses...
+ *
+ * @Override @CallCounted private Response
+ * getDirectoryOrFileContents(List<PathSegment> path, UriInfo ui, Request
+ * req) throws FilesystemAccessException, NoDirectoryEntryException {
+ *
+ * DirectoryEntry de = fileUtils.getDirEntry(run, path);
+ *
+ * // How did the user want the result?
+ *
+ * List<Variant> variants = getVariants(de); Variant v =
+ * req.selectVariant(variants); if (v == null) return
+ * notAcceptable(variants).type(TEXT_PLAIN)
+ * .entity("Do not know what type of response to produce.") .build();
+ *
+ * // Produce the content to deliver up
+ *
+ * Object result; if
+ * (v.getMediaType().equals(APPLICATION_OCTET_STREAM_TYPE))
+ *
+ * // Only for files...
+ *
+ * result = de; else if (v.getMediaType().equals(APPLICATION_ZIP_TYPE))
+ *
+ * // Only for directories...
+ *
+ * result = ((Directory) de).getContentsAsZip(); else
+ *
+ * // Only for directories... // XML or JSON; let CXF pick what to do
+ *
+ * result = new DirectoryContents(ui, ((Directory) de).getContents());
+ * return ok(result).type(v.getMediaType()).build();
+ *
+ * }
+ */
+
+ private boolean matchType(MediaType a, MediaType b) {
+ if (log.isDebugEnabled())
+ log.debug("comparing " + a.getType() + "/" + a.getSubtype()
+ + " and " + b.getType() + "/" + b.getSubtype());
+ return (a.isWildcardType() || b.isWildcardType() || a.getType().equals(
+ b.getType()))
+ && (a.isWildcardSubtype() || b.isWildcardSubtype() || a
+ .getSubtype().equals(b.getSubtype()));
+ }
+
+ /**
+ * What are we willing to serve up a directory or file as?
+ *
+ * @param de
+ * The reference to the object to serve.
+ * @return The variants we can serve it as.
+ * @throws FilesystemAccessException
+ * If we fail to read data necessary to detection of its media
+ * type.
+ */
+ private List<Variant> getVariants(DirectoryEntry de)
+ throws FilesystemAccessException {
+ if (de instanceof Directory)
+ return DIRECTORY_VARIANTS;
+ else if (!(de instanceof File))
+ throw new FilesystemAccessException("not a directory or file!");
+ File f = (File) de;
+ List<Variant> variants = new ArrayList<>(INITIAL_FILE_VARIANTS);
+ String contentType = support.getEstimatedContentType(f);
+ if (!contentType.equals(APPLICATION_OCTET_STREAM)) {
+ String[] ct = contentType.split("/");
+ variants.add(0,
+ new Variant(new MediaType(ct[0], ct[1]), (String) null, null));
+ }
+ return variants;
+ }
+
+ /** How did the user want the result? */
+ private MediaType pickType(HttpHeaders headers, DirectoryEntry de)
+ throws FilesystemAccessException, NegotiationFailedException {
+ List<Variant> variants = getVariants(de);
+ // Manual content negotiation!!! Ugh!
+ for (MediaType mt : headers.getAcceptableMediaTypes())
+ for (Variant v : variants)
+ if (matchType(mt, v.getMediaType()))
+ return v.getMediaType();
+ throw new NegotiationFailedException(
+ "Do not know what type of response to produce.", variants);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Response getDirectoryOrFileContents(List<PathSegment> path,
+ UriInfo ui, HttpHeaders headers) throws FilesystemAccessException,
+ NoDirectoryEntryException, NegotiationFailedException {
+ DirectoryEntry de = fileUtils.getDirEntry(run, path);
+
+ // How did the user want the result?
+ MediaType wanted = pickType(headers, de);
+
+ log.info("producing content of type " + wanted);
+ // Produce the content to deliver up
+ Object result;
+ if (de instanceof File) {
+ // Only for files...
+ result = de;
+ List<String> range = headers.getRequestHeader("Range");
+ if (range != null && range.size() == 1)
+ return new FileSegment((File) de, range.get(0))
+ .toResponse(wanted);
+ } else {
+ // Only for directories...
+ Directory d = (Directory) de;
+ if (wanted.getType().equals(APPLICATION_ZIP_TYPE.getType())
+ && wanted.getSubtype().equals(
+ APPLICATION_ZIP_TYPE.getSubtype()))
+ result = d.getContentsAsZip();
+ else
+ // XML or JSON; let CXF pick what to do
+ result = new DirectoryContents(ui, d.getContents());
+ }
+ return ok(result).type(wanted).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Response makeDirectoryOrUpdateFile(List<PathSegment> parent,
+ MakeOrUpdateDirEntry op, UriInfo ui) throws NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException {
+ support.permitUpdate(run);
+ DirectoryEntry container = fileUtils.getDirEntry(run, parent);
+ if (!(container instanceof Directory))
+ throw new FilesystemAccessException("You may not "
+ + ((op instanceof MakeDirectory) ? "make a subdirectory of"
+ : "place a file in") + " a file.");
+ if (op.name == null || op.name.length() == 0)
+ throw new FilesystemAccessException("missing name attribute");
+ Directory d = (Directory) container;
+ UriBuilder ub = secure(ui).path("{name}");
+
+ // Make a directory in the context directory
+
+ if (op instanceof MakeDirectory) {
+ Directory target = d.makeSubdirectory(support.getPrincipal(),
+ op.name);
+ return created(ub.build(target.getName())).build();
+ }
+
+ // Make or set the contents of a file
+
+ File f = null;
+ for (DirectoryEntry e : d.getContents()) {
+ if (e.getName().equals(op.name)) {
+ if (e instanceof Directory)
+ throw new FilesystemAccessException(
+ "You may not overwrite a directory with a file.");
+ f = (File) e;
+ break;
+ }
+ }
+ if (f == null) {
+ f = d.makeEmptyFile(support.getPrincipal(), op.name);
+ f.setContents(op.contents);
+ return created(ub.build(f.getName())).build();
+ }
+ f.setContents(op.contents);
+ return seeOther(ub.build(f.getName())).build();
+ }
+
+ private File getFileForWrite(List<PathSegment> filePath,
+ Holder<Boolean> isNew) throws FilesystemAccessException,
+ NoDirectoryEntryException, NoUpdateException {
+ support.permitUpdate(run);
+ if (filePath == null || filePath.size() == 0)
+ throw new FilesystemAccessException(
+ "Cannot create a file that is not in a directory.");
+
+ List<PathSegment> dirPath = new ArrayList<>(filePath);
+ String name = dirPath.remove(dirPath.size() - 1).getPath();
+ DirectoryEntry de = fileUtils.getDirEntry(run, dirPath);
+ if (!(de instanceof Directory)) {
+ throw new FilesystemAccessException(
+ "Cannot create a file that is not in a directory.");
+ }
+ Directory d = (Directory) de;
+
+ File f = null;
+ isNew.value = false;
+ for (DirectoryEntry e : d.getContents())
+ if (e.getName().equals(name)) {
+ if (e instanceof File) {
+ f = (File) e;
+ break;
+ }
+ throw new FilesystemAccessException(
+ "Cannot create a file that is not in a directory.");
+ }
+
+ if (f == null) {
+ f = d.makeEmptyFile(support.getPrincipal(), name);
+ isNew.value = true;
+ } else
+ f.setContents(new byte[0]);
+ return f;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Response setFileContents(List<PathSegment> filePath,
+ InputStream contents, UriInfo ui) throws NoDirectoryEntryException,
+ NoUpdateException, FilesystemAccessException {
+ Holder<Boolean> isNew = new Holder<>(true);
+ support.copyStreamToFile(contents, getFileForWrite(filePath, isNew));
+
+ if (isNew.value)
+ return created(ui.getAbsolutePath()).build();
+ else
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response setFileContentsFromURL(List<PathSegment> filePath,
+ List<URI> referenceList, UriInfo ui)
+ throws NoDirectoryEntryException, NoUpdateException,
+ FilesystemAccessException {
+ support.permitUpdate(run);
+ if (referenceList.isEmpty() || referenceList.size() > 1)
+ return status(422).entity("URI list must have single URI in it")
+ .build();
+ URI uri = referenceList.get(0);
+ try {
+ uri.toURL();
+ } catch (MalformedURLException e) {
+ return status(422).entity("URI list must have value URL in it")
+ .build();
+ }
+ Holder<Boolean> isNew = new Holder<>(true);
+ File f = getFileForWrite(filePath, isNew);
+
+ try {
+ support.copyDataToFile(uri, f);
+ } catch (MalformedURLException ex) {
+ // Should not happen; called uri.toURL() successfully above
+ throw new NoUpdateException("failed to parse URI", ex);
+ } catch (IOException ex) {
+ throw new FilesystemAccessException(
+ "failed to transfer data from URI", ex);
+ }
+
+ if (isNew.value)
+ return created(ui.getAbsolutePath()).build();
+ else
+ return noContent().build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
new file mode 100644
index 0000000..3893b3d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
@@ -0,0 +1,68 @@
+package org.taverna.server.master;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.File;
+
+/**
+ * Simple concatenation of files.
+ *
+ * @author Donal Fellows
+ */
+public class FileConcatenation implements Iterable<File> {
+ private List<File> files = new ArrayList<>();
+
+ public void add(File f) {
+ files.add(f);
+ }
+
+ public boolean isEmpty() {
+ return files.isEmpty();
+ }
+
+ /**
+ * @return The total length of the files, or -1 if this cannot be
+ * determined.
+ */
+ public long size() {
+ long size = 0;
+ for (File f : files)
+ try {
+ size += f.getSize();
+ } catch (FilesystemAccessException e) {
+ // Ignore; shouldn't happen but can't guarantee
+ }
+ return (size == 0 && !files.isEmpty() ? -1 : size);
+ }
+
+ /**
+ * Get the concatenated files.
+ *
+ * @param encoding
+ * The encoding to use.
+ * @return The concatenated files.
+ * @throws UnsupportedEncodingException
+ * If the encoding doesn't exist.
+ */
+ public String get(String encoding) throws UnsupportedEncodingException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (File f : files)
+ try {
+ baos.write(f.getContents(0, -1));
+ } catch (FilesystemAccessException | IOException e) {
+ continue;
+ }
+ return baos.toString(encoding);
+ }
+
+ @Override
+ public Iterator<File> iterator() {
+ return files.iterator();
+ }
+}
\ 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/InputREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/InputREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/InputREST.java
new file mode 100644
index 0000000..0f48207
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/InputREST.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static java.util.UUID.randomUUID;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.util.Date;
+
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.model.URITemplate;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.api.InputBean;
+import org.taverna.server.master.common.DirEntryReference;
+import org.taverna.server.master.exceptions.BadInputPortNameException;
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+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.NoUpdateException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.Input;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.rest.TavernaServerInputREST;
+import org.taverna.server.master.rest.TavernaServerInputREST.InDesc.AbstractContents;
+import org.taverna.server.master.rest.TavernaServerInputREST.InDesc.Reference;
+import org.taverna.server.master.utils.FilenameUtils;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+import org.taverna.server.port_description.InputDescription;
+
+/**
+ * RESTful interface to the input descriptor of a single workflow run.
+ *
+ * @author Donal Fellows
+ */
+class InputREST implements TavernaServerInputREST, InputBean {
+ private UriInfo ui;
+ private TavernaServerSupport support;
+ private TavernaRun run;
+ private ContentsDescriptorBuilder cdBuilder;
+ private FilenameUtils fileUtils;
+
+ @Override
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ @Required
+ public void setCdBuilder(ContentsDescriptorBuilder cdBuilder) {
+ this.cdBuilder = cdBuilder;
+ }
+
+ @Override
+ @Required
+ public void setFileUtils(FilenameUtils fileUtils) {
+ this.fileUtils = fileUtils;
+ }
+
+ @Override
+ public InputREST connect(TavernaRun run, UriInfo ui) {
+ this.run = run;
+ this.ui = ui;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public InputsDescriptor get() {
+ return new InputsDescriptor(ui, run);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public InputDescription getExpected() {
+ return cdBuilder.makeInputDescriptor(run, ui);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String getBaclavaFile() {
+ String i = run.getInputBaclavaFile();
+ return i == null ? "" : i;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public InDesc getInput(String name, UriInfo ui) throws BadInputPortNameException {
+ Input i = support.getInput(run, name);
+ if (i == null)
+ throw new BadInputPortNameException("unknown input port name");
+ return new InDesc(i, ui);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String setBaclavaFile(String filename) throws NoUpdateException,
+ BadStateChangeException, FilesystemAccessException {
+ support.permitUpdate(run);
+ run.setInputBaclavaFile(filename);
+ String i = run.getInputBaclavaFile();
+ return i == null ? "" : i;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public InDesc setInput(String name, InDesc inputDescriptor, UriInfo ui)
+ throws NoUpdateException, BadStateChangeException,
+ FilesystemAccessException, BadInputPortNameException,
+ BadPropertyValueException {
+ inputDescriptor.descriptorRef = null;
+ AbstractContents ac = inputDescriptor.assignment;
+ if (name == null || name.isEmpty())
+ throw new BadInputPortNameException("bad input name");
+ if (ac == null)
+ throw new BadPropertyValueException("no content!");
+ if (inputDescriptor.delimiter != null
+ && inputDescriptor.delimiter.isEmpty())
+ inputDescriptor.delimiter = null;
+ if (ac instanceof InDesc.Reference)
+ return setRemoteInput(name, (InDesc.Reference) ac,
+ inputDescriptor.delimiter, ui);
+ if (!(ac instanceof InDesc.File || ac instanceof InDesc.Value))
+ throw new BadPropertyValueException("unknown content type");
+ support.permitUpdate(run);
+ Input i = support.getInput(run, name);
+ if (i == null)
+ i = run.makeInput(name);
+ if (ac instanceof InDesc.File)
+ i.setFile(ac.contents);
+ else
+ i.setValue(ac.contents);
+ i.setDelimiter(inputDescriptor.delimiter);
+ return new InDesc(i, ui);
+ }
+
+ private InDesc setRemoteInput(String name, Reference ref, String delimiter,
+ UriInfo ui) throws BadStateChangeException,
+ BadPropertyValueException, FilesystemAccessException {
+ URITemplate tmpl = new URITemplate(ui.getBaseUri()
+ + "/runs/{runName}/wd/{path:.+}");
+ MultivaluedMap<String, String> mvm = new MetadataMap<>();
+ if (!tmpl.match(ref.contents, mvm)) {
+ throw new BadPropertyValueException(
+ "URI in reference does not refer to local disk resource");
+ }
+ try {
+ File from = fileUtils.getFile(
+ support.getRun(mvm.get("runName").get(0)),
+ SyntheticDirectoryEntry.make(mvm.get("path").get(0)));
+ File to = run.getWorkingDirectory().makeEmptyFile(
+ support.getPrincipal(), randomUUID().toString());
+
+ to.copy(from);
+
+ Input i = support.getInput(run, name);
+ if (i == null)
+ i = run.makeInput(name);
+ i.setFile(to.getFullName());
+ i.setDelimiter(delimiter);
+ return new InDesc(i, ui);
+ } catch (UnknownRunException e) {
+ throw new BadStateChangeException("may not copy from that run", e);
+ } catch (NoDirectoryEntryException e) {
+ throw new BadStateChangeException("source does not exist", e);
+ }
+ }
+
+ @Override
+ @CallCounted
+ public Response options() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response expectedOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response baclavaOptions() {
+ return opt("PUT");
+ }
+
+ @Override
+ @CallCounted
+ public Response inputOptions(@PathParam("name") String name) {
+ return opt("PUT");
+ }
+}
+
+/**
+ * A way to create synthetic directory entries, used during deletion.
+ *
+ * @author Donal Fellows
+ */
+class SyntheticDirectoryEntry implements DirectoryEntry {
+ public static DirEntryReference make(String path) {
+ return DirEntryReference.newInstance(new SyntheticDirectoryEntry(path));
+ }
+
+ private SyntheticDirectoryEntry(String p) {
+ this.p = p;
+ this.d = new Date();
+ }
+
+ private String p;
+ private Date d;
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public String getFullName() {
+ return p;
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public int compareTo(DirectoryEntry o) {
+ return p.compareTo(o.getFullName());
+ }
+
+ @Override
+ public Date getModificationDate() {
+ return d;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
new file mode 100644
index 0000000..b686491
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static org.taverna.server.master.common.Roles.SELF;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.core.Response;
+
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.taverna.server.master.api.FeedBean;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interaction.InteractionFeedSupport;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.rest.InteractionFeedREST;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * How to connect an interaction feed to the webapp.
+ *
+ * @author Donal Fellows
+ */
+public class InteractionFeed implements InteractionFeedREST, FeedBean {
+ private InteractionFeedSupport interactionFeed;
+ private TavernaRun run;
+
+ @Override
+ public void setInteractionFeedSupport(InteractionFeedSupport feed) {
+ this.interactionFeed = feed;
+ }
+
+ InteractionFeed connect(TavernaRun run) {
+ this.run = run;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Feed getFeed() throws FilesystemAccessException,
+ NoDirectoryEntryException {
+ return interactionFeed.getRunFeed(run);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Response addEntry(Entry entry) throws MalformedURLException,
+ FilesystemAccessException, NoDirectoryEntryException,
+ NoUpdateException {
+ Entry realEntry = interactionFeed.addRunFeedEntry(run, entry);
+ URI location;
+ try {
+ location = realEntry.getSelfLink().getHref().toURI();
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("failed to make URI from link?!", e);
+ }
+ return Response.created(location).entity(realEntry)
+ .type("application/atom+xml;type=entry").build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public Entry getEntry(String id) throws FilesystemAccessException,
+ NoDirectoryEntryException {
+ return interactionFeed.getRunFeedEntry(run, id);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public String deleteEntry(String id) throws FilesystemAccessException,
+ NoDirectoryEntryException, NoUpdateException {
+ interactionFeed.removeRunFeedEntry(run, id);
+ return "entry successfully deleted";
+ }
+
+ @Override
+ @CallCounted
+ public Response feedOptions() {
+ return opt("POST");
+ }
+
+ @Override
+ @CallCounted
+ public Response entryOptions(String id) {
+ return opt("DELETE");
+ }
+}
\ 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/ListenerPropertyREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java
new file mode 100644
index 0000000..3e983a9
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.logging.Log;
+import org.taverna.server.master.api.ListenerPropertyBean;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.rest.TavernaServerListenersREST;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * RESTful interface to a single property of a workflow run.
+ *
+ * @author Donal Fellows
+ */
+class ListenerPropertyREST implements TavernaServerListenersREST.Property,
+ ListenerPropertyBean {
+ private Log log = getLog("Taverna.Server.Webapp");
+ private TavernaServerSupport support;
+ private Listener listen;
+ private String propertyName;
+ private TavernaRun run;
+
+ @Override
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ public ListenerPropertyREST connect(Listener listen, TavernaRun run,
+ String propertyName) {
+ this.listen = listen;
+ this.propertyName = propertyName;
+ this.run = run;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String getValue() {
+ try {
+ return listen.getProperty(propertyName);
+ } catch (NoListenerException e) {
+ log.error("unexpected exception; property \"" + propertyName
+ + "\" should exist", e);
+ return null;
+ }
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String setValue(String value) throws NoUpdateException,
+ NoListenerException {
+ support.permitUpdate(run);
+ listen.setProperty(propertyName, value);
+ return listen.getProperty(propertyName);
+ }
+
+ @Override
+ @CallCounted
+ public Response options() {
+ return opt("PUT");
+ }
+}
\ 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/ListenersREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java
new file mode 100644
index 0000000..4b7d7f3
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static javax.ws.rs.core.Response.created;
+import static javax.ws.rs.core.UriBuilder.fromUri;
+import static org.taverna.server.master.common.Uri.secure;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.taverna.server.master.api.ListenersBean;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.rest.ListenerDefinition;
+import org.taverna.server.master.rest.TavernaServerListenersREST;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * RESTful interface to a single workflow run's event listeners.
+ *
+ * @author Donal Fellows
+ */
+abstract class ListenersREST implements TavernaServerListenersREST,
+ ListenersBean {
+ private TavernaRun run;
+ private TavernaServerSupport support;
+
+ @Override
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ public ListenersREST connect(TavernaRun run) {
+ this.run = run;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response addListener(ListenerDefinition typeAndConfiguration,
+ UriInfo ui) throws NoUpdateException, NoListenerException {
+ String name = support.makeListener(run, typeAndConfiguration.type,
+ typeAndConfiguration.configuration).getName();
+ return created(secure(ui).path("{listenerName}").build(name)).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public TavernaServerListenerREST getListener(String name)
+ throws NoListenerException {
+ Listener l = support.getListener(run, name);
+ if (l == null)
+ throw new NoListenerException();
+ return makeListenerInterface().connect(l, run);
+ }
+
+ @Nonnull
+ protected abstract SingleListenerREST makeListenerInterface();
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Listeners getDescription(UriInfo ui) {
+ List<ListenerDescription> result = new ArrayList<>();
+ UriBuilder ub = secure(ui).path("{name}");
+ for (Listener l : run.getListeners())
+ result.add(new ListenerDescription(l,
+ fromUri(ub.build(l.getName()))));
+ return new Listeners(result, ub);
+ }
+
+ @Override
+ @CallCounted
+ public Response listenersOptions() {
+ return opt();
+ }
+}
\ 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/ManagementState.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/ManagementState.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/ManagementState.java
new file mode 100644
index 0000000..9d4a651
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/ManagementState.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import javax.annotation.PostConstruct;
+import javax.jdo.Query;
+import javax.jdo.annotations.PersistenceAware;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.api.ManagementModel;
+import org.taverna.server.master.utils.JDOSupport;
+
+/** The persistent, manageable state of the Taverna Server web application. */
+@PersistenceAware
+class ManagementState extends JDOSupport<WebappState> implements
+ ManagementModel {
+ public ManagementState() {
+ super(WebappState.class);
+ }
+
+ /** Whether we should log all workflows sent to us. */
+ private boolean logIncomingWorkflows = false;
+
+ /** Whether we allow the creation of new workflow runs. */
+ private boolean allowNewWorkflowRuns = true;
+
+ /**
+ * Whether outgoing exceptions should be logged before being converted to
+ * responses.
+ */
+ private boolean logOutgoingExceptions = false;
+
+ /**
+ * The file that all usage records should be appended to, or <tt>null</tt>
+ * if they should be just dropped.
+ */
+ private String usageRecordLogFile = null;
+
+ @Override
+ public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
+ this.logIncomingWorkflows = logIncomingWorkflows;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public boolean getLogIncomingWorkflows() {
+ self.load();
+ return logIncomingWorkflows;
+ }
+
+ @Override
+ public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
+ this.allowNewWorkflowRuns = allowNewWorkflowRuns;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public boolean getAllowNewWorkflowRuns() {
+ self.load();
+ return allowNewWorkflowRuns;
+ }
+
+ @Override
+ public void setLogOutgoingExceptions(boolean logOutgoingExceptions) {
+ this.logOutgoingExceptions = logOutgoingExceptions;
+ if (loadedState)
+ self.store();
+ }
+
+ @Override
+ public boolean getLogOutgoingExceptions() {
+ self.load();
+ return logOutgoingExceptions || true;
+ }
+
+ @Override
+ public String getUsageRecordLogFile() {
+ self.load();
+ return usageRecordLogFile;
+ }
+
+ @Override
+ public void setUsageRecordLogFile(String usageRecordLogFile) {
+ this.usageRecordLogFile = usageRecordLogFile;
+ if (loadedState)
+ self.store();
+ }
+
+ private static final int KEY = 42; // whatever
+
+ private WebappState get() {
+ Query q = query("id == " + KEY);
+ q.setUnique(true);
+ return (WebappState) q.execute();
+ }
+
+ private boolean loadedState;
+ private ManagementState self;
+
+ @Required
+ public void setSelf(ManagementState self) {
+ this.self = self;
+ }
+
+ @PostConstruct
+ @WithinSingleTransaction
+ public void load() {
+ if (loadedState || !isPersistent())
+ return;
+ WebappState state = get();
+ if (state == null)
+ return;
+ allowNewWorkflowRuns = state.getAllowNewWorkflowRuns();
+ logIncomingWorkflows = state.getLogIncomingWorkflows();
+ logOutgoingExceptions = state.getLogOutgoingExceptions();
+ usageRecordLogFile = state.getUsageRecordLogFile();
+ loadedState = true;
+ }
+
+ @WithinSingleTransaction
+ public void store() {
+ if (!isPersistent())
+ return;
+ WebappState state = get();
+ if (state == null) {
+ state = new WebappState();
+ // save state
+ state.id = KEY; // whatever...
+ state = persist(state);
+ }
+ state.setAllowNewWorkflowRuns(allowNewWorkflowRuns);
+ state.setLogIncomingWorkflows(logIncomingWorkflows);
+ state.setLogOutgoingExceptions(logOutgoingExceptions);
+ state.setUsageRecordLogFile(usageRecordLogFile);
+ loadedState = true;
+ }
+}
+
+// WARNING! If you change the name of this class, update persistence.xml as
+// well!
+@PersistenceCapable(table = "MANAGEMENTSTATE__WEBAPPSTATE")
+class WebappState implements ManagementModel {
+ public WebappState() {
+ }
+
+ @PrimaryKey
+ protected int id;
+
+ /** Whether we should log all workflows sent to us. */
+ @Persistent
+ private boolean logIncomingWorkflows;
+
+ /** Whether we allow the creation of new workflow runs. */
+ @Persistent
+ private boolean allowNewWorkflowRuns;
+
+ /**
+ * Whether outgoing exceptions should be logged before being converted to
+ * responses.
+ */
+ @Persistent
+ private boolean logOutgoingExceptions;
+
+ /** Where to write usage records. */
+ @Persistent
+ private String usageRecordLogFile;
+
+ @Override
+ public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
+ this.logIncomingWorkflows = logIncomingWorkflows;
+ }
+
+ @Override
+ public boolean getLogIncomingWorkflows() {
+ return logIncomingWorkflows;
+ }
+
+ @Override
+ public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
+ this.allowNewWorkflowRuns = allowNewWorkflowRuns;
+ }
+
+ @Override
+ public boolean getAllowNewWorkflowRuns() {
+ return allowNewWorkflowRuns;
+ }
+
+ @Override
+ public void setLogOutgoingExceptions(boolean logOutgoingExceptions) {
+ this.logOutgoingExceptions = logOutgoingExceptions;
+ }
+
+ @Override
+ public boolean getLogOutgoingExceptions() {
+ return logOutgoingExceptions;
+ }
+
+ @Override
+ public String getUsageRecordLogFile() {
+ return usageRecordLogFile;
+ }
+
+ @Override
+ public void setUsageRecordLogFile(String usageRecordLogFile) {
+ this.usageRecordLogFile = usageRecordLogFile;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/RunREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/RunREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/RunREST.java
new file mode 100644
index 0000000..563a822
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/RunREST.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static javax.ws.rs.core.Response.noContent;
+import static javax.ws.rs.core.Response.ok;
+import static javax.ws.rs.core.Response.status;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.joda.time.format.ISODateTimeFormat.dateTime;
+import static org.joda.time.format.ISODateTimeFormat.dateTimeParser;
+import static org.taverna.server.master.common.Roles.SELF;
+import static org.taverna.server.master.common.Roles.USER;
+import static org.taverna.server.master.common.Status.Initialized;
+import static org.taverna.server.master.common.Status.Operating;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.util.Date;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.joda.time.DateTime;
+import org.ogf.usage.JobUsageRecord;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.api.RunBean;
+import org.taverna.server.master.common.ProfileList;
+import org.taverna.server.master.common.Status;
+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.exceptions.OverloadedException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.rest.InteractionFeedREST;
+import org.taverna.server.master.rest.TavernaServerInputREST;
+import org.taverna.server.master.rest.TavernaServerListenersREST;
+import org.taverna.server.master.rest.TavernaServerRunREST;
+import org.taverna.server.master.rest.TavernaServerSecurityREST;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+import org.taverna.server.port_description.OutputDescription;
+
+/**
+ * RESTful interface to a single workflow run.
+ *
+ * @author Donal Fellows
+ */
+abstract class RunREST implements TavernaServerRunREST, RunBean {
+ private Log log = getLog("Taverna.Server.Webapp");
+ private String runName;
+ private TavernaRun run;
+ private TavernaServerSupport support;
+ private ContentsDescriptorBuilder cdBuilder;
+
+ @Override
+ @Required
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ @Required
+ public void setCdBuilder(ContentsDescriptorBuilder cdBuilder) {
+ this.cdBuilder = cdBuilder;
+ }
+
+ @Override
+ public void setRunName(String runName) {
+ this.runName = runName;
+ }
+
+ @Override
+ public void setRun(TavernaRun run) {
+ this.run = run;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public RunDescription getDescription(UriInfo ui) {
+ return new RunDescription(run, ui);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response destroy() throws NoUpdateException {
+ try {
+ support.unregisterRun(runName, run);
+ } catch (UnknownRunException e) {
+ log.fatal("can't happen", e);
+ }
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public TavernaServerListenersREST getListeners() {
+ return makeListenersInterface().connect(run);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public TavernaServerSecurityREST getSecurity() throws NotOwnerException {
+ TavernaSecurityContext secContext = run.getSecurityContext();
+ if (!support.getPrincipal().equals(secContext.getOwner()))
+ throw new NotOwnerException();
+
+ // context.getBean("run.security", run, secContext);
+ return makeSecurityInterface().connect(secContext, run);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getExpiryTime() {
+ return dateTime().print(new DateTime(run.getExpiry()));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getCreateTime() {
+ return dateTime().print(new DateTime(run.getCreationTimestamp()));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getFinishTime() {
+ Date f = run.getFinishTimestamp();
+ return f == null ? "" : dateTime().print(new DateTime(f));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getStartTime() {
+ Date f = run.getStartTimestamp();
+ return f == null ? "" : dateTime().print(new DateTime(f));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getStatus() {
+ return run.getStatus().toString();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Workflow getWorkflow() {
+ return run.getWorkflow();
+ }
+
+ @Override
+ @CallCounted
+ public String getMainProfileName() {
+ String name = run.getWorkflow().getMainProfileName();
+ return (name == null ? "" : name);
+ }
+
+ @Override
+ @CallCounted
+ public ProfileList getProfiles() {
+ return support.getProfileDescriptor(run.getWorkflow());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public DirectoryREST getWorkingDirectory() {
+ return makeDirectoryInterface().connect(run);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String setExpiryTime(String expiry) throws NoUpdateException,
+ IllegalArgumentException {
+ DateTime wanted = dateTimeParser().parseDateTime(expiry.trim());
+ Date achieved = support.updateExpiry(run, wanted.toDate());
+ return dateTime().print(new DateTime(achieved));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response setStatus(String status) throws NoUpdateException {
+ Status newStatus = Status.valueOf(status.trim());
+ support.permitUpdate(run);
+ if (newStatus == Operating && run.getStatus() == Initialized) {
+ if (!support.getAllowStartWorkflowRuns())
+ throw new OverloadedException();
+ String issue = run.setStatus(newStatus);
+ if (issue == null)
+ issue = "starting run...";
+ return status(202).entity(issue).type("text/plain").build();
+ }
+ run.setStatus(newStatus); // Ignore the result
+ return ok(run.getStatus().toString()).type("text/plain").build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public TavernaServerInputREST getInputs(UriInfo ui) {
+ return makeInputInterface().connect(run, ui);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getOutputFile() {
+ String o = run.getOutputBaclavaFile();
+ return o == null ? "" : o;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String setOutputFile(String filename) throws NoUpdateException,
+ FilesystemAccessException, BadStateChangeException {
+ support.permitUpdate(run);
+ if (filename != null && filename.length() == 0)
+ filename = null;
+ run.setOutputBaclavaFile(filename);
+ String o = run.getOutputBaclavaFile();
+ return o == null ? "" : o;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public OutputDescription getOutputDescription(UriInfo ui)
+ throws BadStateChangeException, FilesystemAccessException,
+ NoDirectoryEntryException {
+ if (run.getStatus() == Initialized)
+ throw new BadStateChangeException(
+ "may not get output description in initial state");
+ return cdBuilder.makeOutputDescriptor(run, ui);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed({ USER, SELF })
+ public InteractionFeedREST getInteractionFeed() {
+ return makeInteractionFeed().connect(run);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getName() {
+ return run.getName();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String setName(String name) throws NoUpdateException {
+ support.permitUpdate(run);
+ run.setName(name);
+ return run.getName();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getStdout() throws NoListenerException {
+ return support.getProperty(run, "io", "stdout");
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public String getStderr() throws NoListenerException {
+ return support.getProperty(run, "io", "stderr");
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response getUsage() throws NoListenerException, JAXBException {
+ String ur = support.getProperty(run, "io", "usageRecord");
+ if (ur.isEmpty())
+ return noContent().build();
+ return ok(JobUsageRecord.unmarshal(ur), APPLICATION_XML).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response getLogContents() {
+ FileConcatenation fc = support.getLogs(run);
+ if (fc.isEmpty())
+ return Response.noContent().build();
+ return Response.ok(fc, TEXT_PLAIN).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public Response getRunBundle() {
+ FileConcatenation fc = support.getProv(run);
+ if (fc.isEmpty())
+ return Response.status(404).entity("no provenance currently available").build();
+ return Response.ok(fc, "application/vnd.wf4ever.robundle+zip").build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public boolean getGenerateProvenance() {
+ return run.getGenerateProvenance();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ @RolesAllowed(USER)
+ public boolean setGenerateProvenance(boolean newValue) throws NoUpdateException {
+ support.permitUpdate(run);
+ run.setGenerateProvenance(newValue);
+ return run.getGenerateProvenance();
+ }
+
+ /**
+ * Construct a RESTful interface to a run's filestore.
+ *
+ * @return The handle to the interface, as decorated by Spring.
+ */
+ protected abstract DirectoryREST makeDirectoryInterface();
+
+ /**
+ * Construct a RESTful interface to a run's input descriptors.
+ *
+ * @return The handle to the interface, as decorated by Spring.
+ */
+ protected abstract InputREST makeInputInterface();
+
+ /**
+ * Construct a RESTful interface to a run's listeners.
+ *
+ * @return The handle to the interface, as decorated by Spring.
+ */
+ protected abstract ListenersREST makeListenersInterface();
+
+ /**
+ * Construct a RESTful interface to a run's security.
+ *
+ * @return The handle to the interface, as decorated by Spring.
+ */
+ protected abstract RunSecurityREST makeSecurityInterface();
+
+ /**
+ * Construct a RESTful interface to a run's interaction feed.
+ *
+ * @return The handle to the interaface, as decorated by Spring.
+ */
+ protected abstract InteractionFeed makeInteractionFeed();
+
+ @Override
+ @CallCounted
+ public Response runOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response workflowOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response profileOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response expiryOptions() {
+ return opt("PUT");
+ }
+
+ @Override
+ @CallCounted
+ public Response createTimeOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response startTimeOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response finishTimeOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response statusOptions() {
+ return opt("PUT");
+ }
+
+ @Override
+ @CallCounted
+ public Response outputOptions() {
+ return opt("PUT");
+ }
+
+ @Override
+ @CallCounted
+ public Response nameOptions() {
+ return opt("PUT");
+ }
+
+ @Override
+ @CallCounted
+ public Response stdoutOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response stderrOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response usageOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response logOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response runBundleOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response generateProvenanceOptions() {
+ 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/RunSecurityREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java
new file mode 100644
index 0000000..5a366b2
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static java.util.UUID.randomUUID;
+import static javax.ws.rs.core.Response.created;
+import static javax.ws.rs.core.Response.noContent;
+import static org.taverna.server.master.common.Status.Initialized;
+import static org.taverna.server.master.common.Uri.secure;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.taverna.server.master.api.SecurityBean;
+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.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.exceptions.NoCredentialException;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.rest.TavernaServerSecurityREST;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * RESTful interface to a single workflow run's security settings.
+ *
+ * @author Donal Fellows
+ */
+class RunSecurityREST implements TavernaServerSecurityREST, SecurityBean {
+ private TavernaServerSupport support;
+ private TavernaSecurityContext context;
+ private TavernaRun run;
+
+ @Override
+ public void setSupport(TavernaServerSupport support) {
+ this.support = support;
+ }
+
+ @Override
+ public RunSecurityREST connect(TavernaSecurityContext context,
+ TavernaRun run) {
+ this.context = context;
+ this.run = run;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Descriptor describe(UriInfo ui) {
+ return new Descriptor(secure(ui).path("{element}"), context.getOwner()
+ .getName(), context.getCredentials(), context.getTrusted());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String getOwner() {
+ return context.getOwner().getName();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public CredentialList listCredentials() {
+ return new CredentialList(context.getCredentials());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public CredentialHolder getParticularCredential(String id)
+ throws NoCredentialException {
+ for (Credential c : context.getCredentials())
+ if (c.id.equals(id))
+ return new CredentialHolder(c);
+ throw new NoCredentialException();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public CredentialHolder setParticularCredential(String id,
+ CredentialHolder cred, UriInfo ui)
+ throws InvalidCredentialException, BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ Credential c = cred.credential;
+ c.id = id;
+ c.href = ui.getAbsolutePath().toString();
+ context.validateCredential(c);
+ context.deleteCredential(c);
+ context.addCredential(c);
+ return new CredentialHolder(c);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response addCredential(CredentialHolder cred, UriInfo ui)
+ throws InvalidCredentialException, BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ Credential c = cred.credential;
+ c.id = randomUUID().toString();
+ URI uri = secure(ui).path("{id}").build(c.id);
+ c.href = uri.toString();
+ context.validateCredential(c);
+ context.addCredential(c);
+ return created(uri).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response deleteAllCredentials(UriInfo ui)
+ throws BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ for (Credential c : context.getCredentials())
+ context.deleteCredential(c);
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response deleteCredential(String id, UriInfo ui)
+ throws BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ context.deleteCredential(new Credential.Dummy(id));
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public TrustList listTrusted() {
+ return new TrustList(context.getTrusted());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Trust getParticularTrust(String id) throws NoCredentialException {
+ for (Trust t : context.getTrusted())
+ if (t.id.equals(id))
+ return t;
+ throw new NoCredentialException();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Trust setParticularTrust(String id, Trust t, UriInfo ui)
+ throws InvalidCredentialException, BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ t.id = id;
+ t.href = ui.getAbsolutePath().toString();
+ context.validateTrusted(t);
+ context.deleteTrusted(t);
+ context.addTrusted(t);
+ return t;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response addTrust(Trust t, UriInfo ui)
+ throws InvalidCredentialException, BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ t.id = randomUUID().toString();
+ URI uri = secure(ui).path("{id}").build(t.id);
+ t.href = uri.toString();
+ context.validateTrusted(t);
+ context.addTrusted(t);
+ return created(uri).build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response deleteAllTrusts(UriInfo ui) throws BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ for (Trust t : context.getTrusted())
+ context.deleteTrusted(t);
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response deleteTrust(String id, UriInfo ui)
+ throws BadStateChangeException {
+ if (run.getStatus() != Initialized)
+ throw new BadStateChangeException();
+ Trust toDelete = new Trust();
+ toDelete.id = id;
+ context.deleteTrusted(toDelete);
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public PermissionsDescription describePermissions(UriInfo ui) {
+ Map<String, Permission> perm = support.getPermissionMap(context);
+ return new PermissionsDescription(secure(ui).path("{id}"), perm);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Permission describePermission(String id) {
+ return support.getPermission(context, id);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Permission setPermission(String id, Permission perm) {
+ support.setPermission(context, id, perm);
+ return support.getPermission(context, id);
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response deletePermission(String id, UriInfo ui) {
+ support.setPermission(context, id, Permission.None);
+ return noContent().build();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public Response makePermission(PermissionDescription desc, UriInfo ui) {
+ support.setPermission(context, desc.userName, desc.permission);
+ return created(secure(ui).path("{user}").build(desc.userName)).build();
+ }
+
+ @Override
+ @CallCounted
+ public Response descriptionOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response ownerOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response credentialsOptions() {
+ return opt("POST", "DELETE");
+ }
+
+ @Override
+ @CallCounted
+ public Response credentialOptions(String id) {
+ return opt("PUT", "DELETE");
+ }
+
+ @Override
+ @CallCounted
+ public Response trustsOptions() {
+ return opt("POST", "DELETE");
+ }
+
+ @Override
+ @CallCounted
+ public Response trustOptions(String id) {
+ return opt("PUT", "DELETE");
+ }
+
+ @Override
+ @CallCounted
+ public Response permissionsOptions() {
+ return opt("POST");
+ }
+
+ @Override
+ @CallCounted
+ public Response permissionOptions(String id) {
+ return opt("PUT", "DELETE");
+ }
+}
\ 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/SingleListenerREST.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java
new file mode 100644
index 0000000..6c9e8d8
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static java.util.Arrays.asList;
+import static org.taverna.server.master.common.Uri.secure;
+import static org.taverna.server.master.utils.RestUtils.opt;
+
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.taverna.server.master.api.OneListenerBean;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.rest.TavernaServerListenersREST;
+import org.taverna.server.master.rest.TavernaServerListenersREST.ListenerDescription;
+import org.taverna.server.master.rest.TavernaServerListenersREST.TavernaServerListenerREST;
+import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
+import org.taverna.server.master.utils.InvocationCounter.CallCounted;
+
+/**
+ * RESTful interface to a single listener attached to a workflow run.
+ *
+ * @author Donal Fellows
+ */
+abstract class SingleListenerREST implements TavernaServerListenerREST,
+ OneListenerBean {
+ private Listener listen;
+ private TavernaRun run;
+
+ @Override
+ public SingleListenerREST connect(Listener listen, TavernaRun run) {
+ this.listen = listen;
+ this.run = run;
+ return this;
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public String getConfiguration() {
+ return listen.getConfiguration();
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public ListenerDescription getDescription(UriInfo ui) {
+ return new ListenerDescription(listen, secure(ui));
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public TavernaServerListenersREST.Properties getProperties(UriInfo ui) {
+ return new TavernaServerListenersREST.Properties(secure(ui).path(
+ "{prop}"), listen.listProperties());
+ }
+
+ @Override
+ @CallCounted
+ @PerfLogged
+ public TavernaServerListenersREST.Property getProperty(
+ final String propertyName) throws NoListenerException {
+ List<String> p = asList(listen.listProperties());
+ if (p.contains(propertyName)) {
+ return makePropertyInterface().connect(listen, run, propertyName);
+ }
+ throw new NoListenerException("no such property");
+ }
+
+ protected abstract ListenerPropertyREST makePropertyInterface();
+
+ @Override
+ @CallCounted
+ public Response listenerOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response configurationOptions() {
+ return opt();
+ }
+
+ @Override
+ @CallCounted
+ public Response propertiesOptions() {
+ return opt();
+ }
+}
[47/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/wadl/tavserv.wadl
----------------------------------------------------------------------
diff --git a/server-client/src/main/wadl/tavserv.wadl b/server-client/src/main/wadl/tavserv.wadl
deleted file mode 100644
index 2ba8fbe..0000000
--- a/server-client/src/main/wadl/tavserv.wadl
+++ /dev/null
@@ -1,591 +0,0 @@
-<application xmlns="http://wadl.dev.java.net/2009/02"
- xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:prefix1="http://ns.taverna.org.uk/2010/xml/server/rest/"
- xmlns:prefix3="http://ns.taverna.org.uk/2010/xml/server/"
- xmlns:prefix10="http://ns.taverna.org.uk/2010/port/" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
- xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" jxb:version="2.1">
-<grammars>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:admin="http://ns.taverna.org.uk/2010/xml/server/admin/" xmlns:feed="http://ns.taverna.org.uk/2010/xml/server/feed/" xmlns:port="http://ns.taverna.org.uk/2010/port/" xmlns:tns="http://ns.taverna.org.uk/2010/xml/server/rest/" xmlns:ts="http://ns.taverna.org.uk/2010/xml/server/" xmlns:ts-rest="http://ns.taverna.org.uk/2010/xml/server/rest/" xmlns:ts-soap="http://ns.taverna.org.uk/2010/xml/server/soap/" xmlns:xlink="http://www.w3.org/1999/xlink" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ns.taverna.org.uk/2010/xml/server/rest/" jxb:version="2.1">
- <xs:annotation>
- <xs:appinfo>
- <jxb:schemaBindings>
- <jxb:package name="uk.org.taverna.server.client.rest" />
- </jxb:schemaBindings>
- </xs:appinfo>
- </xs:annotation>
- <xs:import namespace="http://ns.taverna.org.uk/2010/xml/server/"/>
- <xs:import namespace="http://www.w3.org/1999/xlink"/>
- <xs:element name="capabilities">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="capability" type="ts:Capability"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="credential" type="ts-rest:Credential"/>
- <xs:element name="credentials" type="ts-rest:credentialList"/>
- <xs:element name="directoryContents" type="ts-rest:DirectoryContents"/>
- <xs:element name="enabledNotificationFabrics">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="notifier" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="filesystemOperation" type="ts-rest:FilesystemCreationOperation"/>
- <xs:element name="listenerDefinition" type="ts-rest:ListenerDefinition"/>
- <xs:element name="listenerDescription" type="ts-rest:ListenerDescription"/>
- <xs:element name="listeners">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="listener" type="ts-rest:ListenerDescription"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="mkdir" type="ts-rest:MakeDirectory"/>
- <xs:element name="permissionUpdate" type="ts-rest:permissionDescription"/>
- <xs:element name="permissionsDescriptor" type="ts-rest:permissionsDescription"/>
- <xs:element name="permittedListeners">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="type" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="permittedWorkflows">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="workflow" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="policyDescription">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element minOccurs="0" name="runLimit" type="ts:Location"/>
- <xs:element minOccurs="0" name="operatingLimit" type="ts:Location"/>
- <xs:element minOccurs="0" name="permittedWorkflows" type="ts:Location"/>
- <xs:element minOccurs="0" name="permittedListenerTypes" type="ts:Location"/>
- <xs:element minOccurs="0" name="enabledNotificationFabrics" type="ts:Location"/>
- <xs:element minOccurs="0" name="capabilities" type="ts:Location"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="properties">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="property" type="ts-rest:PropertyDescription"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="runDescription">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element minOccurs="0" name="expiry">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute ref="xlink:href"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- <xs:element minOccurs="0" name="creationWorkflow" type="ts:Location"/>
- <xs:element minOccurs="0" name="createTime" type="ts:Location"/>
- <xs:element minOccurs="0" name="startTime" type="ts:Location"/>
- <xs:element minOccurs="0" name="finishTime" type="ts:Location"/>
- <xs:element minOccurs="0" name="status" type="ts:Location"/>
- <xs:element minOccurs="0" name="workingDirectory" type="ts:Location"/>
- <xs:element minOccurs="0" name="inputs" type="ts:Location"/>
- <xs:element minOccurs="0" name="output" type="ts:Location"/>
- <xs:element minOccurs="0" name="securityContext" type="ts:Location"/>
- <xs:element minOccurs="0" name="listeners">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="ts:Location">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="listener" nillable="true" type="ts:Location"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:element minOccurs="0" name="interaction" type="ts:Location"/>
- <xs:element minOccurs="0" name="name" type="ts:Location"/>
- <xs:element minOccurs="0" name="stdout" type="ts:Location"/>
- <xs:element minOccurs="0" name="stderr" type="ts:Location"/>
- <xs:element minOccurs="0" name="usage" type="ts:Location"/>
- <xs:element minOccurs="0" name="log" type="ts:Location"/>
- <xs:element minOccurs="0" name="run-bundle" type="ts:Location"/>
- <xs:element minOccurs="0" name="generate-provenance" type="ts:Location"/>
- </xs:sequence>
- <xs:attribute ref="ts-rest:owner"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="runInput" type="ts-rest:InputDescription"/>
- <xs:element name="runInputs" type="ts-rest:TavernaRunInputs"/>
- <xs:element name="runList">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="run" type="ts:TavernaRun"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="securityDescriptor" type="ts-rest:SecurityDescriptor"/>
- <xs:element name="serverDescription">
- <xs:complexType>
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element minOccurs="0" name="runs" type="ts:Location"/>
- <xs:element minOccurs="0" name="policy" type="ts:Location"/>
- <xs:element minOccurs="0" name="feed" type="ts:Location"/>
- <xs:element minOccurs="0" name="interactionFeed" type="ts:Location"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="trustedIdentities" type="ts-rest:trustList"/>
- <xs:element name="upload" type="ts-rest:UploadFile"/>
- <xs:element name="userPermission" type="ts-rest:linkedPermissionDescription"/>
- <xs:complexType name="InputDescription">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:choice minOccurs="0">
- <xs:element name="file">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="ts-rest:InputContents"/>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="reference">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="ts-rest:InputContents"/>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- <xs:element name="value">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="ts-rest:InputContents"/>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:choice>
- </xs:sequence>
- <xs:attribute ref="ts-rest:name"/>
- <xs:attribute ref="ts-rest:descriptorRef"/>
- <xs:attribute ref="ts-rest:listDelimiter"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:simpleType name="InputContents">
- <xs:restriction base="xs:string"/>
- </xs:simpleType>
- <xs:complexType name="ListenerDescription">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element minOccurs="0" name="configuration" type="ts:Location"/>
- <xs:element minOccurs="0" name="properties">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="property" type="ts-rest:PropertyDescription"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute ref="xlink:href"/>
- <xs:attribute ref="ts-rest:name"/>
- <xs:attribute ref="ts-rest:type"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="PropertyDescription">
- <xs:complexContent>
- <xs:extension base="ts:Location">
- <xs:sequence/>
- <xs:attribute ref="ts-rest:name"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="TavernaRunInputs">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element minOccurs="0" name="expected" type="ts:Location"/>
- <xs:element minOccurs="0" name="baclava" type="ts:Location"/>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="input" nillable="true" type="ts:Location"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="Credential">
- <xs:choice>
- <xs:element ref="ts:keypair"/>
- <xs:element ref="ts:userpass"/>
- </xs:choice>
- </xs:complexType>
- <xs:complexType name="DirectoryContents">
- <xs:sequence>
- <xs:choice maxOccurs="unbounded" minOccurs="0">
- <xs:element ref="ts:dir"/>
- <xs:element ref="ts:file"/>
- </xs:choice>
- </xs:sequence>
- </xs:complexType>
- <xs:complexType name="FilesystemCreationOperation">
- <xs:simpleContent>
- <xs:extension base="xs:base64Binary">
- <xs:attribute ref="ts-rest:name"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="MakeDirectory">
- <xs:simpleContent>
- <xs:extension base="ts-rest:FilesystemCreationOperation"/>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="UploadFile">
- <xs:simpleContent>
- <xs:extension base="ts-rest:FilesystemCreationOperation"/>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="permissionsDescription">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="permission" type="ts-rest:linkedPermissionDescription"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="linkedPermissionDescription">
- <xs:complexContent>
- <xs:extension base="ts:Location">
- <xs:sequence>
- <xs:element minOccurs="0" name="userName" type="xs:string"/>
- <xs:element minOccurs="0" name="permission" type="ts:Permission"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="trustList">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="trust" type="ts:TrustDescriptor"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="permissionDescription">
- <xs:sequence>
- <xs:element minOccurs="0" name="userName" type="xs:string"/>
- <xs:element minOccurs="0" name="permission" type="ts:Permission"/>
- </xs:sequence>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="SecurityDescriptor">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element minOccurs="0" name="owner" type="xs:string"/>
- <xs:element minOccurs="0" name="permissions" type="ts:Location"/>
- <xs:element minOccurs="0" name="credentials" type="ts-rest:CredentialCollection"/>
- <xs:element minOccurs="0" name="trusts" type="ts-rest:TrustCollection"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="CredentialCollection">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" ref="ts-rest:credential"/>
- </xs:sequence>
- <xs:attribute ref="xlink:href"/>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="TrustCollection">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="trust" type="ts:TrustDescriptor"/>
- </xs:sequence>
- <xs:attribute ref="xlink:href"/>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="credentialList">
- <xs:complexContent>
- <xs:extension base="ts:VersionedElement">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" ref="ts-rest:credential"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="ListenerDefinition">
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute ref="ts-rest:type"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- <xs:attribute name="descriptorRef" type="xs:anyURI"/>
- <xs:attribute name="listDelimiter" type="xs:string"/>
- <xs:attribute name="name" type="xs:string"/>
- <xs:attribute name="owner" type="xs:string"/>
- <xs:attribute name="type" type="xs:string"/>
-</xs:schema>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/1999/xlink" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://www.w3.org/1999/xlink" jxb:version="2.1">
- <xs:attribute name="href" type="xs:string"/>
-</xs:schema>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:port="http://ns.taverna.org.uk/2010/port/" xmlns:run="http://ns.taverna.org.uk/2010/run/" xmlns:tns="http://ns.taverna.org.uk/2010/port/" xmlns:xlink="http://www.w3.org/1999/xlink" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ns.taverna.org.uk/2010/port/" jxb:version="2.1">
- <xs:annotation>
- <xs:appinfo>
- <jxb:schemaBindings>
- <jxb:package name="uk.org.taverna.server.client.generic.port" />
- </jxb:schemaBindings>
- </xs:appinfo>
- </xs:annotation>
- <xs:import namespace="http://www.w3.org/1999/xlink"/>
- <xs:element name="inputDescription" type="port:inputDescription"/>
- <xs:element name="workflowOutputs" type="port:outputDescription"/>
- <xs:complexType name="outputDescription">
- <xs:complexContent>
- <xs:extension base="port:PortDescription">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="output" type="port:OutputPort"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType abstract="true" name="PortDescription">
- <xs:sequence/>
- <xs:attribute ref="port:workflowId"/>
- <xs:attribute ref="port:workflowRun"/>
- <xs:attribute ref="port:workflowRunId"/>
- </xs:complexType>
- <xs:complexType name="OutputPort">
- <xs:complexContent>
- <xs:extension base="port:Port">
- <xs:choice>
- <xs:element name="value" type="port:LeafValue"/>
- <xs:element name="list" type="port:ListValue"/>
- <xs:element name="error" type="port:ErrorValue"/>
- <xs:element name="absent" type="port:AbsentValue"/>
- </xs:choice>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="Port">
- <xs:sequence/>
- <xs:attribute ref="port:name" use="required"/>
- <xs:attribute ref="port:depth"/>
- </xs:complexType>
- <xs:complexType name="LeafValue">
- <xs:complexContent>
- <xs:extension base="port:Value">
- <xs:sequence/>
- <xs:attribute ref="port:contentFile"/>
- <xs:attribute ref="port:contentType"/>
- <xs:attribute ref="port:contentByteLength"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType abstract="true" name="Value">
- <xs:sequence/>
- <xs:attribute ref="xlink:href"/>
- </xs:complexType>
- <xs:complexType name="ErrorValue">
- <xs:complexContent>
- <xs:extension base="port:Value">
- <xs:sequence/>
- <xs:attribute ref="port:depth"/>
- <xs:attribute ref="port:errorFile"/>
- <xs:attribute ref="port:errorByteLength"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="ListValue">
- <xs:complexContent>
- <xs:extension base="port:Value">
- <xs:sequence>
- <xs:choice maxOccurs="unbounded" minOccurs="0">
- <xs:element name="value" type="port:LeafValue"/>
- <xs:element name="list" type="port:ListValue"/>
- <xs:element name="error" type="port:ErrorValue"/>
- <xs:element name="absent" type="port:AbsentValue"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute ref="port:length"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="AbsentValue">
- <xs:complexContent>
- <xs:extension base="port:Value">
- <xs:sequence/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="inputDescription">
- <xs:complexContent>
- <xs:extension base="port:PortDescription">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="input" type="port:InputPort"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="InputPort">
- <xs:complexContent>
- <xs:extension base="port:Port">
- <xs:sequence/>
- <xs:attribute ref="xlink:href"/>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:attribute name="contentByteLength" type="xs:long"/>
- <xs:attribute name="contentFile" type="xs:string"/>
- <xs:attribute name="contentType" type="xs:string"/>
- <xs:attribute name="depth" type="xs:int"/>
- <xs:attribute name="errorByteLength" type="xs:long"/>
- <xs:attribute name="errorFile" type="xs:string"/>
- <xs:attribute name="length" type="xs:int"/>
- <xs:attribute name="name" type="xs:ID"/>
- <xs:attribute name="workflowId" type="xs:string"/>
- <xs:attribute name="workflowRun" type="xs:anyURI"/>
- <xs:attribute name="workflowRunId" type="xs:string"/>
-</xs:schema>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:admin="http://ns.taverna.org.uk/2010/xml/server/admin/" xmlns:feed="http://ns.taverna.org.uk/2010/xml/server/feed/" xmlns:tns="http://ns.taverna.org.uk/2010/xml/server/" xmlns:ts="http://ns.taverna.org.uk/2010/xml/server/" xmlns:ts-rest="http://ns.taverna.org.uk/2010/xml/server/rest/" xmlns:ts-soap="http://ns.taverna.org.uk/2010/xml/server/soap/" xmlns:xlink="http://www.w3.org/1999/xlink" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ns.taverna.org.uk/2010/xml/server/" jxb:version="2.1">
- <xs:annotation>
- <xs:appinfo>
- <jxb:schemaBindings>
- <jxb:package name="uk.org.taverna.server.client.generic" />
- </jxb:schemaBindings>
- </xs:appinfo>
- </xs:annotation>
- <xs:import namespace="http://www.w3.org/1999/xlink"/>
- <xs:element name="capability" type="ts:Capability"/>
- <xs:element name="dir" type="ts:DirectoryReference"/>
- <xs:element name="file" type="ts:FileReference"/>
- <xs:element name="keypair" type="ts:KeyPairCredential"/>
- <xs:element name="runReference" type="ts:TavernaRun"/>
- <xs:element name="trustedIdentity" type="ts:TrustDescriptor"/>
- <xs:element name="userpass" type="ts:PasswordCredential"/>
- <xs:element name="workflow" type="ts:Workflow"/>
- <xs:complexType abstract="true" name="VersionedElement">
- <xs:sequence/>
- <xs:attribute ref="ts:serverVersion"/>
- <xs:attribute ref="ts:serverRevision"/>
- <xs:attribute ref="ts:serverBuildTimestamp"/>
- </xs:complexType>
- <xs:complexType name="Location">
- <xs:sequence/>
- <xs:attribute ref="xlink:href"/>
- </xs:complexType>
- <xs:complexType name="Capability">
- <xs:sequence/>
- <xs:attribute ref="ts:capability"/>
- <xs:attribute ref="ts:version"/>
- </xs:complexType>
- <xs:complexType name="KeyPairCredential">
- <xs:complexContent>
- <xs:extension base="ts:CredentialDescriptor">
- <xs:sequence>
- <xs:element name="credentialName" type="xs:string"/>
- <xs:element minOccurs="0" name="credentialFile" type="xs:string"/>
- <xs:element minOccurs="0" name="fileType" type="xs:string"/>
- <xs:element minOccurs="0" name="unlockPassword" type="xs:string"/>
- <xs:element minOccurs="0" name="credentialBytes" type="xs:base64Binary"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType abstract="true" name="CredentialDescriptor">
- <xs:sequence>
- <xs:element minOccurs="0" name="serviceURI" type="xs:anyURI"/>
- </xs:sequence>
- <xs:attribute ref="xlink:href"/>
- </xs:complexType>
- <xs:complexType name="PasswordCredential">
- <xs:complexContent>
- <xs:extension base="ts:CredentialDescriptor">
- <xs:sequence>
- <xs:element name="username" type="xs:string"/>
- <xs:element name="password" type="xs:string"/>
- </xs:sequence>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
- <xs:complexType name="DirectoryEntry">
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute ref="xlink:href"/>
- <xs:attribute ref="ts:name"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="DirectoryReference">
- <xs:simpleContent>
- <xs:extension base="ts:DirectoryEntry"/>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="FileReference">
- <xs:simpleContent>
- <xs:extension base="ts:DirectoryEntry"/>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="TavernaRun">
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute ref="xlink:href"/>
- <xs:attribute ref="ts:serverVersion"/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- <xs:complexType name="Workflow">
- <xs:sequence>
- <xs:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="lax"/>
- </xs:sequence>
- </xs:complexType>
- <xs:complexType final="extension restriction" name="TrustDescriptor">
- <xs:sequence>
- <xs:element minOccurs="0" name="certificateFile" type="xs:string"/>
- <xs:element minOccurs="0" name="fileType" type="xs:string"/>
- <xs:element minOccurs="0" name="certificateBytes" type="xs:base64Binary"/>
- <xs:element maxOccurs="unbounded" minOccurs="0" name="serverName" type="xs:string"/>
- </xs:sequence>
- <xs:attribute ref="xlink:href"/>
- </xs:complexType>
- <xs:simpleType name="Permission">
- <xs:restriction base="xs:string">
- <xs:enumeration value="none"/>
- <xs:enumeration value="read"/>
- <xs:enumeration value="update"/>
- <xs:enumeration value="destroy"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:attribute name="capability" type="xs:anyURI"/>
- <xs:attribute name="name" type="xs:string"/>
- <xs:attribute name="serverBuildTimestamp" type="xs:string"/>
- <xs:attribute name="serverRevision" type="xs:string"/>
- <xs:attribute name="serverVersion" type="xs:string"/>
- <xs:attribute name="version" type="xs:string"/>
-</xs:schema>
-</grammars><resources base="http://example.com/taverna/rest"><resource path="/"><method name="GET"><doc>Produces the description of the service.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:serverDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the service.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="runs"><method name="GET"><doc>Produces a list of all runs visible to the user.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:runList"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the operations on the collection of runs.</doc><response><representation mediaType="application/octet-stream"><
/representation></response></method><method name="POST"><doc>Accepts (or not) a request to create a new run executing the given workflow.</doc><request><representation mediaType="application/vnd.taverna.t2flow+xml" element="prefix3:workflow"><doc>Accepts (or not) a request to create a new run executing the given workflow.</doc></representation><representation mediaType="application/xml" element="prefix3:workflow"><doc>Accepts (or not) a request to create a new run executing the given workflow.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Accepts a URL to a workflow to download and run. The URL must be hosted on a publicly-accessible service.</doc><request><representation mediaType="text/uri-list"><doc>Accepts a URL to a workflow to download and run. The URL must be hosted on a publicly-accessible service.</doc></representation></request><response><representation mediaType=
"application/octet-stream"></representation></response></method></resource><resource path="/policy"><method name="GET"><doc>Describe the parts of this policy.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:policyDescription"></representation><representation mediaType="application/json"></representation></response></method><resource path="/capabilities"><method name="GET"><doc>Gets a description of the capabilities supported by this installation of Taverna Server.</doc><response><representation mediaType="application/xml" element="prefix1:capabilities"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/enabledNotificationFabrics"><method name="GET"><doc>Gets the list of supported, enabled notification fabrics. Each corresponds (approximately) to a protocol, e.g., email.</doc><response><representation mediaType="application/xml" element="prefix1:enabledNotificati
onFabrics"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/operatingLimit"><method name="GET"><doc>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.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:int"><doc>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.</doc></param></representation></response></method></resource><resource path="/permittedListenerTypes"><method name="GET"><doc>Gets the list of permitted event listener types.</doc><response><representation mediaType="application/xml" element="prefix1:
permittedListeners"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/permittedWorkflows"><method name="GET"><doc>Gets the list of permitted workflows.</doc><response><representation mediaType="application/xml" element="prefix1:permittedWorkflows"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/runLimit"><method name="GET"><doc>Gets the maximum number of simultaneous runs in any state that the user may create.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:int"><doc>Gets the maximum number of simultaneous runs in any state that the user may create.</doc></param></representation></response></method></resource></resource><resource path="/runs/{runName}"><doc>This represents how a Taverna Server workflow run looks to a RESTful API.</doc><param name="runName" style="template" type="x
s:string"/><method name="DELETE"><doc>Deletes a workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Describes a workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:runDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/createTime"><method name="GET"><doc>Gives the time when the workflow run was first submitted to the server.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the time when the workflow run was first submitted to the server.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the d
escription of the run create time.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/expiry"><method name="GET"><doc>Gives the time when the workflow run becomes eligible for automatic deletion.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the time when the workflow run becomes eligible for automatic deletion.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run expiry.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the time when the workflow run becomes eligible for automatic deletion.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Sets the time when the workflow run becomes eligible for automatic deletion.</doc></param><
/representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Sets the time when the workflow run becomes eligible for automatic deletion.</doc></param></representation></response></method></resource><resource path="/finishTime"><method name="GET"><doc>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).</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>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).</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run finish time.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="
/generate-provenance"><method name="GET"><doc>Whether to create the run bundle for the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:boolean"><doc>Whether to create the run bundle for the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Whether to create the run bundle for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Whether to create the run bundle for the workflow run.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:boolean"><doc>Whether to create the run bundle for the workflow run.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:boolean"><doc>Whether to create the run bundle for the workflow run.</doc></param></representation></response></
method></resource><resource path="/log"><method name="GET"><doc>Return the log for the workflow run.</doc><response><representation mediaType="text/plain"></representation></response></method><method name="OPTIONS"><doc>Return the log for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/name"><method name="GET"><doc>Gives the descriptive name of the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the descriptive name of the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the operations on the run's descriptive name.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Set the descriptive name of the workflow run. Note that this value may be arbitraril
y truncated by the implementation.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Set the descriptive name of the workflow run. Note that this value may be arbitrarily truncated by the implementation.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Set the descriptive name of the workflow run. Note that this value may be arbitrarily truncated by the implementation.</doc></param></representation></response></method></resource><resource path="/output"><method name="GET"><doc>Gives the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc></param></repre
sentation></response></method><method name="GET"><doc>Gives a description of the outputs, as currently understood</doc><request></request><response><representation mediaType="application/xml" element="prefix10:workflowOutputs"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run output.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Sets the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:st
ring"><doc>Sets the Baclava file where output will be written; empty means use multiple simple files in the out directory.</doc></param></representation></response></method></resource><resource path="/run-bundle"><method name="GET"><doc>Return the run bundle for the workflow run.</doc><response><representation mediaType="application/vnd.wf4ever.robundle+zip"></representation></response></method><method name="OPTIONS"><doc>Return the run bundle for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/startTime"><method name="GET"><doc>Gives the time when the workflow run was started, or an empty string if the run has not yet started.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the time when the workflow run was started, or an empty string if the run has not yet started.</doc></param></representation></response></met
hod><method name="OPTIONS"><doc>Produces the description of the run start time.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/status"><method name="GET"><doc>Gives the current status of the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the current status of the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run status.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Attempts to update the status of the workflow run.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Attempts to update the status of the workflow run.</doc></param></representation></request><response><representation mediaType="text/pla
in"></representation></response></method></resource><resource path="/stderr"><method name="GET"><doc>Return the stderr for the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Return the stderr for the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Return the stderr for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/stdout"><method name="GET"><doc>Return the stdout for the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Return the stdout for the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Return the stdout for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resour
ce><resource path="/usage"><method name="GET"><doc>Return the usage record for the workflow run.</doc><response><representation mediaType="application/xml"></representation></response></method><method name="OPTIONS"><doc>Return the usage record for the workflow run.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/workflow"><method name="GET"><doc>Gives the workflow document used to create the workflow run.</doc><response><representation mediaType="application/vnd.taverna.t2flow+xml" element="prefix3:workflow"></representation><representation mediaType="application/xml" element="prefix3:workflow"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run workflow.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/inp
ut"><doc>This represents how a Taverna Server workflow run's inputs looks to a RESTful API.</doc><method name="GET"><doc>Describe the sub-URIs of this resource.</doc><response><representation mediaType="application/xml" element="prefix1:runInputs"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run's inputs' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/baclava"><method name="GET"><doc>Gives the Baclava file describing the inputs, or empty if individual files are used.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the Baclava file describing the inputs, or empty if individual files are used.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the inp
uts' baclava operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the Baclava file describing the inputs.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Sets the Baclava file describing the inputs.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Sets the Baclava file describing the inputs.</doc></param></representation></response></method></resource><resource path="/expected"><method name="GET"><doc>Describe the expected inputs of this workflow run.</doc><response><representation mediaType="application/xml" element="prefix10:inputDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the expected inputs' operati
ons.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/input/{name}"><param name="name" style="template" type="xs:string"/><method name="GET"><doc>Gives a description of what is used to supply a particular input.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:runInput"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the one input's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Sets the source for a particular input port.</doc><request><representation mediaType="application/xml" element="prefix1:runInput"><doc>Sets the source for a particular input port.</doc></representation><representation mediaType="application/json"><doc>Sets the
source for a particular input port.</doc></representation></request><response><representation mediaType="application/xml" element="prefix1:runInput"></representation><representation mediaType="application/json"></representation></response></method></resource></resource><resource path="/interaction"><method name="GET"><doc>Get the feed document for this ATOM feed.</doc><response><representation mediaType="application/atom+xml"></representation></response></method><method name="OPTIONS"><doc>Describes what HTTP operations are supported on the feed.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Adds an entry to this ATOM feed.</doc><request><representation mediaType="application/atom+xml"><doc>Adds an entry to this ATOM feed.</doc></representation></request><response><representation mediaType="application/atom+xml"></representation></response></method><resource path="/{id}"><param name="id" style="temp
late" type="xs:string"/><method name="DELETE"><doc>Deletes an entry from this ATOM feed.</doc><request></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Deletes an entry from this ATOM feed.</doc></param></representation></response></method><method name="GET"><doc>Get the entry with a particular ID within this ATOM feed.</doc><request></request><response><representation mediaType="application/atom+xml"></representation></response></method><method name="OPTIONS"><doc>Describes what HTTP operations are supported on an entry.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource></resource><resource path="/listeners"><doc>This represents all the event listeners attached to a workflow run.</doc><method name="GET"><doc>Get the listeners installed in the workflow run.</doc><request></request><response><representation mediaType="application/xml"
element="prefix1:listeners"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run listeners' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Add a new event listener to the named workflow run.</doc><request><representation mediaType="application/xml" element="prefix1:listenerDefinition"><doc>Add a new event listener to the named workflow run.</doc></representation><representation mediaType="application/json"><doc>Add a new event listener to the named workflow run.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/{name}"><doc>This represents a single event listener attached to a workflow run.</doc><param name="name" style="template" type="xs:string"/><method name="GET"><doc>Get th
e description of this listener.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:listenerDescription"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/configuration"><method name="GET"><doc>Get the configuration for the given event listener that is attached to a workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Get the configuration for the given event listener that is attached to a workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's configuration's operations.</doc><response><representation mediaType="applica
tion/octet-stream"></representation></response></method></resource><resource path="/properties"><method name="GET"><doc>Get the list of properties supported by a given event listener attached to a workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:properties"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's properties' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/properties/{propertyName}"><doc>This represents a single property attached of an event listener.</doc><param name="propertyName" style="template" type="xs:string"/><method name="GET"><doc>Get the value of the particular property of an event listener attached to a workflow run.</doc><response><representation mediaType="text/plain"><param
name="result" style="plain" type="xs:string"><doc>Get the value of the particular property of an event listener attached to a workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run listener's property's operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Set the value of the particular property of an event listener attached to a workflow run.</doc><request><representation mediaType="text/plain"><param name="request" style="plain" type="xs:string"><doc>Set the value of the particular property of an event listener attached to a workflow run.</doc></param></representation></request><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Set the value of the particular property of an event listener attached to a workflow run.</doc></param></representation></response><
/method></resource></resource></resource><resource path="/security"><doc>Manages the security of the workflow run. In general, only the owner of a run may access this resource.</doc><method name="GET"><doc>Gives a description of the security information supported by the workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:securityDescriptor"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run security.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><resource path="/credentials"><method name="DELETE"><doc>Deletes all credentials.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Gives a list of credentials supplied to this workflow run.</doc><response><representation
mediaType="application/xml" element="prefix1:credentials"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run credentials' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Creates a new credential.</doc><request><representation mediaType="application/xml" element="prefix1:credential"><doc>Creates a new credential.</doc></representation><representation mediaType="application/json"><doc>Creates a new credential.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/credentials/{id}"><param name="id" style="template" type="xs:string"/><method name="DELETE"><doc>Deletes a particular credential.</doc><request></request><response><representation mediaType="application/octet-stre
am"></representation></response></method><method name="GET"><doc>Describes a particular credential.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:credential"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run credential's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Updates a particular credential.</doc><request><representation mediaType="application/xml" element="prefix1:credential"><doc>Updates a particular credential.</doc></representation><representation mediaType="application/json"><doc>Updates a particular credential.</doc></representation></request><response><representation mediaType="application/xml" element="prefix1:credential"></representation><representation mediaType="application/json"></represe
ntation></response></method></resource><resource path="/owner"><method name="GET"><doc>Gives the identity of who owns the workflow run.</doc><response><representation mediaType="text/plain"><param name="result" style="plain" type="xs:string"><doc>Gives the identity of who owns the workflow run.</doc></param></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run owner.</doc><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/permissions"><method name="GET"><doc>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.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:permissionsDescriptor"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Pro
duces the description of the run permissions' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Creates a new assignment of permissions to a particular user.</doc><request><representation mediaType="application/xml" element="prefix1:permissionUpdate"><doc>Creates a new assignment of permissions to a particular user.</doc></representation><representation mediaType="application/json"><doc>Creates a new assignment of permissions to a particular user.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/permissions/{id}"><param name="id" style="template" type="xs:string"/><method name="DELETE"><doc>Deletes (by resetting to default) the permissions associated with a particular user.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></
response></method><method name="GET"><doc>Describes the permission granted to a particular user.</doc><request></request><response><representation mediaType="text/plain"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run permission's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Updates the permissions granted to a particular user.</doc><request><representation mediaType="text/plain"><doc>Updates the permissions granted to a particular user.</doc></representation></request><response><representation mediaType="text/plain"></representation></response></method></resource><resource path="/trusts"><method name="DELETE"><doc>Deletes all trusted identities.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Gives a list of trust
ed identities supplied to this workflow run.</doc><response><representation mediaType="application/xml" element="prefix1:trustedIdentities"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the run trusted certificates' operations.</doc><response><representation mediaType="application/octet-stream"></representation></response></method><method name="POST"><doc>Adds a new trusted identity.</doc><request><representation mediaType="application/xml" element="prefix3:trustedIdentity"><doc>Adds a new trusted identity.</doc></representation><representation mediaType="application/json"><doc>Adds a new trusted identity.</doc></representation></request><response><representation mediaType="application/octet-stream"></representation></response></method></resource><resource path="/trusts/{id}"><param name="id" style="template" type="xs:string"/><method name="DELETE"><doc>Deletes a particu
lar trusted identity.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="GET"><doc>Describes a particular trusted identity.</doc><request></request><response><representation mediaType="application/xml" element="prefix3:trustedIdentity"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of one run trusted certificate's operations.</doc><request></request><response><representation mediaType="application/octet-stream"></representation></response></method><method name="PUT"><doc>Updates a particular trusted identity.</doc><request><representation mediaType="application/xml" element="prefix3:trustedIdentity"><doc>Updates a particular trusted identity.</doc></representation><representation mediaType="application/json"><doc>Updates a particular trusted identity.</doc></representation></request><respo
nse><representation mediaType="application/xml" element="prefix3:trustedIdentity"></representation><representation mediaType="application/json"></representation></response></method></resource></resource><resource path="/wd"><doc>Representation of how a workflow run's working directory tree looks.</doc><method name="GET"><doc>Describes the working directory of the workflow run.</doc><request></request><response><representation mediaType="application/xml" element="prefix1:directoryContents"></representation><representation mediaType="application/json"></representation></response></method><resource path="/{path:(.*)}"><param name="path" style="template" repeating="true"/><method name="POST"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run with the contents of a publicly readable URL.</doc><request><representation mediaType="text/uri-list"><doc>Creates or updates a file in a particular location beneath the working directory o
f the workflow run with the contents of a publicly readable URL.</doc></representation></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method><method name="PUT"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run.</doc><request><representation mediaType="application/octet-stream"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run.</doc></representation><representation mediaType="*/*"><doc>Creates or updates a file in a particular location beneath the working directory of the workflow run.</doc></representation></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/{path:.*}"><param name="path" style="template" repeating="true"/><method
name="DELETE"><doc>Deletes a file or directory that is in or below the working directory of a workflow run.</doc><request></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method><method name="OPTIONS"><doc>Produces the description of the files/directories' baclava operations.</doc><request></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method><method name="POST"><doc>Creates a directory in the filesystem beneath the working directory of the workflow run, or creates or updates a file's contents, where that file is in or below the working directory of a workflow run.</doc><request><representation mediaType="application/xml" element="prefix1:filesystemOperation"><doc>Creates a directory in the filesystem beneath the working directory of the workflow run, or create
s or updates a file's contents, where that file is in or below the working directory of a workflow run.</doc></representation><representation mediaType="application/json"><doc>Creates a directory in the filesystem beneath the working directory of the workflow run, or creates or updates a file's contents, where that file is in or below the working directory of a workflow run.</doc></representation></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation></response></method></resource><resource path="/{path:.+}"><param name="path" style="template" repeating="true"/><method name="GET"><doc>Gives a description of the named entity in or beneath the working directory of the workflow run (either a Directory or File).</doc><request></request><response><representation mediaType="application/xml"></representation><representation mediaType="application/json"></representation><representation mediaTyp
e="application/octet-stream"></representation><representation mediaType="application/zip"></representation><representation mediaType="*/*"></representation></response></method></resource></resource></resource></resource></resources></application>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-distribution/pom.xml
----------------------------------------------------------------------
diff --git a/server-distribution/pom.xml b/server-distribution/pom.xml
deleted file mode 100644
index 8939dbf..0000000
--- a/server-distribution/pom.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-distribution</artifactId>
- <name>Apache Taverna Server Distribution Packaging</name>
- <packaging>pom</packaging>
-
- <dependencies>
- <dependency>
- <groupId>${project.parent.version}</groupId>
- <artifactId>taverna-server-webapp</artifactId>
- <version>${project.parent.version}</version>
- <type>war</type>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <finalName>TavernaServer-${project.parent.version}</finalName>
- <descriptors>
- <descriptor>src/assemble/dist.xml</descriptor>
- </descriptors>
- </configuration>
- <executions>
- <execution>
- <id>make-t2server-distribution</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- <executions>
- <execution>
- <id>default</id>
- <phase>none</phase>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <id>default</id>
- <phase>none</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- <reporting>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-project-info-reports-plugin</artifactId>
- <version>2.4</version>
- <reportSets>
- <reportSet>
- <reports>
- <!-- Only generate the index, nothing else. -->
- <report>index</report>
- </reports>
- </reportSet>
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>2.8</version>
- <reportSets>
- <reportSet />
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-changelog-plugin</artifactId>
- <version>2.2</version>
- <reportSets>
- <reportSet />
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-changes-plugin</artifactId>
- <version>2.6</version>
- <reportSets>
- <reportSet />
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-checkstyle-plugin</artifactId>
- <version>2.7</version>
- <reportSets>
- <reportSet />
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-pmd-plugin</artifactId>
- <version>2.5</version>
- <reportSets>
- <reportSet />
- </reportSets>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-report-plugin</artifactId>
- <version>2.9</version>
- <reportSets>
- <reportSet />
- </reportSets>
- </plugin>
- </plugins>
- </reporting>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-distribution/src/assemble/dist.xml
----------------------------------------------------------------------
diff --git a/server-distribution/src/assemble/dist.xml b/server-distribution/src/assemble/dist.xml
deleted file mode 100644
index a77883c..0000000
--- a/server-distribution/src/assemble/dist.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<assembly
- xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
- <id>distribution</id>
- <formats>
- <format>zip</format>
- </formats>
-<!--
- <dependencySets>
- <dependencySet>
- <useTransitiveDependencies>false</useTransitiveDependencies>
- <useProjectArtifact>false</useProjectArtifact>
- <unpack>false</unpack>
- <scope>runtime</scope>
- <fileMode>0644</fileMode>
- </dependencySet>
- </dependencySets>
- <fileSets>
- <fileSet>
- <includes>
- <include>*.html</include>
- <include>*.xml</include>
- <include>*.txt</include>
- <include>*.pdf</include>
- </includes>
- <excludes>
- <exclude>pom.xml</exclude>
- </excludes>
- </fileSet>
- </fileSets>
--->
- <fileSets>
- <fileSet>
- <directory>${project.parent.basedir}</directory>
- <includes>
- <include>*.xml</include>
- <include>*.txt</include>
- <include>*.pdf</include>
- </includes>
- <excludes>
- <exclude>pom.xml</exclude>
- </excludes>
- <fileMode>0644</fileMode>
- <outputDirectory>.</outputDirectory>
- </fileSet>
- <fileSet>
- <directory>${project.parent.basedir}/server-webapp/target</directory>
- <includes>
- <include>*.war</include>
- </includes>
- <outputDirectory>.</outputDirectory>
- <fileMode>0644</fileMode>
- </fileSet>
- </fileSets>
-<!--
- <moduleSets>
- <moduleSet>
- <includes>
- <include>uk.org.taverna.server:server</include>
- </includes>
- <sources>
- <fileSets>
- <fileSet>
- <includes>
- <include>*.html</include>
- <include>*.txt</include>
- </includes>
- </fileSet>
- </fileSets>
- </sources>
- </moduleSet>
- <moduleSet>
- <includes>
- <include>uk.org.taverna.server:server-webapp</include>
- </includes>
- <binaries />
- </moduleSet>
- </moduleSets>
--->
-</assembly>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-execution-delegate/pom.xml
----------------------------------------------------------------------
diff --git a/server-execution-delegate/pom.xml b/server-execution-delegate/pom.xml
deleted file mode 100644
index 59c8aff..0000000
--- a/server-execution-delegate/pom.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-execution-delegate</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Taverna Server Reporting Probe</name>
- <dependencies>
- <dependency>
- <groupId>org.apache.taverna.engine</groupId>
- <artifactId>taverna-execution-api</artifactId>
- <version>${taverna.engine.version}</version>
- <type>bundle</type>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java
----------------------------------------------------------------------
diff --git a/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java b/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java
deleted file mode 100644
index 7ea9998..0000000
--- a/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/ExecutionDelegate.java
+++ /dev/null
@@ -1,172 +0,0 @@
-package org.taverna.server.execution_delegate;
-
-import java.net.URI;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Map;
-
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-import org.taverna.server.execution_delegate.RemoteExecution.ProcessorReportDocument.Property;
-
-import uk.org.taverna.platform.data.api.Data;
-import uk.org.taverna.platform.data.api.DataLocation;
-import uk.org.taverna.platform.execution.api.Execution;
-import uk.org.taverna.platform.report.ActivityReport;
-import uk.org.taverna.platform.report.ProcessorReport;
-import uk.org.taverna.platform.report.StatusReport;
-import uk.org.taverna.platform.report.WorkflowReport;
-import uk.org.taverna.scufl2.api.common.AbstractNamed;
-
-public class ExecutionDelegate extends UnicastRemoteObject implements
- RemoteExecution {
- private Execution delegated;
- private DatatypeFactory dtf;
-
- public ExecutionDelegate(Execution execution) throws RemoteException,
- DatatypeConfigurationException {
- super();
- delegated = execution;
- dtf = DatatypeFactory.newInstance();
- }
-
- @Override
- public String getID() {
- return delegated.getID();
- }
-
- @Override
- public void delete() {
- delegated.delete();
- }
-
- @Override
- public void start() {
- delegated.start();
- }
-
- @Override
- public void pause() {
- delegated.pause();
- }
-
- @Override
- public void resume() {
- delegated.resume();
- }
-
- @Override
- public void cancel() {
- delegated.cancel();
- }
-
- private XMLGregorianCalendar date(Date d) {
- if (d == null)
- return null;
- GregorianCalendar c = new GregorianCalendar();
- c.setTime(d);
- return dtf.newXMLGregorianCalendar(c);
- }
-
- private <R extends ReportDocument, T extends AbstractNamed> R init(
- R snapshot, StatusReport<T, ?, ?> report) {
- snapshot.created = date(report.getCreatedDate());
- snapshot.completed = date(report.getCompletedDate());
- snapshot.cancelled = date(report.getCancelledDate());
- snapshot.failed = date(report.getFailedDate());
- snapshot.started = date(report.getStartedDate());
- for (Date d : report.getPausedDates())
- snapshot.paused.add(date(d));
- for (Date d : report.getResumedDates())
- snapshot.resumed.add(date(d));
- snapshot.subject = report.getSubject().getName();
- snapshot.state = report.getState().toString();
- return snapshot;
- }
-
- private WorkflowReportDocument getReport(WorkflowReport report) {
- WorkflowReportDocument snapshot = init(new WorkflowReportDocument(),
- report);
- for (ProcessorReport pr : report.getChildReports())
- snapshot.processor.add(getReport(pr));
- initMap(snapshot.inputs, report.getInputs());
- initMap(snapshot.outputs, report.getOutputs());
- return snapshot;
- }
-
- private void initMap(ArrayList<PortMapping> snapshot, Map<String, ?> report) {
- for (String port : report.keySet())
- snapshot.add(data(port, report.get(port)));
- }
-
- private static final String DEFAULT_PROPERTY_STRING = "";
-
- private PortMapping data(String name, Object o) {
- String loc;
- if (o instanceof DataLocation) {
- DataLocation d = (DataLocation) o;
- loc = d.getDataServiceURI() + "#" + d.getDataID();
- } else {
- Data d = (Data) o;
- loc = null;
- if (d.hasReferences()) {
- try {
- loc = d.getReferences().iterator().next().getURI()
- .toString();
- } catch (Exception e) {
- }
- }
- if (loc == null) {
- DataLocation dl = d.getDataService().getDataLocation(d);
- loc = dl.getDataServiceURI() + "#" + dl.getDataID();
- }
- }
- return new PortMapping(name, URI.create(loc));
- }
-
- private ProcessorReportDocument getReport(ProcessorReport report) {
- ProcessorReportDocument snapshot = init(new ProcessorReportDocument(),
- report);
- for (ActivityReport pr : report.getChildReports())
- snapshot.activity.add(getReport(pr));
- snapshot.jobsQueued = report.getJobsStarted();
- snapshot.jobsStarted = report.getJobsStarted();
- snapshot.jobsCompleted = report.getJobsCompleted();
- snapshot.jobsErrored = report.getJobsCompletedWithErrors();
- for (String key : report.getPropertyKeys()) {
- Object value = report.getProperty(key);
- if (value instanceof String || value instanceof Number)
- snapshot.properties.add(new Property(key, value.toString()));
- else
- snapshot.properties.add(new Property(key,
- DEFAULT_PROPERTY_STRING));
- }
- return snapshot;
- }
-
- private ActivityReportDocument getReport(ActivityReport report) {
- ActivityReportDocument snapshot = init(new ActivityReportDocument(),
- report);
- for (WorkflowReport pr : report.getChildReports())
- snapshot.workflow.add(getReport(pr));
- initMap(snapshot.inputs, report.getInputs());
- initMap(snapshot.outputs, report.getOutputs());
- return snapshot;
- }
-
- @Override
- public WorkflowReportDocument getWorkflowReport() {
- return getReport(delegated.getWorkflowReport());
- }
-}
-
-// ExecutionDelegate.java:[96,2]
-// initMap(java.util.ArrayList<org.taverna.server.execution_delegate.RemoteExecution.PortMapping>,java.util.Map<java.lang.String,uk.org.taverna.platform.data.api.Data>)
-// in org.taverna.server.execution_delegate.ExecutionDelegate cannot be applied
-// to
-// (java.util.ArrayList<org.taverna.server.execution_delegate.RemoteExecution.PortMapping>,java.util.Map<java.lang.String,uk.org.taverna.platform.data.api.DataLocation>)
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java
----------------------------------------------------------------------
diff --git a/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java b/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java
deleted file mode 100644
index b8510df..0000000
--- a/server-execution-delegate/src/main/java/org/taverna/server/execution_delegate/RemoteExecution.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package org.taverna.server.execution_delegate;
-
-import static javax.xml.bind.annotation.XmlAccessType.NONE;
-
-import java.net.URI;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlAccessorType;
-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.XmlSeeAlso;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-import javax.xml.datatype.XMLGregorianCalendar;
-
-/**
- * Interface for a single execution of a Taverna workflow in a remote process.
- *
- * @author David Withers
- */
-public interface RemoteExecution extends Remote {
-
- /**
- * Returns the identifier for this execution.
- *
- * @return the identifier for this execution
- */
- String getID() throws RemoteException;
-
- /**
- * Returns the <code>WorkflowReport</code> for the execution.
- *
- * @return the <code>WorkflowReport</code> for the execution
- */
- WorkflowReportDocument getWorkflowReport() throws RemoteException;
-
- /**
- * Deletes the execution.
- */
- void delete() throws RemoteException;
-
- /**
- * Starts the execution.
- */
- void start() throws RemoteException;
-
- /**
- * Pauses the execution.
- */
- void pause() throws RemoteException;
-
- /**
- * Resumes a paused execution.
- */
- void resume() throws RemoteException;
-
- /**
- * Cancels the execution.
- */
- void cancel() throws RemoteException;
-
- @XmlType(name = "Report", propOrder = { "state", "created", "started",
- "completed", "failed", "cancelled", "paused", "resumed" })
- @XmlSeeAlso({ WorkflowReportDocument.class, ProcessorReportDocument.class,
- ActivityReportDocument.class })
- @XmlAccessorType(NONE)
- public static abstract class ReportDocument {
- @XmlAttribute
- public String subject;
- @XmlElement
- public String state;
- @XmlElement(required = true)
- @XmlSchemaType(name = "dateTime")
- public XMLGregorianCalendar created;
- @XmlElement
- @XmlSchemaType(name = "dateTime")
- public XMLGregorianCalendar started;
- @XmlElement
- @XmlSchemaType(name = "dateTime")
- public XMLGregorianCalendar completed;
- @XmlElement
- @XmlSchemaType(name = "dateTime")
- public XMLGregorianCalendar failed;
- @XmlElement
- @XmlSchemaType(name = "dateTime")
- public XMLGregorianCalendar cancelled;
- @XmlElement
- @XmlSchemaType(name = "dateTime")
- public List<XMLGregorianCalendar> paused;
- @XmlElement
- @XmlSchemaType(name = "dateTime")
- public List<XMLGregorianCalendar> resumed;
- }
-
- @XmlType(name = "WorkflowReport", propOrder = { "processor", "inputs",
- "outputs" })
- @XmlRootElement(name = "workflowReport")
- @XmlAccessorType(NONE)
- public static class WorkflowReportDocument extends ReportDocument {
- @XmlElement(name = "processor")
- public ArrayList<ProcessorReportDocument> processor = new ArrayList<ProcessorReportDocument>();
- @XmlElement(name = "input")
- public ArrayList<PortMapping> inputs = new ArrayList<PortMapping>();
- @XmlElement(name = "output")
- public ArrayList<PortMapping> outputs = new ArrayList<PortMapping>();
- }
-
- @XmlType(name = "ProcessorReport", propOrder = { "jobsQueued",
- "jobsStarted", "jobsCompleted", "jobsErrored", "properties",
- "activity" })
- @XmlAccessorType(NONE)
- public static class ProcessorReportDocument extends ReportDocument {
- @XmlElement(name = "jobsQueued", required = true)
- public int jobsQueued;
- @XmlElement(name = "jobsStarted", required = true)
- public int jobsStarted;
- @XmlElement(name = "jobsCompleted", required = true)
- public int jobsCompleted;
- @XmlElement(name = "jobsErrored", required = true)
- public int jobsErrored;
- @XmlElement(name = "property")
- @XmlElementWrapper(name = "properties")
- public ArrayList<Property> properties = new ArrayList<Property>();
- @XmlElement(name = "activity")
- public ArrayList<ActivityReportDocument> activity = new ArrayList<ActivityReportDocument>();
-
- @XmlType(name = "ProcessorProperty")
- @XmlAccessorType(NONE)
- public static class Property {
- @XmlAttribute(name = "key", required = true)
- String key;
- @XmlValue
- String value;
-
- public Property() {
- }
-
- public String getKey() {
- return key;
- }
-
- public String getValue() {
- return value;
- }
-
- Property(String key, String value) {
- this.key = key;
- this.value = value;
- }
- }
- }
-
- @XmlType(name = "ActivityReport", propOrder = { "workflow", "inputs",
- "outputs" })
- @XmlAccessorType(NONE)
- public static class ActivityReportDocument extends ReportDocument {
- @XmlElement(name = "workflow")
- public ArrayList<WorkflowReportDocument> workflow = new ArrayList<WorkflowReportDocument>();
- @XmlElement(name = "input")
- public ArrayList<PortMapping> inputs = new ArrayList<PortMapping>();
- @XmlElement(name = "output")
- public ArrayList<PortMapping> outputs = new ArrayList<PortMapping>();
- }
-
- @XmlType(name = "PortMapping")
- @XmlAccessorType(NONE)
- public static class PortMapping {
- public PortMapping() {
- }
-
- PortMapping(String port, URI data) {
- this.name = port;
- this.reference = data;
- }
-
- @XmlAttribute(name = "name")
- public String name;
- @XmlAttribute(name = "ref")
- @XmlSchemaType(name = "anyURI")
- public URI reference;
- }
-}
[35/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java b/server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java
deleted file mode 100644
index e175bf8..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java
+++ /dev/null
@@ -1,1553 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.soap;
-
-import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
-import static org.taverna.server.master.common.Roles.USER;
-
-import java.net.URI;
-import java.util.Date;
-import java.util.List;
-
-import javax.annotation.security.RolesAllowed;
-import javax.jws.WebMethod;
-import javax.jws.WebParam;
-import javax.jws.WebResult;
-import javax.jws.WebService;
-import javax.xml.bind.annotation.XmlElement;
-
-import org.apache.cxf.annotations.WSDLDocumentation;
-import org.ogf.usage.JobUsageRecord;
-import org.taverna.server.master.common.Capability;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.DirEntryReference;
-import org.taverna.server.master.common.InputDescription;
-import org.taverna.server.master.common.Permission;
-import org.taverna.server.master.common.ProfileList;
-import org.taverna.server.master.common.RunReference;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.common.version.Version;
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-import org.taverna.server.master.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.InvalidCredentialException;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoCredentialException;
-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.exceptions.UnknownRunException;
-import org.taverna.server.master.rest.TavernaServerREST;
-import org.taverna.server.port_description.OutputDescription;
-
-/**
- * The SOAP service interface to Taverna 3 Server.
- *
- * @author Donal Fellows
- * @see TavernaServerREST
- */
-@RolesAllowed(USER)
-@WebService(name = "tavernaService", targetNamespace = SERVER_SOAP)
-@WSDLDocumentation("The SOAP service interface to Taverna " + Version.JAVA
- + " Server.")
-public interface TavernaServerSOAP {
- /**
- * Make a run for a particular workflow.
- *
- * @param workflow
- * The workflow to instantiate.
- * @return Annotated handle for created run.
- * @throws NoUpdateException
- * @throws NoCreateException
- */
- @WebResult(name = "Run")
- @WSDLDocumentation("Make a run for a particular workflow.")
- RunReference submitWorkflow(
- @WebParam(name = "workflow") @XmlElement(required = true) Workflow workflow)
- throws NoUpdateException, NoCreateException;
-
- /**
- * Make a run for a particular workflow.
- *
- * @param workflow
- * The workflow to instantiate.
- * @return Annotated handle for created run.
- * @throws NoUpdateException
- * @throws NoCreateException
- */
- @WebResult(name = "Run")
- @WSDLDocumentation("Make a run for a particular workflow.")
- RunReference submitWorkflowMTOM(
- @WebParam(name = "workflow") @XmlElement(required = true) WrappedWorkflow workflow)
- throws NoUpdateException;
-
- /**
- * Make a run for a particular workflow, where that workflow will be
- * downloaded from elsewhere. The URI <i>must</i> be publicly readable.
- *
- * @param workflowURI
- * The URI to the workflow to instantiate.
- * @return Annotated handle for created run.
- * @throws NoUpdateException
- * @throws NoCreateException
- */
- @WebResult(name = "Run")
- @WSDLDocumentation("Make a run for a particular workflow where that "
- + "workflow is given by publicly readable URI.")
- RunReference submitWorkflowByURI(
- @WebParam(name = "workflowURI") @XmlElement(required = true) URI workflowURI)
- throws NoCreateException, NoUpdateException;
-
- /**
- * Get the list of existing runs owned by the user.
- *
- * @return Annotated handle list.
- */
- @WebResult(name = "Run")
- @WSDLDocumentation("Get the list of existing runs owned by the user.")
- RunReference[] listRuns();
-
- /**
- * Get the upper limit on the number of runs that the user may create at
- * once.
- *
- * @return The limit. <b>NB:</b> the number currently operating may be
- * larger, but in that case no further runs can be made until some
- * of the old ones are destroyed.
- */
- @WebResult(name = "MaxSimultaneousRuns")
- @WSDLDocumentation("Get the upper limit on the number of runs that the user may create at once.")
- int getServerMaxRuns();
-
- /**
- * Get the list of allowed workflows. If the list is empty, <i>any</i>
- * workflow may be used.
- *
- * @return A list of workflow documents.
- */
- @WebMethod(operationName = "getPermittedWorkflowURIs")
- @WebResult(name = "PermittedWorkflowURI")
- @WSDLDocumentation("Get the list of URIs to allowed workflows. If the list is empty, any workflow may be used including those not submitted via URI.")
- URI[] getServerWorkflows();
-
- /**
- * Get the list of allowed event listeners.
- *
- * @return A list of listener names.
- */
- @WebMethod(operationName = "getPermittedListenerTypes")
- @WebResult(name = "PermittedListenerType")
- @WSDLDocumentation("Get the list of allowed types of event listeners.")
- String[] getServerListeners();
-
- /**
- * Get the list of notification fabrics.
- *
- * @return A list of listener names.
- */
- @WebMethod(operationName = "getEnabledNotificationFabrics")
- @WebResult(name = "EnabledNotifierFabric")
- @WSDLDocumentation("Get the list of notification fabrics. Each is a URI scheme.")
- String[] getServerNotifiers();
-
- @WebMethod(operationName = "getCapabilities")
- @WebResult(name = "Capabilities")
- @WSDLDocumentation("Get the workflow execution capabilities of this "
- + "Taverna Server instance.")
- List<Capability> getServerCapabilities();
-
- /**
- * Destroy a run immediately. This might or might not actually relinquish
- * resources; that's up to the service implementation and deployment.
- *
- * @param runName
- * The handle of the run.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the lifetime of the
- * run.
- */
- @WSDLDocumentation("Destroy a run immediately.")
- void destroyRun(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException, NoUpdateException;
-
- /**
- * Get the workflow document used to create the given run.
- *
- * @param runName
- * The handle of the run.
- * @return The workflow document.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "CreationWorkflow")
- @WSDLDocumentation("Get the workflow document used to create the given run.")
- Workflow getRunWorkflow(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Get the workflow document used to create the given run.
- *
- * @param runName
- * The handle of the run.
- * @return The workflow document.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "CreationWorkflow")
- @WSDLDocumentation("Get the workflow document used to create the given run.")
- WrappedWorkflow getRunWorkflowMTOM(
- @WebParam(name = "runName") String runName)
- throws UnknownRunException;
-
- /**
- * Get a description of the profiles supported by the workflow document used
- * to create the given run.
- *
- * @param runName
- * The handle of the run.
- * @return A description of the supported profiles.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "Profiles")
- @WSDLDocumentation("Get a description of the profiles supported by the workflow document used to create the given run.")
- ProfileList getRunWorkflowProfiles(
- @WebParam(name = "runName") String runName)
- throws UnknownRunException;
-
- /**
- * Get the descriptive name of the workflow run. The descriptive name
- * carries no deep information.
- *
- * @param runName
- * The handle of the run.
- * @return The descriptive name of the run.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "DescriptiveName")
- @WSDLDocumentation("Get the descriptive name of the workflow run. Carries no deep information.")
- String getRunDescriptiveName(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Set the descriptive name of the workflow run. The descriptive name
- * carries no deep information.
- *
- * @param runName
- * The handle of the run.
- * @param descriptiveName
- * The new descriptive name to set. Note that the implementation
- * is allowed to arbitrarily truncate this value.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not permitted to update this run.
- */
- @WSDLDocumentation("Set the descriptive name of the workflow run. Carries no deep information.")
- void setRunDescriptiveName(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "descriptiveName") @XmlElement(required = true) String descriptiveName)
- throws UnknownRunException, NoUpdateException;
-
- /**
- * Get the description of the inputs to the workflow run.
- *
- * @param runName
- * The handle of the run.
- * @return The input description
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "RunInputDescription")
- @WSDLDocumentation("Get the description of the inputs currently set up for the given workflow run.")
- InputDescription getRunInputs(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Get a description of what inputs the workflow run <i>expects</i> to
- * receive.
- *
- * @param runName
- * The handle of the run.
- * @return The description document.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "RunInputDescriptor")
- @WSDLDocumentation("Get a description of what inputs the given workflow run expects to receive.")
- org.taverna.server.port_description.InputDescription getRunInputDescriptor(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Tells the run to use the given Baclava file for all inputs.
- *
- * @param runName
- * The handle of the run.
- * @param fileName
- * The name of the file to use. Must not start with a <tt>/</tt>
- * or contain a <tt>..</tt> element.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws FilesystemAccessException
- * If the filename is illegal.
- * @throws BadStateChangeException
- * If the run is not in the {@link Status#Initialized
- * Initialized} state
- */
- @WSDLDocumentation("Tells the given run to use the given already-uploaded Baclava file for all inputs.")
- void setRunInputBaclavaFile(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "baclavaFileName") String fileName)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, BadStateChangeException;
-
- /**
- * Tells the run to use the given file for input on the given port. This
- * overrides any previously set file or value on the port and causes the
- * server to forget about using a Baclava file for all inputs.
- *
- * @param runName
- * The handle of the run.
- * @param portName
- * The port to use the file for.
- * @param portFilename
- * The file to use on the port. Must not start with a <tt>/</tt>
- * or contain a <tt>..</tt> element.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws FilesystemAccessException
- * If the filename is illegal.
- * @throws BadStateChangeException
- * If the run is not in the {@link Status#Initialized
- * Initialized} state.
- * @throws BadPropertyValueException
- * If the input port may not be changed to the contents of the
- * given file.
- */
- @WSDLDocumentation("Tells the given run to use the given file for input on the given port.")
- void setRunInputPortFile(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "portName") @XmlElement(required = true) String portName,
- @WebParam(name = "portFileName") @XmlElement(required = true) String portFilename)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, BadStateChangeException,
- BadPropertyValueException;
-
- /**
- * Tells the run to use the given value for input on the given port. This
- * overrides any previously set file or value on the port and causes the
- * server to forget about using a Baclava file for all inputs. Note that
- * this is wholly unsuitable for use with binary data.
- *
- * @param runName
- * The handle of the run.
- * @param portName
- * The port to use the file for.
- * @param portValue
- * The literal value to use on the port.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws BadStateChangeException
- * If the run is not in the {@link Status#Initialized
- * Initialized} state.
- * @throws BadPropertyValueException
- * If the input port may not be changed to the given literal
- * value.
- */
- @WSDLDocumentation("Tells the given run to use the given literal string value for input on the given port.")
- void setRunInputPortValue(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "portName") @XmlElement(required = true) String portName,
- @WebParam(name = "portValue") @XmlElement(required = true) String portValue)
- throws UnknownRunException, NoUpdateException,
- BadStateChangeException, BadPropertyValueException;
-
- /**
- * Tells the given run to use the given list delimiter (a single-character
- * string value) for splitting the input on the given port. Note that
- * nullability of the delimiter is supported here.
- *
- * @param runName
- * The handle of the run.
- * @param portName
- * The port to set the list delimiter for.
- * @param delimiter
- * The single-character value (in range U+00001..U+0007F) to use
- * as the delimiter, or <tt>null</tt> for no delimiter at all.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws BadStateChangeException
- * If the run is not in the {@link Status#Initialized
- * Initialized} state.
- * @throws BadPropertyValueException
- * If the delimiter may not be changed to the given literal
- * value.
- */
- @WSDLDocumentation("Tells the given run to use the given list delimiter (a single-character string value) for splitting the input on the given port. Note that nullability of the delimiter is supported here.")
- void setRunInputPortListDelimiter(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "portName") @XmlElement(required = true) String portName,
- @WebParam(name = "delimiter") String delimiter)
- throws UnknownRunException, NoUpdateException,
- BadStateChangeException, BadPropertyValueException;
-
- /**
- * Get the Baclava file where the output of the run will be written.
- *
- * @param runName
- * The handle of the run.
- * @return The filename, or <tt>null</tt> if the results will be written to
- * a subdirectory <tt>out</tt> of the run's working directory.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "OutputBaclavaFile")
- @WSDLDocumentation("Get the Baclava file where the output of the run will be written.")
- String getRunOutputBaclavaFile(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Set the Baclava file where the output of the run will be written.
- *
- * @param runName
- * The handle of the run.
- * @param outputFile
- * The filename for the Baclava file, or <tt>null</tt> or the
- * empty string to indicate that the results are to be written to
- * the subdirectory <tt>out</tt> of the run's working directory.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws FilesystemAccessException
- * If the filename is illegal (starts with a <tt>/</tt> or
- * contains a <tt>..</tt> element.
- * @throws BadStateChangeException
- * If the run is not in the {@link Status#Initialized
- * Initialized} state
- */
- @WSDLDocumentation("Set the Baclava file where the output of the run will be written.")
- void setRunOutputBaclavaFile(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "baclavaFileName") String outputFile)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, BadStateChangeException;
-
- /**
- * Return a description of the outputs of a run.
- *
- * @param runName
- * The handle of the run.
- * @return Description document (higher level than filesystem traverse).
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws BadStateChangeException
- * If the run is in the {@link Status#Initialized Initialized}
- * state
- * @throws FilesystemAccessException
- * If there is an exception when accessing the filesystem.
- * @throws NoDirectoryEntryException
- * If things are odd in the filesystem.
- */
- @WebResult(name = "OutputDescription")
- @WSDLDocumentation("Return a description of the outputs of a run. Only known during/after the run.")
- OutputDescription getRunOutputDescription(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException, BadStateChangeException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Get the time when the run will be eligible to be automatically deleted.
- *
- * @param runName
- * The handle of the run.
- * @return A date at which the expiry will be scheduled. The actual deletion
- * will happen an arbitrary amount of time later (depending on
- * system policy).
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "Expiry")
- @WSDLDocumentation("Get the time when the run will be eligible to be automatically deleted.")
- Date getRunExpiry(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Set when the run will be eligible to be automatically deleted.
- *
- * @param runName
- * The handle of the run.
- * @param expiry
- * A date at which the expiry will be scheduled. The actual
- * deletion will happen an arbitrary amount of time later
- * (depending on system policy).
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the lifetime of the
- * run.
- */
- @WSDLDocumentation("Set when the run will be eligible to be automatically deleted.")
- void setRunExpiry(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "expiry") @XmlElement(required = true) Date expiry)
- throws UnknownRunException, NoUpdateException;
-
- /**
- * Get the time when the run was created.
- *
- * @param runName
- * The handle of the run.
- * @return The moment when the run was created (modulo some internal
- * overhead).
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "CreationTime")
- @WSDLDocumentation("Get the time when the run was created.")
- Date getRunCreationTime(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Get the time when the run was started.
- *
- * @param runName
- * The handle of the run.
- * @return The moment when the run was started (modulo some internal
- * overhead) or <tt>null</tt> to indicate that it has never started.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "StartTime")
- @WSDLDocumentation("Get the time when the run was started.")
- Date getRunStartTime(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Get the time when the run was detected as having finished.
- *
- * @param runName
- * The handle of the run.
- * @return The moment when the run was believed stopped. Note that this may
- * not be when the run <i>actually</i> finished; promptness of
- * detection depends on many factors.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "FinishTime")
- @WSDLDocumentation("Get the time when the run was detected as having finished.")
- Date getRunFinishTime(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Get the current status of the run.
- *
- * @param runName
- * The handle of the run.
- * @return The status code.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "Status")
- @WSDLDocumentation("Get the current status of the given workflow run.")
- Status getRunStatus(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Set the status of a run. This is used to start it executing, make it stop
- * executing, etc. Note that changing the status of a run can <i>never</i>
- * cause the run to be destroyed.
- *
- * @param runName
- * The handle of the run.
- * @param status
- * The status to change to. Changing to the current status will
- * always have no effect.
- * @return An empty string if the state change was completed, or a
- * description (never empty) of why the state change is ongoing.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws BadStateChangeException
- * If the state change requested is impossible.
- */
- @WebResult(name = "PartialityReason")
- @WSDLDocumentation("Set the status of a given workflow run.")
- String setRunStatus(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "status") @XmlElement(required = true) Status status)
- throws UnknownRunException, NoUpdateException,
- BadStateChangeException;
-
- /**
- * Get the names of the event listeners attached to the run.
- *
- * @param runName
- * The handle of the run.
- * @return The listener names.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "ListenerName")
- @WSDLDocumentation("Get the names of the event listeners attached to the run.")
- String[] getRunListeners(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Adds an event listener to the run.
- *
- * @param runName
- * The handle of the run.
- * @param listenerType
- * The type of event listener to add. Must be one of the names
- * returned by the {@link #getServerListeners()} operation.
- * @param configuration
- * The configuration document for the event listener; the
- * interpretation of the configuration is up to the listener.
- * @return The actual name of the listener.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user isn't allowed to manipulate the run.
- * @throws NoListenerException
- * If the listener construction fails (<i>e.g.</i>, due to an
- * unsupported <b>listenerType</b> or a problem with the
- * <b>configuration</b>).
- */
- @WebResult(name = "ListenerName")
- @WSDLDocumentation("Adds an event listener to the run.")
- String addRunListener(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "listenerType") @XmlElement(required = true) String listenerType,
- @WebParam(name = "configuration") @XmlElement(required = true) String configuration)
- throws UnknownRunException, NoUpdateException, NoListenerException;
-
- /**
- * Returns the standard output of the workflow run. Unstarted runs return
- * the empty string.
- * <p>
- * The equivalent thing can also be fetched from the relevant listener
- * property (i.e., io/stdout).
- *
- * @param runName
- * The handle of the run.
- * @return Whatever the run engine printed on its stdout.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "StandardOutput")
- @WSDLDocumentation("Returns the stdout from the run engine.")
- String getRunStdout(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Returns the standard error of the workflow run. Unstarted runs return the
- * empty string.
- * <p>
- * The equivalent thing can also be fetched from the relevant listener
- * property (i.e., io/stderr).
- *
- * @param runName
- * The handle of the run.
- * @return Whatever the run engine printed on its stderr.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "StandardError")
- @WSDLDocumentation("Returns the stderr from the run engine.")
- String getRunStderr(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Returns the usage record for the workflow run. Unfinished runs return
- * <tt>null</tt>.
- * <p>
- * The equivalent thing can also be fetched from the relevant listener
- * property (i.e., io/usage).
- *
- * @param runName
- * The handle of the run.
- * @return The usage record, or <tt>null</tt>.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "ResourceUsage")
- @WSDLDocumentation("Returns the resource usage from the run engine.")
- JobUsageRecord getRunUsageRecord(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Returns the log of the workflow run. Unstarted runs return the empty
- * string.
- * <p>
- * This can also be fetched from the appropriate file (i.e.,
- * <tt>logs/detail.log</tt>).
- *
- * @param runName
- * The handle of the run.
- * @return Whatever the run engine wrote to its log.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "Log")
- @WSDLDocumentation("Returns the detailed log from the run engine.")
- String getRunLog(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Returns the run bundle of a run. The run must be <i>finished</i> for this
- * to be guaranteed to be present, and must <i>not</i> have had its output
- * generated as Baclava.
- *
- * @param runName
- * The handle of the run.
- * @return The contents of the run bundle.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If there was a problem reading the bundle.
- * @throws NoDirectoryEntryException
- * If the bundle doesn't exist currently.
- */
- @WebResult(name = "RunBundle")
- @WSDLDocumentation("Gets the run bundle of a finished run. MTOM support recommended!")
- FileContents getRunBundle(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Gets whether to generate provenance (in a run bundle) for a run.
- *
- * @param runName
- * The handle of the run.
- * @return Whether provenance will be generated.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "GenerateProvenance")
- @WSDLDocumentation("Gets whether a run generates provenance.")
- boolean getRunGenerateProvenance(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Sets whether to generate provenance (in a run bundle) for a run.
- *
- * @param runName
- * The handle of the run.
- * @param generateProvenance
- * Whether to generate provenance.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to manipulate the run.
- */
- @WSDLDocumentation("Sets whether a run generates provenance. "
- + "Only usefully settable before the run is started.")
- void setRunGenerateProvenance(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "generateProvenance") @XmlElement(required = true) boolean generateProvenance)
- throws UnknownRunException, NoUpdateException;
-
- /**
- * Get the owner of the run.
- *
- * @param runName
- * The handle of the run.
- * @return The status code.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- */
- @WebResult(name = "Owner")
- @WSDLDocumentation("Get the owner of the given workflow run.")
- String getRunOwner(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException;
-
- /**
- * Get the list of permissions associated with a workflow run.
- *
- * @param runName
- * The name of the run whose permissions are to be obtained.
- * @return A description of the non-<tt>none</tt> permissions.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the current
- * user is not permitted to see it.
- * @throws NotOwnerException
- * If asked to provide this information about a run that the
- * current user may see but where they are not the owner of it.
- */
- @WebResult(name = "PermissionList")
- @WSDLDocumentation("Get the list of permissions associated with a given workflow run.")
- PermissionList listRunPermissions(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException, NotOwnerException;
-
- /**
- * Set the permission for a user to access and update a particular workflow
- * run.
- *
- * @param runName
- * The name of the run whose permissions are to be updated.
- * @param userName
- * The name of the user about whom this call is talking.
- * @param permission
- * The permission level to set.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the current
- * user is not permitted to see it.
- * @throws NotOwnerException
- * If asked to provide this information about a run that the
- * current user may see but where they are not the owner of it.
- */
- @WSDLDocumentation("Set the permission for a user to access and update a given workflow run.")
- void setRunPermission(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "userName") @XmlElement(required = true) String userName,
- @WebParam(name = "permission") @XmlElement(required = true) Permission permission)
- throws UnknownRunException, NotOwnerException;
-
- /**
- * Get the credentials associated with the run.
- *
- * @param runName
- * The handle of the run.
- * @return The collection of credentials.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NotOwnerException
- * If the user is permitted to see the run, but isn't the owner;
- * only the owner may see the credentials.
- */
- @WebResult(name = "Credentials")
- @WSDLDocumentation("Get the credentials (passwords, private keys) associated with the given workflow run. Only the owner may do this.")
- Credential[] getRunCredentials(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException, NotOwnerException;
-
- /**
- * Set a credential associated with the run.
- *
- * @param runName
- * The handle of the run.
- * @param credentialID
- * The handle of the credential to set. If empty, a new
- * credential will be created.
- * @param credential
- * The credential to set.
- * @return The handle of the credential that was created or updated.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NotOwnerException
- * If the user is permitted to see the run, but isn't the owner;
- * only the owner may manipulate the credentials.
- * @throws InvalidCredentialException
- * If the <b>credential</b> fails its checks.
- * @throws NoCredentialException
- * If the <b>credentialID</b> is not empty but does not
- * correspond to an existing credential.
- * @throws BadStateChangeException
- * If an attempt to manipulate the credentials is done after the
- * workflow has started running.
- */
- @WebResult(name = "credentialID")
- @WSDLDocumentation("Set a credential (password, private key, etc.) associated with the given run. Only the owner may do this.")
- String setRunCredential(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "credentialID") @XmlElement(required = true) String credentialID,
- @WebParam(name = "credential") @XmlElement(required = true) Credential credential)
- throws UnknownRunException, NotOwnerException,
- InvalidCredentialException, NoCredentialException,
- BadStateChangeException;
-
- /**
- * Delete a credential associated with the run.
- *
- * @param runName
- * The handle of the run.
- * @param credentialID
- * The handle of the credential to delete. If empty, a new
- * credential will be created.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NotOwnerException
- * If the user is permitted to see the run, but isn't the owner;
- * only the owner may manipulate the credentials.
- * @throws NoCredentialException
- * If the given credentialID does not exist.
- * @throws BadStateChangeException
- * If an attempt to manipulate the credentials is done after the
- * workflow has started running.
- */
- @WSDLDocumentation("Delete a credential associated with the given run. Only the owner may do this.")
- void deleteRunCredential(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "credentialID") @XmlElement(required = true) String credentialID)
- throws UnknownRunException, NotOwnerException,
- NoCredentialException, BadStateChangeException;
-
- /**
- * Get the certificate collections associated with the run.
- *
- * @param runName
- * The handle of the run.
- * @return The collection of credentials.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NotOwnerException
- * If the user is permitted to see the run, but isn't the owner;
- * only the owner may see the credentials.
- */
- @WebResult(name = "CertificateCollections")
- @WSDLDocumentation("Get the trusted (server or CA) certificates associated with the run. Only the owner may do this.")
- Trust[] getRunCertificates(
- @WebParam(name = "runName") @XmlElement(required = true) String runName)
- throws UnknownRunException, NotOwnerException;
-
- /**
- * Set a certificate collection associated with the run.
- *
- * @param runName
- * The handle of the run.
- * @param certificateID
- * The handle of the certificate collection to set. If empty, a
- * new certificate collection will be created.
- * @param certificate
- * The certificate collection to set.
- * @return The handle of the certificate set that was created or updated.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NotOwnerException
- * If the user is permitted to see the run, but isn't the owner;
- * only the owner may manipulate the certificates.
- * @throws InvalidCredentialException
- * If the <b>certificate</b> fails its checks.
- * @throws NoCredentialException
- * If the <b>credentialID</b> is not empty but does not
- * correspond to an existing certificate collection.
- * @throws BadStateChangeException
- * If an attempt to manipulate the credentials is done after the
- * workflow has started running.
- */
- @WebResult(name = "certificateID")
- @WSDLDocumentation("Set a trusted (server or CA) certificate associated with the run. Only the owner may do this.")
- String setRunCertificates(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "certificateID") String certificateID,
- @WebParam(name = "certificate") @XmlElement(required = true) Trust certificate)
- throws UnknownRunException, NotOwnerException,
- InvalidCredentialException, NoCredentialException,
- BadStateChangeException;
-
- /**
- * Delete a certificate collection associated with the run.
- *
- * @param runName
- * The handle of the run.
- * @param certificateID
- * The handle of the credential to delete.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NotOwnerException
- * If the user is permitted to see the run, but isn't the owner;
- * only the owner may manipulate the certificates.
- * @throws NoCredentialException
- * If the given certificateID does not exist.
- * @throws BadStateChangeException
- * If an attempt to manipulate the credentials is done after the
- * workflow has started running.
- */
- @WSDLDocumentation("Delete a trusted (server or CA) certificate associated with the run. Only the owner may do this.")
- void deleteRunCertificates(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "certificateID") @XmlElement(required = true) String certificateID)
- throws UnknownRunException, NotOwnerException,
- NoCredentialException, BadStateChangeException;
-
- /**
- * Get the contents of any directory at/under the run's working directory.
- * Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param directory
- * The name of the directory to fetch; the main working directory
- * is <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return A list of entries. They are assumed to be all directories or
- * files.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the contents of
- * a file).
- * @throws NoDirectoryEntryException
- * If the name of the directory can't be looked up.
- */
- @WebResult(name = "DirectoryEntry")
- @WSDLDocumentation("Get the contents of any directory at/under the run's working directory.")
- DirEntry[] getRunDirectoryContents(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "directory") @XmlElement(required = true) DirEntry directory)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Get the contents of any directory (and its subdirectories) at/under the
- * run's working directory, returning it as a compressed ZIP file. Runs do
- * not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param directory
- * The name of the directory to fetch; the main working directory
- * is <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return A serialized ZIP file.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the contents of
- * a file).
- * @throws NoDirectoryEntryException
- * If the name of the directory can't be looked up.
- */
- @WebResult(name = "ZipFile")
- @WSDLDocumentation("Get the contents of any directory (and its subdirectories) at/under the run's working directory, returning it as a compressed ZIP file.")
- byte[] getRunDirectoryAsZip(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "directory") @XmlElement(required = true) DirEntry directory)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Get the contents of any directory (and its subdirectories) at/under the
- * run's working directory, returning it as a compressed ZIP file that is
- * streamed via MTOM. Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param directory
- * The name of the directory to fetch; the main working directory
- * is <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return An MTOM-streamable ZIP file reference.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the contents of
- * a file).
- * @throws NoDirectoryEntryException
- * If the name of the directory can't be looked up.
- */
- @WebResult(name = "ZipStream")
- @WSDLDocumentation("Get the contents of any directory (and its subdirectories) at/under the run's working directory, returning it as a compressed ZIP file that is streamed by MTOM.")
- ZippedDirectory getRunDirectoryAsZipMTOM(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "directory") @XmlElement(required = true) DirEntry directory)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Make a new empty directory beneath an existing one, which must be the
- * run's working directory or a directory beneath it. Runs do not share
- * working directories.
- *
- * @param runName
- * The handle of the run.
- * @param parent
- * The parent directory that will have the new directory added
- * beneath it.
- * @param name
- * The name of the directory to create. Must not be the same as
- * any other file or directory in the <i>parent</i> directory.
- * The name <i>must not</i> consist of <tt>..</tt> or have a
- * <tt>/</tt> in it.
- * @return A reference to the created directory.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., making something with
- * the same name as something that already exists).
- * @throws NoDirectoryEntryException
- * If the name of the containing directory can't be looked up.
- */
- @WebResult(name = "CreatedDirectory")
- @WSDLDocumentation("Make a new empty directory beneath an existing one, all relative to the given run's main working directory.")
- DirEntry makeRunDirectory(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "parentDirectory") @XmlElement(required = true) DirEntry parent,
- @WebParam(name = "directoryName") @XmlElement(required = true) String name)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Make a new empty file in an existing directory, which may be the run's
- * working directory or any directory beneath it. Runs do not share working
- * directories.
- *
- * @param runName
- * The handle of the run.
- * @param parent
- * The parent directory that will have the new file added to it.
- * @param name
- * The name of the file to create. Must not be the same as any
- * other file or directory in the <i>parent</i> directory. The
- * name <i>must not</i> consist of <tt>..</tt> or have a
- * <tt>/</tt> in it.
- * @return A reference to the created file. The file will be empty.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., making something with
- * the same name as something that already exists).
- * @throws NoDirectoryEntryException
- * If the name of the containing directory can't be looked up.
- */
- @WebResult(name = "CreatedFile")
- @WSDLDocumentation("Make a new empty file in an existing directory, which may be the run's working directory or any directory beneath it.")
- DirEntry makeRunFile(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "parentDirectory") @XmlElement(required = true) DirEntry parent,
- @WebParam(name = "fileNameTail") @XmlElement(required = true) String name)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Destroy an entry (file or directory) in or beneath a run's working
- * directory. Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param dirEntry
- * Reference to an existing item in a directory that will be
- * destroyed. May be a reference to either a file or a directory.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., deleting something
- * which doesn't exist or attempting to delete the main working
- * directory).
- * @throws NoDirectoryEntryException
- * If the name of the file or directory can't be looked up.
- */
- @WSDLDocumentation("Destroy an entry (file or directory) in or beneath a run's working directory.")
- void destroyRunDirectoryEntry(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "directoryEntry") @XmlElement(required = true) DirEntry dirEntry)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Get the contents of a file under the run's working directory. Runs do not
- * share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to fetch; the main working directory is
- * <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return The literal byte contents of the file.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the contents of
- * a directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WebResult(name = "FileContents")
- @WSDLDocumentation("Get the contents of a file under the run's working directory.")
- byte[] getRunFileContents(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Get the contents of a file under the run's working directory via MTOM.
- * Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to fetch; the main working directory is
- * <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return The contents, described for transfer via MTOM.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the contents of
- * a directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WebResult(name = "FileContentsMTOM")
- @WSDLDocumentation("Get the contents of a file via MTOM.")
- FileContents getRunFileContentsMTOM(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Set the contents of a file under the run's working directory. Runs do not
- * share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to update; the main working directory is
- * <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @param newContents
- * The literal bytes to set the file contents to.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., writing the contents of
- * a directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WSDLDocumentation("Set the contents of a file under the run's working directory.")
- void setRunFileContents(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file,
- @WebParam(name = "contents") @XmlElement(required = true) byte[] newContents)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Set the contents of a file under the run's working directory. Runs do not
- * share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param newContents
- * The description of what file to set, and what to the file
- * contents should be set to.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., writing the contents of
- * a directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WSDLDocumentation("Set the contents of a file under the run's working directory.")
- void setRunFileContentsMTOM(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "contents") @XmlElement(required = true) FileContents newContents)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Set the contents of a file under the run's working directory to the
- * contents of a publicly readable URI. Runs do not share working
- * directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to update; the main working directory is
- * <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @param reference
- * The publicly readable URI whose contents are to become the
- * literal bytes of the file's contents.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., writing the contents of
- * a directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WSDLDocumentation("Set the contents of a file under the run's working directory from the contents of a publicly readable URI.")
- void setRunFileContentsFromURI(@WebParam(name = "runName") String runName,
- @WebParam(name = "fileName") DirEntryReference file,
- @WebParam(name = "contents") URI reference)
- throws UnknownRunException, NoUpdateException,
- FilesystemAccessException, NoDirectoryEntryException;
-
- /**
- * Get the length of any file (in bytes) at/under the run's working
- * directory. Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to get the length of; the main working
- * directory is <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return The number of bytes in the file.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the length of a
- * directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WebResult(name = "FileLength")
- @WSDLDocumentation("Get the length of any file (in bytes) at/under the run's working directory.")
- long getRunFileLength(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Get the time that the file or directory (at/under the run's working
- * directory) was last modified. Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to get the modification date of; the main
- * working directory is <tt>/</tt> and <tt>..</tt> is always
- * disallowed.
- * @return The modification date of the file or directory, as understood by
- * the underlying operating system.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated.
- * @throws NoDirectoryEntryException
- * If the file or directory doesn't exist.
- */
- @WebResult(name = "FileModified")
- @WSDLDocumentation("Get the length of any file (in bytes) at/under the run's working directory.")
- Date getRunFileModified(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Get the content type of any file at/under the run's working directory.
- * Runs do not share working directories.
- *
- * @param runName
- * The handle of the run.
- * @param file
- * The name of the file to get the length of; the main working
- * directory is <tt>/</tt> and <tt>..</tt> is always disallowed.
- * @return The content type of the file.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws FilesystemAccessException
- * If some assumption is violated (e.g., reading the length of a
- * directory).
- * @throws NoDirectoryEntryException
- * If the file doesn't exist.
- */
- @WebResult(name = "FileContentType")
- @WSDLDocumentation("Get the content type of any file at/under the run's working directory.")
- String getRunFileType(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
- throws UnknownRunException, FilesystemAccessException,
- NoDirectoryEntryException;
-
- /**
- * Get the configuration document for an event listener attached to a run.
- *
- * @param runName
- * The handle of the run.
- * @param listenerName
- * The name of the listener attached.
- * @return The configuration document.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoListenerException
- * If no such listener exists.
- */
- @WebResult(name = "ListenerConfiguration")
- @WSDLDocumentation("Get the configuration document for an event listener attached to a run.")
- String getRunListenerConfiguration(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName)
- throws UnknownRunException, NoListenerException;
-
- /**
- * Get the list of properties supported by an event listener attached to a
- * run.
- *
- * @param runName
- * The handle of the run.
- * @param listenerName
- * The name of the listener attached.
- * @return The list of property names.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoListenerException
- * If no such listener exists.
- */
- @WebResult(name = "ListenerPropertyName")
- @WSDLDocumentation("Get the list of properties supported by an event listener attached to a run.")
- String[] getRunListenerProperties(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName)
- throws UnknownRunException, NoListenerException;
-
- /**
- * Get the value of a property for an event listener attached to a run.
- *
- * @param runName
- * The handle of the run.
- * @param listenerName
- * The name of the listener attached.
- * @param propertyName
- * The name of the property to read.
- * @return The configuration document.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoListenerException
- * If no such listener exists or if the listener has no such
- * property.
- */
- @WebResult(name = "ListenerPropertyValue")
- @WSDLDocumentation("Get the value of a property for an event listener attached to a run.")
- String getRunListenerProperty(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName,
- @WebParam(name = "propertyName") @XmlElement(required = true) String propertyName)
- throws UnknownRunException, NoListenerException;
-
- /**
- * Set the value of a property for an event listener attached to a run.
- *
- * @param runName
- * The handle of the run.
- * @param listenerName
- * The name of the listener attached.
- * @param propertyName
- * The name of the property to write.
- * @param value
- * The value to set the property to.
- * @throws UnknownRunException
- * If the server doesn't know about the run or if the user is
- * not permitted to see it.
- * @throws NoListenerException
- * If no such listener exists, the listener has no such
- * property, or the value is considered "unacceptable" in some
- * way.
- * @throws NoUpdateException
- * If the user is not allowed to make modifications to the run.
- */
- @WSDLDocumentation("Set the value of a property for an event listener attached to a run.")
- void setRunListenerProperty(
- @WebParam(name = "runName") @XmlElement(required = true) String runName,
- @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName,
- @WebParam(name = "propertyName") @XmlElement(required = true) String propertyName,
- @WebParam(name = "propertyValue") @XmlElement(required = true) String value)
- throws UnknownRunException, NoUpdateException, NoListenerException;
-
- /**
- * Gets the status of the server. Follows the HELIO Monitoring Service
- * protocol.
- *
- * @return A status string.
- */
- @WSDLDocumentation("A simple way to get the status of the overall server.")
- @WebResult(name = "ServerStatus")
- String getServerStatus();
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java b/server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java
deleted file mode 100644
index cd06115..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE.txt" for license terms.
- */
-package org.taverna.server.master.soap;
-
-import static javax.xml.bind.annotation.XmlAccessType.NONE;
-import static org.apache.commons.io.IOUtils.closeQuietly;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlMimeType;
-import javax.xml.bind.annotation.XmlTransient;
-import javax.xml.bind.annotation.XmlType;
-
-import org.taverna.server.master.common.Workflow;
-
-import uk.org.taverna.scufl2.api.io.ReaderException;
-import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
-import uk.org.taverna.scufl2.api.io.WriterException;
-
-/**
- * An MTOM-capable description of how to transfer the contents of a file.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "WorkflowReference")
-@XmlAccessorType(NONE)
-public class WrappedWorkflow {
- @XmlMimeType("application/octet-stream")
- // JAXB bug: must be this
- public DataHandler workflowData;
- Workflow workflow;
-
- /**
- * Initialize the contents of this descriptor from the given file and
- * content type.
- *
- * @param workflow
- * The workflow that is to be reported.
- */
- public void setWorkflow(Workflow workflow) {
- workflowData = new DataHandler(new WorkflowSource(workflow));
- }
-
- @XmlTransient
- public Workflow getWorkflow() throws IOException {
- if (workflow != null)
- return workflow;
- try {
- return new Workflow(new WorkflowBundleIO().readBundle(
- workflowData.getInputStream(), null));
- } catch (ReaderException e) {
- throw new IOException("problem converting to scufl2 bundle", e);
- }
- }
-}
-
-/**
- * A data source that knows how to deliver a workflow.
- *
- * @author Donal Fellows
- */
-class WorkflowSource implements DataSource {
- WorkflowSource(Workflow workflow) {
- this.wf = workflow;
- this.io = new WorkflowBundleIO();
- }
-
- Workflow wf;
- final WorkflowBundleIO io;
-
- @Override
- public String getContentType() {
- return wf.getPreferredContentType().getContentType();
- }
-
- @Override
- public String getName() {
- switch (wf.getPreferredContentType()) {
- case SCUFL2:
- return "workflow.scufl2";
- case T2FLOW:
- return "workflow.t2flow";
- default:
- return "workflow";
- }
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- PipedInputStream is = new PipedInputStream();
- final OutputStream os = new PipedOutputStream(is);
- new Worker() {
- @Override
- public void doWork() throws WriterException, IOException {
- io.writeBundle(wf.getScufl2Workflow(), os, wf
- .getPreferredContentType().getContentType());
- }
-
- @Override
- public void doneWork() {
- closeQuietly(os);
- }
- };
- return is;
- }
-
- @Override
- public OutputStream getOutputStream() throws IOException {
- final PipedInputStream is = new PipedInputStream();
- OutputStream os = new PipedOutputStream(is);
- new Worker() {
- @Override
- public void doWork() throws IOException, ReaderException {
- wf = new Workflow(io.readBundle(is, null));
- }
-
- @Override
- public void doneWork() {
- closeQuietly(is);
- }
- };
- return os;
- }
-
- static abstract class Worker extends Thread {
- public Worker() {
- setDaemon(true);
- start();
- }
-
- public abstract void doWork() throws Exception;
-
- public abstract void doneWork();
-
- @Override
- public void run() {
- try {
- doWork();
- } catch (Exception e) {
- // do nothing.
- } finally {
- doneWork();
- }
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java b/server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java
deleted file mode 100644
index 90fe51b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.soap;
-
-import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.activation.UnsupportedDataTypeException;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlMimeType;
-import javax.xml.bind.annotation.XmlType;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.interfaces.Directory;
-
-/**
- * An MTOM-capable description of how to transfer the zipped contents of a
- * directory.
- *
- * @author Donal Fellows
- * @see Directory#getContentsAsZip()
- */
-@XmlType(name = "ZippedDirectory")
-public class ZippedDirectory {
- @XmlElement
- public String name;
- @XmlMimeType("application/octet-stream")
- // JAXB bug: must be this
- public DataHandler fileData;
-
- public ZippedDirectory() {
- }
-
- /**
- * Initialise the contents of this descriptor from the given directory.
- *
- * @param dir
- * The directory that is to be reported.
- */
- public ZippedDirectory(Directory dir) {
- name = dir.getFullName();
- fileData = new DataHandler(new ZipSource(dir));
- }
-}
-
-/**
- * A data source that knows how to communicate with the Taverna Server back-end.
- *
- * @author Donal Fellows
- */
-class ZipSource implements DataSource {
- ZipSource(Directory d) {
- this.d = d;
- }
-
- private final Directory d;
-
- @Override
- public String getContentType() {
- return APPLICATION_ZIP_TYPE.toString();
- }
-
- @Override
- public String getName() {
- return d.getName();
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- try {
- return d.getContentsAsZip();
- } catch (FilesystemAccessException e) {
- throw new IOException(e);
- }
- }
-
- @Override
- public OutputStream getOutputStream() throws IOException {
- throw new UnsupportedDataTypeException();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java
deleted file mode 100644
index 51d9b69..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains the SOAP interface to Taverna Server.
- * @author Donal Fellows
- */
-@XmlSchema(namespace = SERVER_SOAP, 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 = "port", namespaceURI = DATA),
- @XmlNs(prefix = "feed", namespaceURI = FEED),
- @XmlNs(prefix = "admin", namespaceURI = ADMIN) })
-package org.taverna.server.master.soap;
-
-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.XLINK;
-import static org.taverna.server.port_description.Namespaces.DATA;
-
-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/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java b/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java
deleted file mode 100644
index 487dbd0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.usage;
-
-import java.util.Date;
-
-import javax.jdo.annotations.Column;
-import javax.jdo.annotations.Index;
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.PrimaryKey;
-import javax.jdo.annotations.Queries;
-import javax.jdo.annotations.Query;
-import javax.xml.bind.JAXBException;
-
-import org.ogf.usage.JobUsageRecord;
-
-/**
- * A usage record as recorded in the database.
- *
- * @author Donal Fellows
- */
-@PersistenceCapable(table = "USAGE_RECORD_LOG", schema = "UR", cacheable = "true")
-@Queries({ @Query(name = "allByDate", value = "SELECT USAGE_RECORD FROM UR.USAGE_RECORD_LOG ORDER BY CREATE_DATE", resultClass = String.class, unmodifiable = "true", unique = "false", language = "SQL") })
-public class UsageRecord {
- /**
- * Create an empty usage record database entry.
- */
- public UsageRecord() {
- }
-
- /**
- * Create a usage record database entry that is populated from the given UR.
- *
- * @param usageRecord
- * The originating usage record.
- * @throws JAXBException
- * If deserialization of the record fails.
- */
- public UsageRecord(String usageRecord) throws JAXBException {
- JobUsageRecord jur = JobUsageRecord.unmarshal(usageRecord);
- setUsageRecord(usageRecord);
- setCreateDate(jur.getRecordIdentity().getCreateTime()
- .toGregorianCalendar().getTime());
- setId(jur.getRecordIdentity().getRecordId());
- setUserid(jur.getUserIdentity().get(0).getLocalUserId());
- }
-
- /**
- * Create a usage record database entry that is populated from the given UR.
- *
- * @param usageRecord
- * The originating usage record.
- * @throws JAXBException
- * If serialization of the record fails.
- */
- public UsageRecord(JobUsageRecord usageRecord) throws JAXBException {
- setUsageRecord(usageRecord.marshal());
- setCreateDate(usageRecord.getRecordIdentity().getCreateTime()
- .toGregorianCalendar().getTime());
- setId(usageRecord.getRecordIdentity().getRecordId());
- setUserid(usageRecord.getUserIdentity().get(0).getLocalUserId());
- }
-
- @PrimaryKey
- @Column(name = "ID", length = 40)
- private String id;
-
- @Persistent
- @Index(name = "USERID_IDX")
- @Column(name = "USERID", length = 24)
- private String userid;
-
- @Persistent
- @Index(name = "CREATE_IDX")
- @Column(name = "CREATE_DATE")
- private Date createDate;
-
- @Persistent
- @Column(name = "USAGE_RECORD", length = 32000)
- // TODO Consider moving to BLOB (CLOB?) type
- private String usageRecord;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getUserid() {
- return userid;
- }
-
- public void setUserid(String userid) {
- this.userid = userid;
- }
-
- public Date getCreateDate() {
- return createDate;
- }
-
- public void setCreateDate(Date createDate) {
- this.createDate = createDate;
- }
-
- public String getUsageRecord() {
- return usageRecord;
- }
-
- public void setUsageRecord(String usageRecord) {
- this.usageRecord = usageRecord;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java b/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java
deleted file mode 100644
index 12de304..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.usage;
-
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.PreDestroy;
-import javax.xml.bind.JAXBException;
-
-import org.apache.commons.logging.Log;
-import org.ogf.usage.JobUsageRecord;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.api.ManagementModel;
-import org.taverna.server.master.utils.Contextualizer;
-import org.taverna.server.master.utils.JDOSupport;
-
-/**
- * A simple state-aware writer of usage records. It just appends them, one by
- * one, to the file whose name is stored in the state.
- *
- * @author Donal Fellows
- */
-public class UsageRecordRecorder extends JDOSupport<UsageRecord> {
- private Log log = getLog("Taverna.Server.Webapp");
- public UsageRecordRecorder() {
- super(UsageRecord.class);
- }
-
- private String logFile = null;
- private boolean disableDB = false;
- private ManagementModel state;
- private Contextualizer contextualizer;
- private String logDestination;
- private PrintWriter writer;
- private Object lock = new Object();
- private UsageRecordRecorder self;
-
- /**
- * @param state
- * the state to set
- */
- @Required
- public void setState(ManagementModel state) {
- this.state = state;
- }
-
- @Required
- public void setSelf(UsageRecordRecorder self) {
- this.self = self;
- }
-
- public void setLogFile(String logFile) {
- this.logFile = (logFile == null || logFile.equals("none")) ? null : logFile;
- }
-
- public void setDisableDB(String disable) {
- disableDB = "yes".equalsIgnoreCase(disable);
- }
-
- /**
- * @param contextualizer
- * the system's contextualizer, used to allow making the UR dump
- * file be placed relative to the webapp.
- */
- @Required
- public void setContextualizer(Contextualizer contextualizer) {
- this.contextualizer = contextualizer;
- }
-
- /**
- * Accept a usage record for recording.
- *
- * @param usageRecord
- * The serialized usage record to record.
- */
- public void storeUsageRecord(String usageRecord) {
- String logfile = state.getUsageRecordLogFile();
- if (logfile == null)
- logfile = this.logFile;
- if (logfile != null) {
- logfile = contextualizer.contextualize(logfile);
- synchronized (lock) {
- if (!logfile.equals(logDestination)) {
- if (writer != null) {
- writer.close();
- writer = null;
- }
- try {
- writer = new PrintWriter(new FileWriter(logfile));
- logDestination = logfile;
- } catch (IOException e) {
- log.warn("failed to open usage record log file", e);
- }
- }
- if (writer != null) {
- writer.println(usageRecord);
- writer.flush();
- }
- }
- }
-
- if (!disableDB)
- saveURtoDB(usageRecord);
- }
-
- /**
- * How to save a usage record to the database.
- *
- * @param usageRecord
- * The serialized usage record to save.
- */
- protected void saveURtoDB(String usageRecord) {
- UsageRecord ur;
- try {
- ur = new UsageRecord(usageRecord);
- } catch (JAXBException e) {
- log.warn("failed to deserialize usage record", e);
- return;
- }
-
- try {
- self.saveURtoDB(ur);
- } catch (RuntimeException e) {
- log.warn("failed to save UR to database", e);
- }
- }
-
- @WithinSingleTransaction
- public void saveURtoDB(UsageRecord ur) {
- persist(ur);
- }
-
- @WithinSingleTransaction
- public List<JobUsageRecord> getUsageRecords() {
- @SuppressWarnings("unchecked")
- Collection<String> urs = (Collection<String>) namedQuery("allByDate")
- .execute();
- List<JobUsageRecord> result = new ArrayList<>();
- for (String ur : urs)
- try {
- result.add(JobUsageRecord.unmarshal(ur));
- } catch (JAXBException e) {
- log.warn("failed to unmarshal UR", e);
- }
- return result;
- }
-
- @PreDestroy
- public void close() {
- if (writer != null)
- writer.close();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java
deleted file mode 100644
index 13e14cd..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * Resource usage recording mechanism.
- */
-package org.taverna.server.master.usage;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java b/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java
deleted file mode 100644
index a1ac04a..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.utils;
-
-import static java.lang.String.format;
-import static java.lang.System.nanoTime;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import org.apache.commons.logging.Log;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.taverna.server.master.common.version.Version;
-
-/**
- * This class is responsible for timing all invocations of publicly-exposed
- * methods of the webapp. It's connected to the webapp through an AspectJ-style
- * pointcut that targets a custom annotation.
- *
- * @author Donal Fellows
- */
-@Aspect
-@ManagedResource(objectName = JMX_ROOT + "PerformanceMonitor", description = "The performance monitor for Taverna Server "
- + Version.JAVA
- + ". Writes to application log using the category 'Taverna.Server.Performance'.")
-public class CallTimeLogger {
- private long threshold = 4000000;
- private Log log = getLog("Taverna.Server.Performance");
-
- @ManagedAttribute(description = "Threshold beneath which monitored call times are not logged. In nanoseconds.")
- public long getThreshold() {
- return threshold;
- }
-
- @ManagedAttribute(description = "Threshold beneath which monitored call times are not logged. In nanoseconds.")
- public void setThreshold(long threshold) {
- this.threshold = threshold;
- }
-
- /**
- * The timer for this aspect. The wrapped invocation will be timed, and a
- * log message written if the configured threshold is exceeded.
- *
- * @param call
- * The call being wrapped.
- * @return The result of the call.
- * @throws Throwable
- * If anything goes wrong with the wrapped call.
- * @see System#nanoTime()
- */
- @Around("@annotation(org.taverna.server.master.utils.CallTimeLogger.PerfLogged)")
- public Object time(ProceedingJoinPoint call) throws Throwable {
- long fore = nanoTime();
- try {
- return call.proceed();
- } finally {
- long aft = nanoTime();
- long elapsed = aft - fore;
- if (elapsed > threshold)
- log.info(format("call to %s took %.3fms", call.toShortString(),
- elapsed / 1000000.0));
- }
- }
-
- /**
- * Mark methods that should be counted by the invocation counter.
- *
- * @author Donal Fellows
- */
- @Retention(RUNTIME)
- @Documented
- @Target(METHOD)
- public static @interface PerfLogged {
- }
-}
[08/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java
new file mode 100644
index 0000000..ff14986
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java
@@ -0,0 +1,649 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static java.lang.String.format;
+import static java.util.Arrays.fill;
+import static java.util.UUID.randomUUID;
+import static org.taverna.server.master.defaults.Default.CERTIFICATE_FIELD_NAMES;
+import static org.taverna.server.master.defaults.Default.CERTIFICATE_TYPE;
+import static org.taverna.server.master.defaults.Default.CREDENTIAL_FILE_SIZE_LIMIT;
+import static org.taverna.server.master.identity.WorkflowInternalAuthProvider.PREFIX;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.rmi.RemoteException;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+import javax.security.auth.x500.X500Principal;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriBuilder;
+import javax.xml.ws.handler.MessageContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.localworker.remote.RemoteSecurityContext;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Implementation of a security context.
+ *
+ * @author Donal Fellows
+ */
+public abstract class SecurityContextDelegate implements TavernaSecurityContext {
+ Log log = LogFactory.getLog("Taverna.Server.Worker");
+ private final UsernamePrincipal owner;
+ private final List<Credential> credentials = new ArrayList<>();
+ private final List<Trust> trusted = new ArrayList<>();
+ private final RemoteRunDelegate run;
+ private final Object lock = new Object();
+ final SecurityContextFactory factory;
+
+ private transient Keystore keystore;
+ private transient Map<URI, String> uriToAliasMap;
+
+ /**
+ * Initialise the context delegate.
+ *
+ * @param run
+ * What workflow run is this for?
+ * @param owner
+ * Who owns the workflow run?
+ * @param factory
+ * What class built this object?
+ */
+ protected SecurityContextDelegate(RemoteRunDelegate run,
+ UsernamePrincipal owner, SecurityContextFactory factory) {
+ this.run = run;
+ this.owner = owner;
+ this.factory = factory;
+ }
+
+ @Override
+ public SecurityContextFactory getFactory() {
+ return factory;
+ }
+
+ @Override
+ public UsernamePrincipal getOwner() {
+ return owner;
+ }
+
+ @Override
+ public Credential[] getCredentials() {
+ synchronized (lock) {
+ return credentials.toArray(new Credential[credentials.size()]);
+ }
+ }
+
+ /**
+ * Get the human-readable name of a principal.
+ *
+ * @param principal
+ * The principal being decoded.
+ * @return A name.
+ */
+ protected final String getPrincipalName(X500Principal principal) {
+ return factory.x500Utils.getName(principal, CERTIFICATE_FIELD_NAMES);
+ }
+
+ /**
+ * Cause the current state to be flushed to the database.
+ */
+ protected final void flushToDB() {
+ factory.db.flushToDisk(run);
+ }
+
+ @Override
+ public void addCredential(Credential toAdd) {
+ synchronized (lock) {
+ int idx = credentials.indexOf(toAdd);
+ if (idx != -1)
+ credentials.set(idx, toAdd);
+ else
+ credentials.add(toAdd);
+ flushToDB();
+ }
+ }
+
+ @Override
+ public void deleteCredential(Credential toDelete) {
+ synchronized (lock) {
+ credentials.remove(toDelete);
+ flushToDB();
+ }
+ }
+
+ @Override
+ public Trust[] getTrusted() {
+ synchronized (lock) {
+ return trusted.toArray(new Trust[trusted.size()]);
+ }
+ }
+
+ @Override
+ public void addTrusted(Trust toAdd) {
+ synchronized (lock) {
+ int idx = trusted.indexOf(toAdd);
+ if (idx != -1)
+ trusted.set(idx, toAdd);
+ else
+ trusted.add(toAdd);
+ flushToDB();
+ }
+ }
+
+ @Override
+ public void deleteTrusted(Trust toDelete) {
+ synchronized (lock) {
+ trusted.remove(toDelete);
+ flushToDB();
+ }
+ }
+
+ @Override
+ public abstract void validateCredential(Credential c)
+ throws InvalidCredentialException;
+
+ @Override
+ public void validateTrusted(Trust t) throws InvalidCredentialException {
+ InputStream contentsAsStream;
+ if (t.certificateBytes != null && t.certificateBytes.length > 0) {
+ contentsAsStream = new ByteArrayInputStream(t.certificateBytes);
+ t.certificateFile = null;
+ } else if (t.certificateFile == null
+ || t.certificateFile.trim().isEmpty())
+ throw new InvalidCredentialException(
+ "absent or empty certificateFile");
+ else {
+ contentsAsStream = contents(t.certificateFile);
+ t.certificateBytes = null;
+ }
+ t.serverName = null;
+ if (t.fileType == null || t.fileType.trim().isEmpty())
+ t.fileType = CERTIFICATE_TYPE;
+ t.fileType = t.fileType.trim();
+ try {
+ t.loadedCertificates = CertificateFactory.getInstance(t.fileType)
+ .generateCertificates(contentsAsStream);
+ t.serverName = new ArrayList<>(t.loadedCertificates.size());
+ for (Certificate c : t.loadedCertificates)
+ t.serverName.add(getPrincipalName(((X509Certificate) c)
+ .getSubjectX500Principal()));
+ } catch (CertificateException e) {
+ throw new InvalidCredentialException(e);
+ } catch (ClassCastException e) {
+ // Do nothing; truncates the list of server names
+ }
+ }
+
+ @Override
+ public void initializeSecurityFromContext(SecurityContext securityContext)
+ throws Exception {
+ // This is how to get the info from Spring Security
+ Authentication auth = securityContext.getAuthentication();
+ if (auth == null)
+ return;
+ auth.getPrincipal();
+ // do nothing else in this implementation
+ }
+
+ @Override
+ public void initializeSecurityFromSOAPContext(MessageContext context) {
+ // do nothing in this implementation
+ }
+
+ @Override
+ public void initializeSecurityFromRESTContext(HttpHeaders context) {
+ // do nothing in this implementation
+ }
+
+ private UriBuilder getUB() {
+ return factory.uriSource.getRunUriBuilder(run);
+ }
+
+ private RunDatabaseDAO getDAO() {
+ return ((RunDatabase) factory.db).dao;
+ }
+
+ @Nullable
+ private List<X509Certificate> getCerts(URI uri) throws IOException,
+ GeneralSecurityException {
+ return factory.certFetcher.getTrustsForURI(uri);
+ }
+
+ private void installLocalPasswordCredential(List<Credential> credentials,
+ List<Trust> trusts) throws InvalidCredentialException, IOException,
+ GeneralSecurityException {
+ Credential.Password pw = new Credential.Password();
+ pw.id = "run:self";
+ pw.username = PREFIX + run.id;
+ pw.password = getDAO().getSecurityToken(run.id);
+ UriBuilder ub = getUB().segment("").fragment(factory.httpRealm);
+ pw.serviceURI = ub.build();
+ validateCredential(pw);
+ log.info("issuing self-referential credential for " + pw.serviceURI);
+ credentials.add(pw);
+ List<X509Certificate> myCerts = getCerts(pw.serviceURI);
+ if (myCerts != null && myCerts.size() > 0) {
+ Trust t = new Trust();
+ t.loadedCertificates = getCerts(pw.serviceURI);
+ trusts.add(t);
+ }
+ }
+
+ /**
+ * Builds and transfers a keystore with suitable credentials to the back-end
+ * workflow execution engine.
+ *
+ * @throws GeneralSecurityException
+ * If the manipulation of the keystore, keys or certificates
+ * fails.
+ * @throws IOException
+ * If there are problems building the data (should not happen).
+ * @throws RemoteException
+ * If the conveyancing fails.
+ */
+ @Override
+ public final void conveySecurity() throws GeneralSecurityException,
+ IOException, ImplementationException {
+ RemoteSecurityContext rc = run.run.getSecurityContext();
+
+ List<Trust> trusted = new ArrayList<>(this.trusted);
+ this.trusted.clear();
+ List<Credential> credentials = new ArrayList<>(this.credentials);
+ this.credentials.clear();
+
+ try {
+ installLocalPasswordCredential(credentials, trusted);
+ } catch (Exception e) {
+ log.warn("failed to construct local credential: "
+ + "interaction service will fail", e);
+ }
+
+ char[] password = null;
+ try {
+ password = generateNewPassword();
+
+ log.info("constructing merged keystore");
+ Truststore truststore = new Truststore(password);
+ Keystore keystore = new Keystore(password);
+ Map<URI, String> uriToAliasMap = new HashMap<>();
+ int trustedCount = 0, keyCount = 0;
+
+ synchronized (lock) {
+ try {
+ for (Trust t : trusted) {
+ if (t == null || t.loadedCertificates == null)
+ continue;
+ for (Certificate cert : t.loadedCertificates)
+ if (cert != null) {
+ truststore.addCertificate(cert);
+ trustedCount++;
+ }
+ }
+
+ this.uriToAliasMap = uriToAliasMap;
+ this.keystore = keystore;
+ for (Credential c : credentials) {
+ addCredentialToKeystore(c);
+ keyCount++;
+ }
+ } finally {
+ this.uriToAliasMap = null;
+ this.keystore = null;
+ credentials.clear();
+ trusted.clear();
+ flushToDB();
+ }
+ }
+
+ byte[] trustbytes = null, keybytes = null;
+ try {
+ trustbytes = truststore.serialize();
+ keybytes = keystore.serialize();
+
+ // Now we've built the security information, ship it off...
+
+ log.info("transfering merged truststore with " + trustedCount
+ + " entries");
+ rc.setTruststore(trustbytes);
+
+ log.info("transfering merged keystore with " + keyCount
+ + " entries");
+ rc.setKeystore(keybytes);
+ } finally {
+ if (trustbytes != null)
+ fill(trustbytes, (byte) 0);
+ if (keybytes != null)
+ fill(keybytes, (byte) 0);
+ }
+ rc.setPassword(password);
+
+ log.info("transferring serviceURL->alias map with "
+ + uriToAliasMap.size() + " entries");
+ rc.setUriToAliasMap(uriToAliasMap);
+ } finally {
+ if (password != null)
+ fill(password, ' ');
+ }
+
+ synchronized (lock) {
+ conveyExtraSecuritySettings(rc);
+ }
+ }
+
+ /**
+ * Hook that allows additional information to be conveyed to the remote run.
+ *
+ * @param remoteSecurityContext
+ * The remote resource that information would be passed to.
+ * @throws IOException
+ * If anything goes wrong with the communication.
+ */
+ protected void conveyExtraSecuritySettings(
+ RemoteSecurityContext remoteSecurityContext) throws IOException {
+ // Does nothing by default; overrideable
+ }
+
+ /**
+ * @return A new password with a reasonable level of randomness.
+ */
+ protected final char[] generateNewPassword() {
+ return randomUUID().toString().toCharArray();
+ }
+
+ /**
+ * Adds a credential to the current keystore.
+ *
+ * @param alias
+ * The alias to create within the keystore.
+ * @param c
+ * The key-pair.
+ * @throws KeyStoreException
+ */
+ protected final void addKeypairToKeystore(String alias, Credential c)
+ throws KeyStoreException {
+ if (c.loadedKey == null)
+ throw new KeyStoreException("critical: credential was not verified");
+ if (uriToAliasMap.containsKey(c.serviceURI))
+ log.warn("duplicate URI in alias mapping: " + c.serviceURI);
+ keystore.addKey(alias, c.loadedKey, c.loadedTrustChain);
+ uriToAliasMap.put(c.serviceURI, alias);
+ }
+
+ /**
+ * Adds a credential to the current keystore.
+ *
+ * @param c
+ * The credential to add.
+ * @throws KeyStoreException
+ */
+ public abstract void addCredentialToKeystore(Credential c)
+ throws KeyStoreException;
+
+ /**
+ * Read a file up to {@value #FILE_SIZE_LIMIT}kB in size.
+ *
+ * @param name
+ * The path name of the file, relative to the context run's
+ * working directory.
+ * @return A stream of the file's contents.
+ * @throws InvalidCredentialException
+ * If anything goes wrong.
+ */
+ final InputStream contents(String name) throws InvalidCredentialException {
+ try {
+ File f = (File) factory.fileUtils.getDirEntry(run, name);
+ long size = f.getSize();
+ if (size > CREDENTIAL_FILE_SIZE_LIMIT * 1024)
+ throw new InvalidCredentialException(CREDENTIAL_FILE_SIZE_LIMIT
+ + "kB limit hit");
+ return new ByteArrayInputStream(f.getContents(0, (int) size));
+ } catch (NoDirectoryEntryException | FilesystemAccessException e) {
+ throw new InvalidCredentialException(e);
+ } catch (ClassCastException e) {
+ throw new InvalidCredentialException("not a file", e);
+ }
+ }
+
+ @Override
+ public Set<String> getPermittedDestroyers() {
+ return run.getDestroyers();
+ }
+
+ @Override
+ public void setPermittedDestroyers(Set<String> destroyers) {
+ run.setDestroyers(destroyers);
+ }
+
+ @Override
+ public Set<String> getPermittedUpdaters() {
+ return run.getWriters();
+ }
+
+ @Override
+ public void setPermittedUpdaters(Set<String> updaters) {
+ run.setWriters(updaters);
+ }
+
+ @Override
+ public Set<String> getPermittedReaders() {
+ return run.getReaders();
+ }
+
+ @Override
+ public void setPermittedReaders(Set<String> readers) {
+ run.setReaders(readers);
+ }
+
+ /**
+ * Reinstall the credentials and the trust extracted from serialization to
+ * the database.
+ *
+ * @param credentials
+ * The credentials to reinstall.
+ * @param trust
+ * The trusted certificates to reinstall.
+ */
+ void setCredentialsAndTrust(Credential[] credentials, Trust[] trust) {
+ synchronized (lock) {
+ this.credentials.clear();
+ if (credentials != null)
+ for (Credential c : credentials)
+ try {
+ validateCredential(c);
+ this.credentials.add(c);
+ } catch (InvalidCredentialException e) {
+ log.warn("failed to revalidate credential: " + c, e);
+ }
+ this.trusted.clear();
+ if (trust != null)
+ for (Trust t : trust)
+ try {
+ validateTrusted(t);
+ this.trusted.add(t);
+ } catch (InvalidCredentialException e) {
+ log.warn("failed to revalidate trust assertion: " + t,
+ e);
+ }
+ }
+ }
+
+ static class SecurityStore {
+ private KeyStore ks;
+ private char[] password;
+
+ SecurityStore(char[] password) throws GeneralSecurityException {
+ this.password = password.clone();
+ ks = KeyStore.getInstance("UBER", "BC");
+ try {
+ ks.load(null, this.password);
+ } catch (IOException e) {
+ throw new GeneralSecurityException(
+ "problem initializing blank truststore", e);
+ }
+ }
+
+ final synchronized void setCertificate(String alias, Certificate c)
+ throws KeyStoreException {
+ if (ks == null)
+ throw new IllegalStateException("store already written");
+ ks.setCertificateEntry(alias, c);
+ }
+
+ final synchronized void setKey(String alias, Key key, Certificate[] trustChain)
+ throws KeyStoreException {
+ if (ks == null)
+ throw new IllegalStateException("store already written");
+ ks.setKeyEntry(alias, key, password, trustChain);
+ }
+
+ final synchronized byte[] serialize(boolean logIt)
+ throws GeneralSecurityException {
+ if (ks == null)
+ throw new IllegalStateException("store already written");
+ try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
+ ks.store(stream, password);
+ if (logIt)
+ LogFactory.getLog("Taverna.Server.Worker").debug(
+ "serialized UBER/BC truststore (size: " + ks.size()
+ + ") with password \""
+ + new String(password) + "\"");
+ return stream.toByteArray();
+ } catch (IOException e) {
+ throw new GeneralSecurityException(
+ "problem serializing keystore", e);
+ } finally {
+ ks = null;
+ fill(password, ' ');
+ }
+ }
+
+ @Override
+ protected final void finalize() {
+ fill(password, ' ');
+ ks = null;
+ }
+ }
+
+ /**
+ * A trust store that can only be added to or serialized. Only trusted
+ * certificates can be placed in it.
+ *
+ * @author Donal Fellows
+ */
+ class Truststore extends SecurityStore {
+ Truststore(char[] password) throws GeneralSecurityException {
+ super(password);
+ }
+
+ /**
+ * Add a trusted certificate to the truststore. No certificates can be
+ * added after the truststore is serialized.
+ *
+ * @param cert
+ * The certificate (typically belonging to a root CA) to add.
+ * @throws KeyStoreException
+ * If anything goes wrong.
+ */
+ public void addCertificate(Certificate cert) throws KeyStoreException {
+ X509Certificate c = (X509Certificate) cert;
+ String alias = format("trustedcert#%s#%s#%s",
+ getPrincipalName(c.getSubjectX500Principal()),
+ getPrincipalName(c.getIssuerX500Principal()),
+ factory.x500Utils.getSerial(c));
+ setCertificate(alias, c);
+ if (log.isDebugEnabled() && factory.logSecurityDetails)
+ log.debug("added cert with alias \"" + alias + "\" of type "
+ + c.getClass().getCanonicalName());
+ }
+
+ /**
+ * Get the byte serialization of this truststore. This can only be
+ * fetched exactly once.
+ *
+ * @return The serialization.
+ * @throws GeneralSecurityException
+ * If anything goes wrong.
+ */
+ public byte[] serialize() throws GeneralSecurityException {
+ return serialize(log.isDebugEnabled() && factory.logSecurityDetails);
+ }
+ }
+
+ /**
+ * A key store that can only be added to or serialized. Only keys can be
+ * placed in it.
+ *
+ * @author Donal Fellows
+ */
+ class Keystore extends SecurityStore {
+ Keystore(char[] password) throws GeneralSecurityException {
+ super(password);
+ }
+
+ /**
+ * Add a key to the keystore. No keys can be added after the keystore is
+ * serialized.
+ *
+ * @param alias
+ * The alias of the key.
+ * @param key
+ * The secret/private key to add.
+ * @param trustChain
+ * The trusted certificate chain of the key. Should be
+ * <tt>null</tt> for secret keys.
+ * @throws KeyStoreException
+ * If anything goes wrong.
+ */
+ public void addKey(String alias, Key key, Certificate[] trustChain)
+ throws KeyStoreException {
+ setKey(alias, key, trustChain);
+ if (log.isDebugEnabled() && factory.logSecurityDetails)
+ log.debug("added key with alias \"" + alias + "\" of type "
+ + key.getClass().getCanonicalName());
+ }
+
+ /**
+ * Get the byte serialization of this keystore. This can only be fetched
+ * exactly once.
+ *
+ * @return The serialization.
+ * @throws GeneralSecurityException
+ * If anything goes wrong.
+ */
+ public byte[] serialize() throws GeneralSecurityException {
+ return serialize(log.isDebugEnabled() && factory.logSecurityDetails);
+ }
+ }
+}
\ 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/worker/SecurityContextDelegateImpl.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java
new file mode 100644
index 0000000..d36d2da
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static java.lang.String.format;
+import static javax.xml.ws.handler.MessageContext.HTTP_REQUEST_HEADERS;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.rmi.RemoteException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.ws.handler.MessageContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.taverna.server.localworker.remote.RemoteSecurityContext;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.utils.UsernamePrincipal;
+import org.taverna.server.master.utils.X500Utils;
+
+/**
+ * Factoring out of the part of the security context handling that actually
+ * deals with the different types of credentials.
+ *
+ * @author Donal Fellows
+ */
+class SecurityContextDelegateImpl extends SecurityContextDelegate {
+ private static final char USERNAME_PASSWORD_SEPARATOR = '\u0000';
+ private static final String USERNAME_PASSWORD_KEY_ALGORITHM = "DUMMY";
+ /** What passwords are encoded as. */
+ private static final Charset UTF8 = Charset.forName("UTF-8");
+
+ private X500Utils x500Utils;
+
+ /**
+ * Initialise the context delegate.
+ *
+ * @param run
+ * What workflow run is this for?
+ * @param owner
+ * Who owns the workflow run?
+ * @param factory
+ * What class built this object?
+ */
+ protected SecurityContextDelegateImpl(RemoteRunDelegate run,
+ UsernamePrincipal owner, SecurityContextFactory factory) {
+ super(run, owner, factory);
+ this.x500Utils = factory.x500Utils;
+ }
+
+ @Override
+ public void validateCredential(Credential c)
+ throws InvalidCredentialException {
+ try {
+ if (c instanceof Credential.Password)
+ validatePasswordCredential((Credential.Password) c);
+ else if (c instanceof Credential.KeyPair)
+ validateKeyCredential((Credential.KeyPair) c);
+ else
+ throw new InvalidCredentialException("unknown credential type");
+ } catch (InvalidCredentialException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidCredentialException(e);
+ }
+ }
+
+ @Override
+ public void addCredentialToKeystore(Credential c) throws KeyStoreException {
+ try {
+ if (c instanceof Credential.Password)
+ addUserPassToKeystore((Credential.Password) c);
+ else if (c instanceof Credential.KeyPair)
+ addKeypairToKeystore((Credential.KeyPair) c);
+ else
+ throw new KeyStoreException("unknown credential type");
+ } catch (KeyStoreException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new KeyStoreException(e);
+ }
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ /**
+ * Tests whether the given username+password credential descriptor is valid.
+ * If it is invalid, an exception will be thrown describing what the problem
+ * is. Validation mainly consists of listing what the username is.
+ *
+ * @param passwordDescriptor
+ * The credential descriptor to validate.
+ * @throws InvalidCredentialException
+ * If the username is empty. NB: the password may be empty!
+ * That's legal (if unwise).
+ */
+ protected void validatePasswordCredential(
+ Credential.Password passwordDescriptor)
+ throws InvalidCredentialException {
+ if (passwordDescriptor.username == null
+ || passwordDescriptor.username.trim().isEmpty())
+ throw new InvalidCredentialException("absent or empty username");
+ if (passwordDescriptor.serviceURI == null)
+ throw new InvalidCredentialException("absent service URI");
+ String keyToSave = passwordDescriptor.username
+ + USERNAME_PASSWORD_SEPARATOR + passwordDescriptor.password;
+ passwordDescriptor.loadedKey = encodeKey(keyToSave);
+ passwordDescriptor.loadedTrustChain = null;
+ }
+
+ private static Key encodeKey(String key) {
+ return new SecretKeySpec(key.getBytes(UTF8),
+ USERNAME_PASSWORD_KEY_ALGORITHM);
+ }
+
+ /**
+ * Adds a username/password credential pair to the current keystore.
+ *
+ * @param userpassCredential
+ * The username and password.
+ * @throws KeyStoreException
+ */
+ protected void addUserPassToKeystore(Credential.Password userpassCredential)
+ throws KeyStoreException {
+ String alias = format("password#%s",
+ userpassCredential.serviceURI.toASCIIString());
+ addKeypairToKeystore(alias, userpassCredential);
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+ /**
+ * Tests whether the given key-pair credential descriptor is valid. If it is
+ * invalid, an exception will be thrown describing what the problem is.
+ *
+ * @param keypairDescriptor
+ * The descriptor to validate.
+ * @throws InvalidCredentialException
+ * If the descriptor is invalid
+ * @throws KeyStoreException
+ * If we don't understand the keystore type or the contents of
+ * the keystore
+ * @throws NoSuchAlgorithmException
+ * If the keystore is of a known type but we can't comprehend
+ * its security
+ * @throws CertificateException
+ * If the keystore does not include enough information about the
+ * trust chain of the keypair
+ * @throws UnrecoverableKeyException
+ * If we can't get the key out of the keystore
+ * @throws IOException
+ * If we can't read the keystore for prosaic reasons (e.g., file
+ * absent)
+ */
+ protected void validateKeyCredential(Credential.KeyPair keypairDescriptor)
+ throws InvalidCredentialException, KeyStoreException,
+ NoSuchAlgorithmException, CertificateException, IOException,
+ UnrecoverableKeyException {
+ if (keypairDescriptor.credentialName == null
+ || keypairDescriptor.credentialName.trim().isEmpty())
+ throw new InvalidCredentialException(
+ "absent or empty credentialName");
+
+ InputStream contentsAsStream;
+ if (keypairDescriptor.credentialBytes != null
+ && keypairDescriptor.credentialBytes.length > 0) {
+ contentsAsStream = new ByteArrayInputStream(
+ keypairDescriptor.credentialBytes);
+ keypairDescriptor.credentialFile = null;
+ } else if (keypairDescriptor.credentialFile == null
+ || keypairDescriptor.credentialFile.trim().isEmpty())
+ throw new InvalidCredentialException(
+ "absent or empty credentialFile");
+ else {
+ contentsAsStream = contents(keypairDescriptor.credentialFile);
+ keypairDescriptor.credentialBytes = new byte[0];
+ }
+ if (keypairDescriptor.fileType == null
+ || keypairDescriptor.fileType.trim().isEmpty())
+ keypairDescriptor.fileType = KeyStore.getDefaultType();
+ keypairDescriptor.fileType = keypairDescriptor.fileType.trim();
+
+ KeyStore ks = KeyStore.getInstance(keypairDescriptor.fileType);
+ char[] password = keypairDescriptor.unlockPassword.toCharArray();
+ ks.load(contentsAsStream, password);
+
+ try {
+ keypairDescriptor.loadedKey = ks.getKey(
+ keypairDescriptor.credentialName, password);
+ } catch (UnrecoverableKeyException ignored) {
+ keypairDescriptor.loadedKey = ks.getKey(
+ keypairDescriptor.credentialName, new char[0]);
+ }
+ if (keypairDescriptor.loadedKey == null)
+ throw new InvalidCredentialException(
+ "no such credential in key store");
+ keypairDescriptor.loadedTrustChain = ks
+ .getCertificateChain(keypairDescriptor.credentialName);
+ if (keypairDescriptor.loadedTrustChain == null
+ || keypairDescriptor.loadedTrustChain.length == 0)
+ throw new InvalidCredentialException(
+ "could not establish trust chain for credential");
+ }
+
+ /**
+ * Adds a key-pair to the current keystore.
+ *
+ * @param c
+ * The key-pair.
+ * @throws KeyStoreException
+ */
+ protected void addKeypairToKeystore(Credential.KeyPair c)
+ throws KeyStoreException {
+ X509Certificate subjectCert = (X509Certificate) c.loadedTrustChain[0];
+ String alias = format("keypair#%s#%s#%s",
+ getPrincipalName(subjectCert.getSubjectX500Principal()),
+ getPrincipalName(subjectCert.getIssuerX500Principal()),
+ x500Utils.getSerial(subjectCert));
+ addKeypairToKeystore(alias, c);
+ }
+}
+
+/**
+ * Special subclass that adds support for HELIO project security tokens.
+ *
+ * @author Donal Fellows
+ */
+class HelioSecurityContextDelegateImpl extends SecurityContextDelegateImpl {
+ /**
+ * Initialise the context delegate.
+ *
+ * @param run
+ * What workflow run is this for?
+ * @param owner
+ * Who owns the workflow run?
+ * @param factory
+ * What class built this object?
+ */
+ protected HelioSecurityContextDelegateImpl(RemoteRunDelegate run,
+ UsernamePrincipal owner, SecurityContextFactory factory) {
+ super(run, owner, factory);
+ }
+
+ private Log log = LogFactory.getLog("Taverna.Server.Worker");
+ /** The name of the HTTP header holding the CIS token. */
+ private static final String HELIO_CIS_TOKEN = "X-Helio-CIS";
+ private transient String helioToken;
+
+ @Override
+ public void initializeSecurityFromSOAPContext(MessageContext context) {
+ // does nothing
+ @SuppressWarnings("unchecked")
+ Map<String, List<String>> headers = (Map<String, List<String>>) context
+ .get(HTTP_REQUEST_HEADERS);
+ if (factory.supportHelioToken && headers.containsKey(HELIO_CIS_TOKEN))
+ helioToken = headers.get(HELIO_CIS_TOKEN).get(0);
+ }
+
+ @Override
+ public void initializeSecurityFromRESTContext(HttpHeaders context) {
+ // does nothing
+ MultivaluedMap<String, String> headers = context.getRequestHeaders();
+ if (factory.supportHelioToken && headers.containsKey(HELIO_CIS_TOKEN))
+ helioToken = headers.get(HELIO_CIS_TOKEN).get(0);
+ }
+
+ @Override
+ protected void conveyExtraSecuritySettings(RemoteSecurityContext rc)
+ throws RemoteException {
+ try {
+ if (factory.supportHelioToken && helioToken != null) {
+ if (factory.logSecurityDetails)
+ log.info("transfering HELIO CIS token: " + helioToken);
+ rc.setHelioToken(helioToken);
+ }
+ } finally {
+ helioToken = null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java
new file mode 100644
index 0000000..cbccf34
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static java.security.Security.addProvider;
+import static java.security.Security.getProvider;
+import static java.security.Security.removeProvider;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
+
+import java.io.Serializable;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.apache.commons.logging.Log;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.beans.factory.annotation.Value;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+import org.taverna.server.master.utils.CertificateChainFetcher;
+import org.taverna.server.master.utils.FilenameUtils;
+import org.taverna.server.master.utils.UsernamePrincipal;
+import org.taverna.server.master.utils.X500Utils;
+
+/**
+ * Singleton factory. Really is a singleton (and is also very trivial); the
+ * singleton-ness is just about limiting the number of instances of this around
+ * even when lots of serialization is going on.
+ *
+ * @see Serializable
+ * @author Donal Fellows
+ */
+public class SecurityContextFactory implements
+ org.taverna.server.master.interfaces.SecurityContextFactory {
+ private static final long serialVersionUID = 12345678987654321L;
+ private static SecurityContextFactory instance;
+ transient RunDBSupport db;
+ transient FilenameUtils fileUtils;
+ transient X500Utils x500Utils;
+ transient UriBuilderFactory uriSource;
+ transient CertificateChainFetcher certFetcher;
+ transient String httpRealm;
+ private transient PasswordIssuer passwordIssuer;
+ private transient BouncyCastleProvider provider;
+
+ /**
+ * Whether to support HELIO CIS tokens.
+ */
+ @Value("${helio.cis.enableTokenPassing}")
+ boolean supportHelioToken;
+
+ /**
+ * Whether to log the details of security (passwords, etc).
+ */
+ @Value("${log.security.details}")
+ boolean logSecurityDetails;
+
+ private Log log() {
+ return getLog("Taverna.Server.Worker.Security");
+ }
+
+ private void installAsInstance(SecurityContextFactory handle) {
+ instance = handle;
+ }
+
+ @PreDestroy
+ void removeAsSingleton() {
+ installAsInstance(null);
+ try {
+ if (provider != null)
+ removeProvider(provider.getName());
+ } catch (SecurityException e) {
+ log().warn(
+ "failed to remove BouncyCastle security provider; "
+ + "might be OK if configured in environment", e);
+ }
+ }
+
+ @PostConstruct
+ void setAsSingleton() {
+ installAsInstance(this);
+ if (getProvider(PROVIDER_NAME) == null)
+ try {
+ provider = new BouncyCastleProvider();
+ if (addProvider(provider) == -1)
+ provider = null;
+ } catch (SecurityException e) {
+ log().warn(
+ "failed to install BouncyCastle security provider; "
+ + "might be OK if already configured", e);
+ provider = null;
+ }
+ }
+
+ @Required
+ public void setRunDatabase(RunDBSupport db) {
+ this.db = db;
+ }
+
+ @Required
+ public void setCertificateFetcher(CertificateChainFetcher fetcher) {
+ this.certFetcher = fetcher;
+ }
+
+ @Required
+ public void setFilenameConverter(FilenameUtils fileUtils) {
+ this.fileUtils = fileUtils;
+ }
+
+ @Required
+ public void setX500Utils(X500Utils x500Utils) {
+ this.x500Utils = x500Utils;
+ }
+
+ @Required
+ public void setUriSource(UriBuilderFactory uriSource) {
+ this.uriSource = uriSource;
+ }
+
+ @Required
+ public void setHttpRealm(String realm) {
+ this.httpRealm = realm; //${http.realmName}
+ }
+
+ @Required
+ public void setPasswordIssuer(PasswordIssuer issuer) {
+ this.passwordIssuer = issuer;
+ }
+
+ @Override
+ public SecurityContextDelegate create(TavernaRun run,
+ UsernamePrincipal owner) throws Exception {
+ Log log = log();
+ if (log.isDebugEnabled())
+ log.debug("constructing security context delegate for " + owner);
+ RemoteRunDelegate rrd = (RemoteRunDelegate) run;
+ return new HelioSecurityContextDelegateImpl(rrd, owner, this);
+ }
+
+ private Object readResolve() {
+ if (instance == null)
+ installAsInstance(this);
+ return instance;
+ }
+
+ public String issueNewPassword() {
+ return passwordIssuer.issue();
+ }
+}
\ 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/worker/SimpleFormattedCompletionNotifier.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java
new file mode 100644
index 0000000..793d291
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static org.taverna.server.master.defaults.Default.NOTIFY_MESSAGE_FORMAT;
+
+import java.text.MessageFormat;
+
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Completion notifier that sends messages by email.
+ *
+ * @author Donal Fellows
+ */
+public class SimpleFormattedCompletionNotifier implements CompletionNotifier {
+ @Required
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @param subject
+ * The subject of the notification email.
+ */
+ @Required
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ /**
+ * @param messageFormat
+ * The template for the body of the message to send. Parameter #0
+ * will be substituted with the ID of the job, and parameter #1
+ * will be substituted with the exit code.
+ */
+ public void setMessageFormat(String messageFormat) {
+ this.format = new MessageFormat(messageFormat);
+ }
+
+ private String name;
+ private String subject;
+ private MessageFormat format = new MessageFormat(NOTIFY_MESSAGE_FORMAT);
+
+ @Override
+ public String makeCompletionMessage(String name, RemoteRunDelegate run,
+ int code) {
+ return format.format(new Object[] { name, code });
+ }
+
+ @Override
+ public String makeMessageSubject(String name, RemoteRunDelegate run,
+ int code) {
+ return subject;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
\ 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/worker/VelocityCompletionNotifier.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java
new file mode 100644
index 0000000..cf67853
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java
@@ -0,0 +1,105 @@
+package org.taverna.server.master.worker;
+
+import java.io.StringWriter;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.common.version.Version;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.UriBuilderFactory;
+
+public class VelocityCompletionNotifier implements CompletionNotifier {
+ private String subject;
+ private VelocityEngine engine;
+ private Template template;
+ private String name;
+ private String templateName;
+ private UriBuilderFactory ubf;
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param subject
+ * The subject of the notification email.
+ */
+ @Required
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ /**
+ * @param engine
+ * The configured Apache Velocity engine.
+ */
+ @Required
+ public void setVelocityEngine(VelocityEngine engine) {
+ this.engine = engine;
+ }
+
+ /**
+ * @param uriBuilderFactory
+ * The configured URI builder factory.
+ */
+ @Required
+ public void setUriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
+ this.ubf = uriBuilderFactory;
+ }
+
+ /**
+ * @param name
+ * The name of the template.
+ */
+ @Required
+ public void setName(String name) {
+ this.name = name;
+ this.templateName = getClass().getName() + "_" + name + ".vtmpl";
+ }
+
+ private Template getTemplate() {
+ if (template == null)
+ synchronized(this) {
+ if (template == null)
+ template = engine.getTemplate(templateName);
+ }
+ return template;
+ }
+
+ @Override
+ public String makeCompletionMessage(String name, RemoteRunDelegate run,
+ int code) {
+ VelocityContext ctxt = new VelocityContext();
+ ctxt.put("id", name);
+ ctxt.put("uriBuilder", ubf.getRunUriBuilder(run));
+ ctxt.put("name", run.getName());
+ ctxt.put("creationTime", run.getCreationTimestamp());
+ ctxt.put("startTime", run.getStartTimestamp());
+ ctxt.put("finishTime", run.getFinishTimestamp());
+ ctxt.put("expiryTime", run.getExpiry());
+ ctxt.put("serverVersion", Version.JAVA);
+ for (Listener l : run.getListeners())
+ if (l.getName().equals("io")) {
+ for (String p : l.listProperties())
+ try {
+ ctxt.put("prop_" + p, l.getProperty(p));
+ } catch (NoListenerException e) {
+ // Ignore...
+ }
+ break;
+ }
+ StringWriter sw = new StringWriter();
+ getTemplate().merge(ctxt, sw);
+ return sw.toString();
+ }
+
+ @Override
+ public String makeMessageSubject(String name, RemoteRunDelegate run,
+ int code) {
+ return subject;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java
new file mode 100644
index 0000000..1abe617
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2010-2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import java.net.URI;
+import java.util.List;
+
+import org.taverna.server.master.common.Status;
+
+/**
+ * Profile of the getters and setters in a worker system. Ensures that the
+ * persisted state matches the public view on the state model at least fairly
+ * closely.
+ *
+ * @author Donal Fellows
+ */
+public interface WorkerModel extends PolicyLimits {
+
+ /**
+ * @param defaultLifetime
+ * how long a workflow run should live by default, in minutes.
+ */
+ public abstract void setDefaultLifetime(int defaultLifetime);
+
+ /**
+ * @return how long a workflow run should live by default, in minutes.
+ */
+ public abstract int getDefaultLifetime();
+
+ /**
+ * @param maxRuns
+ * the maximum number of extant workflow runs
+ */
+ public abstract void setMaxRuns(int maxRuns);
+
+ /**
+ * @param factoryProcessNamePrefix
+ * the prefix used for factory processes in RMI
+ */
+ public abstract void setFactoryProcessNamePrefix(
+ String factoryProcessNamePrefix);
+
+ /**
+ * @return the prefix used for factory processes in RMI
+ */
+ public abstract String getFactoryProcessNamePrefix();
+
+ /**
+ * @param executeWorkflowScript
+ * the script to run to actually run a workflow
+ */
+ public abstract void setExecuteWorkflowScript(String executeWorkflowScript);
+
+ /**
+ * @return the script to run to actually run a workflow
+ */
+ public abstract String getExecuteWorkflowScript();
+
+ /**
+ * @param extraArgs
+ * the extra arguments to pass into the workflow runner
+ */
+ public abstract void setExtraArgs(String[] extraArgs);
+
+ /**
+ * @return the extra arguments to pass into the workflow runner
+ */
+ public abstract String[] getExtraArgs();
+
+ /**
+ * @param waitSeconds
+ * the number of seconds to wait for subprocesses to start
+ */
+ public abstract void setWaitSeconds(int waitSeconds);
+
+ /**
+ * @return the number of seconds to wait for subprocesses to start
+ */
+ public abstract int getWaitSeconds();
+
+ /**
+ * @param sleepMS
+ * milliseconds to wait between polling for a started
+ * subprocess's status
+ */
+ public abstract void setSleepMS(int sleepMS);
+
+ /**
+ * @return milliseconds to wait between polling for a started subprocess's
+ * status
+ */
+ public abstract int getSleepMS();
+
+ /**
+ * @param serverWorkerJar
+ * the full path name of the file system access worker
+ * subprocess's implementation JAR
+ */
+ public abstract void setServerWorkerJar(String serverWorkerJar);
+
+ /**
+ * @return the full path name of the file system access worker subprocess's
+ * implementation JAR
+ */
+ public abstract String getServerWorkerJar();
+
+ /**
+ * @param javaBinary
+ * the full path name to the Java binary to use
+ */
+ public abstract void setJavaBinary(String javaBinary);
+
+ /**
+ * @return the full path name to the Java binary to use
+ */
+ public abstract String getJavaBinary();
+
+ /**
+ * @param registryPort
+ * what port is the RMI registry on
+ */
+ public abstract void setRegistryPort(int registryPort);
+
+ /**
+ * @return what port is the RMI registry on
+ */
+ public abstract int getRegistryPort();
+
+ /**
+ * @param registryHost
+ * what host (network interface) is the RMI registry on
+ */
+ public abstract void setRegistryHost(String registryHost);
+
+ /**
+ * @return what host (network interface) is the RMI registry on
+ */
+ public abstract String getRegistryHost();
+
+ /**
+ * @param serverForkerJar
+ * the full path name of the impersonation engine's
+ * implementation JAR
+ */
+ public abstract void setServerForkerJar(String serverForkerJar);
+
+ /**
+ * @return the full path name of the impersonation engine's implementation
+ * JAR
+ */
+ public abstract String getServerForkerJar();
+
+ /**
+ * @param passwordFile
+ * the full path name of a file containing a password to use with
+ * sudo (or empty for none)
+ */
+ public abstract void setPasswordFile(String passwordFile);
+
+ /**
+ * @return the full path name of a file containing a password to use with
+ * sudo (or empty for none)
+ */
+ public abstract String getPasswordFile();
+
+ /**
+ * @param operatingLimit
+ * the maximum number of runs in the
+ * {@linkplain Status#Operating operating} state at once
+ */
+ public abstract void setOperatingLimit(int operatingLimit);
+
+ @Override
+ void setPermittedWorkflowURIs(List<URI> permittedWorkflows);
+
+ /**
+ * @return the full path name of the RMI registry subprocess's
+ * implementation JAR
+ */
+ String getRegistryJar();
+
+ /**
+ * @param rmiRegistryJar
+ * the full path name of the RMI registry subprocess's
+ * implementation JAR
+ */
+ void setRegistryJar(String rmiRegistryJar);
+
+ /**
+ * @return whether a run should generate provenance information by default
+ */
+ boolean getGenerateProvenance();
+
+ /**
+ * @param generateProvenance
+ * whether a run should generate provenance information by
+ * default
+ */
+ void setGenerateProvenance(boolean generateProvenance);
+}
\ 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/worker/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java
new file mode 100644
index 0000000..6007f88
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * A Taverna Server back-end that works by forking off workflow executors.
+ */
+package org.taverna.server.master.worker;
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/replacementscripts/executeworkflow.bat
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/replacementscripts/executeworkflow.bat b/taverna-server-webapp/src/main/replacementscripts/executeworkflow.bat
new file mode 100644
index 0000000..c678855
--- /dev/null
+++ b/taverna-server-webapp/src/main/replacementscripts/executeworkflow.bat
@@ -0,0 +1,25 @@
+@ECHO OFF
+
+REM Taverna startup script
+
+REM distribution directory
+set TAVERNA_HOME=%~dp0
+
+REM 300 MB memory, 140 MB for classes
+set ARGS=-Xmx300m -XX:MaxPermSize=140m
+
+REM Taverna system properties
+set ARGS=%ARGS% "-Draven.profile=file:%TAVERNA_HOME%conf/current-profile.xml"
+set ARGS=%ARGS% -Djava.system.class.loader=net.sf.taverna.raven.prelauncher.BootstrapClassLoader
+set ARGS=%ARGS% -Draven.launcher.app.main=net.sf.taverna.t2.commandline.CommandLineLauncher
+set ARGS=%ARGS% -Draven.launcher.show_splashscreen=false
+set ARGS=%ARGS% -Djava.awt.headless=true
+set ARGS=%ARGS% "-Dtaverna.startup=%TAVERNA_HOME%."
+IF NOT x%RAVEN_APPHOME%==x SET ARGS=%ARGS% "-Draven.launcher.app.home=%RAVEN_APPHOME%"
+IF NOT x%TAVERNA_RUN_ID%==x SET ARGS=%ARGS% "-Dtaverna.runid=%TAVERNA_RUN_ID%"
+IF NOT x%INTERACTION_HOST%==x SET ARGS=%ARGS% "-Dtaverna.interaction.host=%INTERACTION_HOST%"
+IF NOT x%INTERACTION_PORT%==x SET ARGS=%ARGS% "-Dtaverna.interaction.port=%INTERACTION_PORT%"
+IF NOT x%INTERACTION_WEBDAV%==x SET ARGS=%ARGS% "-Dtaverna.interaction.webdav_path=%INTERACTION_WEBDAV%"
+IF NOT x%INTERACTION_FEED%==x SET ARGS=%ARGS% "-Dtaverna.interaction.feed_path=%INTERACTION_FEED%"
+
+java %ARGS% -jar "%TAVERNA_HOME%lib\prelauncher-2.3.jar" %*
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/replacementscripts/executeworkflow.sh
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/replacementscripts/executeworkflow.sh b/taverna-server-webapp/src/main/replacementscripts/executeworkflow.sh
new file mode 100644
index 0000000..e9e1d36
--- /dev/null
+++ b/taverna-server-webapp/src/main/replacementscripts/executeworkflow.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+set -e
+
+# 300 MB memory, 140 MB for classes
+memlimit=-Xmx300m
+permsize=-XX:MaxPermSize=140m
+
+## Parse the command line to extract the pieces to move around to before or
+## after the JAR filename...
+pre=-Djava.awt.headless=true
+post=
+for arg
+do
+ case $arg in
+ -JXmx*) memlimit=`echo $arg | sed 's/-JX/-X/'` ;;
+ -JXX:MaxPermSize=*) permsize=`echo $arg | sed 's/-JXX/-XX/'` ;;
+ -J*) pre="$pre `echo $arg | sed 's/-J/-/'`" ;;
+ -D*) pre="$pre $arg" ;;
+ *) post="$post \"$arg\"" ;;
+ esac
+done
+if test "xx" = "x${post}x"; then
+ echo "Missing arguments! Bug in argument processing?" >&2
+ exit 1
+fi
+eval set x $post
+shift
+
+## resolve links - $0 may be a symlink
+prog="$0"
+
+real_path() {
+ readlink -m "$1" 2>/dev/null || python -c 'import os,sys;print os.path.realpath(sys.argv[1])' "$1"
+}
+
+realprog=`real_path "$prog"`
+taverna_home=`dirname "$realprog"`
+javabin=java
+if test -x "$JAVA_HOME/bin/java"; then
+ javabin="$JAVA_HOME/bin/java"
+fi
+APPHOME_PROP=
+if test x != "x$TAVERNA_APPHOME"; then
+ APPHOME_PROP="-Dtaverna.app.home=$TAVERNA_APPHOME"
+fi
+RUNID_PROP=
+if test x != "x$TAVERNA_RUN_ID"; then
+ RUNID_PROP="-Dtaverna.runid=$TAVERNA_RUN_ID"
+fi
+INTERACTION_PROPS=-Dtaverna.interaction.ignore_requests=true
+if test x != "x$INTERACTION_HOST"; then
+ INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.host=$INTERACTION_HOST"
+ INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.port=$INTERACTION_PORT"
+ INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.webdav_path=$INTERACTION_WEBDAV"
+ INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.feed_path=$INTERACTION_FEED"
+ if test x != "x$INTERACTION_PUBLISH"; then
+ INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.publishAddressOverride=$INTERACTION_PUBLISH"
+ fi
+fi
+
+MainClass=net.sf.taverna.t2.commandline.CommandLineLauncher
+
+echo "pid:$$"
+exec "$javabin" $memlimit $permsize \
+ "-Dlog4j.configuration=file://$taverna_home/conf/log4j.properties " \
+ "-Djava.util.logging.config.file=$taverna_home/conf/logging.properties " \
+ "-Dtaverna.app.startup=$taverna_home" -Dtaverna.interaction.ignore_requests=true \
+ $APPHOME_PROP $RUNID_PROP $INTERACTION_PROPS -Djava.awt.headless=true \
+ -Dcom.sun.net.ssl.enableECC=false -Djsse.enableSNIExtension=false $pre \
+ -jar "$taverna_home/lib/taverna-command-line-0.1.1.jar" \
+ ${1+"$@"}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/admin.html
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/admin.html b/taverna-server-webapp/src/main/resources/admin.html
new file mode 100644
index 0000000..a80a783
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/admin.html
@@ -0,0 +1,240 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Taverna Server ${project.version} Administration Interface</title>
+<link id="admin" href="admin" />
+<script type="text/javascript" src="admin/static/jquery-1.8.0.min.js"></script>
+<script type="text/javascript" src="admin/static/jquery-ui-1.8.23.custom.min.js"></script>
+<script type="text/javascript" src="admin/static/admin.js"></script>
+<link href="admin/static/jquery-ui-1.8.23.custom.css" rel="stylesheet" type="text/css" />
+
+</head>
+<body>
+<img height="70" style="float:left" src="admin/static/t2cogs.png">
+<h1>Taverna Server ${project.version} Administration Interface</h1>
+<br clear="left"/>
+<div id="body">
+<ul>
+ <li><a href="#t-global">Global Settings</a></li>
+ <li><a href="#t-users">Users</a></li>
+ <li><a href="#t-workflows">Workflows</a></li>
+ <li><a href="#t-usage">Usage Records</a></li>
+ <li><a href="#t-worker">Local Worker Configuration</a></li>
+</ul>
+
+<div id="t-global">
+<label title="The number of invocations of the main interface webapp that have been done. Be aware that one service call can result in many invocations due to resource resolution." for="invokationCount">Invocation Count:</label>
+<span title="The number of invocations of the main interface webapp that have been done. Be aware that one service call can result in many invocations due to resource resolution." id="invokationCount">0</span>
+<br>
+<label title="The number of runs that currently exist." for="runCount">Run Count:</label>
+<span title="The number of runs that currently exist." id="runCount">0</span>
+<br>
+<label title="The number of runs that are currently operating." for="operatingCount">Operating Run Count:</label>
+<span title="The number of runs that are currently operating." id="operatingCount">0</span>
+<br>
+<label title="Whether workflow runs should create provenance traces by default. Users can explicitly override this." for="generateProvenance">Generate Provenance by Default</label>
+<input type="checkbox" id="generateProvenance" />
+<br>
+<label title="The time it took for the back-end engine to start up, in seconds. Should usually be short." for="startupTime">Back-End Startup Time (seconds):</label>
+<span title="The time it took for the back-end engine to start up, in seconds. Should usually be short." id="startupTime">0</span>
+<br>
+<label title="The exit code from the last time the back-end was shut down. Blank if the back end has never been shut down while the current webapp instance is running (i.e., since the last boot of the container)." for="lastExitCode">Back-End Last Exit Code:</label>
+<span title="The exit code from the last time the back-end was shut down. Blank if the back end has never been shut down while the current webapp instance is running (i.e., since the last boot of the container)." id="lastExitCode"></span>
+<p>
+<label title="Whether new workflow runs should be created. Disabling this does not prevent existing runs from executing." for="allowNew">Allow New Runs</label>
+<input type="checkbox" id="allowNew" />
+<label title="Whether to record the workflows being run by users. Very noisy due to length of workflow documents, occasionally useful." for="logWorkflows">Log Executed Workflows</label>
+<input type="checkbox" id="logWorkflows" />
+<label title="Whether to record exceptions generated by users in the code (as well as converting them to faults and error responses). Useful for debugging, but noisy." for="logFaults">Log User Exceptions</label>
+<input type="checkbox" id="logFaults" />
+<p>
+<label title="The maximum number of workflow runs that can exist at once, in any state." for="runLimit">Maximum Simultaneous Existing Workflow Runs</label>
+<input title="The maximum number of workflow runs that can exist at once, in any state." id="runLimit" size="3" />
+<br>
+<label title="The maximum number of workflow runs that can be executing at once." for="operatingLimit">Maximum Simultaneous Executing Workflow Runs</label>
+<input title="The maximum number of workflow runs that can be executing at once." id="operatingLimit" size="3" />
+<br>
+<label title="How long to allow a workflow to execute for by default (clients can change this), in minutes." for="defaultLifetime">Default Run Lifetime (minutes)</label>
+<input title="How long to allow a workflow to execute for by default (clients can change this), in minutes." id="defaultLifetime" size="7" />
+</div><!-- t-global -->
+
+<div id="t-users">
+<table id="userList">
+ <tr><th>Username<th>System Username</tr>
+</table>
+<h3>Add a user</h3>
+<table border=1>
+ <tr>
+ <td><label title="The user name to create." for="newUsername">Username</label>
+ <td><input title="The user name to create." size=12 id="newUsername" />
+ </tr>
+ <tr>
+ <td><label title="The password to use for the user." for="newPassword">Password</label>
+ <td><input title="The password to use for the user." size=12 id="newPassword" type="password"/>
+ </tr>
+ <tr>
+ <td><label title="The system account to run the user's workflows in; leave blank for the default." for="newSysID">System ID</label>
+ <td><input title="The system account to run the user's workflows in; leave blank for the default." size=12 id="newSysID" />
+ </tr>
+ <tr><td colspan=2>
+ <label title="Whether to allow this user to log in at all." for="newEnabled">Enabled</label>
+ <input type="checkbox" id="newEnabled" />
+ <label title="Whether the user has administrative privileges (can see all workflow runs, can access the administration page)." for="newAdmin">Admin</label>
+ <input type="checkbox" id="newAdmin" />
+ </td></tr>
+ <tr><td colspan=2>
+ <button id="makeNewUser">Create a new user</button>
+ </td></tr>
+</table>
+</div><!-- t-users -->
+
+<div id="t-workflows">
+<label title="Workflow URIs to limit execution to." for="workflows">Workflow URIs (one per line)</label>
+<br>
+<textarea title="Workflow URIs to limit execution to." rows="5" cols="60" id="workflows"></textarea>
+<p>
+<button id="saveWorkflows">Save</button> <button id="refreshWorkflows">Refresh</button> <button id="emptyWorkflows">Empty URIs list</button>
+</div>
+
+<div id="t-usage">
+Download <a href="#" id="ur">usage records</a> (warning: may be slow!)
+<p>
+<label title="The name of a file to write usage records to. Note that this file will end up containing many XML documents concatenated together; it is up to you to split them up as necessary. Each record is only written as it is generated; this does not produce historic data." for="usageRecordDumpFile">Usage Record Dump File</label>
+<input title="The name of a file to write usage records to. Note that this file will end up containing many XML documents concatenated together; it is up to you to split them up as necessary. Each record is only written as it is generated; this does not produce historic data." id="usageRecordDumpFile" size="50" />
+</div><!-- t-usage -->
+
+<div id="t-worker">
+ <div id="a-worker">
+
+ <h3><a href="#">Subprocess Implementation Control</a></h3>
+ <div>
+ <table>
+ <tr>
+ <td> <label title="The full path of the Java executable to use. Normally set correct by default." for="javaBinary">Java Executable (for subprocesses):</label> </td>
+ <td> <input title="The full path of the Java executable to use. Normally set correct by default." id="javaBinary" size="80" /> </td>
+ </tr>
+ <tr>
+ <td> <label title="The full path of the secure subprocess fork engine to use. Normally set correct by default." for="serverForkerJar">Subprocess Factory JAR:</label> </td>
+ <td> <input title="The full path of the secure subprocess fork engine to use. Normally set correct by default." id="serverForkerJar" size="80" /> </td>
+ </tr>
+ <tr>
+ <td> <label title="The full path of a file containing the credentials to use with sudo. Leave blank to use a password-less connection (see documentation for how to configure)." for="runasPasswordFile">File with password for sudo:</label> </td>
+ <td> <input title="The full path of a file containing the credentials to use with sudo. Leave blank to use a password-less connection (see documentation for how to configure)." id="runasPasswordFile" size="80" /> </td>
+ </tr>
+ <tr>
+ <td> <label title="The full path of the user filesystem access and workflow initiation engine to use. Normally set correct by default." for="serverWorkerJar">User Filesystem Access JAR:</label> </td>
+ <td> <input title="The full path of the user filesystem access and workflow initiation engine to use. Normally set correct by default." id="serverWorkerJar" size="80" /> </td>
+ </tr>
+ <tr>
+ <td> <label title="The full path of the workflow engine executable. Normally set correctly by default." for="executeWorkflowScript">Workflow Engine Executable:</label> </td>
+ <td> <input title="The full path of the workflow engine executable. Normally set correctly by default." id="executeWorkflowScript" size="80" /> </td>
+ </tr>
+ </table>
+ </div>
+
+ <h3><a href="#">Worker Registration Control</a></h3>
+ <div>
+ <label title="The machine hosting the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" for="registryHost">Registry Host</label>
+ <input title="The machine hosting the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" id="registryHost" size="20" />
+ <label title="The port number the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" for="registryPort">Port</label>
+ <input title="The port number the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" id="registryPort" size="5" />
+ <br>
+ <label title="The full path of the RMI registry implementation JAR file. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" for="registryJar">RMI Registry JAR</label>
+ <input title="The full path of the RMI registry implementation JAR file. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" id="registryJar" size="80" />
+ <br>
+ <label title="The time to wait (in seconds) for the back-end processes to boot and register themselves with the RMI registry. Busy machines may need a longer value here." for="registrationWaitSeconds">Time to wait for registration (seconds)</label>
+ <input title="The time to wait (in seconds) for the back-end processes to boot and register themselves with the RMI registry. Busy machines may need a longer value here." id="registrationWaitSeconds" size="5" />
+ <br>
+ <label title="How long to wait (in milliseconds) between probes to the registry to detect the registration of a back-end process." for="registrationPollMillis">Time to wait between polling to
+ detect registration (milliseconds)</label>
+ <input title="How long to wait (in milliseconds) between probes to the registry to detect the registration of a back-end process." id="registrationPollMillis" size="5" />
+ </div>
+
+ <h3><a href="#">System User/Factory ID Mapping</a></h3>
+ <div>
+ <table title="The mapping of system user IDs to factory identifiers (used in the RMI registry). Note that this is read-only." id="factoryProcessMapping" border="1">
+ </table>
+ </div>
+
+ <h3><a href="#">Extra Workflow Engine Configuration</a></h3>
+ <div>
+ <h4>System Properties</h4>
+ <table id="extraArguments-prop">
+ <tr><td></td><td><button title="Add a system property to pass to the back-end engine." id="extra-prop-add">Add System Property</button></td></tr>
+ </table>
+ <h4>Environment Variables</h4>
+ <table id="extraArguments-env">
+ <tr><td></td><td><button title="Add an environment variable to pass to the back-end engine." id="extra-env-add">Add Environment Variable</button></td></tr>
+ </table>
+ <h4>Java Runtime Configuration</h4>
+ <table id="extraArguments-runtime">
+ <tr><td></td><td><button title="Add a Java runtime parameter (e.g., Xmx=400m to set the memory usage limit to 400MB) to pass to the back-end engine. Note the lack of a leading '-' character!" id="extra-run-add">Add Runtime Configuration</button></td></tr>
+ </table>
+ </div>
+
+ </div><!-- a-worker -->
+</div><!-- t-worker -->
+
+</div>
+
+<hr>
+<address>Donal Fellows / University of Manchester</address>
+
+<!-- DIALOG BOXES -->
+<div id="dialog-confirm" title="Delete user?" style="display: none">
+ <p>
+ <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
+ This user will be permanently deleted from the system. Are you sure?
+ </p>
+</div>
+
+<div id="dialog-password" title="Change password?" style="display: none">
+ <p>
+ <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
+ This will permanently change the user's password. Make sure you wish
+ to do this.
+ </p>
+ <p>
+ <input title="New password" id="change-password" type="password" size="12" />
+ <br>
+ Please repeat it to be sure...
+ <br>
+ <input title="New password (again)" id="change-password2" type="password" size="12" />
+ </p>
+</div>
+
+<div id="dialog-environment" title="Set environment variable?" style="display: none">
+ <p>
+ <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
+ Set an environment variable to be passed to the workflow engine.
+ </p>
+ <p>
+ <input title="Environment variable name" id="env-key" size="15" /> =
+ <input title="Environment variable value" id="env-value" size="20" />
+ </p>
+</div>
+
+<div id="dialog-runtime" title="Set runtime configuration?" style="display: none">
+ <p>
+ <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
+ Set a runtime parameter (e.g., -Xmx400m for a 400MB memory limit) for the Java runtime.
+ </p>
+ <p>
+ <input title="Java runtime configuration parameter" id="runtime-value" size="20" />
+ </p>
+</div>
+
+<div id="dialog-property" title="Set runtime property?" style="display: none">
+ <p>
+ <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
+ Set a configuration property for the Java runtime.
+ </p>
+ <p>
+ <input title="System property name" id="prop-key" size="15" /> =
+ <input title="System property value" id="prop-value" size="20" />
+ </p>
+</div>
+
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/capabilities.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/capabilities.properties b/taverna-server-webapp/src/main/resources/capabilities.properties
new file mode 100644
index 0000000..2b4844f
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/capabilities.properties
@@ -0,0 +1,38 @@
+# This is currently a hand-curated list. This sucks!
+
+######## --- PLATFORM --- ########
+http\://ns.taverna.org.uk/2013/software/taverna = 2.5
+
+######## --- OUTPUTS/PROVENANCE --- ########
+http\://ns.taverna.org.uk/2013/bundle/run = 1.0
+http\://ns.taverna.org.uk/2013/provenance/prov = 1.0
+
+######## --- ACTIVITIES --- ########
+http\://ns.taverna.org.uk/2010/activity/nested-workflow = 1.5
+http\://ns.taverna.org.uk/2010/activity/apiconsumer = 1.5
+http\://ns.taverna.org.uk/2010/activity/beanshell = 1.5
+http\://ns.taverna.org.uk/2010/activity/localworker = 1.5
+http\://ns.taverna.org.uk/2010/activity/biomart = 1.5
+http\://ns.taverna.org.uk/2010/activity/biomoby/object = 1.5
+http\://ns.taverna.org.uk/2010/activity/biomoby/service = 1.5
+http\://ns.taverna.org.uk/2010/activity/rshell = 1.5
+http\://ns.taverna.org.uk/2010/activity/soaplab = 1.5
+http\://ns.taverna.org.uk/2010/activity/spreadsheet-import = 1.5
+http\://ns.taverna.org.uk/2010/activity/constant = 1.5
+http\://ns.taverna.org.uk/2010/activity/component = 1.5
+http\://ns.taverna.org.uk/2010/activity/wsdl = 1.5
+http\://ns.taverna.org.uk/2010/activity/wsdl/xml-splitter/in = 1.5
+http\://ns.taverna.org.uk/2010/activity/wsdl/xml-splitter/out = 1.5
+http\://ns.taverna.org.uk/2010/activity/tool = 1.5
+http\://ns.taverna.org.uk/2010/activity/rest = 1.5
+http\://ns.taverna.org.uk/2010/activity/xpath = 1.5
+http\://ns.taverna.org.uk/2010/activity/webdav = 1.5
+http\://ns.taverna.org.uk/2010/activity/interaction = 1.5
+
+######## --- DISPATCH LAYERS --- ########
+http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/ErrorBounce = 1.5
+http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Failover = 1.5
+http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Invoke = 1.5
+http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Loop = 1.5
+http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Parallelize = 1.5
+http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Retry = 1.5
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/log4j.properties b/taverna-server-webapp/src/main/resources/log4j.properties
new file mode 100644
index 0000000..ea0ea12
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/log4j.properties
@@ -0,0 +1,39 @@
+log4j.rootLogger=info, R
+log4j.category.DataNucleus.Query=warn
+#log4j.category.DataNucleus.Datastore.Schema=debug
+#log4j.logger.org.springframework.security=DEBUG
+#log4j.category.Taverna=debug
+
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=${catalina.home}/logs/tavserv.out
+log4j.appender.R.MaxFileSize=10MB
+log4j.appender.R.MaxBackupIndex=30
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
+
+#log4j.category.Taverna=INFO, A1
+#log4j.category.Taverna.Server.LocalWorker.RunDB=INFO
+#log4j.category.Taverna.Server.Webapp=INFO
+#log4j.category.Taverna.Server.LocalWorker.Policy=INFO
+#log4j.category.Taverna.Server.LocalWorker.Security=INFO
+## Swallow Derby's messages
+#log4j.category.Derby=WARN, B2
+## Will you _shut up_, DataNucleus! <hits with rolled-up newspaper>
+#log4j.category.DataNucleus=WARN, B2
+##log4j.category.DataNucleus.SchemaTool=DEBUG
+##log4j.category.DataNucleus.Datastore.Schema=DEBUG
+##log4j.category.DataNucleus.Datastore.Native=DEBUG
+##log4j.logger.org.springframework.security=DEBUG, B2
+#log4j.category.org.springframework=INFO, B2
+#log4j.category.org.apache.cxf=INFO, B2
+#log4j.category.org.apache.cxf.jaxrs.utils.JAXRSUtils=INFO
+#log4j.category.eu.medsea=INFO, B2
+#log4j.category.org.apache.axiom=INFO, B2
+## Appender for Taverna Server components
+#log4j.appender.A1=org.apache.log4j.ConsoleAppender
+#log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+#log4j.appender.A1.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
+## Appender for Framework components
+#log4j.appender.B2=org.apache.log4j.ConsoleAppender
+#log4j.appender.B2.layout=org.apache.log4j.PatternLayout
+#log4j.appender.B2.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} - %m%n
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/security.policy
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/security.policy b/taverna-server-webapp/src/main/resources/security.policy
new file mode 100644
index 0000000..1ec4166
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/security.policy
@@ -0,0 +1,3 @@
+grant {
+ permission java.security.AllPermission "*:*";
+};
[25/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
deleted file mode 100644
index adf3ea7..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/LocalWorker.java
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.lang.Runtime.getRuntime;
-import static java.lang.System.getProperty;
-import static java.lang.System.out;
-import static java.lang.management.ManagementFactory.getRuntimeMXBean;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.UUID.randomUUID;
-import static org.apache.commons.io.FileUtils.forceDelete;
-import static org.apache.commons.io.FileUtils.forceMkdir;
-import static org.apache.commons.io.FileUtils.writeByteArrayToFile;
-import static org.apache.commons.io.FileUtils.writeLines;
-import static org.taverna.server.localworker.api.Constants.HELIO_TOKEN_NAME;
-import static org.taverna.server.localworker.api.Constants.KEYSTORE_FILE;
-import static org.taverna.server.localworker.api.Constants.KEYSTORE_PASSWORD;
-import static org.taverna.server.localworker.api.Constants.SECURITY_DIR_NAME;
-import static org.taverna.server.localworker.api.Constants.SHARED_DIR_PROP;
-import static org.taverna.server.localworker.api.Constants.SUBDIR_LIST;
-import static org.taverna.server.localworker.api.Constants.SYSTEM_ENCODING;
-import static org.taverna.server.localworker.api.Constants.TRUSTSTORE_FILE;
-import static org.taverna.server.localworker.impl.utils.FilenameVerifier.getValidatedFile;
-import static org.taverna.server.localworker.remote.RemoteStatus.Finished;
-import static org.taverna.server.localworker.remote.RemoteStatus.Initialized;
-import static org.taverna.server.localworker.remote.RemoteStatus.Operating;
-import static org.taverna.server.localworker.remote.RemoteStatus.Stopped;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.api.WorkerFactory;
-import org.taverna.server.localworker.remote.IllegalStateTransitionException;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteInput;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteSecurityContext;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.remote.StillWorkingOnItException;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-/**
- * This class implements one side of the connection between the Taverna Server
- * master server and this process. It delegates to a {@link Worker} instance the
- * handling of actually running a workflow.
- *
- * @author Donal Fellows
- * @see DirectoryDelegate
- * @see FileDelegate
- * @see WorkerCore
- */
-@SuppressWarnings("serial")
-public class LocalWorker extends UnicastRemoteObject implements RemoteSingleRun {
- // ----------------------- CONSTANTS -----------------------
-
- /** Handle to the directory containing the security info. */
- static final File SECURITY_DIR;
- static final String SLASHTEMP;
- static {
- SLASHTEMP = getProperty("java.io.tmpdir");
- File home = new File(getProperty("user.home"));
- // If we can't write to $HOME (i.e., we're in an odd deployment) use
- // the official version of /tmp/$PID as a fallback.
- if (!home.canWrite())
- home = new File(SLASHTEMP, getRuntimeMXBean().getName());
- SECURITY_DIR = new File(home, SECURITY_DIR_NAME);
- }
-
- // ----------------------- VARIABLES -----------------------
-
- /**
- * Magic flag used to turn off problematic code when testing inside CI
- * environment.
- */
- static boolean DO_MKDIR = true;
-
- /** What to use to run a workflow engine. */
- private final String executeWorkflowCommand;
- /** What workflow to run. */
- private final byte[] workflow;
- /** The remote access object for the working directory. */
- private final DirectoryDelegate baseDir;
- /** What inputs to pass as files. */
- final Map<String, String> inputFiles;
- /** What inputs to pass as files (as file refs). */
- final Map<String, File> inputRealFiles;
- /** What inputs to pass as direct values. */
- final Map<String, String> inputValues;
- /** What delimiters to use. */
- final Map<String, String> inputDelimiters;
- /** The interface to the workflow engine subprocess. */
- private final Worker core;
- /** Our descriptor token (UUID). */
- private final String masterToken;
- /**
- * The root working directory for a workflow run, or <tt>null</tt> if it has
- * been deleted.
- */
- private File base;
- /**
- * When did this workflow start running, or <tt>null</tt> for
- * "never/not yet".
- */
- private Date start;
- /**
- * When did this workflow finish running, or <tt>null</tt> for
- * "never/not yet".
- */
- private Date finish;
- /** The cached status of the workflow run. */
- RemoteStatus status;
- /**
- * The name of the input Baclava document, or <tt>null</tt> to not do it
- * that way.
- */
- String inputBaclava;
- /**
- * The name of the output Baclava document, or <tt>null</tt> to not do it
- * that way.
- */
- String outputBaclava;
- /**
- * The file containing the input Baclava document, or <tt>null</tt> to not
- * do it that way.
- */
- private File inputBaclavaFile;
- /**
- * The file containing the output Baclava document, or <tt>null</tt> to not
- * do it that way.
- */
- private File outputBaclavaFile;
- /**
- * Registered shutdown hook so that we clean up when this process is killed
- * off, or <tt>null</tt> if that is no longer necessary.
- */
- Thread shutdownHook;
- /** Location for security information to be written to. */
- File securityDirectory;
- /**
- * Password to use to encrypt security information.
- */
- char[] keystorePassword = KEYSTORE_PASSWORD;
- /** Additional server-specified environment settings. */
- Map<String, String> environment = new HashMap<>();
- /** Additional server-specified java runtime settings. */
- List<String> runtimeSettings = new ArrayList<>();
- URL interactionFeedURL;
- URL webdavURL;
- URL publishURL;//FIXME
- private boolean doProvenance = true;
-
- // ----------------------- METHODS -----------------------
-
- /**
- * @param executeWorkflowCommand
- * The script used to execute workflows.
- * @param workflow
- * The workflow to execute.
- * @param workerClass
- * The class to instantiate as our local representative of the
- * run.
- * @param urReceiver
- * The remote class to report the generated usage record(s) to.
- * @param id
- * The UUID to use, or <tt>null</tt> if we are to invent one.
- * @param seedEnvironment
- * The key/value pairs to seed the worker subprocess environment
- * with.
- * @param javaParams
- * Parameters to pass to the worker subprocess java runtime
- * itself.
- * @param workerFactory
- * How to make instances of the low-level worker objects.
- * @throws RemoteException
- * If registration of the worker fails.
- * @throws ImplementationException
- * If something goes wrong during local setup.
- */
- protected LocalWorker(String executeWorkflowCommand, byte[] workflow,
- UsageRecordReceiver urReceiver, UUID id,
- Map<String, String> seedEnvironment, List<String> javaParams,
- WorkerFactory workerFactory) throws RemoteException,
- ImplementationException {
- super();
- if (id == null)
- id = randomUUID();
- masterToken = id.toString();
- this.workflow = workflow;
- this.executeWorkflowCommand = executeWorkflowCommand;
- String sharedDir = getProperty(SHARED_DIR_PROP, SLASHTEMP);
- base = new File(sharedDir, masterToken);
- out.println("about to create " + base);
- try {
- forceMkdir(base);
- for (String subdir : SUBDIR_LIST) {
- new File(base, subdir).mkdir();
- }
- } catch (IOException e) {
- throw new ImplementationException(
- "problem creating run working directory", e);
- }
- baseDir = new DirectoryDelegate(base, null);
- inputFiles = new HashMap<>();
- inputRealFiles = new HashMap<>();
- inputValues = new HashMap<>();
- inputDelimiters = new HashMap<>();
- environment.putAll(seedEnvironment);
- runtimeSettings.addAll(javaParams);
- try {
- core = workerFactory.makeInstance();
- } catch (Exception e) {
- out.println("problem when creating core worker implementation");
- e.printStackTrace(out);
- throw new ImplementationException(
- "problem when creating core worker implementation", e);
- }
- core.setURReceiver(urReceiver);
- Thread t = new Thread(new Runnable() {
- /**
- * Kill off the worker launched by the core.
- */
- @Override
- public void run() {
- try {
- shutdownHook = null;
- destroy();
- } catch (ImplementationException e) {
- // Absolutely nothing we can do here
- }
- }
- });
- getRuntime().addShutdownHook(t);
- shutdownHook = t;
- status = Initialized;
- }
-
- @Override
- public void destroy() throws ImplementationException {
- killWorkflowSubprocess();
- removeFromShutdownHooks();
- // Is this it?
- deleteWorkingDirectory();
- deleteSecurityManagerDirectory();
- core.deleteLocalResources();
- }
-
- private void killWorkflowSubprocess() {
- if (status != Finished && status != Initialized)
- try {
- core.killWorker();
- if (finish == null)
- finish = new Date();
- } catch (Exception e) {
- out.println("problem when killing worker");
- e.printStackTrace(out);
- }
- }
-
- private void removeFromShutdownHooks() throws ImplementationException {
- try {
- if (shutdownHook != null)
- getRuntime().removeShutdownHook(shutdownHook);
- } catch (RuntimeException e) {
- throw new ImplementationException("problem removing shutdownHook",
- e);
- } finally {
- shutdownHook = null;
- }
- }
-
- private void deleteWorkingDirectory() throws ImplementationException {
- try {
- if (base != null)
- forceDelete(base);
- } catch (IOException e) {
- out.println("problem deleting working directory");
- e.printStackTrace(out);
- throw new ImplementationException(
- "problem deleting working directory", e);
- } finally {
- base = null;
- }
- }
-
- private void deleteSecurityManagerDirectory()
- throws ImplementationException {
- try {
- if (securityDirectory != null)
- forceDelete(securityDirectory);
- } catch (IOException e) {
- out.println("problem deleting security directory");
- e.printStackTrace(out);
- throw new ImplementationException(
- "problem deleting security directory", e);
- } finally {
- securityDirectory = null;
- }
- }
-
- @Override
- public void addListener(RemoteListener listener) throws RemoteException,
- ImplementationException {
- throw new ImplementationException("not implemented");
- }
-
- @Override
- public String getInputBaclavaFile() {
- return inputBaclava;
- }
-
- @Override
- public List<RemoteInput> getInputs() throws RemoteException {
- ArrayList<RemoteInput> result = new ArrayList<>();
- for (String name : inputFiles.keySet())
- result.add(new InputDelegate(name));
- return result;
- }
-
- @Override
- public List<String> getListenerTypes() {
- return emptyList();
- }
-
- @Override
- public List<RemoteListener> getListeners() {
- return singletonList(core.getDefaultListener());
- }
-
- @Override
- public String getOutputBaclavaFile() {
- return outputBaclava;
- }
-
- class SecurityDelegate extends UnicastRemoteObject implements
- RemoteSecurityContext {
- private void setPrivatePerms(File dir) {
- if (!dir.setReadable(false, false) || !dir.setReadable(true, true)
- || !dir.setExecutable(false, false)
- || !dir.setExecutable(true, true)
- || !dir.setWritable(false, false)
- || !dir.setWritable(true, true)) {
- out.println("warning: "
- + "failed to set permissions on security context directory");
- }
- }
-
- protected SecurityDelegate(String token) throws IOException {
- super();
- if (DO_MKDIR) {
- securityDirectory = new File(SECURITY_DIR, token);
- forceMkdir(securityDirectory);
- setPrivatePerms(securityDirectory);
- }
- }
-
- /**
- * Write some data to a given file in the context directory.
- *
- * @param name
- * The name of the file to write.
- * @param data
- * The bytes to put in the file.
- * @throws RemoteException
- * If anything goes wrong.
- * @throws ImplementationException
- */
- protected void write(String name, byte[] data) throws RemoteException,
- ImplementationException {
- try {
- File f = new File(securityDirectory, name);
- writeByteArrayToFile(f, data);
- } catch (IOException e) {
- throw new ImplementationException("problem writing " + name, e);
- }
- }
-
- /**
- * Write some data to a given file in the context directory.
- *
- * @param name
- * The name of the file to write.
- * @param data
- * The lines to put in the file. The
- * {@linkplain LocalWorker#SYSTEM_ENCODING system encoding}
- * will be used to do the writing.
- * @throws RemoteException
- * If anything goes wrong.
- * @throws ImplementationException
- */
- protected void write(String name, Collection<String> data)
- throws RemoteException, ImplementationException {
- try {
- File f = new File(securityDirectory, name);
- writeLines(f, SYSTEM_ENCODING, data);
- } catch (IOException e) {
- throw new ImplementationException("problem writing " + name, e);
- }
- }
-
- /**
- * Write some data to a given file in the context directory.
- *
- * @param name
- * The name of the file to write.
- * @param data
- * The line to put in the file. The
- * {@linkplain LocalWorker#SYSTEM_ENCODING system encoding}
- * will be used to do the writing.
- * @throws RemoteException
- * If anything goes wrong.
- * @throws ImplementationException
- */
- protected void write(String name, char[] data) throws RemoteException,
- ImplementationException {
- try {
- File f = new File(securityDirectory, name);
- writeLines(f, SYSTEM_ENCODING, asList(new String(data)));
- } catch (IOException e) {
- throw new ImplementationException("problem writing " + name, e);
- }
- }
-
- @Override
- public void setKeystore(byte[] keystore) throws RemoteException,
- ImplementationException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (keystore == null)
- throw new IllegalArgumentException("keystore may not be null");
- write(KEYSTORE_FILE, keystore);
- }
-
- @Override
- public void setPassword(char[] password) throws RemoteException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (password == null)
- throw new IllegalArgumentException("password may not be null");
- keystorePassword = password.clone();
- }
-
- @Override
- public void setTruststore(byte[] truststore) throws RemoteException,
- ImplementationException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (truststore == null)
- throw new IllegalArgumentException("truststore may not be null");
- write(TRUSTSTORE_FILE, truststore);
- }
-
- @Override
- public void setUriToAliasMap(Map<URI, String> uriToAliasMap)
- throws RemoteException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- if (uriToAliasMap == null)
- return;
- ArrayList<String> lines = new ArrayList<>();
- for (Entry<URI, String> site : uriToAliasMap.entrySet())
- lines.add(site.getKey().toASCIIString() + " " + site.getValue());
- // write(URI_ALIAS_MAP, lines);
- }
-
- @Override
- public void setHelioToken(String helioToken) throws RemoteException {
- if (status != Initialized)
- throw new RemoteException("not initializing");
- out.println("registering HELIO CIS token for export");
- environment.put(HELIO_TOKEN_NAME, helioToken);
- }
- }
-
- @Override
- public RemoteSecurityContext getSecurityContext() throws RemoteException,
- ImplementationException {
- try {
- return new SecurityDelegate(masterToken);
- } catch (RemoteException e) {
- if (e.getCause() != null)
- throw new ImplementationException(
- "problem initializing security context", e.getCause());
- throw e;
- } catch (IOException e) {
- throw new ImplementationException(
- "problem initializing security context", e);
- }
- }
-
- @Override
- public RemoteStatus getStatus() {
- // only state that can spontaneously change to another
- if (status == Operating) {
- status = core.getWorkerStatus();
- if (status == Finished && finish == null)
- finish = new Date();
- }
- return status;
- }
-
- @Override
- public RemoteDirectory getWorkingDirectory() {
- return baseDir;
- }
-
- File validateFilename(String filename) throws RemoteException {
- if (filename == null)
- throw new IllegalArgumentException("filename must be non-null");
- try {
- return getValidatedFile(base, filename.split("/"));
- } catch (IOException e) {
- throw new IllegalArgumentException("failed to validate filename", e);
- }
- }
-
- class InputDelegate extends UnicastRemoteObject implements RemoteInput {
- private String name;
-
- InputDelegate(String name) throws RemoteException {
- super();
- this.name = name;
- if (!inputFiles.containsKey(name)) {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputFiles.put(name, null);
- inputRealFiles.put(name, null);
- inputValues.put(name, null);
- inputDelimiters.put(name, null);
- }
- }
-
- @Override
- public String getFile() {
- return inputFiles.get(name);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getValue() {
- return inputValues.get(name);
- }
-
- @Override
- public String getDelimiter() throws RemoteException {
- return inputDelimiters.get(name);
- }
-
- @Override
- public void setFile(String file) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputRealFiles.put(name, validateFilename(file));
- inputValues.put(name, null);
- inputFiles.put(name, file);
- inputBaclava = null;
- }
-
- @Override
- public void setValue(String value) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputValues.put(name, value);
- inputFiles.put(name, null);
- inputRealFiles.put(name, null);
- inputBaclava = null;
- }
-
- @Override
- public void setDelimiter(String delimiter) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- if (inputBaclava != null)
- throw new IllegalStateException("input baclava file set");
- if (delimiter != null) {
- if (delimiter.length() > 1)
- throw new IllegalStateException(
- "multi-character delimiter not permitted");
- if (delimiter.charAt(0) == 0)
- throw new IllegalStateException(
- "may not use NUL for splitting");
- if (delimiter.charAt(0) > 127)
- throw new IllegalStateException(
- "only ASCII characters supported for splitting");
- }
- inputDelimiters.put(name, delimiter);
- }
- }
-
- @Override
- public RemoteInput makeInput(String name) throws RemoteException {
- return new InputDelegate(name);
- }
-
- @Override
- public RemoteListener makeListener(String type, String configuration)
- throws RemoteException {
- throw new RemoteException("listener manufacturing unsupported");
- }
-
- @Override
- public void setInputBaclavaFile(String filename) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- inputBaclavaFile = validateFilename(filename);
- for (String input : inputFiles.keySet()) {
- inputFiles.put(input, null);
- inputRealFiles.put(input, null);
- inputValues.put(input, null);
- }
- inputBaclava = filename;
- }
-
- @Override
- public void setOutputBaclavaFile(String filename) throws RemoteException {
- if (status != Initialized)
- throw new IllegalStateException("not initializing");
- if (filename != null)
- outputBaclavaFile = validateFilename(filename);
- else
- outputBaclavaFile = null;
- outputBaclava = filename;
- }
-
- @Override
- public void setGenerateProvenance(boolean prov) {
- doProvenance = prov;
- }
-
- @Override
- public void setStatus(RemoteStatus newStatus)
- throws IllegalStateTransitionException, RemoteException,
- ImplementationException, StillWorkingOnItException {
- if (status == newStatus)
- return;
-
- switch (newStatus) {
- case Initialized:
- throw new IllegalStateTransitionException(
- "may not move back to start");
- case Operating:
- switch (status) {
- case Initialized:
- boolean started;
- try {
- started = createWorker();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem creating executing workflow", e);
- }
- if (!started)
- throw new StillWorkingOnItException(
- "workflow start in process");
- break;
- case Stopped:
- try {
- core.startWorker();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem continuing workflow run", e);
- }
- break;
- case Finished:
- throw new IllegalStateTransitionException("already finished");
- default:
- break;
- }
- status = Operating;
- break;
- case Stopped:
- switch (status) {
- case Initialized:
- throw new IllegalStateTransitionException(
- "may only stop from Operating");
- case Operating:
- try {
- core.stopWorker();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem stopping workflow run", e);
- }
- break;
- case Finished:
- throw new IllegalStateTransitionException("already finished");
- default:
- break;
- }
- status = Stopped;
- break;
- case Finished:
- switch (status) {
- case Operating:
- case Stopped:
- try {
- core.killWorker();
- if (finish == null)
- finish = new Date();
- } catch (Exception e) {
- throw new ImplementationException(
- "problem killing workflow run", e);
- }
- default:
- break;
- }
- status = Finished;
- break;
- }
- }
-
- private boolean createWorker() throws Exception {
- start = new Date();
- char[] pw = keystorePassword;
- keystorePassword = null;
- /*
- * Do not clear the keystorePassword array here; its ownership is
- * *transferred* to the worker core which doesn't copy it but *does*
- * clear it after use.
- */
- return core.initWorker(this, executeWorkflowCommand, workflow, base,
- inputBaclavaFile, inputRealFiles, inputValues, inputDelimiters,
- outputBaclavaFile, securityDirectory, pw, doProvenance,
- environment, masterToken, runtimeSettings);
- }
-
- @Override
- public Date getFinishTimestamp() {
- return finish == null ? null : new Date(finish.getTime());
- }
-
- @Override
- public Date getStartTimestamp() {
- return start == null ? null : new Date(start.getTime());
- }
-
- @Override
- public void setInteractionServiceDetails(URL feed, URL webdav, URL publish) {
- interactionFeedURL = feed;
- webdavURL = webdav;
- publishURL = publish;
- }
-
- @Override
- public void ping() {
- // Do nothing here; this *should* be empty
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
deleted file mode 100644
index 03ee69d..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/TavernaRunManager.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.lang.Runtime.getRuntime;
-import static java.lang.System.exit;
-import static java.lang.System.getProperty;
-import static java.lang.System.out;
-import static java.lang.System.setProperty;
-import static java.lang.System.setSecurityManager;
-import static java.rmi.registry.LocateRegistry.getRegistry;
-import static org.taverna.server.localworker.api.Constants.DEATH_DELAY;
-import static org.taverna.server.localworker.api.Constants.LOCALHOST;
-import static org.taverna.server.localworker.api.Constants.RMI_HOST_PROP;
-import static org.taverna.server.localworker.api.Constants.SECURITY_POLICY_FILE;
-import static org.taverna.server.localworker.api.Constants.SEC_POLICY_PROP;
-import static org.taverna.server.localworker.api.Constants.UNSECURE_PROP;
-
-import java.io.ByteArrayInputStream;
-import java.net.URI;
-import java.rmi.RMISecurityManager;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.taverna.server.localworker.api.RunAccounting;
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.api.WorkerFactory;
-import org.taverna.server.localworker.remote.RemoteRunFactory;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
-
-/**
- * The registered factory for runs, this class is responsible for constructing
- * runs that are suitable for particular users. It is also the entry point for
- * this whole process.
- *
- * @author Donal Fellows
- * @see LocalWorker
- */
-@SuppressWarnings("serial")
-public class TavernaRunManager extends UnicastRemoteObject implements
- RemoteRunFactory, RunAccounting, WorkerFactory {
- String command;
- Map<String, String> seedEnvironment = new HashMap<>();
- List<String> javaInitParams = new ArrayList<>();
- private WorkflowBundleIO io;
- private int activeRuns = 0;
- // Hacks!
- public static String interactionHost;
- public static String interactionPort;
- public static String interactionWebdavPath;
- public static String interactionFeedPath;
-
- /**
- * How to get the actual workflow document from the XML document that it is
- * contained in.
- *
- * @param containerDocument
- * The document sent from the web interface.
- * @return The element describing the workflow, as expected by the Taverna
- * command line executor.
- */
- protected Element unwrapWorkflow(Document containerDocument) {
- return (Element) containerDocument.getDocumentElement().getFirstChild();
- }
-
- private static final String usage = "java -jar server.worker.jar workflowExecScript ?-Ekey=val...? ?-Jconfig? UUID";
-
- /**
- * An RMI-enabled factory for runs.
- *
- * @param command
- * What command to call to actually run a run.
- * @throws RemoteException
- * If anything goes wrong during creation of the instance.
- */
- public TavernaRunManager(String command) throws RemoteException {
- this.command = command;
- this.io = new WorkflowBundleIO();
- }
-
- @Override
- public RemoteSingleRun make(byte[] workflow, String creator,
- UsageRecordReceiver urReceiver, UUID id) throws RemoteException {
- if (creator == null)
- throw new RemoteException("no creator");
- try {
- URI wfid = io.readBundle(new ByteArrayInputStream(workflow), null)
- .getMainWorkflow().getWorkflowIdentifier();
- out.println("Creating run from workflow <" + wfid + "> for <"
- + creator + ">");
- return new LocalWorker(command, workflow, urReceiver, id,
- seedEnvironment, javaInitParams, this);
- } catch (RemoteException e) {
- throw e;
- } catch (Exception e) {
- throw new RemoteException("bad instance construction", e);
- }
- }
-
- private static boolean shuttingDown;
- private static String factoryName;
- private static Registry registry;
-
- static synchronized void unregisterFactory() {
- if (!shuttingDown) {
- shuttingDown = true;
- try {
- if (factoryName != null && registry != null)
- registry.unbind(factoryName);
- } catch (Exception e) {
- e.printStackTrace(out);
- }
- }
- }
-
- @Override
- public void shutdown() {
- unregisterFactory();
- new Thread(new DelayedDeath()).start();
- }
-
- static class DelayedDeath implements Runnable {
- @Override
- public void run() {
- try {
- Thread.sleep(DEATH_DELAY);
- } catch (InterruptedException e) {
- } finally {
- exit(0);
- }
- }
- }
-
- private void addArgument(String arg) {
- if (arg.startsWith("-E")) {
- String trimmed = arg.substring(2);
- int idx = trimmed.indexOf('=');
- if (idx > 0) {
- addEnvironmentDefinition(trimmed.substring(0, idx),
- trimmed.substring(idx + 1));
- return;
- }
- } else if (arg.startsWith("-D")) {
- if (arg.indexOf('=') > 0) {
- addJavaParameter(arg);
- return;
- }
- } else if (arg.startsWith("-J")) {
- addJavaParameter(arg.substring(2));
- return;
- }
- throw new IllegalArgumentException("argument \"" + arg
- + "\" must start with -D, -E or -J; "
- + "-D and -E must contain a \"=\"");
- }
-
- /**
- * @param args
- * The arguments from the command line invocation.
- * @throws Exception
- * If we can't connect to the RMI registry, or if we can't read
- * the workflow, or if we can't build the worker instance, or
- * register it. Also if the arguments are wrong.
- */
- public static void main(String[] args) throws Exception {
- if (args.length < 2)
- throw new Exception("wrong # args: must be \"" + usage + "\"");
- if (!getProperty(UNSECURE_PROP, "no").equals("yes")) {
- setProperty(SEC_POLICY_PROP, LocalWorker.class.getClassLoader()
- .getResource(SECURITY_POLICY_FILE).toExternalForm());
- setProperty(RMI_HOST_PROP, LOCALHOST);
- }
- setSecurityManager(new RMISecurityManager());
- factoryName = args[args.length - 1];
- TavernaRunManager man = new TavernaRunManager(args[0]);
- for (int i = 1; i < args.length - 1; i++)
- man.addArgument(args[i]);
- registry = getRegistry(LOCALHOST);
-
- registry.bind(factoryName, man);
- getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run() {
- unregisterFactory();
- }
- });
- out.println("registered RemoteRunFactory with ID " + factoryName);
- }
-
- private void addJavaParameter(String string) {
- this.javaInitParams.add(string);
- }
-
- private void addEnvironmentDefinition(String key, String value) {
- this.seedEnvironment.put(key, value);
- }
-
- @Override
- public void setInteractionServiceDetails(String host, String port,
- String webdavPath, String feedPath) throws RemoteException {
- if (host == null || port == null || webdavPath == null
- || feedPath == null)
- throw new IllegalArgumentException("all params must be non-null");
- interactionHost = host;
- interactionPort = port;
- interactionWebdavPath = webdavPath;
- interactionFeedPath = feedPath;
- }
-
- @Override
- public synchronized int countOperatingRuns() {
- return (activeRuns < 0 ? 0 : activeRuns);
- }
-
- @Override
- public synchronized void runStarted() {
- activeRuns++;
- }
-
- @Override
- public synchronized void runCeased() {
- activeRuns--;
- }
-
- @Override
- public Worker makeInstance() throws Exception {
- return new WorkerCore(this);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
deleted file mode 100644
index 1a6cff8..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/WorkerCore.java
+++ /dev/null
@@ -1,918 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.io.File.createTempFile;
-import static java.io.File.pathSeparator;
-import static java.lang.Boolean.parseBoolean;
-import static java.lang.Double.parseDouble;
-import static java.lang.Integer.parseInt;
-import static java.lang.Long.parseLong;
-import static java.lang.Runtime.getRuntime;
-import static java.lang.System.out;
-import static java.net.InetAddress.getLocalHost;
-import static org.apache.commons.io.FileUtils.forceDelete;
-import static org.apache.commons.io.FileUtils.sizeOfDirectory;
-import static org.apache.commons.io.FileUtils.write;
-import static org.apache.commons.io.IOUtils.copy;
-import static org.taverna.server.localworker.api.Constants.CREDENTIAL_MANAGER_DIRECTORY;
-import static org.taverna.server.localworker.api.Constants.CREDENTIAL_MANAGER_PASSWORD;
-import static org.taverna.server.localworker.api.Constants.DEATH_TIME;
-import static org.taverna.server.localworker.api.Constants.DEFAULT_LISTENER_NAME;
-import static org.taverna.server.localworker.api.Constants.KEYSTORE_PASSWORD;
-import static org.taverna.server.localworker.api.Constants.START_WAIT_TIME;
-import static org.taverna.server.localworker.api.Constants.SYSTEM_ENCODING;
-import static org.taverna.server.localworker.api.Constants.TIME;
-import static org.taverna.server.localworker.impl.Status.Aborted;
-import static org.taverna.server.localworker.impl.Status.Completed;
-import static org.taverna.server.localworker.impl.Status.Failed;
-import static org.taverna.server.localworker.impl.Status.Held;
-import static org.taverna.server.localworker.impl.Status.Started;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionFeedPath;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionHost;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionPort;
-import static org.taverna.server.localworker.impl.TavernaRunManager.interactionWebdavPath;
-import static org.taverna.server.localworker.impl.WorkerCore.pmap;
-import static org.taverna.server.localworker.remote.RemoteStatus.Finished;
-import static org.taverna.server.localworker.remote.RemoteStatus.Initialized;
-import static org.taverna.server.localworker.remote.RemoteStatus.Operating;
-import static org.taverna.server.localworker.remote.RemoteStatus.Stopped;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.rmi.RemoteException;
-import java.rmi.server.UnicastRemoteObject;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.ws.Holder;
-
-import org.ogf.usage.JobUsageRecord;
-import org.taverna.server.localworker.api.RunAccounting;
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.impl.utils.TimingOutTask;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-/**
- * The core class that connects to a Taverna command-line workflow execution
- * engine. This implementation always registers a single listener, &lquo;
- * <tt>io</tt> &rquo;, with two properties representing the stdout and stderr of
- * the run and one representing the exit code. The listener is
- * remote-accessible. It does not support attaching any other listeners.
- *
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-public class WorkerCore extends UnicastRemoteObject implements Worker,
- RemoteListener {
- @Nonnull
- static final Map<String, Property> pmap = new HashMap<>();
- /**
- * Regular expression to extract the detailed timing information from the
- * output of /usr/bin/time
- */
- @Nonnull
- private static final Pattern TimeRE;
- static {
- final String TIMERE = "([0-9.:]+)";
- final String TERMS = "(real|user|system|sys|elapsed)";
- TimeRE = Pattern.compile(TIMERE + " *" + TERMS + "[ \t]*" + TIMERE
- + " *" + TERMS + "[ \t]*" + TIMERE + " *" + TERMS);
- }
-
- /**
- * Environment variables to remove before any fork (because they're large or
- * potentially leaky).
- */
- // TODO Conduct a proper survey of what to remove
- @Nonnull
- private static final String[] ENVIRONMENT_TO_REMOVE = { "SUDO_COMMAND",
- "SUDO_USER", "SUDO_GID", "SUDO_UID", "DISPLAY", "LS_COLORS",
- "XFILESEARCHPATH", "SSH_AGENT_PID", "SSH_AUTH_SOCK" };
-
- @Nullable
- Process subprocess;
- @Nonnull
- final StringWriter stdout;
- @Nonnull
- final StringWriter stderr;
- @Nullable
- Integer exitCode;
- boolean readyToSendEmail;
- @Nullable
- String emailAddress;
- @Nullable
- Date start;
- @Nonnull
- final RunAccounting accounting;
- @Nonnull
- final Holder<Integer> pid;
-
- private boolean finished;
- @Nullable
- private JobUsageRecord ur;
- @Nullable
- private File wd;
- @Nullable
- private UsageRecordReceiver urreceiver;
- @Nullable
- private File workflowFile;
- private boolean stopped;
-
- /**
- * @param accounting
- * Object that looks after how many runs are executing.
- * @throws RemoteException
- */
- public WorkerCore(@Nonnull RunAccounting accounting) throws RemoteException {
- super();
- stdout = new StringWriter();
- stderr = new StringWriter();
- pid = new Holder<>();
- this.accounting = accounting;
- }
-
- private int getPID() {
- synchronized (pid) {
- if (pid.value == null)
- return -1;
- return pid.value;
- }
- }
-
- /**
- * Fire up the workflow. This causes a transition into the operating state.
- *
- * @param executeWorkflowCommand
- * The command to run to execute the workflow.
- * @param workflow
- * The workflow document to execute.
- * @param workingDir
- * What directory to use as the working directory.
- * @param inputBaclava
- * The baclava file to use for inputs, or <tt>null</tt> to use
- * the other <b>input*</b> arguments' values.
- * @param inputFiles
- * A mapping of input names to files that supply them. Note that
- * we assume that nothing mapped here will be mapped in
- * <b>inputValues</b>.
- * @param inputValues
- * A mapping of input names to values to supply to them. Note
- * that we assume that nothing mapped here will be mapped in
- * <b>inputFiles</b>.
- * @param outputBaclava
- * What baclava file to write the output from the workflow into,
- * or <tt>null</tt> to have it written into the <tt>out</tt>
- * subdirectory.
- * @param token
- * The name of the workflow run.
- * @return <tt>true</tt> if the worker started, or <tt>false</tt> if a
- * timeout occurred.
- * @throws IOException
- * If any of quite a large number of things goes wrong.
- */
- @Override
- public boolean initWorker(
- @Nonnull final LocalWorker local,
- @Nonnull final String executeWorkflowCommand,
- @Nonnull final byte[] workflow,
- @Nonnull final File workingDir,
- @Nullable final File inputBaclava,
- @Nonnull final Map<String, File> inputFiles,
- @Nonnull final Map<String, String> inputValues,
- @Nonnull final Map<String, String> inputDelimiters,
- @Nullable final File outputBaclava,
- @Nonnull final File securityDir,
- @Nullable final char[] password,
- final boolean generateProvenance,
- @Nonnull final Map<String, String> environment,
- @Nullable final String token,
- @Nonnull final List<String> runtime) throws IOException {
- try {
- new TimingOutTask() {
- @Override
- public void doIt() throws IOException {
- startExecutorSubprocess(
- createProcessBuilder(local, executeWorkflowCommand,
- workflow, workingDir, inputBaclava,
- inputFiles, inputValues, inputDelimiters,
- outputBaclava, securityDir, password,
- generateProvenance, environment, token,
- runtime), password);
- }
- }.doOrTimeOut(START_WAIT_TIME);
- } catch (IOException e) {
- throw e;
- } catch (Exception e) {
- throw new IOException(e);
- }
- return subprocess != null;
- }
-
- private void startExecutorSubprocess(@Nonnull ProcessBuilder pb,
- @Nullable char[] password) throws IOException {
- // Start the subprocess
- out.println("starting " + pb.command() + " in directory "
- + pb.directory() + " with environment " + pb.environment());
- subprocess = pb.start();
- if (subprocess == null)
- throw new IOException("unknown failure creating process");
- start = new Date();
- accounting.runStarted();
-
- // Capture its stdout and stderr
- new AsyncCopy(subprocess.getInputStream(), stdout, pid);
- new AsyncCopy(subprocess.getErrorStream(), stderr);
- if (password != null)
- new PasswordWriterThread(subprocess, password);
- }
-
- /**
- * Assemble the process builder. Does not launch the subprocess.
- *
- * @param local
- * The local worker container.
- * @param executeWorkflowCommand
- * The reference to the workflow engine implementation.
- * @param workflow
- * The workflow to execute.
- * @param workingDir
- * The working directory to use.
- * @param inputBaclava
- * What file to read a baclava document from (or <tt>null</tt>)
- * @param inputFiles
- * The mapping from inputs to files.
- * @param inputValues
- * The mapping from inputs to literal values.
- * @param outputBaclava
- * What file to write a baclava document to (or <tt>null</tt>)
- * @param securityDir
- * The credential manager directory.
- * @param password
- * The password for the credential manager.
- * @param environment
- * The seed environment
- * @param token
- * The run identifier that the server wants to use.
- * @param runtime
- * Any runtime parameters to Java.
- * @return The configured process builder.
- * @throws IOException
- * If file handling fails
- * @throws UnsupportedEncodingException
- * If we can't encode any text (unlikely)
- * @throws FileNotFoundException
- * If we can't write the workflow out (unlikely)
- */
- @Nonnull
- ProcessBuilder createProcessBuilder(@Nonnull LocalWorker local,
- @Nonnull String executeWorkflowCommand, @Nonnull byte[] workflow,
- @Nonnull File workingDir, @Nullable File inputBaclava,
- @Nonnull Map<String, File> inputFiles,
- @Nonnull Map<String, String> inputValues,
- @Nonnull Map<String, String> inputDelimiters,
- @Nullable File outputBaclava, @Nonnull File securityDir,
- @Nonnull char[] password, boolean generateProvenance,
- @Nonnull Map<String, String> environment, @Nonnull String token,
- @Nonnull List<String> runtime) throws IOException,
- UnsupportedEncodingException, FileNotFoundException {
- ProcessBuilder pb = new ProcessBuilder();
- pb.command().add(TIME);
- /*
- * WARNING! HERE THERE BE DRAGONS! BE CAREFUL HERE!
- *
- * Work around _Maven_ bug with permissions in zip files! The executable
- * bit is stripped by Maven's handling of file permissions, and there's
- * no practical way to work around it without massively increasing the
- * pain in other ways. Only want this on Unix - Windows isn't affected
- * by this - so we use the file separator as a proxy for whether this is
- * a true POSIX system. Ugly! Ugly ugly ugly...
- *
- * http://jira.codehaus.org/browse/MASSEMBLY-337 is relevant, but not
- * the whole story as we don't want to use a non-standard packaging
- * method as there's a real chance of it going wrong in an unexpected
- * way then. Other parts of the story are that the executable bit isn't
- * preserved when unpacking with the dependency plugin, and there's no
- * way to be sure that the servlet container will preserve the bit
- * either (as that's probably using a Java-based ZIP engine).
- */
- if (File.separatorChar == '/')
- pb.command().add("/bin/sh");
- pb.command().add(executeWorkflowCommand);
- if (runtime != null)
- pb.command().addAll(runtime);
-
- // Enable verbose logging
- pb.command().add("-logfile");
- pb.command().add(
- new File(new File(workingDir, "logs"), "detail.log")
- .getAbsolutePath());
-
- if (securityDir != null) {
- pb.command().add(CREDENTIAL_MANAGER_DIRECTORY);
- pb.command().add(securityDir.getAbsolutePath());
- out.println("security dir location: " + securityDir);
- }
- if (password != null) {
- pb.command().add(CREDENTIAL_MANAGER_PASSWORD);
- out.println("password of length " + password.length
- + " will be written to subprocess stdin");
- }
-
- // Add arguments denoting inputs
- if (inputBaclava != null) {
- pb.command().add("-inputdoc");
- pb.command().add(inputBaclava.getAbsolutePath());
- if (!inputBaclava.exists())
- throw new IOException("input baclava file doesn't exist");
- } else {
- for (Entry<String, File> port : inputFiles.entrySet()) {
- if (port.getValue() == null)
- continue;
- pb.command().add("-inputfile");
- pb.command().add(port.getKey());
- pb.command().add(port.getValue().getAbsolutePath());
- if (!port.getValue().exists())
- throw new IOException("input file for port \"" + port
- + "\" doesn't exist");
- }
- for (Entry<String, String> port : inputValues.entrySet()) {
- if (port.getValue() == null)
- continue;
- pb.command().add("-inputfile");
- pb.command().add(port.getKey());
- File f = createTempFile(".tav_in_", null, workingDir);
- pb.command().add(f.getAbsolutePath());
- write(f, port.getValue(), "UTF-8");
- }
- for (Entry<String, String> delim : inputDelimiters.entrySet()) {
- if (delim.getValue() == null)
- continue;
- pb.command().add("-inputdelimiter");
- pb.command().add(delim.getKey());
- pb.command().add(delim.getValue());
- }
- }
-
- // Add arguments denoting outputs
- if (outputBaclava != null) {
- pb.command().add("-outputdoc");
- pb.command().add(outputBaclava.getAbsolutePath());
- if (!outputBaclava.getParentFile().exists())
- throw new IOException(
- "parent directory of output baclava file does not exist");
- if (outputBaclava.exists())
- throw new IOException("output baclava file exists");
- // Provenance cannot be supported when using baclava output
- } else {
- File out = new File(workingDir, "out");
- if (!out.mkdir())
- throw new IOException("failed to make output directory \"out\"");
- // Taverna needs the dir to *not* exist now
- forceDelete(out);
- pb.command().add("-outputdir");
- pb.command().add(out.getAbsolutePath());
- // Enable provenance generation
- if (generateProvenance) {
- pb.command().add("-embedded");
- pb.command().add("-provenance");
- pb.command().add("-provbundle");
- pb.command().add("out.bundle.zip");
- }
- }
-
- // Add an argument holding the workflow
- File tmp = createTempFile(".wf_", ".scufl2", workingDir);
- try (OutputStream os = new FileOutputStream(tmp)) {
- os.write(workflow);
- }
- pb.command().add(workflowFile.getAbsolutePath());
-
- // Indicate what working directory to use
- pb.directory(workingDir);
- wd = workingDir;
-
- Map<String, String> env = pb.environment();
- for (String name : ENVIRONMENT_TO_REMOVE)
- env.remove(name);
-
- // Merge any options we have had imposed on us from outside
- env.putAll(environment);
-
- // Patch the environment to deal with TAVUTILS-17
- assert env.get("PATH") != null;
- env.put("PATH", new File(System.getProperty("java.home"), "bin")
- + pathSeparator + env.get("PATH"));
- // Patch the environment to deal with TAVSERV-189
- env.put("TAVERNA_APPHOME", workingDir.getCanonicalPath());
- // Patch the environment to deal with TAVSERV-224
- env.put("TAVERNA_RUN_ID", token);
- if (interactionHost != null || local.interactionFeedURL != null
- || local.webdavURL != null) {
- env.put("INTERACTION_HOST", makeInterHost(local.interactionFeedURL));
- env.put("INTERACTION_PORT", makeInterPort(local.interactionFeedURL));
- env.put("INTERACTION_FEED", makeInterPath(local.interactionFeedURL));
- env.put("INTERACTION_WEBDAV",
- local.webdavURL != null ? local.webdavURL.getPath()
- : interactionWebdavPath);
- String pub = makeInterPublish(local.publishURL);
- if (pub != null && !pub.isEmpty())
- env.put("INTERACTION_PUBLISH", pub);
- }
- return pb;
- }
-
- @Nullable
- private static String makeInterHost(@Nullable URL url) {
- if (url == null)
- return interactionHost;
- return url.getProtocol() + "://" + url.getHost();
- }
-
- @Nullable
- private static String makeInterPort(@Nullable URL url) {
- if (url == null)
- return interactionPort;
- int port = url.getPort();
- if (port == -1)
- port = url.getDefaultPort();
- return Integer.toString(port);
- }
-
- @Nullable
- private static String makeInterPublish(@Nullable URL url)
- throws IOException {
- if (url == null)
- return null;
- try {
- URI uri = url.toURI();
- int port = uri.getPort();
- if (port == -1)
- return uri.getScheme() + "://" + uri.getHost();
- else
- return uri.getScheme() + "://" + uri.getHost() + ":" + port;
- } catch (URISyntaxException e) {
- throw new IOException("problem constructing publication url", e);
- }
- }
-
- @Nullable
- private static String makeInterPath(@Nullable URL url) {
- if (url == null)
- return interactionFeedPath;
- return url.getPath();
- }
-
- /**
- * Kills off the subprocess if it exists and is alive.
- */
- @Override
- public void killWorker() {
- if (!finished && subprocess != null) {
- final Holder<Integer> code = new Holder<>();
- for (TimingOutTask tot : new TimingOutTask[] { new TimingOutTask() {
- /** Check if the workflow terminated of its own accord */
- @Override
- public void doIt() throws IOException {
- code.value = subprocess.exitValue();
- accounting.runCeased();
- buildUR(code.value == 0 ? Completed : Failed, code.value);
- }
- }, new TimingOutTask() {
- /** Tell the workflow to stop */
- @Override
- public void doIt() throws IOException {
- code.value = killNicely();
- accounting.runCeased();
- buildUR(code.value == 0 ? Completed : Aborted, code.value);
- }
- }, new TimingOutTask() {
- /** Kill the workflow, kill it with fire */
- @Override
- public void doIt() throws IOException {
- code.value = killHard();
- accounting.runCeased();
- buildUR(code.value == 0 ? Completed : Aborted, code.value);
- }
- } }) {
- try {
- tot.doOrTimeOut(DEATH_TIME);
- } catch (Exception e) {
- }
- if (code.value != null)
- break;
- }
- finished = true;
- setExitCode(code.value);
- readyToSendEmail = true;
- }
- }
-
- /**
- * Integrated spot to handle writing/logging of the exit code.
- *
- * @param code
- * The exit code.
- */
- private void setExitCode(int code) {
- exitCode = code;
- if (code > 256 - 8) {
- out.println("workflow aborted, Raven issue = " + (code - 256));
- } else if (code > 128) {
- out.println("workflow aborted, signal=" + (code - 128));
- } else {
- out.println("workflow exited, code=" + code);
- }
- }
-
- @Nonnull
- private JobUsageRecord newUR() throws DatatypeConfigurationException {
- try {
- if (wd != null)
- return new JobUsageRecord(wd.getName());
- } catch (RuntimeException e) {
- }
- return new JobUsageRecord("unknown");
- }
-
- /**
- * Fills in the accounting information from the exit code and stderr.
- *
- * @param exitCode
- * The exit code from the program.
- */
- private void buildUR(@Nonnull Status status, int exitCode) {
- try {
- Date now = new Date();
- long user = -1, sys = -1, real = -1;
- Matcher m = TimeRE.matcher(stderr.toString());
- ur = newUR();
- while (m.find())
- for (int i = 1; i < 6; i += 2)
- if (m.group(i + 1).equals("user"))
- user = parseDuration(m.group(i));
- else if (m.group(i + 1).equals("sys")
- || m.group(i + 1).equals("system"))
- sys = parseDuration(m.group(i));
- else if (m.group(i + 1).equals("real")
- || m.group(i + 1).equals("elapsed"))
- real = parseDuration(m.group(i));
- if (user != -1)
- ur.addCpuDuration(user).setUsageType("user");
- if (sys != -1)
- ur.addCpuDuration(sys).setUsageType("system");
- ur.addUser(System.getProperty("user.name"), null);
- ur.addStartAndEnd(start, now);
- if (real != -1)
- ur.addWallDuration(real);
- else
- ur.addWallDuration(now.getTime() - start.getTime());
- ur.setStatus(status.toString());
- ur.addHost(getLocalHost().getHostName());
- ur.addResource("exitcode", Integer.toString(exitCode));
- ur.addDisk(sizeOfDirectory(wd)).setStorageUnit("B");
- if (urreceiver != null)
- urreceiver.acceptUsageRecord(ur.marshal());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private long parseDuration(@Nonnull String durationString) {
- try {
- return (long) (parseDouble(durationString) * 1000);
- } catch (NumberFormatException nfe) {
- // Not a double; maybe MM:SS.mm or HH:MM:SS.mm
- }
- long dur = 0;
- for (String d : durationString.split(":"))
- try {
- dur = 60 * dur + parseLong(d);
- } catch (NumberFormatException nfe) {
- // Assume that only one thing is fractional, and that it is last
- return 60000 * dur + (long) (parseDouble(d) * 1000);
- }
- return dur * 1000;
- }
-
- private void signal(@Nonnull String signal) throws Exception {
- int pid = getPID();
- if (pid > 0
- && getRuntime().exec("kill -" + signal + " " + pid).waitFor() == 0)
- return;
- throw new Exception("failed to send signal " + signal + " to process "
- + pid);
- }
-
- @Nullable
- private Integer killNicely() {
- try {
- signal("TERM");
- return subprocess.waitFor();
- } catch (Exception e) {
- return null;
- }
- }
-
- @Nullable
- private Integer killHard() {
- try {
- signal("QUIT");
- return subprocess.waitFor();
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Move the worker out of the stopped state and back to operating.
- *
- * @throws Exception
- * if it fails.
- */
- @Override
- public void startWorker() throws Exception {
- signal("CONT");
- stopped = false;
- }
-
- /**
- * Move the worker into the stopped state from the operating state.
- *
- * @throws Exception
- * if it fails.
- */
- @Override
- public void stopWorker() throws Exception {
- signal("STOP");
- stopped = true;
- }
-
- /**
- * @return The status of the workflow run. Note that this can be an
- * expensive operation.
- */
- @Override
- public RemoteStatus getWorkerStatus() {
- if (subprocess == null)
- return Initialized;
- if (finished)
- return Finished;
- try {
- setExitCode(subprocess.exitValue());
- } catch (IllegalThreadStateException e) {
- if (stopped)
- return Stopped;
- return Operating;
- }
- finished = true;
- readyToSendEmail = true;
- accounting.runCeased();
- buildUR(exitCode.intValue() == 0 ? Completed : Failed, exitCode);
- return Finished;
- }
-
- @Override
- public String getConfiguration() {
- return "";
- }
-
- @Override
- public String getName() {
- return DEFAULT_LISTENER_NAME;
- }
-
- @Override
- public String getProperty(String propName) throws RemoteException {
- switch (Property.is(propName)) {
- case STDOUT:
- return stdout.toString();
- case STDERR:
- return stderr.toString();
- case EXIT_CODE:
- return (exitCode == null) ? "" : exitCode.toString();
- case EMAIL:
- return emailAddress;
- case READY_TO_NOTIFY:
- return Boolean.toString(readyToSendEmail);
- case USAGE:
- try {
- JobUsageRecord toReturn;
- if (subprocess == null) {
- toReturn = newUR();
- toReturn.setStatus(Held.toString());
- } else if (ur == null) {
- toReturn = newUR();
- toReturn.setStatus(Started.toString());
- toReturn.addStartAndEnd(start, new Date());
- toReturn.addUser(System.getProperty("user.name"), null);
- } else {
- toReturn = ur;
- }
- /*
- * Note that this record is not to be pushed to the server. That
- * is done elsewhere (when a proper record is produced)
- */
- return toReturn.marshal();
- } catch (Exception e) {
- e.printStackTrace();
- return "";
- }
- default:
- throw new RemoteException("unknown property");
- }
- }
-
- @Override
- public String getType() {
- return DEFAULT_LISTENER_NAME;
- }
-
- @Override
- public String[] listProperties() {
- return Property.names();
- }
-
- @Override
- public void setProperty(String propName, String value)
- throws RemoteException {
- switch (Property.is(propName)) {
- case EMAIL:
- emailAddress = value;
- return;
- case READY_TO_NOTIFY:
- readyToSendEmail = parseBoolean(value);
- return;
- case STDOUT:
- case STDERR:
- case EXIT_CODE:
- case USAGE:
- throw new RemoteException("property is read only");
- default:
- throw new RemoteException("unknown property");
- }
- }
-
- @Override
- public RemoteListener getDefaultListener() {
- return this;
- }
-
- @Override
- public void setURReceiver(@Nonnull UsageRecordReceiver receiver) {
- urreceiver = receiver;
- }
-
- @Override
- public void deleteLocalResources() throws ImplementationException {
- try {
- if (workflowFile != null && workflowFile.getParentFile().exists())
- forceDelete(workflowFile);
- } catch (IOException e) {
- throw new ImplementationException("problem deleting workflow file",
- e);
- }
- }
-}
-
-/**
- * An engine for asynchronously copying from an {@link InputStream} to a
- * {@link Writer}.
- *
- * @author Donal Fellows
- */
-class AsyncCopy extends Thread {
- @Nonnull
- private BufferedReader from;
- @Nonnull
- private Writer to;
- @Nullable
- private Holder<Integer> pidHolder;
-
- AsyncCopy(@Nonnull InputStream from, @Nonnull Writer to)
- throws UnsupportedEncodingException {
- this(from, to, null);
- }
-
- AsyncCopy(@Nonnull InputStream from, @Nonnull Writer to,
- @Nullable Holder<Integer> pid) throws UnsupportedEncodingException {
- this.from = new BufferedReader(new InputStreamReader(from,
- SYSTEM_ENCODING));
- this.to = to;
- this.pidHolder = pid;
- setDaemon(true);
- start();
- }
-
- @Override
- public void run() {
- try {
- if (pidHolder != null) {
- String line = from.readLine();
- if (line.matches("^pid:\\d+$"))
- synchronized (pidHolder) {
- pidHolder.value = parseInt(line.substring(4));
- }
- else
- to.write(line + System.getProperty("line.separator"));
- }
- copy(from, to);
- } catch (IOException e) {
- }
- }
-}
-
-/**
- * A helper for asynchronously writing a password to a subprocess's stdin.
- *
- * @author Donal Fellows
- */
-class PasswordWriterThread extends Thread {
- private OutputStream to;
- private char[] chars;
-
- PasswordWriterThread(@Nonnull Process to, @Nonnull char[] chars) {
- this.to = to.getOutputStream();
- assert chars != null;
- this.chars = chars;
- setDaemon(true);
- start();
- }
-
- @Override
- public void run() {
- try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(to,
- SYSTEM_ENCODING))) {
- pw.println(chars);
- } catch (UnsupportedEncodingException e) {
- // Not much we can do here
- e.printStackTrace();
- } finally {
- /*
- * We don't trust GC to clear password from memory. We also take
- * care not to clear the default password!
- */
- if (chars != KEYSTORE_PASSWORD)
- Arrays.fill(chars, '\00');
- }
- }
-}
-
-enum Property {
- STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
- "readyToNotify"), EMAIL("notificationAddress"), USAGE("usageRecord");
-
- private String s;
-
- private Property(String s) {
- this.s = s;
- pmap.put(s, this);
- }
-
- @Override
- public String toString() {
- return s;
- }
-
- public static Property is(@Nonnull String s) {
- return pmap.get(s);
- }
-
- @Nonnull
- public static String[] names() {
- return pmap.keySet().toArray(new String[pmap.size()]);
- }
-}
-
-enum Status {
- Aborted, Completed, Failed, Held, Queued, Started, Suspended
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
deleted file mode 100644
index fbc3a72..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/FilenameVerifier.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl.utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Utility class that handles filename validation on different target platforms.
- *
- * @author Donal Fellows.
- */
-public abstract class FilenameVerifier {
- private FilenameVerifier(){}
-
- static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win");
-
- @SuppressWarnings("serial")
- private static final Set<String> ILLEGAL_NAMES = new HashSet<String>(){{
- add("");
- add("..");
- add(".");
- if (IS_WINDOWS) {
- add("con");
- add("prn");
- add("nul");
- add("aux");
- for (int i = 1; i <= 9; i++) {
- add("com" + i);
- add("lpt" + i);
- }
- }
- }};
- @SuppressWarnings("serial")
- private static final Set<Character> ILLEGAL_CHARS = new HashSet<Character>(){{
- add('/');
- for (char i=0 ; i<32 ; i++)
- add(i);
- if (IS_WINDOWS) {
- add('\\');
- add('>');
- add('<');
- add(':');
- add('"');
- add('|');
- add('?');
- add('*');
- } else {
- add(' '); // whitespace; too much trouble from these
- add('\t');
- add('\r');
- add('\n');
- }
- }};
- @SuppressWarnings("serial")
- private static final Set<String> ILLEGAL_PREFIXES = new HashSet<String>(){{
- if (IS_WINDOWS) {
- add("con.");
- add("prn.");
- add("nul.");
- add("aux.");
- for (int i = 1; i <= 9; i++) {
- add("com" + i + ".");
- add("lpt" + i + ".");
- }
- }
- }};
- @SuppressWarnings("serial")
- private static final Set<String> ILLEGAL_SUFFIXES = new HashSet<String>(){{
- if (IS_WINDOWS) {
- add(" ");
- add(".");
- }
- }};
-
- /**
- * Construct a file handle, applying platform-specific filename validation
- * rules in the process.
- *
- * @param dir
- * The directory acting as a root, which is assumed to be
- * correctly named. May be <tt>null</tt>.
- * @param names
- * The names of filename fragments to apply the checks to. Must
- * have at least one value.
- * @return The file handle. Never <tt>null</tt>.
- * @throws IOException
- * If validation fails.
- */
- public static File getValidatedFile(File dir, String... names)
- throws IOException {
- if (names.length == 0)
- throw new IOException("empty filename");
- File f = dir;
- for (String name : names) {
- String low = name.toLowerCase();
- if (ILLEGAL_NAMES.contains(low))
- throw new IOException("illegal filename");
- for (char c : ILLEGAL_CHARS)
- if (low.indexOf(c) >= 0)
- throw new IOException("illegal filename");
- for (String s : ILLEGAL_PREFIXES)
- if (low.startsWith(s))
- throw new IOException("illegal filename");
- for (String s : ILLEGAL_SUFFIXES)
- if (low.endsWith(s))
- throw new IOException("illegal filename");
- f = new File(f, name);
- }
- assert f != null;
- return f;
- }
-
- /**
- * Create a file handle where the underlying file must exist.
- *
- * @param dir
- * The directory that will contain the file.
- * @param name
- * The name of the file; will be validated.
- * @return The handle.
- * @throws IOException
- * If validation fails or the file doesn't exist.
- */
- public static File getValidatedExistingFile(File dir, String name)
- throws IOException {
- File f = getValidatedFile(dir, name);
- if (!f.exists())
- throw new IOException("doesn't exist");
- return f;
- }
-
- /**
- * Create a file handle where the underlying file must <i>not</i> exist.
- *
- * @param dir
- * The directory that will contain the file.
- * @param name
- * The name of the file; will be validated.
- * @return The handle. The file will not be created by this method.
- * @throws IOException
- * If validation fails or the file does exist.
- */
- public static File getValidatedNewFile(File dir, String name)
- throws IOException {
- File f = getValidatedFile(dir, name);
- if (f.exists())
- throw new IOException("already exists");
- return f;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
----------------------------------------------------------------------
diff --git a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java b/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
deleted file mode 100644
index 3dd3ac1..0000000
--- a/server-worker/src/main/java/org/taverna/server/localworker/impl/utils/TimingOutTask.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.taverna.server.localworker.impl.utils;
-
-import javax.annotation.Nullable;
-
-/**
- * A class that handles running a task that can take some time.
- *
- * @author Donal Fellows
- *
- */
-public abstract class TimingOutTask extends Thread {
- public abstract void doIt() throws Exception;
-
- @Nullable
- private Exception ioe;
-
- @Override
- public final void run() {
- try {
- doIt();
- } catch (Exception ioe) {
- this.ioe = ioe;
- }
- }
-
- public TimingOutTask() {
- this.setDaemon(true);
- }
-
- public void doOrTimeOut(long timeout) throws Exception {
- start();
- try {
- join(timeout);
- } catch (InterruptedException e) {
- interrupt();
- }
- if (ioe != null)
- throw ioe;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/main/resources/security.policy
----------------------------------------------------------------------
diff --git a/server-worker/src/main/resources/security.policy b/server-worker/src/main/resources/security.policy
deleted file mode 100644
index 5b5c322..0000000
--- a/server-worker/src/main/resources/security.policy
+++ /dev/null
@@ -1,11 +0,0 @@
-//keystore "signers.jks";
-//grant signedBy "taverna" {
-// permission java.util.PropertyPermission "*", "read,write";
-// permission java.lang.RuntimePermission "shutdownHooks";
-// permission java.lang.RuntimePermission "exitVM";
-// permission java.io.FilePermission "<<ALL FILES>>", "read,write,execute,delete";
-// permission java.net.SocketPermission "localhost:1024-" "accept,connect,listen";
-//};
-grant {
- permission java.security.AllPermission "*:*";
-};
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
----------------------------------------------------------------------
diff --git a/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java b/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
deleted file mode 100644
index 7bcd92e..0000000
--- a/server-worker/src/test/java/org/taverna/server/localworker/impl/LocalWorkerTest.java
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.localworker.impl;
-
-import static java.util.UUID.randomUUID;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.taverna.server.localworker.impl.LocalWorker.DO_MKDIR;
-
-import java.io.File;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.taverna.server.localworker.api.Worker;
-import org.taverna.server.localworker.api.WorkerFactory;
-import org.taverna.server.localworker.remote.IllegalStateTransitionException;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteInput;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.server.UsageRecordReceiver;
-
-public class LocalWorkerTest {
- LocalWorker lw;
- static List<String> events;
-
- public static RemoteStatus returnThisStatus = RemoteStatus.Operating;
-
- static class DummyWorker implements Worker {
- @Override
- public RemoteListener getDefaultListener() {
- return new RemoteListener() {
- @Override
- public String getConfiguration() {
- return "RLCONFIG";
- }
-
- @Override
- public String getName() {
- return "RLNAME";
- }
-
- @Override
- public String getProperty(String propName) {
- return "RLPROP[" + propName + "]";
- }
-
- @Override
- public String getType() {
- return "RLTYPE";
- }
-
- @Override
- public String[] listProperties() {
- return new String[] { "RLP1", "RLP2" };
- }
-
- @Override
- public void setProperty(String propName, String value) {
- events.add("setProperty[");
- events.add(propName);
- events.add(value);
- events.add("]");
- }
- };
- }
-
- @Override
- public RemoteStatus getWorkerStatus() {
- events.add("status=" + returnThisStatus);
- return returnThisStatus;
- }
-
- @Override
- public boolean initWorker(LocalWorker local,
- String executeWorkflowCommand, byte[] workflow,
- File workingDir, File inputBaclava,
- Map<String, File> inputFiles, Map<String, String> inputValues,
- Map<String, String> delimiters, File outputBaclava, File cmdir,
- char[] cmpass, boolean doprov, Map<String, String> env,
- String id, List<String> conf) throws Exception {
- events.add("init[");
- events.add(executeWorkflowCommand);
- events.add(new String(workflow, "UTF-8"));
- int dirLen = workingDir.getName().length();
- events.add(Integer.toString(dirLen));
- events.add(inputBaclava == null ? "<null>" : inputBaclava
- .toString().substring(dirLen));
- Map<String, String> in = new TreeMap<>();
- for (Entry<String, File> name : inputFiles.entrySet())
- in.put(name.getKey(), name.getValue() == null ? "<null>" : name
- .getValue().getName());
- events.add(in.toString());
- events.add(new TreeMap<>(inputValues).toString());
- events.add(outputBaclava == null ? "<null>" : outputBaclava
- .getName());
- // TODO: check cmdir and cmpass
- // TODO: check doprov
- // TODO: log env
- // TODO: check delimiters
- events.add("]");
- return true;
- }
-
- @Override
- public void killWorker() throws Exception {
- events.add("kill");
- }
-
- @Override
- public void startWorker() throws Exception {
- events.add("start");
- }
-
- @Override
- public void stopWorker() throws Exception {
- events.add("stop");
- }
-
- @Override
- public void setURReceiver(UsageRecordReceiver receiver) {
- // We just ignore this
- }
-
- @Override
- public void deleteLocalResources() throws ImplementationException {
- // Nothing to do here
- }
- }
-
- WorkerFactory factory = new WorkerFactory() {
- @Override
- public Worker makeInstance() throws Exception {
- return new DummyWorker();
- }
- };
-
- @Before
- public void setUp() throws Exception {
- lw = new LocalWorker("XWC", "WF".getBytes("UTF-8"), null, randomUUID(),
- new HashMap<String, String>(), new ArrayList<String>(), factory);
- events = new ArrayList<>();
- returnThisStatus = RemoteStatus.Operating;
- }
-
- @After
- public void tearDown() throws Exception {
- lw.destroy();
- }
-
- private List<String> l(String... strings) {
- return Arrays.asList(strings);
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- @Test
- public void testDestroy1() throws Exception {
- lw.destroy();
- assertEquals(l(), events);
- }
-
- @Test
- public void testDestroy2() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.destroy();
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "kill"), events);
- }
-
- @Test
- public void testDestroy3() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.destroy();
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "stop", "kill"), events);
- }
-
- @Test
- public void testDestroy4() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "kill"), events);
- lw.destroy();
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "kill"), events);
- }
-
- @Test
- public void testAddListener() {
- Throwable t = null;
- try {
- lw.addListener(null);
- } catch (Throwable caught) {
- t = caught;
- }
- assertNotNull(t);
- assertSame(ImplementationException.class, t.getClass());
- assertNotNull(t.getMessage());
- assertEquals("not implemented", t.getMessage());
- }
-
- @Test
- public void testGetInputBaclavaFile() throws Exception {
- assertNull(lw.getInputBaclavaFile());
- lw.setInputBaclavaFile("IBaclava");
- assertNotNull(lw.getInputBaclavaFile());
- assertEquals("IBaclava", lw.getInputBaclavaFile());
- lw.makeInput("FOO").setValue("BAR");
- assertNull(lw.getInputBaclavaFile());
- }
-
- @Test
- public void testGetInputsWithValue() throws Exception {
- assertEquals(0, lw.getInputs().size());
-
- lw.makeInput("FOO").setValue("BAR");
-
- assertEquals(1, lw.getInputs().size());
- assertEquals("FOO", lw.getInputs().get(0).getName());
- assertNull(lw.getInputs().get(0).getFile());
- assertNotNull(lw.getInputs().get(0).getValue());
-
- lw.setInputBaclavaFile("BLAH");
-
- assertEquals(1, lw.getInputs().size());
- assertNull(lw.getInputs().get(0).getFile());
- assertNull(lw.getInputs().get(0).getValue());
- }
-
- @Test
- public void testGetInputsWithFile() throws Exception {
- assertEquals(0, lw.getInputs().size());
-
- lw.makeInput("BAR").setFile("FOO");
-
- assertEquals(1, lw.getInputs().size());
- assertEquals("BAR", lw.getInputs().get(0).getName());
- assertNotNull(lw.getInputs().get(0).getFile());
- assertNull(lw.getInputs().get(0).getValue());
-
- lw.setInputBaclavaFile("BLAH");
-
- assertEquals(1, lw.getInputs().size());
- assertNull(lw.getInputs().get(0).getFile());
- assertNull(lw.getInputs().get(0).getValue());
- }
-
- @Test
- public void testGetListenerTypes() {
- assertEquals("[]", lw.getListenerTypes().toString());
- }
-
- @Test
- public void testGetListeners() throws Exception {
- assertEquals(1, lw.getListeners().size());
- RemoteListener rl = lw.getListeners().get(0);
- assertEquals("RLNAME", rl.getName());
- assertEquals("RLCONFIG", rl.getConfiguration());
- assertEquals("RLTYPE", rl.getType());
- assertEquals("[RLP1, RLP2]", Arrays.asList(rl.listProperties())
- .toString());
- assertEquals("RLPROP[RLP1]", rl.getProperty("RLP1"));
- assertEquals("RLPROP[RLP2]", rl.getProperty("RLP2"));
- rl.setProperty("FOOBAR", "BARFOO");
- assertEquals(l("setProperty[", "FOOBAR", "BARFOO", "]"), events);
- }
-
- @Test
- public void testGetOutputBaclavaFile() throws Exception {
- assertNull(lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile("notnull");
- assertEquals("notnull", lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile(null);
- assertNull(lw.getOutputBaclavaFile());
- }
-
- @Test
- public void testGetSecurityContext() throws Exception {
- boolean md = DO_MKDIR;
- LocalWorker.DO_MKDIR = false; // HACK! Work around Hudson problem...
- try {
- assertNotNull(lw.getSecurityContext());
- } finally {
- LocalWorker.DO_MKDIR = md;
- }
- }
-
- @Test
- public void testGetStatusInitial() {
- assertEquals(RemoteStatus.Initialized, lw.getStatus());
- }
-
- @Test
- public void testGetStatus() throws Exception {
- assertEquals(RemoteStatus.Initialized, lw.getStatus());
- returnThisStatus = RemoteStatus.Operating;
- assertEquals(RemoteStatus.Initialized, lw.getStatus());
- lw.setStatus(RemoteStatus.Operating);
- assertEquals(RemoteStatus.Operating, lw.getStatus());
- assertEquals(RemoteStatus.Operating, lw.getStatus());
- returnThisStatus = RemoteStatus.Finished;
- assertEquals(RemoteStatus.Finished, lw.getStatus());
- returnThisStatus = RemoteStatus.Stopped;
- assertEquals(RemoteStatus.Finished, lw.getStatus());
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "status=Operating", "status=Operating",
- "status=Finished"), events);
- }
-
- @Test
- public void testGetWorkingDirectory() throws Exception {
- RemoteDirectory rd = lw.getWorkingDirectory();
- assertNotNull(rd);
- assertNotNull(rd.getContents());
- assertNull(rd.getContainingDirectory());
- assertNotNull(rd.getName());
- assertEquals(-1, rd.getName().indexOf('/'));
- assertFalse("..".equals(rd.getName()));
- assertEquals("", rd.getName());
- }
-
- @Test
- public void testValidateFilename() throws Exception {
- lw.validateFilename("foobar");
- lw.validateFilename("foo/bar");
- lw.validateFilename("foo.bar");
- lw.validateFilename("foo..bar");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad0() throws Exception {
- lw.validateFilename("./.");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad1() throws Exception {
- lw.validateFilename("/");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad2() throws Exception {
- lw.validateFilename("");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad3() throws Exception {
- lw.validateFilename(null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad4() throws Exception {
- lw.validateFilename("..");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testValidateFilenameBad5() throws Exception {
- lw.validateFilename("foo/../bar");
- }
-
- @Test
- public void testMakeInput() throws Exception {
- assertEquals(0, lw.getInputs().size());
-
- RemoteInput ri = lw.makeInput("TEST");
-
- assertNotNull(ri);
- assertEquals(1, lw.getInputs().size());
- assertNotSame(ri, lw.getInputs().get(0)); // different delegates
- assertEquals("TEST", ri.getName());
- assertNull(ri.getFile());
- assertNull(ri.getValue());
-
- lw.setInputBaclavaFile("bad");
- ri.setFile("good");
- assertEquals("good", ri.getFile());
- assertNull(lw.getInputBaclavaFile());
- ri.setValue("very good");
- assertEquals("very good", ri.getValue());
- assertNull(ri.getFile());
- assertNull(lw.getInputBaclavaFile());
-
- lw.makeInput("TEST2");
- assertEquals(2, lw.getInputs().size());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testMakeInputFileSanity() throws Exception {
- lw.makeInput("foo").setFile("/../bar");
- }
-
- @Test
- public void testMakeListener() {
- Throwable t = null;
- try {
- lw.makeListener("?", "?");
- } catch (Throwable caught) {
- t = caught;
- }
- assertNotNull(t);
- assertSame(RemoteException.class, t.getClass());
- assertNotNull(t.getMessage());
- assertEquals("listener manufacturing unsupported", t.getMessage());
- }
-
- @Test
- public void testSetInputBaclavaFile1() throws Exception {
- assertNull(lw.getInputBaclavaFile());
- lw.setInputBaclavaFile("eg");
- assertEquals("eg", lw.getInputBaclavaFile());
- }
-
- @Test
- public void testSetInputBaclavaFile2() throws Exception {
- RemoteInput ri = lw.makeInput("foo");
- ri.setValue("bar");
- assertEquals("bar", ri.getValue());
- lw.setInputBaclavaFile("eg");
- assertNull(ri.getValue());
- }
-
- @Test
- public void testSetOutputBaclavaFile1() throws Exception {
- assertNull(lw.outputBaclava);
- lw.setOutputBaclavaFile("foobar");
- assertEquals("foobar", lw.outputBaclava);
- assertEquals("foobar", lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile("foo/bar");
- assertEquals("foo/bar", lw.outputBaclava);
- assertEquals("foo/bar", lw.getOutputBaclavaFile());
- lw.setOutputBaclavaFile(null);
- assertNull(lw.outputBaclava);
- assertNull(lw.getOutputBaclavaFile());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSetOutputBaclavaFile2() throws Exception {
- lw.setOutputBaclavaFile("/foobar");
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testSetOutputBaclavaFile3() throws Exception {
- lw.setOutputBaclavaFile("foo/../bar");
- }
-
- @Test
- public void testSetStatus0() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Finished);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "stop", "start", "kill"), events);
- }
-
- @Test
- public void testSetStatus1() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>", "{}", "{}", "<null>",
- "]", "stop", "kill"), events);
- }
-
- @Test
- public void testSetStatus2() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Finished);
- assertEquals(l(), events);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus3() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Finished);
- lw.setStatus(RemoteStatus.Initialized);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus4() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Initialized);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus5() throws Exception {
- lw.setStatus(RemoteStatus.Initialized);
- lw.setStatus(RemoteStatus.Stopped);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus6() throws Exception {
- lw.setStatus(RemoteStatus.Finished);
- lw.setStatus(RemoteStatus.Stopped);
- }
-
- @Test(expected = IllegalStateTransitionException.class)
- public void testSetStatus7() throws Exception {
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Stopped);
- lw.setStatus(RemoteStatus.Initialized);
- }
-
- @Test
- public void testLifecycle() throws Exception {
- lw.makeInput("foo").setFile("foofile");
- lw.makeInput("bar").setValue("barvalue");
- lw.setOutputBaclavaFile("spong");
- lw.setOutputBaclavaFile("boo");
- lw.setStatus(RemoteStatus.Operating);
- lw.setStatus(RemoteStatus.Finished);
- // Assumes order of map, so fragile but works...
- assertEquals(
- l("init[", "XWC", "WF", "36", "<null>",
- "{bar=<null>, foo=foofile}",
- "{bar=barvalue, foo=null}", "boo", "]", "kill"), events);
- }
-}
[36/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java
deleted file mode 100644
index f387cf6..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import static java.lang.Math.min;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.rest.FileSegment;
-
-/**
- * How to write out a segment of a file with JAX-RS.
- *
- * @author Donal Fellows
- */
-@Provider
-public class FileSegmentHandler implements MessageBodyWriter<FileSegment> {
- /** How much to pull from the worker in one read. */
- private int maxChunkSize;
-
- /**
- * @param maxChunkSize
- * How much to pull from the worker in one read.
- */
- public void setMaxChunkSize(int maxChunkSize) {
- this.maxChunkSize = maxChunkSize;
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return FileSegment.class.isAssignableFrom(type);
- }
-
- @Override
- public long getSize(FileSegment t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return t.to - t.from;
- }
-
- @Override
- public void writeTo(FileSegment t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- try {
- int off = t.from;
- while (off < t.to) {
- byte[] buffer = t.file.getContents(off,
- min(maxChunkSize, t.to - off));
- if (buffer == null || buffer.length == 0)
- break;
- entityStream.write(buffer);
- off += buffer.length;
- }
- } catch (FilesystemAccessException e) {
- throw new IOException("problem when reading file", e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java
deleted file mode 100644
index 12c137e..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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 javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-
-@Provider
-public class FilesystemAccessHandler extends HandlerCore implements
- ExceptionMapper<FilesystemAccessException> {
- @Override
- public Response toResponse(FilesystemAccessException exn) {
- return respond(FORBIDDEN, exn);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java
deleted file mode 100644
index 775805b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 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.INTERNAL_SERVER_ERROR;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-
-import org.taverna.server.master.exceptions.GeneralFailureException;
-
-public class GeneralFailureHandler extends HandlerCore implements
- ExceptionMapper<GeneralFailureException> {
- @Override
- public Response toResponse(GeneralFailureException exception) {
- return respond(INTERNAL_SERVER_ERROR, exception);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java
deleted file mode 100644
index 0e3fb51..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.MediaType.TEXT_PLAIN_TYPE;
-import static javax.ws.rs.core.Response.status;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import javax.ws.rs.core.Response;
-
-import org.apache.commons.logging.Log;
-import org.taverna.server.master.api.ManagementModel;
-
-/**
- * Base class for handlers that grants Spring-enabled access to the management
- * model.
- *
- * @author Donal Fellows
- */
-public class HandlerCore {
- private Log log = getLog("Taverna.Server.Webapp");
- private ManagementModel managementModel;
-
- /**
- * @param managementModel
- * the managementModel to set
- */
- public void setManagementModel(ManagementModel managementModel) {
- this.managementModel = managementModel;
- }
-
- /**
- * Simplified interface for building responses.
- *
- * @param status
- * What status code to use?
- * @param exception
- * What exception to report on?
- * @return The build response.
- */
- protected Response respond(Response.Status status, Exception exception) {
- if (managementModel.getLogOutgoingExceptions()
- || status.getStatusCode() >= 500)
- log.info("converting exception to response", exception);
- return status(status).type(TEXT_PLAIN_TYPE)
- .entity(exception.getMessage()).build();
- }
-
- /**
- * Simplified interface for building responses.
- *
- * @param status
- * What status code to use?
- * @param partialMessage
- * The prefix to the message.
- * @param exception
- * What exception to report on?
- * @return The build response.
- */
- protected Response respond(Response.Status status, String partialMessage,
- Exception exception) {
- if (managementModel.getLogOutgoingExceptions()
- || status.getStatusCode() >= 500)
- log.info("converting exception to response", exception);
- return status(status).type(TEXT_PLAIN_TYPE)
- .entity(partialMessage + "\n" + exception.getMessage()).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java
deleted file mode 100644
index ac02015..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 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.UNSUPPORTED_MEDIA_TYPE;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
-@Provider
-public class IllegalArgumentHandler extends HandlerCore implements
- ExceptionMapper<IllegalArgumentException> {
- @Override
- public Response toResponse(IllegalArgumentException exn) {
- return respond(UNSUPPORTED_MEDIA_TYPE, exn);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java
deleted file mode 100644
index 1458667..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 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.INTERNAL_SERVER_ERROR;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-
-import org.taverna.server.localworker.remote.ImplementationException;
-
-public class ImplementationProblemHandler extends HandlerCore implements
- ExceptionMapper<ImplementationException> {
- @Override
- public Response toResponse(ImplementationException exception) {
- return respond(INTERNAL_SERVER_ERROR, exception);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java
deleted file mode 100644
index 2c0c092..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import static java.lang.Long.parseLong;
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
-import static org.apache.commons.logging.LogFactory.getLog;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.List;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.Provider;
-
-import org.apache.commons.logging.Log;
-
-/**
- * Maps a stream from a client into a bounded ordinary input stream that the
- * webapp can work with more easily.
- *
- * @author Donal Fellows
- */
-@Provider
-@Consumes(APPLICATION_OCTET_STREAM)
-public class InputStreamMessageHandler implements
- MessageBodyReader<InputStream> {
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return InputStream.class.isAssignableFrom(type);
- }
-
- @Override
- public InputStream readFrom(Class<InputStream> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
- return new TransferStream(entityStream,
- httpHeaders.get("Content-Length"));
- }
-}
-
-/**
- * The actual transfer thunk.
- *
- * @author Donal Fellows
- */
-class TransferStream extends InputStream {
- private Log log = getLog("Taverna.Server.Handlers");
-
- public TransferStream(InputStream entityStream, List<String> contentLength) {
- this.entityStream = new BufferedInputStream(entityStream);
- if (contentLength != null && contentLength.size() > 0) {
- this.limit = parseLong(contentLength.get(0));
- if (log.isDebugEnabled())
- log.debug("will attempt to transfer " + this.limit + " bytes");
- } else {
- this.limit = -1;
- if (log.isDebugEnabled())
- log.debug("will attempt to transfer until EOF");
- }
- }
-
- InputStream entityStream;
- long limit;
- long doneBytes = 0;
-
- @Override
- public int read() throws IOException {
- if (limit >= 0 && doneBytes >= limit)
- return -1;
- int result = entityStream.read();
- if (result >= 0)
- doneBytes++;
- return result;
- }
-
- @Override
- public int read(byte[] ary, int off, int len) throws IOException {
- if (limit >= 0) {
- if (doneBytes >= limit)
- return -1;
- if (doneBytes + len > limit)
- len = (int) (limit - doneBytes);
- }
- int readBytes = entityStream.read(ary, off, len);
- if (readBytes >= 0)
- doneBytes += readBytes;
- return readBytes;
- }
-
- @Override
- public void close() throws IOException {
- entityStream.close();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java
deleted file mode 100644
index fe11de8..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 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.InvalidCredentialException;
-
-@Provider
-public class InvalidCredentialHandler extends HandlerCore implements
- ExceptionMapper<InvalidCredentialException> {
- @Override
- public Response toResponse(InvalidCredentialException 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java
deleted file mode 100644
index 33ac6a0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 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 javax.xml.bind.JAXBException;
-
-@Provider
-public class JAXBExceptionHandler extends HandlerCore implements
- ExceptionMapper<JAXBException> {
- @Override
- public Response toResponse(JAXBException exn) {
- return respond(BAD_REQUEST, "APIEpicFail: " + exn.getErrorCode(), exn);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java
deleted file mode 100644
index 47153e7..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-import static javax.ws.rs.core.Response.notAcceptable;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.rest.TavernaServerDirectoryREST.NegotiationFailedException;
-
-@Provider
-public class NegotiationFailedHandler implements
- ExceptionMapper<NegotiationFailedException> {
- @Override
- public Response toResponse(NegotiationFailedException exn) {
- return notAcceptable(exn.accepted).type(TEXT_PLAIN)
- .entity(exn.getMessage()).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java
deleted file mode 100644
index e4215a1..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.SERVICE_UNAVAILABLE;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.exceptions.NoCreateException;
-
-@Provider
-public class NoCreateHandler extends HandlerCore implements
- ExceptionMapper<NoCreateException> {
- @Override
- public Response toResponse(NoCreateException exn) {
- return respond(SERVICE_UNAVAILABLE, exn);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java
deleted file mode 100644
index d81f6ba..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 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 org.taverna.server.master.exceptions.NoCredentialException;
-
-public class NoCredentialHandler extends HandlerCore implements
- ExceptionMapper<NoCredentialException> {
- @Override
- public Response toResponse(NoCredentialException exn) {
- return respond(NOT_FOUND, exn);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java
deleted file mode 100644
index 927af4b..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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 javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.exceptions.NoDestroyException;
-
-@Provider
-public class NoDestroyHandler extends HandlerCore implements
- ExceptionMapper<NoDestroyException> {
- @Override
- public Response toResponse(NoDestroyException exn) {
- return respond(FORBIDDEN, exn);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
deleted file mode 100644
index ab2e54d..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.NoDirectoryEntryException;
-
-@Provider
-public class NoDirectoryEntryHandler extends HandlerCore implements
- ExceptionMapper<NoDirectoryEntryException> {
- @Override
- public Response toResponse(NoDirectoryEntryException 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java
deleted file mode 100644
index 36e3053..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.NoListenerException;
-
-@Provider
-public class NoListenerHandler extends HandlerCore implements
- ExceptionMapper<NoListenerException> {
- @Override
- public Response toResponse(NoListenerException 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java
deleted file mode 100644
index 61a89d4..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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 javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.exceptions.NoUpdateException;
-
-@Provider
-public class NoUpdateHandler extends HandlerCore implements
- ExceptionMapper<NoUpdateException> {
- @Override
- public Response toResponse(NoUpdateException exn) {
- return respond(FORBIDDEN, exn);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java
deleted file mode 100644
index 44de871..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 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.taverna.server.master.exceptions.NotOwnerException;
-
-public class NotOwnerHandler extends HandlerCore implements
- ExceptionMapper<NotOwnerException> {
- @Override
- public Response toResponse(NotOwnerException exn) {
- return respond(FORBIDDEN, exn);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java
deleted file mode 100644
index 21e5e68..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2013 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.SERVICE_UNAVAILABLE;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.exceptions.OverloadedException;
-
-@Provider
-public class OverloadedHandler extends HandlerCore implements
- ExceptionMapper<OverloadedException> {
- @Override
- public Response toResponse(OverloadedException exn) {
- return respond(SERVICE_UNAVAILABLE, exn);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java
deleted file mode 100644
index 03a4dd4..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 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.MediaType.TEXT_PLAIN_TYPE;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-
-import org.taverna.server.master.common.Permission;
-
-/**
- * Handler that allows CXF to send and receive {@linkplain Permission
- * permissions} as plain text directly.
- *
- * @author Donal Fellows
- */
-public class PermissionHandler implements MessageBodyReader<Permission>,
- MessageBodyWriter<Permission> {
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return type.isAssignableFrom(Permission.class)
- && mediaType.isCompatible(TEXT_PLAIN_TYPE);
- }
-
- @Override
- public long getSize(Permission t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return t.toString().length();
- }
-
- @Override
- public void writeTo(Permission t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- new OutputStreamWriter(entityStream).write(t.toString());
- }
-
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return type.isAssignableFrom(Permission.class)
- && mediaType.isCompatible(TEXT_PLAIN_TYPE);
- }
-
- @Override
- public Permission readFrom(Class<Permission> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
- char[] cbuf = new char[7];
- int len = new InputStreamReader(entityStream).read(cbuf);
- if (len < 0)
- throw new IllegalArgumentException("no entity supplied");
- return Permission.valueOf(new String(cbuf, 0, len));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
deleted file mode 100644
index edeac63..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE.txt" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.common.Workflow;
-
-import uk.org.taverna.scufl2.api.io.ReaderException;
-import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
-import uk.org.taverna.scufl2.api.io.WriterException;
-
-/**
- * Handler that allows a .scufl2 document to be read from and written to a REST
- * message directly.
- *
- * @author Donal Fellows
- */
-@Provider
-public class Scufl2DocumentHandler implements MessageBodyReader<Workflow>,
- MessageBodyWriter<Workflow> {
- private static final MediaType SCUFL2_TYPE = new MediaType("application",
- "vnd.taverna.scufl2.workflow-bundle");
- public static final String SCUFL2 = "application/vnd.taverna.scufl2.workflow-bundle";
- private WorkflowBundleIO io = new WorkflowBundleIO();
-
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (type.isAssignableFrom(Workflow.class))
- return mediaType.isCompatible(SCUFL2_TYPE);
- return false;
- }
-
- @Override
- public Workflow readFrom(Class<Workflow> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
- try {
- return new Workflow(io.readBundle(entityStream, SCUFL2));
- } catch (ReaderException e) {
- throw new WebApplicationException(e, 403);
- }
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (Workflow.class.isAssignableFrom(type))
- return mediaType.isCompatible(SCUFL2_TYPE);
- return false;
- }
-
- @Override
- public long getSize(Workflow workflow, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(Workflow workflow, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- try {
- io.writeBundle(workflow.getScufl2Workflow(), entityStream, SCUFL2);
- } catch (WriterException e) {
- throw new WebApplicationException(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
deleted file mode 100644
index 4227d80..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.taverna.server.master.common.Workflow;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-/**
- * Handler that allows a .t2flow document to be read from and written to a REST
- * message directly.
- *
- * @author Donal Fellows
- */
-@Provider
-public class T2FlowDocumentHandler implements MessageBodyReader<Workflow>,
- MessageBodyWriter<Workflow> {
- private static final MediaType T2FLOW_TYPE = new MediaType("application",
- "vnd.taverna.t2flow+xml");
- public static final String T2FLOW = "application/vnd.taverna.t2flow+xml";
- public static final String T2FLOW_ROOTNAME = "workflow";
- public static final String T2FLOW_NS = "http://taverna.sf.net/2008/xml/t2flow";
- private DocumentBuilderFactory db;
- private TransformerFactory transformer;
-
- public T2FlowDocumentHandler() throws ParserConfigurationException,
- TransformerConfigurationException {
- db = DocumentBuilderFactory.newInstance();
- db.setNamespaceAware(true);
- transformer = TransformerFactory.newInstance();
- }
-
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (type.isAssignableFrom(Workflow.class))
- return mediaType.isCompatible(T2FLOW_TYPE);
- return false;
- }
-
- @Override
- public Workflow readFrom(Class<Workflow> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
- Document doc;
- try {
- doc = db.newDocumentBuilder().parse(entityStream);
- } catch (SAXException e) {
- throw new WebApplicationException(e, 403);
- } catch (ParserConfigurationException e) {
- throw new WebApplicationException(e);
- }
- Workflow workflow = new Workflow(doc.getDocumentElement());
- if (doc.getDocumentElement().getNamespaceURI().equals(T2FLOW_NS)
- && doc.getDocumentElement().getNodeName()
- .equals(T2FLOW_ROOTNAME))
- return workflow;
- throw new WebApplicationException(Response.status(403)
- .entity("invalid T2flow document; bad root element")
- .type("text/plain").build());
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- if (Workflow.class.isAssignableFrom(type))
- return mediaType.isCompatible(T2FLOW_TYPE);
- return false;
- }
-
- @Override
- public long getSize(Workflow workflow, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(Workflow workflow, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- try {
- transformer.newTransformer().transform(
- new DOMSource(workflow.getT2flowWorkflow()),
- new StreamResult(entityStream));
- } catch (TransformerException e) {
- if (e.getCause() != null && e.getCause() instanceof IOException)
- throw (IOException) e.getCause();
- throw new WebApplicationException(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java
deleted file mode 100644
index a90a229..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-import static org.taverna.server.master.rest.handler.URIListHandler.URI_LIST;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyReader;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-/**
- * Deserialization and serialization engine for the <tt>{@value #URI_LIST}</tt>
- * content type.
- *
- * @author Donal Fellows
- */
-@Provider
-@Consumes(URI_LIST)
-public class URIListHandler implements MessageBodyReader<List<URI>>,
- MessageBodyWriter<List<URI>> {
- /** The content type we handle. */
- public static final String URI_LIST = "text/uri-list";
- private static final MediaType URILIST = new MediaType("text", "uri-list");
-
- @Override
- public boolean isReadable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return type.isAssignableFrom(ArrayList.class)
- && genericType instanceof ParameterizedType
- && ((Class<?>) ((ParameterizedType) genericType)
- .getActualTypeArguments()[0])
- .isAssignableFrom(URI.class)
- && URILIST.isCompatible(mediaType);
- }
-
- @Override
- public List<URI> readFrom(Class<List<URI>> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
- throws IOException, WebApplicationException {
- String enc = mediaType.getParameters().get("encoding");
- Charset c = (enc == null) ? Charset.defaultCharset() : Charset
- .forName(enc);
- BufferedReader br = new BufferedReader(new InputStreamReader(
- entityStream, c));
- ArrayList<URI> uris = new ArrayList<>();
- String line;
- while ((line = br.readLine()) != null) {
- if (line.startsWith("#"))
- continue;
- try {
- uris.add(new URI(line));
- } catch (URISyntaxException e) {
- throw new WebApplicationException(e, status(422).entity(
- "ill-formed URI").build());
- }
- }
- return uris;
- }
-
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return List.class.isAssignableFrom(type)
- && genericType instanceof ParameterizedType
- && ((ParameterizedType) genericType).getActualTypeArguments()[0] == URI.class
- && URILIST.isCompatible(mediaType);
- }
-
- @Override
- public long getSize(List<URI> list, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- private static final String PREFERRED_ENCODING = "UTF-8";
-
- @Override
- public void writeTo(List<URI> list, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException {
- String encoding = mediaType.getParameters().get("encoding");
- if (encoding == null) {
- encoding = PREFERRED_ENCODING;
- httpHeaders.putSingle("Content-Type", URI_LIST + ";encoding="
- + encoding);
- }
- BufferedWriter w = new BufferedWriter(new OutputStreamWriter(
- entityStream, encoding));
- for (URI uri : list) {
- w.write(uri.toString());
- w.newLine();
- }
- w.flush();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java
deleted file mode 100644
index 4542237..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.UnknownRunException;
-
-@Provider
-public class UnknownRunHandler extends HandlerCore implements
- ExceptionMapper<UnknownRunException> {
- @Override
- public Response toResponse(UnknownRunException 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/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java
deleted file mode 100644
index 2241220..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.rest.handler;
-
-import static org.apache.commons.io.IOUtils.copy;
-import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.ext.MessageBodyWriter;
-import javax.ws.rs.ext.Provider;
-
-import org.taverna.server.master.interfaces.Directory.ZipStream;
-
-/**
- * How to write a ZIP file as the result entity of a request.
- *
- * @author Donal Fellows
- */
-@Provider
-@Produces("application/zip")
-public class ZipStreamHandler implements MessageBodyWriter<ZipStream> {
- @Override
- public boolean isWriteable(Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return ZipStream.class.isAssignableFrom(type)
- && mediaType.equals(APPLICATION_ZIP_TYPE);
- }
-
- @Override
- public long getSize(ZipStream t, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- @Override
- public void writeTo(ZipStream zipStream, Class<?> type, Type genericType,
- Annotation[] annotations, MediaType mediaType,
- MultivaluedMap<String, Object> httpHeaders,
- OutputStream entityStream) throws IOException,
- WebApplicationException {
- copy(zipStream, entityStream);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java
deleted file mode 100644
index e72af22..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains type handlers for the RESTful interface to Taverna Server.
- * @author Donal Fellows
- */
-@XmlSchema(namespace = SERVER_REST, 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 = "port", namespaceURI = DATA),
- @XmlNs(prefix = "feed", namespaceURI = FEED),
- @XmlNs(prefix = "admin", namespaceURI = ADMIN) })
-package org.taverna.server.master.rest.handler;
-
-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.XLINK;
-import static org.taverna.server.port_description.Namespaces.DATA;
-
-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/server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java
deleted file mode 100644
index 0a0b069..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * This package contains the RESTful interface to Taverna Server.
- * @author Donal Fellows
- */
-@XmlSchema(namespace = SERVER_REST, 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 = "port", namespaceURI = DATA),
- @XmlNs(prefix = "feed", namespaceURI = FEED),
- @XmlNs(prefix = "admin", namespaceURI = ADMIN) })
-package org.taverna.server.master.rest;
-
-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.XLINK;
-import static org.taverna.server.port_description.Namespaces.DATA;
-
-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/server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java b/server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java
deleted file mode 100644
index bb8d73f..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.soap;
-
-import static org.taverna.server.master.common.Namespaces.XLINK;
-
-import java.net.URI;
-
-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.XmlType;
-
-import org.taverna.server.master.common.DirEntryReference;
-
-/**
- * A more Taverna-friendly version of the directory entry descriptor classes.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "DirectoryEntry")
-@XmlRootElement(name = "entry")
-@XmlSeeAlso({ DirEntry.File.class, DirEntry.Directory.class })
-public class DirEntry {
- /** A link to the entry. Ignored on input. */
- @XmlAttribute(name = "href", namespace = XLINK)
- @XmlSchemaType(name = "anyURI")
- public URI link;
- @XmlAttribute
- public String name;
- @XmlElement(required = true)
- public String path;
-
- /**
- * A file in a directory.
- *
- * @author Donal Fellows
- */
- @XmlType(name = "FileDirEntry")
- @XmlRootElement(name = "file")
- public static class File extends DirEntry {
- }
-
- /**
- * A directory in a directory. That is, a sub-directory.
- *
- * @author Donal Fellows
- */
- @XmlType(name = "DirectoryDirEntry")
- @XmlRootElement(name = "dir")
- public static class Directory extends DirEntry {
- }
-
- /**
- * Converts from the "common" format to the subclasses of this class.
- *
- * @param deref
- * The "common" format handle to convert.
- * @return The converted handle
- */
- public static DirEntry convert(DirEntryReference deref) {
- DirEntry result;
- if (deref instanceof DirEntryReference.DirectoryReference)
- result = new Directory();
- else if (deref instanceof DirEntryReference.FileReference)
- result = new File();
- else
- result = new DirEntry();
- result.link = deref.link;
- result.name = deref.name;
- result.path = deref.path;
- return result;
- }
-
- /**
- * Converts to the "common" format from the subclasses of this class.
- *
- * @param deref
- * The subclass of this class to convert.
- * @return The converted reference.
- */
- public static DirEntryReference convert(DirEntry de) {
- DirEntryReference result;
- if (de instanceof Directory)
- result = new DirEntryReference.DirectoryReference();
- else if (de instanceof File)
- result = new DirEntryReference.FileReference();
- else
- result = new DirEntryReference();
- result.link = de.link;
- result.name = de.name;
- result.path = de.path;
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java b/server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java
deleted file mode 100644
index 7ebc991..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.soap;
-
-import static java.lang.Math.min;
-import static java.lang.System.arraycopy;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlMimeType;
-import javax.xml.bind.annotation.XmlType;
-
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.interfaces.File;
-
-/**
- * An MTOM-capable description of how to transfer the contents of a file.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "FileContents")
-public class FileContents {
- @XmlElement
- public String name;
- @XmlMimeType("application/octet-stream") // JAXB bug: must be this
- public DataHandler fileData;
-
- /**
- * Initialize the contents of this descriptor from the given file and
- * content type.
- *
- * @param file
- * The file that is to be reported.
- * @param contentType
- * The estimated content type of the file.
- */
- public void setFile(File file, String contentType) {
- name = file.getFullName();
- fileData = new DataHandler(new TavernaFileSource(file, contentType));
- }
-
- /**
- * Write the content described by this class to the specified file.
- * @param file The file to write to; must already exist.
- * @throws IOException
- * @throws FilesystemAccessException
- */
- public void writeToFile(File file) throws IOException,
- FilesystemAccessException {
- try (InputStream is = fileData.getInputStream()) {
- byte[] buf = new byte[65536];
- file.setContents(new byte[0]);
- while (true) {
- int len = is.read(buf);
- if (len <= 0)
- return;
- if (len == buf.length)
- file.appendContents(buf);
- else {
- byte[] shortbuf = new byte[len];
- arraycopy(buf, 0, shortbuf, 0, len);
- file.appendContents(shortbuf);
- }
- }
- }
- }
-}
-
-/**
- * A data source that knows how to communicate with the Taverna Server back-end.
- *
- * @author Donal Fellows
- */
-class TavernaFileSource implements DataSource {
- TavernaFileSource(File f, String type) {
- this.f = f;
- this.type = type;
- }
-
- private final File f;
- private final String type;
-
- @Override
- public String getContentType() {
- return type;
- }
-
- @Override
- public String getName() {
- return f.getName();
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- final File f = this.f;
- return new InputStream() {
- private int idx;
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- byte[] r;
- try {
- r = f.getContents(idx, len);
- } catch (FilesystemAccessException e) {
- throw new IOException(e);
- }
- if (r == null)
- return -1;
- len = min(len, r.length);
- arraycopy(r, 0, b, off, len);
- idx += len;
- return len;
- }
-
- @Override
- public int read() throws IOException {
- byte[] r;
- try {
- r = f.getContents(idx, 1);
- } catch (FilesystemAccessException e) {
- throw new IOException(e);
- }
- if (r == null)
- return -1;
- idx++;
- return r[0];
- }
- };
- }
-
- @Override
- public OutputStream getOutputStream() throws IOException {
- final File f = this.f;
- return new OutputStream() {
- private boolean append = false;
-
- @Override
- public void write(int b) throws IOException {
- write(new byte[] { (byte) b });
- }
-
- @Override
- public void write(byte[] b) throws IOException {
- try {
- if (append)
- f.appendContents(b);
- else
- f.setContents(b);
- append = true;
- } catch (FilesystemAccessException e) {
- throw new IOException(e);
- }
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- byte[] ary = new byte[len];
- arraycopy(b, off, ary, 0, len);
- write(ary);
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java b/server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java
deleted file mode 100644
index 3ab6d0c..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.soap;
-
-import java.util.List;
-
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
-import org.taverna.server.master.common.Permission;
-
-/**
- * The list of permissions to access a workflow run of users <i>other than the
- * owner</i>. This class exists to support the JAXB mapping.
- *
- * @author Donal Fellows
- */
-@XmlType(name = "PermissionList")
-@XmlRootElement(name = "permissionList")
-public class PermissionList {
- /**
- * The type of a single mapped permission. This class exists to support the
- * JAXB mapping.
- *
- * @author Donal Fellows
- */
- @XmlType(name = "")
- public static class SinglePermissionMapping {
- public SinglePermissionMapping() {
- }
-
- public SinglePermissionMapping(String user, Permission permission) {
- this.userName = user;
- this.permission = permission;
- }
-
- /** The name of the user that this talks about. */
- public String userName;
- /** The permission level that the user is granted. */
- public Permission permission;
- }
-
- /** The list of (non-default) permissions granted. */
- @XmlElement
- public List<SinglePermissionMapping> permission;
-}
\ No newline at end of file
[31/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/admin.js
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/admin.js b/server-webapp/src/main/resources/static/admin.js
deleted file mode 100644
index c2c41bf..0000000
--- a/server-webapp/src/main/resources/static/admin.js
+++ /dev/null
@@ -1,549 +0,0 @@
-// Wrappers round AJAX calls to simplify *most* of this stuff
-
-/** How to retrieve text asynchronously. */
-function getText(u, done) {
- $.ajax({
- type : "GET",
- url : u,
- async : true,
- cache : false,
- accept : "text/plain",
- dataType : "text",
- success : done
- });
-}
-/** How to retrieve JSON asynchronously. */
-function getJSON(u, done) {
- $.ajax({
- type : "GET",
- url : u,
- async : true,
- cache : false,
- dataType : "json",
- accept : "application/json",
- success : done
- });
-}
-/** How to send a PUT of text asynchronously. */
-function putText(u, val, done) {
- $.ajax({
- type : "PUT",
- url : u,
- async : false,
- cache : false,
- data : val,
- contentType : "text/plain",
- dataType : "text",
- processData : false,
- success : done,
- error : function(jqXHR, textStatus, errorThrown) {
- alert(errorThrown);
- }
- });
-}
-/** How to send a PUT of XML asynchronously. */
-function putXML(u, xml, done) {
- $.ajax({
- type : "PUT",
- url : u,
- async : false,
- cache : false,
- contentType : "application/xml",
- data : new XMLSerializer().serializeToString(xml),
- success : done,
- error : function(jqXHR, textStatus, errorThrown) {
- alert(errorThrown);
- }
- });
-}
-/** How to send a POST of XML asynchronously. */
-function postXML(u, xml, done) {
- $.ajax({
- type : "POST",
- url : u,
- async : false,
- cache : false,
- contentType : "application/xml",
- data : new XMLSerializer().serializeToString(xml),
- success : done,
- error : function(jqXHR, textStatus, errorThrown) {
- alert(errorThrown);
- }
- });
-}
-/** How to send a DELETE asynchronously. */
-function deleteUrl(u, done) {
- $.ajax({
- type : "DELETE",
- url : u,
- async : true,
- cache : false,
- success : done,
- error : function(jqXHR, textStatus, errorThrown) {
- alert(errorThrown);
- }
- });
-}
-
-/** Locates a URL with respect to the administrative REST interface. */
-function where(tail) {
- return $("#admin")[0].href + "/" + tail;
-}
-
-// Make an XML element structure
-// Derived from hack on Stack Overflow, but with extra tinkering
-/** Function called to create a node in an XML structure. */
-var Node;
-/** Function called to create nodes in an XML structure from an array. */
-var NodeAll;
-(function() {
- var doc = document.implementation.createDocument(null, null, null);
- var adminNS = "http://ns.taverna.org.uk/2010/xml/server/admin/";
- Node = function() {
- var node = doc.createElementNS(adminNS, arguments[0]), child;
- for ( var i = 1; i < arguments.length; i++) {
- child = arguments[i];
- if (child == undefined)
- continue;
- if (typeof child != 'object')
- child = doc.createTextNode(child.toString());
- node.appendChild(child);
- }
- return node;
- };
- NodeAll = function(wrapperElem, wrappedElem, elements) {
- var node = doc.createElementNS(adminNS, wrapperElem);
- for ( var i = 0; i < elements.length; i++) {
- var child = doc.createElementNS(adminNS, wrappedElem);
- var text = doc.createTextNode(elements[i]);
- child.appendChild(text);
- node.appendChild(child);
- }
- return node;
- };
-})();
-
-/** The IDs of boolean-coupled buttons. */
-var buttonlist = [ "allowNew", "logFaults", "logWorkflows", "generateProvenance" ];
-/** The IDs of values that track server variables without setting things. */
-var readonlies = [ "invokationCount", "lastExitCode", "runCount", "startupTime", "operatingCount" ];
-/** The IDs of text/numeric-coupled entries. */
-var entries = [ "defaultLifetime", "executeWorkflowScript", "javaBinary",
- "registrationPollMillis", "registrationWaitSeconds", "registryHost",
- "registryPort", "runLimit", "runasPasswordFile", "serverForkerJar",
- "serverWorkerJar", "usageRecordDumpFile", "operatingLimit",
- "registryJar" ];
-/** Cached information about users. */
-var userinfo = [];
-/** Extra arguments to pass to the runtime. */
-var extraAry = [];
-
-/** How to update the read-only fields; will be called periodically */
-function updateRO() {
- $.each(readonlies, function(idx, val) {
- var widget = $("#" + val);
- getText(where(val), function(data) {
- widget.html(data);
- });
- });
- getJSON(where("factoryProcessMapping"),
- function(data) {
- var ary = data.stringList.string;
- var tbl = $("#factoryProcessMapping");
- tbl.html("<tr><th>User<th>ID</tr>");
- if (ary != undefined)
- for ( var i = 0; i < ary.length - 1; i += 2)
- tbl.append("<tr><td>" + ary[i] + "<td>" + ary[i + 1]
- + "</tr>");
- });
-}
-
-/**
- * Generate a user row with suitable indices, but no content (it will be pushed
- * into the row later).
- */
-function userRowHTML(idx) {
- // USER NAME
- var content = "<td><span id='username" + idx
- + "' title='The login name of the user.'></span></td>";
- // SYSTEM ID MAPPING
- content += "<td><input id='userlocal"
- + idx
- + "' title='The system username to run workflows as, or blank for default.' /></td>";
- // ENABLED
- content += "<td><label title='Is this user allowed to log in?' for='useron"
- + idx + "'>Enabled</label>" + "<input type='checkbox' id='useron"
- + idx + "' /></td>";
- // ADMIN
- content += "<td><label title='Is this user an admin (allowed to access this page)?' for='useradmin"
- + idx
- + "'>Admin</label>"
- + "<input type='checkbox' id='useradmin"
- + idx + "' /></td>";
- // SET PASSWORD
- content += "<td><button title='Set the password for this user.' id='userpass"
- + idx + "'>Set Password</button></td>";
- // DELETE
- content += "<td><button title='Delete this user. Take care to not delete yourself!' id='userdel"
- + idx + "'>Delete</button></td>";
-
- return "<tr id='usersep" + idx + "' class='userrows'>"
- + "<td colspan=6><hr></td></tr>" + "<tr id='userrow" + idx
- + "' class='userrows'>" + content + "</tr>";
-}
-
-/** How to get the list of permitted workflows; called on demand */
-function refreshWorkflows() {
- var wftable = $("#workflows"), wfbut = $("#saveWorkflows"), wfbut1 = $("#emptyWorkflows"), wfref = $("#refreshWorkflows");
- wfbut.button("disable");
- wfbut1.button("disable");
- wfref.button("disable");
- getJSON(where("permittedWorkflowURIs"), function(data) {
- var s = "";
- $.each(data.stringList.string || [], function(idx, str) {
- s += $.trim(str) + "\n";
- });
- wftable.val($.trim(s));
- wfbut.button("enable");
- wfbut1.button("enable");
- wfref.button("enable");
- });
-}
-/** How to set the list of permitted workflows; called when the user clicks */
-function saveWorkflows() {
- var wftable = $("#workflows"), wfbut = $("#saveWorkflows"), wfbut1 = $("#emptyWorkflows");
- var xml = NodeAll("stringList", "string", wftable.val().split("\n"));
- wfbut.button("disable");
- wfbut1.button("disable");
- putXML(where("permittedWorkflowURIs"), xml, function() {
- refreshWorkflows();
- });
-}
-
-/** How to empty the list of permitted workflows; called when the user clicks */
-function emptyWorkflows() {
- var wftable = $("#workflows"), wfbut = $("#saveWorkflows"), wfbut1 = $("#emptyWorkflows");
- var xml = NodeAll("stringList", "string", "");
- wfbut.button("disable");
- wfbut1.button("disable");
- putXML(where("permittedWorkflowURIs"), xml, function() {
- refreshWorkflows();
- });
-}
-
-/** How to update the table of users; called on demand */
-function refreshUsers() {
- var usertable = $("#userList");
- getJSON(where("users"), function(data) {
- $(".userrows").remove();
- userinfo = [];
- $.each(data.userList.user, function(idx, url) {
- usertable.append(userRowHTML(idx));
- var i = idx;
- userinfo[i] = {
- url : url
- };
- getJSON(url, function(data) {
- var model = userinfo[i].model = data.userDesc;
- $("#username" + i).html(model.username);
- $("#userlocal" + i).val(model.localUserId).change(function() {
- updateUser(i, "localUserId", $(this).val());
- });
- $("#useron" + i).button().attr("checked", model.enabled)
- .button("refresh").click(
- function() {
- updateUser(i, "enabled", $(this).attr(
- "checked") == "checked");
- });
- $("#useradmin" + i).button().attr("checked", model.admin)
- .button("refresh").click(
- function() {
- updateUser(i, "admin", $(this).attr(
- "checked") == "checked");
- });
- $("#userpass" + i).button({
- icons : {
- primary : "ui-icon-alert"
- }
- }).click(function() {
- updatePasswordUser(i);
- });
- $("#userdel" + i).button({
- icons : {
- primary : "ui-icon-trash"
- },
- text : false
- }).click(function() {
- deleteUser(i);
- });
- });
- return true;
- });
- });
-}
-
-/** How to delete a user by index (with dialog) */
-function deleteUser(idx) {
- $("#dialog-confirm").dialog({
- modal : true,
- autoOpen : false,
- buttons : {
- "OK" : function() {
- $(this).dialog("close");
- deleteUrl(userinfo[idx].url, function() {
- refreshUsers();
- });
- },
- "Cancel" : function() {
- $(this).dialog("close");
- }
- }
- });
- $("#dialog-confirm").dialog("open");
-}
-
-/** How to update a user's password by index (with dialog) */
-function updatePasswordUser(idx) {
- $("#change-password").val("");
- $("#change-password2").val("");
- $("#dialog-password").dialog({
- modal : true,
- autoOpen : false,
- buttons : {
- "OK" : function() {
- $(this).dialog("close");
- var pass = $("#change-password").val();
- var pass2 = $("#change-password2").val();
- $("#change-password").val("");
- $("#change-password2").val("");
- if (pass.equals(pass2))
- updateUser(idx, "password", pass);
- },
- "Cancel" : function() {
- $(this).dialog("close");
- $("#change-password").val("");
- }
- }
- });
- $("#dialog-password").dialog("open");
-}
-
-/** How to set a specific field of a user record */
-function updateUser(idx, field, value) {
- var model = userinfo[idx].model;
- var xml = Node("userDesc", Node("username", model.username),
- field == "password" ? Node("password", value) : undefined,
- field == "localUserId" ? Node("localUserId", value)
- : model.localUserId == undefined ? undefined : Node(
- "localUserId", model.localUserId), Node("enabled",
- field == "enabled" ? value : model.enabled), Node("admin",
- field == "admin" ? value : model.admin));
- putXML(userinfo[idx].url, xml, function() {
- refreshUsers();
- });
-}
-
-/** How to configure all the buttons and entries */
-function connectButtonsAndEntries() {
- $.each(buttonlist, function(idx, val) {
- var widget = $("#" + val);
- var u = where(val);
- widget.button();
- getText(u, function(data) {
- widget.attr('checked', (data + "") != "false");
- widget.button("refresh");
- });
- widget.change(function() {
- putText(u, widget.attr("checked") == "checked", function(data) {
- widget.attr('checked', (data + "") != "false");
- widget.button("refresh");
- return true;
- });
- });
- });
- $.each(entries, function(idx, val) {
- var widget = $("#" + val);
- var u = where(val);
- getText(u, function(data) {
- widget.val(data);
- });
- widget.change(function() {
- putText(u, widget.val(), function(data) {
- widget.val(data);
- return true;
- });
- });
- });
-}
-
-/** What happens when the user tries to make a new user */
-function makeNewUser() {
- var sysid = $("#newSysID").val();
- var newuserinfo = {
- admin : $("#newAdmin").attr("checked") == "checked",
- enabled : $("#newEnabled").attr("checked") == "checked",
- username : $("#newUsername").val(),
- password : $("#newPassword").val()
- };
- // Blank out the password immediately!
- $("#newPassword").val("");
- if (sysid.length > 0) {
- newuserinfo.localUserId = sysid;
- }
- if (newuserinfo.username == "" || newuserinfo.password == "") {
- alert("Won't create user; need a username and a password!");
- return;
- }
- var xml = newuserinfo = Node("userDesc", Node("username",
- newuserinfo.username), Node("password", newuserinfo.password),
- newuserinfo.localUserId == undefined ? undefined : Node(
- "localUserId", newuserinfo.localUserId), Node("enabled",
- newuserinfo.enabled), Node("admin", newuserinfo.admin));
- postXML(where("users"), xml, function() {
- refreshUsers();
- });
-}
-
-/** Handle the extra arguments */
-function loadExtraArgs() {
- getJSON(where("extraArguments"),
- function(data) {
- var rows = data.stringList.string || [];
- if ((typeof rows) == "string")
- rows = [ rows ];
- $(".extraargrow").remove();
- extraAry = rows;
- var i;
- function row() {
- var buf = "<tr class='extraargrow'>";
- for ( var i = 1; i < arguments.length; i++)
- buf += "<td>" + arguments[i] + "</td>";
- return $(arguments[0]).append(buf + "</tr>");
- }
- function delbutn(id, what) {
- return "<button id='" + id + "' title='Delete this " + what
- + ".'>Del</button>";
- }
- for (i = 0; i < extraAry.length; i++) {
- var rowid = "extradel" + i;
- if (rows[i].match("^-D")) {
- var m = rows[i].match("^-D([^=]*)=(.*)$");
- row("#extraArguments-prop", delbutn(rowid,
- "property assignment"), "<tt><b>-D</b>" + m[1]
- + "<b>=</b>" + m[2] + "</tt>");
- } else if (rows[i].match("-E")) {
- var m = rows[i].match("^-E([^=]*)=(.*)$");
- row("#extraArguments-env", delbutn(rowid,
- "environment assignment"), "<tt><b>-E</b>"
- + m[1] + "<b>=</b>" + m[2] + "</tt>");
- } else {
- var m = rows[i].match("^-J(.*)$");
- row("#extraArguments-runtime", delbutn(rowid,
- "runtime parameter"), "<tt><b>-J</b>" + m[1]
- + "</tt>");
- }
- $("#" + rowid).button({
- icons : {
- primary : "ui-icon-trash"
- },
- text : false
- }).click(
- (function(row) {
- return function() {
- extraAry.splice(row, 1);
- var xml = NodeAll("stringList", "string",
- extraAry);
- putXML(where("extraArguments"), xml,
- function() {
- loadExtraArgs();
- });
- };
- })(i));
- }
- });
-}
-
-/** Run a dialog for creating an extra argument. */
-function addExtraArg(dialogId, prefix, part1id, part2id) {
- $(dialogId).dialog({
- modal : true,
- autoOpen : false,
- buttons : {
- "OK" : function() {
- $(this).dialog("close");
- var str = prefix + $(part1id).val();
- if (part2id != undefined)
- str += "=" + $(part2id).val();
- extraAry.push(str);
- var xml = NodeAll("stringList", "string", extraAry);
- putXML(where("extraArguments"), xml, function() {
- loadExtraArgs();
- });
- },
- "Cancel" : function() {
- $(this).dialog("close");
- }
- }
- });
- $(dialogId).dialog("open");
-}
-
-/** Start everything going on page load */
-$(function() {
- // Must be done in this order because the accordion is inside a tab
- $("#a-worker").accordion({
- collapsible : true,
- fillSpace : true,
- autoHeight : false
- });
- $("#body").tabs({
- selected : 0
- });
- $("#saveWorkflows").button({
- disabled : true
- }).click(function(event) {
- saveWorkflows();
- event.preventDefault();
- });
- $("#refreshWorkflows").button({
- disabled : true
- }).click(function(event) {
- refreshWorkflows();
- event.preventDefault();
- });
- $("#emptyWorkflows").button({
- disabled : true
- }).click(function(event) {
- emptyWorkflows();
- event.preventDefault();
- });
-
- // Make the link to the list of usage records point correctly
- // Original plan called for browsable table, but that's too slow
- $("#ur").attr("href", where("usageRecords"));
-
- connectButtonsAndEntries();
- updateRO();
- setInterval(updateRO, 30000);
- refreshUsers();
- refreshWorkflows();
- $("#newEnabled").button();
- $("#newAdmin").button({
- icons : {
- primary : "ui-icon-alert"
- }
- });
- $("#makeNewUser").button().click(function() {
- makeNewUser();
- });
- $("#extra-prop-add").button().click(function() {
- addExtraArg("#dialog-property", "-D", "#prop-key", "#prop-value");
- });
- $("#extra-env-add").button().click(function() {
- addExtraArg("#dialog-environment", "-E", "#env-key", "#env-value");
- });
- $("#extra-run-add").button().click(function() {
- addExtraArg("#dialog-runtime", "-J", "#runtime-value");
- });
- loadExtraArgs();
-});
[48/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
taverna-* module names
Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/commit/2c71f9a9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/tree/2c71f9a9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/diff/2c71f9a9
Branch: refs/heads/master
Commit: 2c71f9a95c7fe6c525cacedeac76646262059dfe
Parents: 529e59d
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Feb 23 15:33:34 2015 +0000
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Feb 23 15:33:34 2015 +0000
----------------------------------------------------------------------
pom.xml | 20 +-
server-client/pom.xml | 130 --
.../uk/org/taverna/server/client/Connected.java | 20 -
.../uk/org/taverna/server/client/DirEntry.java | 39 -
.../uk/org/taverna/server/client/Directory.java | 94 --
.../java/uk/org/taverna/server/client/File.java | 95 --
.../uk/org/taverna/server/client/Property.java | 18 -
.../java/uk/org/taverna/server/client/Run.java | 215 ---
.../uk/org/taverna/server/client/Status.java | 36 -
.../taverna/server/client/TavernaServer.java | 128 --
.../client/TavernaServerConnectionFactory.java | 23 -
.../org/taverna/server/client/package-info.java | 5 -
server-client/src/main/wadl/tavserv.wadl | 591 -------
server-distribution/pom.xml | 145 --
server-distribution/src/assemble/dist.xml | 82 -
server-execution-delegate/pom.xml | 41 -
.../execution_delegate/ExecutionDelegate.java | 172 --
.../execution_delegate/RemoteExecution.java | 188 ---
.../src/test/java/SerializationTest.java | 54 -
server-port-description/.gitignore | 1 -
server-port-description/pom.xml | 45 -
.../server/port_description/AbsentValue.java | 13 -
.../server/port_description/AbstractPort.java | 26 -
.../AbstractPortDescription.java | 29 -
.../server/port_description/AbstractValue.java | 32 -
.../server/port_description/ErrorValue.java | 25 -
.../port_description/InputDescription.java | 51 -
.../server/port_description/LeafValue.java | 19 -
.../server/port_description/ListValue.java | 32 -
.../server/port_description/Namespaces.java | 12 -
.../port_description/OutputDescription.java | 52 -
.../server/port_description/package-info.java | 19 -
.../port_description/utils/IntAdapter.java | 32 -
.../server/port_description/JaxbSanityTest.java | 98 --
server-rmidaemon/pom.xml | 61 -
.../org/taverna/server/rmidaemon/Registry.java | 72 -
.../taverna/server/rmidaemon/package-info.java | 5 -
server-runinterface/.gitignore | 1 -
server-runinterface/pom.xml | 30 -
.../src/main/java/META-INF/MANIFEST.MF | 3 -
.../remote/IllegalStateTransitionException.java | 36 -
.../remote/ImplementationException.java | 26 -
.../localworker/remote/RemoteDirectory.java | 62 -
.../remote/RemoteDirectoryEntry.java | 62 -
.../server/localworker/remote/RemoteFile.java | 98 --
.../server/localworker/remote/RemoteInput.java | 92 --
.../localworker/remote/RemoteListener.java | 77 -
.../localworker/remote/RemoteRunFactory.java | 84 -
.../remote/RemoteSecurityContext.java | 34 -
.../localworker/remote/RemoteSingleRun.java | 254 ---
.../server/localworker/remote/RemoteStatus.java | 40 -
.../remote/StillWorkingOnItException.java | 20 -
.../server/localworker/remote/package-info.java | 9 -
.../localworker/server/UsageRecordReceiver.java | 29 -
.../server/localworker/server/package-info.java | 9 -
server-unix-forker/pom.xml | 61 -
.../org/taverna/server/unixforker/Forker.java | 208 ---
server-usagerecord/.gitignore | 1 -
server-usagerecord/pom.xml | 79 -
.../main/java/org/ogf/usage/JobUsageRecord.java | 304 ----
server-usagerecord/src/main/xsd/ur.xsd | 425 -----
server-usagerecord/src/main/xsd/xmlds.xsd | 318 ----
server-usagerecord/src/test/java/TestUR.java | 120 --
server-webapp/.gitignore | 1 -
server-webapp/.springBeans | 59 -
server-webapp/pom.xml | 889 ----------
.../resources/datanucleus_log4j.properties | 4 -
.../master/ContentsDescriptorBuilder.java | 292 ----
.../taverna/server/master/DirectoryREST.java | 375 -----
.../server/master/FileConcatenation.java | 68 -
.../org/taverna/server/master/InputREST.java | 252 ---
.../taverna/server/master/InteractionFeed.java | 107 --
.../server/master/ListenerPropertyREST.java | 78 -
.../taverna/server/master/ListenersREST.java | 93 --
.../taverna/server/master/ManagementState.java | 215 ---
.../java/org/taverna/server/master/RunREST.java | 499 ------
.../taverna/server/master/RunSecurityREST.java | 303 ----
.../server/master/SingleListenerREST.java | 97 --
.../taverna/server/master/TavernaServer.java | 1425 ----------------
.../server/master/TavernaServerSupport.java | 957 -----------
.../org/taverna/server/master/admin/Admin.java | 1100 -------------
.../taverna/server/master/admin/AdminBean.java | 794 ---------
.../server/master/admin/package-info.java | 33 -
.../taverna/server/master/api/ContentTypes.java | 50 -
.../server/master/api/DirectoryBean.java | 16 -
.../org/taverna/server/master/api/FeedBean.java | 13 -
.../taverna/server/master/api/InputBean.java | 21 -
.../server/master/api/ListenerPropertyBean.java | 15 -
.../server/master/api/ListenersBean.java | 13 -
.../server/master/api/ManagementModel.java | 61 -
.../server/master/api/OneListenerBean.java | 14 -
.../org/taverna/server/master/api/RunBean.java | 17 -
.../taverna/server/master/api/SecurityBean.java | 14 -
.../taverna/server/master/api/SupportAware.java | 21 -
.../server/master/api/TavernaServerBean.java | 101 --
.../taverna/server/master/api/package-info.java | 6 -
.../server/master/common/Capability.java | 22 -
.../server/master/common/Credential.java | 149 --
.../server/master/common/DirEntryReference.java | 93 --
.../server/master/common/InputDescription.java | 110 --
.../server/master/common/Namespaces.java | 39 -
.../server/master/common/Permission.java | 43 -
.../server/master/common/ProfileList.java | 42 -
.../org/taverna/server/master/common/Roles.java | 25 -
.../server/master/common/RunReference.java | 67 -
.../taverna/server/master/common/Status.java | 44 -
.../org/taverna/server/master/common/Trust.java | 79 -
.../org/taverna/server/master/common/Uri.java | 432 -----
.../server/master/common/VersionedElement.java | 65 -
.../taverna/server/master/common/Workflow.java | 367 -----
.../server/master/common/package-info.java | 29 -
.../server/master/common/version/Version.java | 43 -
.../taverna/server/master/defaults/Default.java | 99 --
.../server/master/defaults/package-info.java | 5 -
.../exceptions/BadInputPortNameException.java | 21 -
.../exceptions/BadPropertyValueException.java | 26 -
.../exceptions/BadStateChangeException.java | 35 -
.../exceptions/FilesystemAccessException.java | 38 -
.../exceptions/GeneralFailureException.java | 28 -
.../exceptions/InvalidCredentialException.java | 36 -
.../master/exceptions/NoCreateException.java | 32 -
.../exceptions/NoCredentialException.java | 18 -
.../master/exceptions/NoDestroyException.java | 24 -
.../exceptions/NoDirectoryEntryException.java | 24 -
.../master/exceptions/NoListenerException.java | 33 -
.../master/exceptions/NoUpdateException.java | 33 -
.../master/exceptions/NotOwnerException.java | 23 -
.../master/exceptions/OverloadedException.java | 35 -
.../master/exceptions/UnknownRunException.java | 27 -
.../server/master/exceptions/package-info.java | 29 -
.../taverna/server/master/facade/Facade.java | 73 -
.../server/master/facade/package-info.java | 10 -
.../factories/ConfigurableRunFactory.java | 133 --
.../master/factories/ListenerFactory.java | 46 -
.../server/master/factories/RunFactory.java | 40 -
.../server/master/factories/package-info.java | 10 -
.../identity/AuthorityDerivedIDMapper.java | 50 -
.../master/identity/CompositeIDMapper.java | 65 -
.../master/identity/ConstantIDMapper.java | 32 -
.../server/master/identity/NameIDMapper.java | 50 -
.../identity/StrippedDownAuthProvider.java | 278 ----
.../taverna/server/master/identity/User.java | 153 --
.../server/master/identity/UserStore.java | 389 -----
.../server/master/identity/UserStoreAPI.java | 91 -
.../identity/WorkflowInternalAuthProvider.java | 304 ----
.../server/master/identity/package-info.java | 10 -
.../interaction/InteractionFeedSupport.java | 316 ----
.../server/master/interaction/package-info.java | 10 -
.../server/master/interfaces/Directory.java | 82 -
.../master/interfaces/DirectoryEntry.java | 47 -
.../taverna/server/master/interfaces/File.java | 69 -
.../taverna/server/master/interfaces/Input.java | 92 --
.../server/master/interfaces/Listener.java | 64 -
.../master/interfaces/LocalIdentityMapper.java | 29 -
.../master/interfaces/MessageDispatcher.java | 45 -
.../server/master/interfaces/Policy.java | 120 --
.../server/master/interfaces/RunStore.java | 82 -
.../interfaces/SecurityContextFactory.java | 32 -
.../server/master/interfaces/TavernaRun.java | 219 ---
.../interfaces/TavernaSecurityContext.java | 213 ---
.../master/interfaces/UriBuilderFactory.java | 43 -
.../server/master/interfaces/package-info.java | 10 -
.../localworker/AbstractRemoteRunFactory.java | 440 -----
.../master/localworker/ForkRunFactory.java | 323 ----
.../localworker/IdAwareForkRunFactory.java | 516 ------
.../master/localworker/LocalWorkerFactory.java | 31 -
.../master/localworker/LocalWorkerState.java | 454 -----
.../master/localworker/PersistedState.java | 257 ---
.../server/master/localworker/StreamLogger.java | 62 -
.../server/master/localworker/package-info.java | 10 -
.../master/notification/EmailDispatcher.java | 113 --
.../master/notification/JabberDispatcher.java | 140 --
.../master/notification/NotificationEngine.java | 145 --
.../notification/RateLimitedDispatcher.java | 89 -
.../master/notification/SMSDispatcher.java | 158 --
.../master/notification/TwitterDispatcher.java | 132 --
.../master/notification/atom/AtomFeed.java | 134 --
.../server/master/notification/atom/Event.java | 110 --
.../master/notification/atom/EventDAO.java | 206 ---
.../master/notification/atom/package-info.java | 29 -
.../master/notification/package-info.java | 10 -
.../org/taverna/server/master/package-info.java | 11 -
.../server/master/rest/ContentTypes.java | 28 -
.../server/master/rest/DirectoryContents.java | 61 -
.../taverna/server/master/rest/FileSegment.java | 78 -
.../server/master/rest/InteractionFeedREST.java | 126 --
.../server/master/rest/ListenerDefinition.java | 32 -
.../master/rest/MakeOrUpdateDirEntry.java | 56 -
.../master/rest/TavernaServerDirectoryREST.java | 240 ---
.../master/rest/TavernaServerInputREST.java | 355 ----
.../master/rest/TavernaServerListenersREST.java | 428 -----
.../server/master/rest/TavernaServerREST.java | 604 -------
.../master/rest/TavernaServerRunREST.java | 797 ---------
.../master/rest/TavernaServerSecurityREST.java | 775 ---------
.../rest/handler/AccessDeniedHandler.java | 21 -
.../rest/handler/BadInputPortNameHandler.java | 23 -
.../rest/handler/BadPropertyValueHandler.java | 23 -
.../rest/handler/BadStateChangeHandler.java | 23 -
.../master/rest/handler/EntryHandler.java | 131 --
.../server/master/rest/handler/FeedHandler.java | 66 -
.../rest/handler/FileConcatenationHandler.java | 61 -
.../master/rest/handler/FileMessageHandler.java | 80 -
.../master/rest/handler/FileSegmentHandler.java | 74 -
.../rest/handler/FilesystemAccessHandler.java | 23 -
.../rest/handler/GeneralFailureHandler.java | 21 -
.../server/master/rest/handler/HandlerCore.java | 71 -
.../rest/handler/IllegalArgumentHandler.java | 21 -
.../handler/ImplementationProblemHandler.java | 21 -
.../rest/handler/InputStreamMessageHandler.java | 107 --
.../rest/handler/InvalidCredentialHandler.java | 23 -
.../rest/handler/JAXBExceptionHandler.java | 22 -
.../rest/handler/NegotiationFailedHandler.java | 25 -
.../master/rest/handler/NoCreateHandler.java | 23 -
.../rest/handler/NoCredentialHandler.java | 21 -
.../master/rest/handler/NoDestroyHandler.java | 23 -
.../rest/handler/NoDirectoryEntryHandler.java | 23 -
.../master/rest/handler/NoListenerHandler.java | 23 -
.../master/rest/handler/NoUpdateHandler.java | 23 -
.../master/rest/handler/NotOwnerHandler.java | 21 -
.../master/rest/handler/OverloadedHandler.java | 22 -
.../master/rest/handler/PermissionHandler.java | 74 -
.../rest/handler/Scufl2DocumentHandler.java | 87 -
.../rest/handler/T2FlowDocumentHandler.java | 118 --
.../master/rest/handler/URIListHandler.java | 121 --
.../master/rest/handler/UnknownRunHandler.java | 23 -
.../master/rest/handler/ZipStreamHandler.java | 54 -
.../master/rest/handler/package-info.java | 31 -
.../server/master/rest/package-info.java | 31 -
.../taverna/server/master/soap/DirEntry.java | 100 --
.../server/master/soap/FileContents.java | 171 --
.../server/master/soap/PermissionList.java | 50 -
.../server/master/soap/TavernaServerSOAP.java | 1553 ------------------
.../server/master/soap/WrappedWorkflow.java | 156 --
.../server/master/soap/ZippedDirectory.java | 89 -
.../server/master/soap/package-info.java | 31 -
.../server/master/usage/UsageRecord.java | 118 --
.../master/usage/UsageRecordRecorder.java | 163 --
.../server/master/usage/package-info.java | 9 -
.../server/master/utils/CallTimeLogger.java | 87 -
.../server/master/utils/CallTimingFilter.java | 65 -
.../server/master/utils/CapabilityLister.java | 44 -
.../master/utils/CertificateChainFetcher.java | 199 ---
.../server/master/utils/Contextualizer.java | 66 -
.../taverna/server/master/utils/DerbyUtils.java | 68 -
.../server/master/utils/FilenameUtils.java | 268 ---
.../utils/FlushThreadLocalCacheInterceptor.java | 18 -
.../server/master/utils/InvocationCounter.java | 48 -
.../taverna/server/master/utils/JCECheck.java | 60 -
.../taverna/server/master/utils/JDOSupport.java | 270 ---
.../master/utils/LoggingDerbyAdapter.java | 138 --
.../server/master/utils/OneShotThread.java | 10 -
.../taverna/server/master/utils/RestUtils.java | 32 -
.../master/utils/RuntimeExceptionWrapper.java | 37 -
.../server/master/utils/UsernamePrincipal.java | 69 -
.../utils/WSDLHeadOptionsInterceptor.java | 65 -
.../master/utils/WebappAwareDataSource.java | 134 --
.../taverna/server/master/utils/X500Utils.java | 107 --
.../server/master/utils/package-info.java | 10 -
.../master/worker/CompletionNotifier.java | 45 -
.../server/master/worker/FactoryBean.java | 26 -
.../server/master/worker/PasswordIssuer.java | 57 -
.../server/master/worker/PolicyImpl.java | 158 --
.../server/master/worker/PolicyLimits.java | 43 -
.../server/master/worker/RemoteRunDelegate.java | 967 -----------
.../server/master/worker/RunConnection.java | 239 ---
.../server/master/worker/RunDBSupport.java | 83 -
.../server/master/worker/RunDatabase.java | 311 ----
.../server/master/worker/RunDatabaseDAO.java | 306 ----
.../master/worker/RunFactoryConfiguration.java | 395 -----
.../master/worker/SecurityContextDelegate.java | 649 --------
.../worker/SecurityContextDelegateImpl.java | 298 ----
.../master/worker/SecurityContextFactory.java | 154 --
.../SimpleFormattedCompletionNotifier.java | 64 -
.../worker/VelocityCompletionNotifier.java | 105 --
.../server/master/worker/WorkerModel.java | 203 ---
.../server/master/worker/package-info.java | 10 -
.../main/replacementscripts/executeworkflow.bat | 25 -
.../main/replacementscripts/executeworkflow.sh | 72 -
server-webapp/src/main/resources/admin.html | 240 ---
.../src/main/resources/capabilities.properties | 38 -
.../src/main/resources/log4j.properties | 39 -
.../src/main/resources/security.policy | 3 -
.../src/main/resources/static/admin.js | 549 -------
.../main/resources/static/jquery-1.8.0.min.js | 2 -
.../static/jquery-ui-1.8.23.custom.css | 563 -------
.../static/jquery-ui-1.8.23.custom.min.js | 125 --
.../src/main/resources/static/t2cogs.png | Bin 135202 -> 0 bytes
.../ui-bg_diagonals-small_25_c5ddfc_40x40.png | Bin 194 -> 0 bytes
.../ui-bg_diagonals-thick_20_e69700_40x40.png | Bin 257 -> 0 bytes
.../ui-bg_diagonals-thick_22_1484e6_40x40.png | Bin 384 -> 0 bytes
.../ui-bg_diagonals-thick_26_2293f7_40x40.png | Bin 259 -> 0 bytes
.../static/ui-bg_flat_0_e69700_40x100.png | Bin 181 -> 0 bytes
.../static/ui-bg_flat_0_e6b900_40x100.png | Bin 212 -> 0 bytes
.../ui-bg_highlight-soft_100_f9f9f9_1x100.png | Bin 88 -> 0 bytes
.../ui-bg_inset-hard_100_eeeeee_1x100.png | Bin 91 -> 0 bytes
.../static/ui-icons_0a82eb_256x240.png | Bin 4369 -> 0 bytes
.../static/ui-icons_0b54d5_256x240.png | Bin 4369 -> 0 bytes
.../static/ui-icons_5fa5e3_256x240.png | Bin 5355 -> 0 bytes
.../static/ui-icons_fcdd4a_256x240.png | Bin 4369 -> 0 bytes
.../static/ui-icons_ffffff_256x240.png | Bin 4369 -> 0 bytes
.../src/main/resources/version.properties | 5 -
server-webapp/src/main/resources/welcome.html | 122 --
.../src/main/webapp/META-INF/MANIFEST.MF | 3 -
.../webapp/META-INF/cxf/org.apache.cxf.Logger | 1 -
.../src/main/webapp/META-INF/persistence.xml | 14 -
server-webapp/src/main/webapp/WEB-INF/beans.xml | 518 ------
.../src/main/webapp/WEB-INF/insecure.xml | 32 -
...orker.VelocityCompletionNotifier_email.vtmpl | 15 -
....worker.VelocityCompletionNotifier_sms.vtmpl | 1 -
...ker.VelocityCompletionNotifier_twitter.vtmpl | 1 -
.../src/main/webapp/WEB-INF/partsecure.xml | 36 -
.../src/main/webapp/WEB-INF/providers.xml | 96 --
.../src/main/webapp/WEB-INF/secure.xml | 35 -
.../webapp/WEB-INF/security/users.properties | 48 -
.../webapp/WEB-INF/tavernaserver.properties | 77 -
.../src/main/webapp/WEB-INF/web-nosec.xml | 79 -
.../src/main/webapp/WEB-INF/web-partsec.xml | 79 -
.../src/main/webapp/WEB-INF/web-sec.xml | 79 -
.../src/main/webapp/WEB-INF/webappBeans.xml | 213 ---
server-webapp/src/misc/xsd/persistence_1_0.xsd | 305 ----
.../taverna/server/master/JaxbSanityTest.java | 357 ----
.../server/master/TavernaServerImplTest.java | 246 ---
.../master/WorkflowSerializationTest.java | 68 -
.../taverna/server/master/mocks/ExampleRun.java | 452 -----
.../taverna/server/master/mocks/MockPolicy.java | 59 -
.../master/mocks/SimpleListenerFactory.java | 64 -
.../mocks/SimpleNonpersistentRunStore.java | 151 --
.../server/master/mocks/SimpleServerPolicy.java | 110 --
server-webapp/src/test/resources/example.xml | 55 -
.../src/test/resources/log4j.properties | 4 -
server-worker/pom.xml | 125 --
.../src/main/java/META-INF/MANIFEST.MF | 3 -
.../server/localworker/api/Constants.java | 141 --
.../server/localworker/api/RunAccounting.java | 22 -
.../taverna/server/localworker/api/Worker.java | 135 --
.../server/localworker/api/WorkerFactory.java | 18 -
.../localworker/impl/DirectoryDelegate.java | 161 --
.../server/localworker/impl/FileDelegate.java | 142 --
.../server/localworker/impl/LocalWorker.java | 769 ---------
.../localworker/impl/TavernaRunManager.java | 243 ---
.../server/localworker/impl/WorkerCore.java | 918 -----------
.../impl/utils/FilenameVerifier.java | 156 --
.../localworker/impl/utils/TimingOutTask.java | 40 -
.../src/main/resources/security.policy | 11 -
.../localworker/impl/LocalWorkerTest.java | 551 -------
taverna-server-client/pom.xml | 130 ++
.../uk/org/taverna/server/client/Connected.java | 20 +
.../uk/org/taverna/server/client/DirEntry.java | 39 +
.../uk/org/taverna/server/client/Directory.java | 94 ++
.../java/uk/org/taverna/server/client/File.java | 95 ++
.../uk/org/taverna/server/client/Property.java | 18 +
.../java/uk/org/taverna/server/client/Run.java | 215 +++
.../uk/org/taverna/server/client/Status.java | 36 +
.../taverna/server/client/TavernaServer.java | 128 ++
.../client/TavernaServerConnectionFactory.java | 23 +
.../org/taverna/server/client/package-info.java | 5 +
.../src/main/wadl/tavserv.wadl | 591 +++++++
taverna-server-distribution/pom.xml | 145 ++
.../src/assemble/dist.xml | 82 +
taverna-server-execution-delegate/pom.xml | 41 +
.../execution_delegate/ExecutionDelegate.java | 172 ++
.../execution_delegate/RemoteExecution.java | 188 +++
.../src/test/java/SerializationTest.java | 54 +
taverna-server-port-description/.gitignore | 1 +
taverna-server-port-description/pom.xml | 45 +
.../server/port_description/AbsentValue.java | 13 +
.../server/port_description/AbstractPort.java | 26 +
.../AbstractPortDescription.java | 29 +
.../server/port_description/AbstractValue.java | 32 +
.../server/port_description/ErrorValue.java | 25 +
.../port_description/InputDescription.java | 51 +
.../server/port_description/LeafValue.java | 19 +
.../server/port_description/ListValue.java | 32 +
.../server/port_description/Namespaces.java | 12 +
.../port_description/OutputDescription.java | 52 +
.../server/port_description/package-info.java | 19 +
.../port_description/utils/IntAdapter.java | 32 +
.../server/port_description/JaxbSanityTest.java | 98 ++
taverna-server-rmidaemon/pom.xml | 61 +
.../org/taverna/server/rmidaemon/Registry.java | 72 +
.../taverna/server/rmidaemon/package-info.java | 5 +
taverna-server-runinterface/.gitignore | 1 +
taverna-server-runinterface/pom.xml | 30 +
.../src/main/java/META-INF/MANIFEST.MF | 3 +
.../remote/IllegalStateTransitionException.java | 36 +
.../remote/ImplementationException.java | 26 +
.../localworker/remote/RemoteDirectory.java | 62 +
.../remote/RemoteDirectoryEntry.java | 62 +
.../server/localworker/remote/RemoteFile.java | 98 ++
.../server/localworker/remote/RemoteInput.java | 92 ++
.../localworker/remote/RemoteListener.java | 77 +
.../localworker/remote/RemoteRunFactory.java | 84 +
.../remote/RemoteSecurityContext.java | 34 +
.../localworker/remote/RemoteSingleRun.java | 254 +++
.../server/localworker/remote/RemoteStatus.java | 40 +
.../remote/StillWorkingOnItException.java | 20 +
.../server/localworker/remote/package-info.java | 9 +
.../localworker/server/UsageRecordReceiver.java | 29 +
.../server/localworker/server/package-info.java | 9 +
taverna-server-unix-forker/pom.xml | 61 +
.../org/taverna/server/unixforker/Forker.java | 208 +++
taverna-server-usagerecord/.gitignore | 1 +
taverna-server-usagerecord/pom.xml | 79 +
.../main/java/org/ogf/usage/JobUsageRecord.java | 304 ++++
taverna-server-usagerecord/src/main/xsd/ur.xsd | 425 +++++
.../src/main/xsd/xmlds.xsd | 318 ++++
.../src/test/java/TestUR.java | 120 ++
taverna-server-webapp/.gitignore | 1 +
taverna-server-webapp/pom.xml | 889 ++++++++++
.../resources/datanucleus_log4j.properties | 4 +
.../master/ContentsDescriptorBuilder.java | 292 ++++
.../taverna/server/master/DirectoryREST.java | 375 +++++
.../server/master/FileConcatenation.java | 68 +
.../org/taverna/server/master/InputREST.java | 252 +++
.../taverna/server/master/InteractionFeed.java | 107 ++
.../server/master/ListenerPropertyREST.java | 78 +
.../taverna/server/master/ListenersREST.java | 93 ++
.../taverna/server/master/ManagementState.java | 215 +++
.../java/org/taverna/server/master/RunREST.java | 499 ++++++
.../taverna/server/master/RunSecurityREST.java | 303 ++++
.../server/master/SingleListenerREST.java | 97 ++
.../taverna/server/master/TavernaServer.java | 1425 ++++++++++++++++
.../server/master/TavernaServerSupport.java | 957 +++++++++++
.../org/taverna/server/master/admin/Admin.java | 1100 +++++++++++++
.../taverna/server/master/admin/AdminBean.java | 794 +++++++++
.../server/master/admin/package-info.java | 33 +
.../taverna/server/master/api/ContentTypes.java | 50 +
.../server/master/api/DirectoryBean.java | 16 +
.../org/taverna/server/master/api/FeedBean.java | 13 +
.../taverna/server/master/api/InputBean.java | 21 +
.../server/master/api/ListenerPropertyBean.java | 15 +
.../server/master/api/ListenersBean.java | 13 +
.../server/master/api/ManagementModel.java | 61 +
.../server/master/api/OneListenerBean.java | 14 +
.../org/taverna/server/master/api/RunBean.java | 17 +
.../taverna/server/master/api/SecurityBean.java | 14 +
.../taverna/server/master/api/SupportAware.java | 21 +
.../server/master/api/TavernaServerBean.java | 101 ++
.../taverna/server/master/api/package-info.java | 6 +
.../server/master/common/Capability.java | 22 +
.../server/master/common/Credential.java | 149 ++
.../server/master/common/DirEntryReference.java | 93 ++
.../server/master/common/InputDescription.java | 110 ++
.../server/master/common/Namespaces.java | 39 +
.../server/master/common/Permission.java | 43 +
.../server/master/common/ProfileList.java | 42 +
.../org/taverna/server/master/common/Roles.java | 25 +
.../server/master/common/RunReference.java | 67 +
.../taverna/server/master/common/Status.java | 44 +
.../org/taverna/server/master/common/Trust.java | 79 +
.../org/taverna/server/master/common/Uri.java | 432 +++++
.../server/master/common/VersionedElement.java | 65 +
.../taverna/server/master/common/Workflow.java | 367 +++++
.../server/master/common/package-info.java | 29 +
.../server/master/common/version/Version.java | 43 +
.../taverna/server/master/defaults/Default.java | 99 ++
.../server/master/defaults/package-info.java | 5 +
.../exceptions/BadInputPortNameException.java | 21 +
.../exceptions/BadPropertyValueException.java | 26 +
.../exceptions/BadStateChangeException.java | 35 +
.../exceptions/FilesystemAccessException.java | 38 +
.../exceptions/GeneralFailureException.java | 28 +
.../exceptions/InvalidCredentialException.java | 36 +
.../master/exceptions/NoCreateException.java | 32 +
.../exceptions/NoCredentialException.java | 18 +
.../master/exceptions/NoDestroyException.java | 24 +
.../exceptions/NoDirectoryEntryException.java | 24 +
.../master/exceptions/NoListenerException.java | 33 +
.../master/exceptions/NoUpdateException.java | 33 +
.../master/exceptions/NotOwnerException.java | 23 +
.../master/exceptions/OverloadedException.java | 35 +
.../master/exceptions/UnknownRunException.java | 27 +
.../server/master/exceptions/package-info.java | 29 +
.../taverna/server/master/facade/Facade.java | 73 +
.../server/master/facade/package-info.java | 10 +
.../factories/ConfigurableRunFactory.java | 133 ++
.../master/factories/ListenerFactory.java | 46 +
.../server/master/factories/RunFactory.java | 40 +
.../server/master/factories/package-info.java | 10 +
.../identity/AuthorityDerivedIDMapper.java | 50 +
.../master/identity/CompositeIDMapper.java | 65 +
.../master/identity/ConstantIDMapper.java | 32 +
.../server/master/identity/NameIDMapper.java | 50 +
.../identity/StrippedDownAuthProvider.java | 278 ++++
.../taverna/server/master/identity/User.java | 153 ++
.../server/master/identity/UserStore.java | 389 +++++
.../server/master/identity/UserStoreAPI.java | 91 +
.../identity/WorkflowInternalAuthProvider.java | 304 ++++
.../server/master/identity/package-info.java | 10 +
.../interaction/InteractionFeedSupport.java | 316 ++++
.../server/master/interaction/package-info.java | 10 +
.../server/master/interfaces/Directory.java | 82 +
.../master/interfaces/DirectoryEntry.java | 47 +
.../taverna/server/master/interfaces/File.java | 69 +
.../taverna/server/master/interfaces/Input.java | 92 ++
.../server/master/interfaces/Listener.java | 64 +
.../master/interfaces/LocalIdentityMapper.java | 29 +
.../master/interfaces/MessageDispatcher.java | 45 +
.../server/master/interfaces/Policy.java | 120 ++
.../server/master/interfaces/RunStore.java | 82 +
.../interfaces/SecurityContextFactory.java | 32 +
.../server/master/interfaces/TavernaRun.java | 219 +++
.../interfaces/TavernaSecurityContext.java | 213 +++
.../master/interfaces/UriBuilderFactory.java | 43 +
.../server/master/interfaces/package-info.java | 10 +
.../localworker/AbstractRemoteRunFactory.java | 440 +++++
.../master/localworker/ForkRunFactory.java | 323 ++++
.../localworker/IdAwareForkRunFactory.java | 516 ++++++
.../master/localworker/LocalWorkerFactory.java | 31 +
.../master/localworker/LocalWorkerState.java | 454 +++++
.../master/localworker/PersistedState.java | 257 +++
.../server/master/localworker/StreamLogger.java | 62 +
.../server/master/localworker/package-info.java | 10 +
.../master/notification/EmailDispatcher.java | 113 ++
.../master/notification/JabberDispatcher.java | 140 ++
.../master/notification/NotificationEngine.java | 145 ++
.../notification/RateLimitedDispatcher.java | 89 +
.../master/notification/SMSDispatcher.java | 158 ++
.../master/notification/TwitterDispatcher.java | 132 ++
.../master/notification/atom/AtomFeed.java | 134 ++
.../server/master/notification/atom/Event.java | 110 ++
.../master/notification/atom/EventDAO.java | 206 +++
.../master/notification/atom/package-info.java | 29 +
.../master/notification/package-info.java | 10 +
.../org/taverna/server/master/package-info.java | 11 +
.../server/master/rest/ContentTypes.java | 28 +
.../server/master/rest/DirectoryContents.java | 61 +
.../taverna/server/master/rest/FileSegment.java | 78 +
.../server/master/rest/InteractionFeedREST.java | 126 ++
.../server/master/rest/ListenerDefinition.java | 32 +
.../master/rest/MakeOrUpdateDirEntry.java | 56 +
.../master/rest/TavernaServerDirectoryREST.java | 240 +++
.../master/rest/TavernaServerInputREST.java | 355 ++++
.../master/rest/TavernaServerListenersREST.java | 428 +++++
.../server/master/rest/TavernaServerREST.java | 604 +++++++
.../master/rest/TavernaServerRunREST.java | 797 +++++++++
.../master/rest/TavernaServerSecurityREST.java | 775 +++++++++
.../rest/handler/AccessDeniedHandler.java | 21 +
.../rest/handler/BadInputPortNameHandler.java | 23 +
.../rest/handler/BadPropertyValueHandler.java | 23 +
.../rest/handler/BadStateChangeHandler.java | 23 +
.../master/rest/handler/EntryHandler.java | 131 ++
.../server/master/rest/handler/FeedHandler.java | 66 +
.../rest/handler/FileConcatenationHandler.java | 61 +
.../master/rest/handler/FileMessageHandler.java | 80 +
.../master/rest/handler/FileSegmentHandler.java | 74 +
.../rest/handler/FilesystemAccessHandler.java | 23 +
.../rest/handler/GeneralFailureHandler.java | 21 +
.../server/master/rest/handler/HandlerCore.java | 71 +
.../rest/handler/IllegalArgumentHandler.java | 21 +
.../handler/ImplementationProblemHandler.java | 21 +
.../rest/handler/InputStreamMessageHandler.java | 107 ++
.../rest/handler/InvalidCredentialHandler.java | 23 +
.../rest/handler/JAXBExceptionHandler.java | 22 +
.../rest/handler/NegotiationFailedHandler.java | 25 +
.../master/rest/handler/NoCreateHandler.java | 23 +
.../rest/handler/NoCredentialHandler.java | 21 +
.../master/rest/handler/NoDestroyHandler.java | 23 +
.../rest/handler/NoDirectoryEntryHandler.java | 23 +
.../master/rest/handler/NoListenerHandler.java | 23 +
.../master/rest/handler/NoUpdateHandler.java | 23 +
.../master/rest/handler/NotOwnerHandler.java | 21 +
.../master/rest/handler/OverloadedHandler.java | 22 +
.../master/rest/handler/PermissionHandler.java | 74 +
.../rest/handler/Scufl2DocumentHandler.java | 87 +
.../rest/handler/T2FlowDocumentHandler.java | 118 ++
.../master/rest/handler/URIListHandler.java | 121 ++
.../master/rest/handler/UnknownRunHandler.java | 23 +
.../master/rest/handler/ZipStreamHandler.java | 54 +
.../master/rest/handler/package-info.java | 31 +
.../server/master/rest/package-info.java | 31 +
.../taverna/server/master/soap/DirEntry.java | 100 ++
.../server/master/soap/FileContents.java | 171 ++
.../server/master/soap/PermissionList.java | 50 +
.../server/master/soap/TavernaServerSOAP.java | 1553 ++++++++++++++++++
.../server/master/soap/WrappedWorkflow.java | 156 ++
.../server/master/soap/ZippedDirectory.java | 89 +
.../server/master/soap/package-info.java | 31 +
.../server/master/usage/UsageRecord.java | 118 ++
.../master/usage/UsageRecordRecorder.java | 163 ++
.../server/master/usage/package-info.java | 9 +
.../server/master/utils/CallTimeLogger.java | 87 +
.../server/master/utils/CallTimingFilter.java | 65 +
.../server/master/utils/CapabilityLister.java | 44 +
.../master/utils/CertificateChainFetcher.java | 199 +++
.../server/master/utils/Contextualizer.java | 66 +
.../taverna/server/master/utils/DerbyUtils.java | 68 +
.../server/master/utils/FilenameUtils.java | 268 +++
.../utils/FlushThreadLocalCacheInterceptor.java | 18 +
.../server/master/utils/InvocationCounter.java | 48 +
.../taverna/server/master/utils/JCECheck.java | 60 +
.../taverna/server/master/utils/JDOSupport.java | 270 +++
.../master/utils/LoggingDerbyAdapter.java | 138 ++
.../server/master/utils/OneShotThread.java | 10 +
.../taverna/server/master/utils/RestUtils.java | 32 +
.../master/utils/RuntimeExceptionWrapper.java | 37 +
.../server/master/utils/UsernamePrincipal.java | 69 +
.../utils/WSDLHeadOptionsInterceptor.java | 65 +
.../master/utils/WebappAwareDataSource.java | 134 ++
.../taverna/server/master/utils/X500Utils.java | 107 ++
.../server/master/utils/package-info.java | 10 +
.../master/worker/CompletionNotifier.java | 45 +
.../server/master/worker/FactoryBean.java | 26 +
.../server/master/worker/PasswordIssuer.java | 57 +
.../server/master/worker/PolicyImpl.java | 158 ++
.../server/master/worker/PolicyLimits.java | 43 +
.../server/master/worker/RemoteRunDelegate.java | 967 +++++++++++
.../server/master/worker/RunConnection.java | 239 +++
.../server/master/worker/RunDBSupport.java | 83 +
.../server/master/worker/RunDatabase.java | 311 ++++
.../server/master/worker/RunDatabaseDAO.java | 306 ++++
.../master/worker/RunFactoryConfiguration.java | 395 +++++
.../master/worker/SecurityContextDelegate.java | 649 ++++++++
.../worker/SecurityContextDelegateImpl.java | 298 ++++
.../master/worker/SecurityContextFactory.java | 154 ++
.../SimpleFormattedCompletionNotifier.java | 64 +
.../worker/VelocityCompletionNotifier.java | 105 ++
.../server/master/worker/WorkerModel.java | 203 +++
.../server/master/worker/package-info.java | 10 +
.../main/replacementscripts/executeworkflow.bat | 25 +
.../main/replacementscripts/executeworkflow.sh | 72 +
.../src/main/resources/admin.html | 240 +++
.../src/main/resources/capabilities.properties | 38 +
.../src/main/resources/log4j.properties | 39 +
.../src/main/resources/security.policy | 3 +
.../src/main/resources/static/admin.js | 549 +++++++
.../main/resources/static/jquery-1.8.0.min.js | 2 +
.../static/jquery-ui-1.8.23.custom.css | 563 +++++++
.../static/jquery-ui-1.8.23.custom.min.js | 125 ++
.../src/main/resources/static/t2cogs.png | Bin 0 -> 135202 bytes
.../ui-bg_diagonals-small_25_c5ddfc_40x40.png | Bin 0 -> 194 bytes
.../ui-bg_diagonals-thick_20_e69700_40x40.png | Bin 0 -> 257 bytes
.../ui-bg_diagonals-thick_22_1484e6_40x40.png | Bin 0 -> 384 bytes
.../ui-bg_diagonals-thick_26_2293f7_40x40.png | Bin 0 -> 259 bytes
.../static/ui-bg_flat_0_e69700_40x100.png | Bin 0 -> 181 bytes
.../static/ui-bg_flat_0_e6b900_40x100.png | Bin 0 -> 212 bytes
.../ui-bg_highlight-soft_100_f9f9f9_1x100.png | Bin 0 -> 88 bytes
.../ui-bg_inset-hard_100_eeeeee_1x100.png | Bin 0 -> 91 bytes
.../static/ui-icons_0a82eb_256x240.png | Bin 0 -> 4369 bytes
.../static/ui-icons_0b54d5_256x240.png | Bin 0 -> 4369 bytes
.../static/ui-icons_5fa5e3_256x240.png | Bin 0 -> 5355 bytes
.../static/ui-icons_fcdd4a_256x240.png | Bin 0 -> 4369 bytes
.../static/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes
.../src/main/resources/version.properties | 5 +
.../src/main/resources/welcome.html | 122 ++
.../src/main/webapp/META-INF/MANIFEST.MF | 3 +
.../webapp/META-INF/cxf/org.apache.cxf.Logger | 1 +
.../src/main/webapp/META-INF/persistence.xml | 14 +
.../src/main/webapp/WEB-INF/beans.xml | 518 ++++++
.../src/main/webapp/WEB-INF/insecure.xml | 32 +
...orker.VelocityCompletionNotifier_email.vtmpl | 15 +
....worker.VelocityCompletionNotifier_sms.vtmpl | 1 +
...ker.VelocityCompletionNotifier_twitter.vtmpl | 1 +
.../src/main/webapp/WEB-INF/partsecure.xml | 36 +
.../src/main/webapp/WEB-INF/providers.xml | 96 ++
.../src/main/webapp/WEB-INF/secure.xml | 35 +
.../webapp/WEB-INF/security/users.properties | 48 +
.../webapp/WEB-INF/tavernaserver.properties | 77 +
.../src/main/webapp/WEB-INF/web-nosec.xml | 79 +
.../src/main/webapp/WEB-INF/web-partsec.xml | 79 +
.../src/main/webapp/WEB-INF/web-sec.xml | 79 +
.../src/main/webapp/WEB-INF/webappBeans.xml | 213 +++
.../src/misc/xsd/persistence_1_0.xsd | 305 ++++
.../taverna/server/master/JaxbSanityTest.java | 357 ++++
.../server/master/TavernaServerImplTest.java | 246 +++
.../master/WorkflowSerializationTest.java | 68 +
.../taverna/server/master/mocks/ExampleRun.java | 452 +++++
.../taverna/server/master/mocks/MockPolicy.java | 59 +
.../master/mocks/SimpleListenerFactory.java | 64 +
.../mocks/SimpleNonpersistentRunStore.java | 151 ++
.../server/master/mocks/SimpleServerPolicy.java | 110 ++
.../src/test/resources/example.xml | 55 +
.../src/test/resources/log4j.properties | 4 +
taverna-server-worker/pom.xml | 125 ++
.../src/main/java/META-INF/MANIFEST.MF | 3 +
.../server/localworker/api/Constants.java | 141 ++
.../server/localworker/api/RunAccounting.java | 22 +
.../taverna/server/localworker/api/Worker.java | 135 ++
.../server/localworker/api/WorkerFactory.java | 18 +
.../localworker/impl/DirectoryDelegate.java | 161 ++
.../server/localworker/impl/FileDelegate.java | 142 ++
.../server/localworker/impl/LocalWorker.java | 769 +++++++++
.../localworker/impl/TavernaRunManager.java | 243 +++
.../server/localworker/impl/WorkerCore.java | 918 +++++++++++
.../impl/utils/FilenameVerifier.java | 156 ++
.../localworker/impl/utils/TimingOutTask.java | 40 +
.../src/main/resources/security.policy | 11 +
.../localworker/impl/LocalWorkerTest.java | 551 +++++++
688 files changed, 43826 insertions(+), 43885 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 4240e5d..850b30b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -412,16 +412,16 @@ executing.</description>
</profiles>
<modules>
- <module>server-webapp</module>
- <module>server-runinterface</module>
- <module>server-worker</module>
- <module>server-unix-forker</module>
- <module>server-usagerecord</module>
- <module>server-port-description</module>
- <module>server-execution-delegate</module>
- <module>server-rmidaemon</module>
- <module>server-client</module>
- <module>server-distribution</module>
+ <module>taverna-server-webapp</module>
+ <module>taverna-server-runinterface</module>
+ <module>taverna-server-worker</module>
+ <module>taverna-server-unix-forker</module>
+ <module>taverna-server-usagerecord</module>
+ <module>taverna-server-port-description</module>
+ <module>taverna-server-execution-delegate</module>
+ <module>taverna-server-rmidaemon</module>
+ <module>taverna-server-client</module>
+ <module>taverna-server-distribution</module>
</modules>
<scm>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/pom.xml
----------------------------------------------------------------------
diff --git a/server-client/pom.xml b/server-client/pom.xml
deleted file mode 100644
index d16b07a..0000000
--- a/server-client/pom.xml
+++ /dev/null
@@ -1,130 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-client</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Taverna Server Client OSGi Module</name>
-
- <dependencies>
- <dependency>
- <groupId>org.jvnet.ws.wadl</groupId>
- <artifactId>wadl-core</artifactId>
- <version>1.1.6</version>
- </dependency>
- <dependency>
- <groupId>com.sun.jersey</groupId>
- <artifactId>jersey-client</artifactId>
- <version>1.8</version>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.4</version>
- </dependency>
- <dependency>
- <groupId>org.apache.tika</groupId>
- <artifactId>tika-core</artifactId>
- <version>1.5</version>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-usagerecord</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <Export-Package>uk.org.taverna.server.client</Export-Package>
- <Private-Package>uk.org.taverna.server.client.*</Private-Package>
- </instructions>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.jvnet.ws.wadl</groupId>
- <artifactId>wadl-client-plugin</artifactId>
- <version>1.1.6</version>
- <executions>
- <execution>
- <goals>
- <goal>generate</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <packageName>org.taverna.server.client.wadl</packageName>
- <includes>*.wadl</includes>
- <customClassNames>
- <property>
- <name>http://example.com/taverna/rest</name>
- <value>TavernaServer</value>
- </property>
- </customClassNames>
- </configuration>
- </plugin>
- </plugins>
- <pluginManagement>
- <plugins>
- <!--This plugin's configuration is used to store Eclipse m2e settings
- only. It has no influence on the Maven build itself. -->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>
- org.jvnet.ws.wadl
- </groupId>
- <artifactId>
- wadl-client-plugin
- </artifactId>
- <versionRange>
- [1.1.6,)
- </versionRange>
- <goals>
- <goal>generate</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute />
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/Connected.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Connected.java b/server-client/src/main/java/uk/org/taverna/server/client/Connected.java
deleted file mode 100644
index 263034c..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/Connected.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package uk.org.taverna.server.client;
-
-import uk.org.taverna.server.client.TavernaServer.ClientException;
-import uk.org.taverna.server.client.TavernaServer.ServerException;
-
-import com.sun.jersey.api.client.ClientResponse;
-
-abstract class Connected {
- void checkError(ClientResponse response) throws ClientException,
- ServerException {
- ClientResponse.Status s = response.getClientResponseStatus();
- if (s.getStatusCode() == 401)
- throw new TavernaServer.AuthorizationException("not authorized",
- null);
- if (s.getStatusCode() >= 500)
- throw new TavernaServer.ServerException(s.getReasonPhrase(), null);
- if (s.getStatusCode() >= 400)
- throw new TavernaServer.ClientException(s.getReasonPhrase(), null);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java b/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
deleted file mode 100644
index 267707d..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/DirEntry.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package uk.org.taverna.server.client;
-
-import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd.Path2;
-
-import uk.org.taverna.server.client.TavernaServer.ClientException;
-import uk.org.taverna.server.client.TavernaServer.ServerException;
-
-import com.sun.jersey.api.client.ClientResponse;
-
-public abstract class DirEntry extends Connected {
- final Path2 handle;
- final String path;
- final Run run;
-
- protected DirEntry(Run run, String path) {
- this.run = run;
- this.path = path.replaceFirst("/+$", "");
- this.handle = run.run.wd().path2(this.path);
- }
-
- public void delete() throws ClientException, ServerException {
- checkError(handle.deleteAsXml(ClientResponse.class));
- }
-
- String path(ClientResponse response) throws ClientException, ServerException {
- checkError(response);
- String[] bits = response.getLocation().getPath().split("/");
- return concat(bits[bits.length - 1]);
- }
-
- String localName() {
- String[] bits = path.split("/");
- return bits[bits.length - 1];
- }
-
- String concat(String name) {
- return path + "/" + name.split("/", 2)[0];
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/Directory.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Directory.java b/server-client/src/main/java/uk/org/taverna/server/client/Directory.java
deleted file mode 100644
index 38dc394..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/Directory.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package uk.org.taverna.server.client;
-
-import static java.io.File.createTempFile;
-import static javax.ws.rs.client.Entity.entity;
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.ZipFile;
-
-import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd;
-
-import uk.org.taverna.server.client.TavernaServer.ClientException;
-import uk.org.taverna.server.client.TavernaServer.ServerException;
-import uk.org.taverna.server.client.generic.DirectoryEntry;
-import uk.org.taverna.server.client.generic.DirectoryReference;
-import uk.org.taverna.server.client.generic.FileReference;
-import uk.org.taverna.server.client.rest.DirectoryContents;
-import uk.org.taverna.server.client.rest.MakeDirectory;
-import uk.org.taverna.server.client.rest.UploadFile;
-
-import com.sun.jersey.api.client.ClientResponse;
-
-public class Directory extends DirEntry {
- private final Wd wd;
-
- Directory(Run run) {
- super(run, "");
- this.wd = run.run.wd();
- }
-
- Directory(Run run, String path) {
- super(run, path);
- this.wd = run.run.wd();
- }
-
- public List<DirEntry> list() {
- List<DirEntry> result = new ArrayList<>();
- for (DirectoryEntry de : wd.path3(path)
- .getAsXml(DirectoryContents.class).getDirOrFile())
- if (de instanceof DirectoryReference)
- result.add(new Directory(run, de.getValue()));
- else if (de instanceof FileReference)
- result.add(new File(run, de.getValue()));
- return result;
- }
-
- public File createFile(String name, byte[] content) throws ClientException,
- ServerException {
- UploadFile uf = new UploadFile();
- uf.setName(name);
- uf.setValue(content);
- return new File(run, path(wd.path(path).putAsXml(uf,
- ClientResponse.class)));
- }
-
- public File createFile(String name, java.io.File content)
- throws ClientException, ServerException {
- return new File(run, path(wd.path(concat(name)).putOctetStreamAsXml(
- entity(content, APPLICATION_OCTET_STREAM_TYPE),
- ClientResponse.class)));
- }
-
- public File createFile(String name, URI source) throws ClientException,
- ServerException {
- return new File(run, path(wd.path(concat(name)).postTextUriListAsXml(
- source.toString(), ClientResponse.class)));
- }
-
- public Directory createDirectory(String name) throws ClientException,
- ServerException {
- MakeDirectory mkdir = new MakeDirectory();
- mkdir.setName(name);
- return new Directory(run, path(wd.path(path).putAsXml(mkdir,
- ClientResponse.class)));
- }
-
- public byte[] getZippedContents() {
- return wd.path3(path).getAsZip(byte[].class);
- }
-
- public ZipFile getZip() throws IOException {
- byte[] contents = getZippedContents();
- java.io.File tmp = createTempFile(localName(), ".zip");
- try (OutputStream os = new FileOutputStream(tmp)) {
- os.write(contents);
- }
- return new ZipFile(tmp);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/File.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/File.java b/server-client/src/main/java/uk/org/taverna/server/client/File.java
deleted file mode 100644
index 0287afb..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/File.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package uk.org.taverna.server.client;
-
-import static java.io.File.createTempFile;
-import static javax.ws.rs.client.Entity.entity;
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
-import static org.apache.commons.io.IOUtils.copy;
-import static org.apache.tika.mime.MimeTypes.getDefaultMimeTypes;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-
-import org.apache.tika.mime.MimeTypeException;
-import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName.Wd;
-
-import uk.org.taverna.server.client.TavernaServer.ClientException;
-import uk.org.taverna.server.client.TavernaServer.ServerException;
-
-import com.sun.jersey.api.client.ClientHandlerException;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.UniformInterfaceException;
-
-public class File extends DirEntry {
- private final Wd wd;
-
- File(Run run, String path) {
- super(run, path);
- wd = run.run.wd();
- }
-
- public InputStream getAsStream() {
- return wd.path3(path).getAsOctetStream(InputStream.class);
- }
-
- public byte[] get() {
- return wd.path3(path).getAsOctetStream(byte[].class);
- }
-
- public String get(Charset encoding) {
- return new String(wd.path3(path).getAsOctetStream(byte[].class),
- encoding);
- }
-
- public java.io.File getAsFile() throws ClientHandlerException,
- UniformInterfaceException, IOException, MimeTypeException,
- ClientException, ServerException {
- ClientResponse cr = wd.path3(path).getAsOctetStream(
- ClientResponse.class);
- checkError(cr);
- String[] bits = localName().split("[.]");
- String ext = getDefaultMimeTypes().forName(
- cr.getHeaders().getFirst("Content-Type")).getExtension();
- if (ext == null)
- ext = bits[bits.length - 1];
- java.io.File tmp = createTempFile(bits[0], ext);
- try (OutputStream os = new FileOutputStream(tmp);
- InputStream is = cr.getEntity(InputStream.class)) {
- copy(is, os);
- }
- return tmp;
- }
-
- public void setContents(byte[] newContents) throws ClientException,
- ServerException {
- checkError(wd.path(path).putOctetStreamAsXml(newContents,
- ClientResponse.class));
- }
-
- public void setContents(String newContents) throws ClientException,
- ServerException {
- checkError(wd.path(path).putOctetStreamAsXml(newContents,
- ClientResponse.class));
- }
-
- public void setContents(String newContents, Charset encoding)
- throws ClientException, ServerException {
- checkError(wd.path(path).putOctetStreamAsXml(
- newContents.getBytes(encoding), ClientResponse.class));
- }
-
- public void setContents(InputStream newContents) throws ClientException,
- ServerException {
- checkError(wd.path(path).putOctetStreamAsXml(newContents,
- ClientResponse.class));
- }
-
- public void setContents(java.io.File newContents) throws IOException,
- ClientException, ServerException {
- checkError(wd.path(path).putOctetStreamAsXml(
- entity(newContents, APPLICATION_OCTET_STREAM_TYPE),
- ClientResponse.class));
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/Property.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Property.java b/server-client/src/main/java/uk/org/taverna/server/client/Property.java
deleted file mode 100644
index 0e6542f..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/Property.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package uk.org.taverna.server.client;
-
-public enum Property {
- STDOUT("stdout"), STDERR("stderr"), EXIT_CODE("exitcode"), READY_TO_NOTIFY(
- "readyToNotify"), EMAIL("notificationAddress"), USAGE(
- "usageRecord");
-
- private String s;
-
- private Property(String s) {
- this.s = s;
- }
-
- @Override
- public String toString() {
- return s;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/Run.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Run.java b/server-client/src/main/java/uk/org/taverna/server/client/Run.java
deleted file mode 100644
index 5c6875e..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/Run.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package uk.org.taverna.server.client;
-
-import static org.joda.time.format.ISODateTimeFormat.dateTime;
-import static org.joda.time.format.ISODateTimeFormat.dateTimeParser;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Date;
-import java.util.List;
-
-import javax.xml.bind.JAXBException;
-
-import org.apache.commons.io.IOUtils;
-import org.joda.time.DateTime;
-import org.ogf.usage.JobUsageRecord;
-import org.taverna.server.client.wadl.TavernaServer.Root.RunsRunName;
-import org.w3c.dom.Element;
-
-import uk.org.taverna.server.client.TavernaServer.ClientException;
-import uk.org.taverna.server.client.TavernaServer.ServerException;
-import uk.org.taverna.server.client.generic.KeyPairCredential;
-import uk.org.taverna.server.client.generic.PasswordCredential;
-import uk.org.taverna.server.client.generic.port.InputPort;
-import uk.org.taverna.server.client.generic.port.OutputPort;
-import uk.org.taverna.server.client.rest.InputDescription;
-import uk.org.taverna.server.client.rest.InputDescription.Value;
-
-import com.sun.jersey.api.client.ClientResponse;
-
-public class Run extends Connected {
- RunsRunName run;
-
- Run(TavernaServer server, String value) {
- run = server.root.runsRunName(value);
- }
-
- public String getName() {
- return run.name().getAsTextPlain(ClientResponse.class)
- .getEntity(String.class);
- }
-
- public void setName(String name) {
- run.name().putTextPlain(name, String.class);
- }
-
- public Date getExpiry() {
- return dateTimeParser().parseDateTime(
- run.expiry().getAsTextPlain(String.class)).toDate();
- }
-
- public void setExpiry(Date expiryTimestamp) {
- run.expiry().putTextPlain(
- dateTime().print(new DateTime(expiryTimestamp)), String.class);
- }
-
- public Date getCreate() {
- String timestamp = run.createTime().getAsTextPlain(String.class);
- if (timestamp == null || timestamp.trim().isEmpty())
- return null;
- return dateTimeParser().parseDateTime(timestamp).toDate();
- }
-
- public Date getStart() {
- String timestamp = run.startTime().getAsTextPlain(String.class);
- if (timestamp == null || timestamp.trim().isEmpty())
- return null;
- return dateTimeParser().parseDateTime(timestamp).toDate();
- }
-
- public Date getFinish() {
- String timestamp = run.finishTime().getAsTextPlain(String.class);
- if (timestamp == null || timestamp.trim().isEmpty())
- return null;
- return dateTimeParser().parseDateTime(timestamp).toDate();
- }
-
- public Status getStatus() {
- return Status.valueOf(run.status().getAsTextPlain(String.class));
- }
-
- public void setStatus(Status status) {
- run.status().putTextPlain(status, String.class);
- }
-
- public void start() {
- setStatus(Status.Operating);
- }
-
- public void kill() {
- setStatus(Status.Finished);
- }
-
- public boolean isRunning() {
- return getStatus() == Status.Operating;
- }
-
- public String getStandardOutput() {
- return run.stdout().getAsTextPlain(String.class);
- }
-
- public String getStandardError() {
- return run.stderr().getAsTextPlain(String.class);
- }
-
- public String getLog() {
- return run.log().getAsTextPlain(String.class);
- }
-
- public Integer getExitCode() {
- String code = run.listeners().name("io")
- .propertiesPropertyName("exitCode")
- .getAsTextPlain(String.class);
- if (code == null || code.trim().isEmpty())
- return null;
- return Integer.parseInt(code);
- }
-
- public String getProperty(Property prop) {
- return run.listeners().name("io")
- .propertiesPropertyName(prop.toString())
- .getAsTextPlain(String.class);
- }
-
- public void setGenerateRunBundle(boolean generateRunBundle) {
- run.generateProvenance().putTextPlain(generateRunBundle, String.class);
- }
-
- public byte[] getRunBundle() {
- return run.runBundle().getAsVndWf4everRobundleZip(byte[].class);
- }
-
- public List<InputPort> getInputs() {
- return run.input().expected().getAsInputDescriptionXml().getInput();
- }
-
- public List<OutputPort> getOutputs() {
- return run.output().getAsOutputDescriptionXml().getOutput();
- }
-
- public void setInput(String name, String value) {
- Value v = new Value();
- v.setValue(value);
- InputDescription idesc = new InputDescription();
- idesc.setValue(v);
- run.input().inputName(name).putXmlAsInputDescription(idesc);
- }
-
- public void setInput(String name, String value, char listSeparator) {
- Value v = new Value();
- v.setValue(value);
- InputDescription idesc = new InputDescription();
- idesc.setValue(v);
- idesc.setListDelimiter(new String(new char[] { listSeparator }));
- run.input().inputName(name).putXmlAsInputDescription(idesc);
- }
-
- public byte[] getWorkflow() {
- return run.workflow().getAsVndTavernaT2flowXml(byte[].class);
- }
-
- // TODO Consider better ways to do this
- public Element getInteractionFeed() {
- return run.interaction().getAsAtomXml(Element.class);
- }
-
- public Element getInteractionEntry(String id) {
- return run.interaction().id(id).getAsAtomXml(Element.class);
- }
-
- public JobUsageRecord getUsageRecord() throws JAXBException {
- return JobUsageRecord.unmarshal(run.usage().getAsXml(Element.class));
- }
-
- public Directory getWorkingDirectory() {
- return new Directory(this);
- }
-
- public String getOwner() {
- return run.security().owner().getAsTextPlain(String.class);
- }
-
- // TODO permissions
-
- public void grantPasswordCredential(URI contextService, String username,
- String password) throws ClientException, ServerException {
- PasswordCredential pc = new PasswordCredential();
- pc.setServiceURI(contextService.toString());
- pc.setUsername(username);
- pc.setPassword(password);
- checkError(run.security().credentials()
- .postXmlAsOctetStream(pc, ClientResponse.class));
- }
-
- public void grantKeyCredential(URI contextService, java.io.File source,
- String unlockPassword, String aliasEntry) throws IOException,
- ClientException, ServerException {
- KeyPairCredential kpc = new KeyPairCredential();
- kpc.setServiceURI(contextService.toString());
- try (InputStream in = new FileInputStream(source)) {
- byte[] buffer = new byte[(int) source.length()];
- IOUtils.read(in, buffer);
- kpc.setCredentialBytes(buffer);
- }
- if (source.getName().endsWith(".p12"))
- kpc.setFileType("PKCS12");
- else
- kpc.setFileType("JKS");
- kpc.setCredentialName(aliasEntry);
- kpc.setUnlockPassword(unlockPassword);
- checkError(run.security().credentials()
- .postXmlAsOctetStream(kpc, ClientResponse.class));
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/Status.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/Status.java b/server-client/src/main/java/uk/org/taverna/server/client/Status.java
deleted file mode 100644
index 9c375ad..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/Status.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package uk.org.taverna.server.client;
-
-/**
- * States of a workflow run. They are {@link #Initialized Initialized},
- * {@link #Operating Operating}, {@link #Stopped Stopped}, and
- * {@link #Finished Finished}. Conceptually, there is also a
- * <tt>Destroyed</tt> state, but the workflow run does not exist (and hence
- * can't have its state queried or set) in that case.
- *
- * @author Donal Fellows
- */
-public enum Status {
- /**
- * The workflow run has been created, but is not yet running. The run
- * will need to be manually moved to {@link #Operating Operating} when
- * ready.
- */
- Initialized,
- /**
- * The workflow run is going, reading input, generating output, etc.
- * Will eventually either move automatically to {@link #Finished
- * Finished} or can be moved manually to {@link #Stopped Stopped} (where
- * supported).
- */
- Operating,
- /**
- * The workflow run is paused, and will need to be moved back to
- * {@link #Operating Operating} manually.
- */
- Stopped,
- /**
- * The workflow run has ceased; data files will continue to exist until
- * the run is destroyed (which may be manual or automatic).
- */
- Finished
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java b/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
deleted file mode 100644
index 7c0dcdd..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServer.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package uk.org.taverna.server.client;
-
-import static java.nio.file.Files.readAllBytes;
-import static org.taverna.server.client.wadl.TavernaServer.createClient;
-import static org.taverna.server.client.wadl.TavernaServer.root;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.taverna.server.client.wadl.TavernaServer.Root;
-
-import uk.org.taverna.server.client.generic.Capability;
-import uk.org.taverna.server.client.generic.TavernaRun;
-import uk.org.taverna.server.client.generic.VersionedElement;
-
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
-
-public class TavernaServer extends Connected {
- final Root root;
- private final URI location;
- private final boolean authenticated;
-
- TavernaServer(URI serviceRoot) {
- root = root(createClient(), location = serviceRoot);
- authenticated = false;
- }
-
- TavernaServer(URI serviceRoot, String username, String password) {
- Client client = createClient();
- client.addFilter(new HTTPBasicAuthFilter(username, password));
- authenticated = true;
- root = root(client, location = serviceRoot);
- }
-
- TavernaServer(TavernaServer service, String username, String password) {
- Client client = createClient();
- client.addFilter(new HTTPBasicAuthFilter(username, password));
- authenticated = true;
- root = root(client, location = service.location);
- getServerVersionInfo();
- }
-
- public TavernaServer upgradeToAuth(String username, String password) {
- if (authenticated)
- throw new IllegalStateException("may only upgrade an unauthenticated connection");
- return new TavernaServer(this, username, password);
- }
-
- public List<Capability> getCapabilities() {
- return root.policy().capabilities().getAsCapabilitiesXml()
- .getCapability();
- }
-
- public int getRunLimit() {
- return root.policy().runLimit().getAsTextPlain(Integer.class);
- }
-
- public int getOperatingLimit() {
- return root.policy().operatingLimit().getAsTextPlain(Integer.class);
- }
-
- public List<String> getPermittedWorkflows() {
- return root.policy().permittedWorkflows().getAsPermittedWorkflowsXml()
- .getWorkflow();
- }
-
- public List<Run> getExistingRuns() {
- List<Run> runs = new ArrayList<>();
- for (TavernaRun run : root.runs().getAsRunListXml().getRun())
- runs.add(new Run(this, run.getValue()));
- return runs;
- }
-
- public VersionedElement getServerVersionInfo() {
- return root.getAsServerDescriptionXml();
- }
-
- private Run response2run(ClientResponse response) throws ClientException, ServerException {
- checkError(response);
- if (response.getClientResponseStatus().getStatusCode() == 201) {
- String[] path = response.getLocation().getPath().split("/");
- return new Run(this, path[path.length - 1]);
- }
- return null;
- }
-
- public Run createWorkflowRun(byte[] t2flowBytes) throws ClientException, ServerException {
- return response2run(root.runs().postVndTavernaT2flowXmlAsOctetStream(
- t2flowBytes, ClientResponse.class));
- }
-
- public Run createWorkflowRun(File t2flowFile) throws IOException, ClientException, ServerException {
- return createWorkflowRun(readAllBytes(t2flowFile.toPath()));
- }
-
- public Run createWorkflowRun(URI t2flowUri) throws ClientException, ServerException {
- return response2run(root.runs().postTextUriListAsOctetStream(
- t2flowUri.toString(), ClientResponse.class));
- }
-
-
- public static class ClientException extends Exception {
- private static final long serialVersionUID = 1L;
-
- ClientException(String msg, Throwable cause) {
- super(msg, cause);
- }
- }
- public static class AuthorizationException extends ClientException {
- private static final long serialVersionUID = 1L;
-
- AuthorizationException(String msg, Throwable cause) {
- super(msg, cause);
- }
- }
- static class ServerException extends Exception {
- private static final long serialVersionUID = 1L;
-
- ServerException(String msg, Throwable cause) {
- super(msg, cause);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java b/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
deleted file mode 100644
index b00b075..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/TavernaServerConnectionFactory.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package uk.org.taverna.server.client;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-public class TavernaServerConnectionFactory {
- private Map<URI, TavernaServer> cache = new HashMap<>();
-
- public synchronized TavernaServer connectNoAuth(URI uri) {
- TavernaServer conn = cache.get(uri);
- if (conn == null)
- cache.put(uri, conn = new TavernaServer(uri));
- return conn;
- }
-
- public TavernaServer connectAuth(URI uri, String username, String password) {
- TavernaServer conn = new TavernaServer(uri, username, password);
- // Force a check of the credentials by getting the server version
- conn.getServerVersionInfo();
- return conn;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-client/src/main/java/uk/org/taverna/server/client/package-info.java
----------------------------------------------------------------------
diff --git a/server-client/src/main/java/uk/org/taverna/server/client/package-info.java b/server-client/src/main/java/uk/org/taverna/server/client/package-info.java
deleted file mode 100644
index 59e809d..0000000
--- a/server-client/src/main/java/uk/org/taverna/server/client/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-/**
- * Implementation of a basic client for Taverna Server.
- * @author Donal Fellows
- */
-package uk.org.taverna.server.client;
\ No newline at end of file
[02/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/misc/xsd/persistence_1_0.xsd
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/misc/xsd/persistence_1_0.xsd b/taverna-server-webapp/src/misc/xsd/persistence_1_0.xsd
new file mode 100644
index 0000000..a485e30
--- /dev/null
+++ b/taverna-server-webapp/src/misc/xsd/persistence_1_0.xsd
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- persistence.xml schema -->
+<xsd:schema targetNamespace="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:persistence="http://java.sun.com/xml/ns/persistence"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ version="1.0">
+
+ <xsd:annotation>
+ <xsd:documentation>
+ @(#)persistence_1_0.xsd 1.0 Feb 9 2006
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:annotation>
+ <xsd:documentation>
+
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+
+ Copyright 2005-2007 Sun Microsystems, Inc. All rights reserved.
+
+ The contents of this file are subject to the terms of either the
+ GNU General Public License Version 2 only ("GPL") or the Common
+ Development and Distribution License("CDDL") (collectively, the
+ "License"). You may not use this file except in compliance with
+ the License. You can obtain a copy of the License at
+ https://glassfish.dev.java.net/public/CDDL+GPL.html or
+ glassfish/bootstrap/legal/LICENSE.txt. See the License for the
+ specific language governing permissions and limitations under the
+ License.
+
+ When distributing the software, include this License Header
+ Notice in each file and include the License file at
+ glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
+ particular file as subject to the "Classpath" exception as
+ provided by Sun in the GPL Version 2 section of the License file
+ that accompanied this code. If applicable, add the following
+ below the License Header, with the fields enclosed by brackets []
+ replaced by your own identifying information:
+ "Portions Copyrighted [year] [name of copyright owner]"
+
+ Contributor(s):
+
+ If you wish your version of this file to be governed by only the
+ CDDL or only the GPL Version 2, indicate your decision by adding
+ "[Contributor] elects to include this software in this
+ distribution under the [CDDL or GPL Version 2] license." If you
+ don't indicate a single choice of license, a recipient has the
+ option to distribute your version of this file under either the
+ CDDL, the GPL Version 2 or to extend the choice of license to its
+ licensees as provided above. However, if you add GPL Version 2
+ code and therefore, elected the GPL Version 2 license, then the
+ option applies only if the new code is made subject to such
+ option by the copyright holder.
+
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+
+ This is the XML Schema for the persistence configuration file.
+ The file must be named "META-INF/persistence.xml" in the
+ persistence archive.
+ Persistence configuration files must indicate
+ the persistence schema by using the persistence namespace:
+
+ http://java.sun.com/xml/ns/persistence
+
+ and indicate the version of the schema by
+ using the version element as shown below:
+
+ <persistence xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+ http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+ version="1.0">
+ ...
+ </persistence>
+
+ ]]></xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:simpleType name="versionType">
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[0-9]+(\.[0-9]+)*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="persistence">
+ <xsd:complexType>
+ <xsd:sequence>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="persistence-unit"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Configuration of a persistence unit.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="description" type="xsd:string"
+ minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Textual description of this persistence unit.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="provider" type="xsd:string"
+ minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Provider class that supplies EntityManagers for this
+ persistence unit.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="jta-data-source" type="xsd:string"
+ minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ The container-specific name of the JTA datasource to use.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="non-jta-data-source" type="xsd:string"
+ minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ The container-specific name of a non-JTA datasource to use.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="mapping-file" type="xsd:string"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ File containing mapping information. Loaded as a resource
+ by the persistence provider.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="jar-file" type="xsd:string"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Jar file that should be scanned for entities.
+ Not applicable to Java SE persistence units.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="class" type="xsd:string"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Class to scan for annotations. It should be annotated
+ with either @Entity, @Embeddable or @MappedSuperclass.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="exclude-unlisted-classes" type="xsd:boolean"
+ default="false" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ When set to true then only listed classes and jars will
+ be scanned for persistent classes, otherwise the enclosing
+ jar or directory will also be scanned. Not applicable to
+ Java SE persistence units.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:element name="properties" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ A list of vendor-specific properties.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="property"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation>
+ A name-value pair.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="name" type="xsd:string"
+ use="required"/>
+ <xsd:attribute name="value" type="xsd:string"
+ use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ </xsd:sequence>
+
+ <!-- **************************************************** -->
+
+ <xsd:attribute name="name" type="xsd:string" use="required">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Name used in code to reference this persistence unit.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+
+ <!-- **************************************************** -->
+
+ <xsd:attribute name="transaction-type"
+ type="persistence:persistence-unit-transaction-type">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Type of transactions used by EntityManagers from this
+ persistence unit.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="persistence:versionType"
+ fixed="1.0" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- **************************************************** -->
+
+ <xsd:simpleType name="persistence-unit-transaction-type">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ public enum TransactionType { JTA, RESOURCE_LOCAL };
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="JTA"/>
+ <xsd:enumeration value="RESOURCE_LOCAL"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+</xsd:schema>
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java
new file mode 100644
index 0000000..79c026b
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/JaxbSanityTest.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.taverna.server.master.admin.Admin;
+import org.taverna.server.master.common.Credential.KeyPair;
+import org.taverna.server.master.common.Credential.Password;
+import org.taverna.server.master.common.Capability;
+import org.taverna.server.master.common.DirEntryReference;
+import org.taverna.server.master.common.InputDescription;
+import org.taverna.server.master.common.Permission;
+import org.taverna.server.master.common.ProfileList;
+import org.taverna.server.master.common.RunReference;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.common.Uri;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.rest.DirectoryContents;
+import org.taverna.server.master.rest.ListenerDefinition;
+import org.taverna.server.master.rest.MakeOrUpdateDirEntry;
+import org.taverna.server.master.rest.TavernaServerInputREST.InDesc;
+import org.taverna.server.master.rest.TavernaServerInputREST.InputsDescriptor;
+import org.taverna.server.master.rest.TavernaServerListenersREST.ListenerDescription;
+import org.taverna.server.master.rest.TavernaServerListenersREST.Listeners;
+import org.taverna.server.master.rest.TavernaServerListenersREST.Properties;
+import org.taverna.server.master.rest.TavernaServerListenersREST.PropertyDescription;
+import org.taverna.server.master.rest.TavernaServerREST.EnabledNotificationFabrics;
+import org.taverna.server.master.rest.TavernaServerREST.PermittedListeners;
+import org.taverna.server.master.rest.TavernaServerREST.PermittedWorkflows;
+import org.taverna.server.master.rest.TavernaServerREST.PolicyView.CapabilityList;
+import org.taverna.server.master.rest.TavernaServerREST.PolicyView.PolicyDescription;
+import org.taverna.server.master.rest.TavernaServerREST.RunList;
+import org.taverna.server.master.rest.TavernaServerREST.ServerDescription;
+import org.taverna.server.master.rest.TavernaServerRunREST.RunDescription;
+import org.taverna.server.master.rest.TavernaServerSecurityREST;
+import org.taverna.server.master.rest.TavernaServerSecurityREST.CredentialHolder;
+import org.taverna.server.master.soap.DirEntry;
+import org.taverna.server.master.soap.FileContents;
+import org.taverna.server.master.soap.PermissionList;
+
+/**
+ * This test file ensures that the JAXB bindings will work once deployed instead
+ * of mysteriously failing in service.
+ *
+ * @author Donal Fellows
+ */
+public class JaxbSanityTest {
+ SchemaOutputResolver sink;
+ StringWriter schema;
+
+ String schema() {
+ return schema.toString();
+ }
+
+ @Before
+ public void init() {
+ schema = new StringWriter();
+ sink = new SchemaOutputResolver() {
+ @Override
+ public Result createOutput(String namespaceUri,
+ String suggestedFileName) throws IOException {
+ StreamResult sr = new StreamResult(schema);
+ sr.setSystemId("/dev/null");
+ return sr;
+ }
+ };
+ assertEquals("", schema());
+ }
+
+ private boolean printSchema = false;
+
+ private void testJAXB(Class<?>... classes) throws Exception {
+ JAXBContext.newInstance(classes).generateSchema(sink);
+ if (printSchema)
+ System.out.println(schema());
+ assertTrue(schema().length() > 0);
+ }
+
+ @Test
+ public void testJAXBForDirEntryReference() throws Exception {
+ JAXBContext.newInstance(DirEntryReference.class).generateSchema(sink);
+ assertTrue(schema().length() > 0);
+ }
+
+ @Test
+ public void testJAXBForInputDescription() throws Exception {
+ testJAXB(InputDescription.class);
+ }
+
+ @Test
+ public void testJAXBForRunReference() throws Exception {
+ testJAXB(RunReference.class);
+ }
+
+ @Test
+ public void testJAXBForWorkflow() throws Exception {
+ testJAXB(Workflow.class);
+ }
+
+ @Test
+ public void testJAXBForStatus() throws Exception {
+ testJAXB(Status.class);
+ }
+
+ @Test
+ public void testJAXBForUri() throws Exception {
+ testJAXB(Uri.class);
+ }
+
+ @Test
+ public void testJAXBForDirectoryContents() throws Exception {
+ testJAXB(DirectoryContents.class);
+ }
+
+ @Test
+ public void testJAXBForListenerDefinition() throws Exception {
+ testJAXB(ListenerDefinition.class);
+ }
+
+ @Test
+ public void testJAXBForMakeOrUpdateDirEntry() throws Exception {
+ testJAXB(MakeOrUpdateDirEntry.class);
+ }
+
+ @Test
+ public void testJAXBForInDesc() throws Exception {
+ testJAXB(InDesc.class);
+ }
+
+ @Test
+ public void testJAXBForInputsDescriptor() throws Exception {
+ testJAXB(InputsDescriptor.class);
+ }
+
+ @Test
+ public void testJAXBForListenerDescription() throws Exception {
+ testJAXB(ListenerDescription.class);
+ }
+
+ @Test
+ public void testJAXBForListeners() throws Exception {
+ testJAXB(Listeners.class);
+ }
+
+ @Test
+ public void testJAXBForProperties() throws Exception {
+ testJAXB(Properties.class);
+ }
+
+ @Test
+ public void testJAXBForPropertyDescription() throws Exception {
+ testJAXB(PropertyDescription.class);
+ }
+
+ @Test
+ public void testJAXBForPermittedListeners() throws Exception {
+ testJAXB(PermittedListeners.class);
+ }
+
+ @Test
+ public void testJAXBForPermittedWorkflows() throws Exception {
+ testJAXB(PermittedWorkflows.class);
+ }
+
+ @Test
+ public void testJAXBForEnabledNotifiers() throws Exception {
+ testJAXB(EnabledNotificationFabrics.class);
+ }
+
+ @Test
+ public void testJAXBForServerDescription() throws Exception {
+ testJAXB(ServerDescription.class);
+ }
+
+ @Test
+ public void testJAXBForRunDescription() throws Exception {
+ testJAXB(RunDescription.class);
+ }
+
+ @Test
+ public void testJAXBForRunList() throws Exception {
+ testJAXB(RunList.class);
+ }
+
+ @Test
+ public void testJAXBForPolicyDescription() throws Exception {
+ testJAXB(PolicyDescription.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityCredential() throws Exception {
+ testJAXB(CredentialHolder.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityCredentialList() throws Exception {
+ testJAXB(TavernaServerSecurityREST.CredentialList.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityTrust() throws Exception {
+ testJAXB(Trust.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityTrustList() throws Exception {
+ testJAXB(TavernaServerSecurityREST.TrustList.class);
+ }
+
+ @Test
+ public void testJAXBForPermission() throws Exception {
+ testJAXB(Permission.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityPermissionDescription() throws Exception {
+ testJAXB(TavernaServerSecurityREST.PermissionDescription.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityPermissionsDescription() throws Exception {
+ testJAXB(TavernaServerSecurityREST.PermissionsDescription.class);
+ }
+
+ @Test
+ public void testJAXBForSecurityDescriptor() throws Exception {
+ testJAXB(TavernaServerSecurityREST.Descriptor.class);
+ }
+
+ @Test
+ public void testJAXBForProfileList() throws Exception {
+ testJAXB(ProfileList.class);
+ }
+
+ @Test
+ public void testJAXBForDirEntry() throws Exception {
+ testJAXB(DirEntry.class);
+ }
+
+ @Test
+ public void testJAXBForCapability() throws Exception {
+ testJAXB(Capability.class);
+ }
+
+ @Test
+ public void testJAXBForCapabilityList() throws Exception {
+ testJAXB(CapabilityList.class);
+ }
+
+ @Test
+ public void testJAXBForEverythingREST() throws Exception {
+ testJAXB(DirEntryReference.class, InputDescription.class,
+ RunReference.class, Workflow.class, Status.class,
+ DirectoryContents.class, InDesc.class,
+ ListenerDefinition.class, MakeOrUpdateDirEntry.class,
+ InputsDescriptor.class, ListenerDescription.class,
+ Listeners.class, Properties.class, PropertyDescription.class,
+ PermittedListeners.class, PermittedWorkflows.class,
+ EnabledNotificationFabrics.class, ServerDescription.class,
+ RunDescription.class, Uri.class, RunList.class,
+ PolicyDescription.class, CredentialHolder.class, Trust.class,
+ TavernaServerSecurityREST.CredentialList.class,
+ TavernaServerSecurityREST.TrustList.class, Permission.class,
+ TavernaServerSecurityREST.Descriptor.class,
+ TavernaServerSecurityREST.PermissionDescription.class,
+ TavernaServerSecurityREST.PermissionsDescription.class,
+ ProfileList.class, Capability.class, CapabilityList.class);
+ }
+
+ @Test
+ public void testJAXBForEverythingSOAP() throws Exception {
+ testJAXB(DirEntry.class, FileContents.class, InputDescription.class,
+ Permission.class, PermissionList.class,
+ PermissionList.SinglePermissionMapping.class,
+ RunReference.class, Status.class, Trust.class, Uri.class,
+ ProfileList.class, Workflow.class, Capability.class);
+ }
+
+ @Test
+ public void testUserPassSerializeDeserialize() throws Exception {
+ JAXBContext c = JAXBContext.newInstance(CredentialHolder.class);
+
+ Password password = new Password();
+ password.username = "foo";
+ password.password = "bar";
+
+ // Serialize
+ StringWriter sw = new StringWriter();
+ CredentialHolder credIn = new CredentialHolder(password);
+ c.createMarshaller().marshal(credIn, sw);
+
+ // Deserialize
+ StringReader sr = new StringReader(sw.toString());
+ Object credOutObj = c.createUnmarshaller().unmarshal(sr);
+
+ // Test value-equivalence
+ assertEquals(credIn.getClass(), credOutObj.getClass());
+ CredentialHolder credOut = (CredentialHolder) credOutObj;
+ assertEquals(credIn.credential.getClass(),
+ credOut.credential.getClass());
+ assertEquals(credIn.getUserpass().username,
+ credOut.getUserpass().username);
+ assertEquals(credIn.getUserpass().password,
+ credOut.getUserpass().password);
+ }
+
+ @Test
+ public void testKeypairSerializeDeserialize() throws Exception {
+ JAXBContext c = JAXBContext.newInstance(CredentialHolder.class);
+
+ KeyPair keypair = new KeyPair();
+ keypair.credentialName = "foo";
+ keypair.credentialBytes = new byte[] { 1, 2, 3 };
+
+ // Serialize
+ StringWriter sw = new StringWriter();
+ CredentialHolder credIn = new CredentialHolder(keypair);
+ c.createMarshaller().marshal(credIn, sw);
+
+ // Deserialize
+ StringReader sr = new StringReader(sw.toString());
+ Object credOutObj = c.createUnmarshaller().unmarshal(sr);
+
+ // Test value-equivalence
+ assertEquals(credIn.getClass(), credOutObj.getClass());
+ CredentialHolder credOut = (CredentialHolder) credOutObj;
+ assertEquals(credIn.credential.getClass(),
+ credOut.credential.getClass());
+ assertEquals(credIn.getKeypair().credentialName,
+ credOut.getKeypair().credentialName);
+ assertTrue(Arrays.equals(credIn.getKeypair().credentialBytes,
+ credOut.getKeypair().credentialBytes));
+ }
+
+ @Test
+ public void testJAXBforAdmininstration() throws Exception {
+ testJAXB(Admin.AdminDescription.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java
new file mode 100644
index 0000000..9665cf0
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/TavernaServerImplTest.java
@@ -0,0 +1,246 @@
+package org.taverna.server.master;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonMap;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.taverna.server.master.api.ManagementModel;
+import org.taverna.server.master.common.RunReference;
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.mocks.ExampleRun;
+import org.taverna.server.master.mocks.MockPolicy;
+import org.taverna.server.master.mocks.SimpleListenerFactory;
+import org.taverna.server.master.mocks.SimpleNonpersistentRunStore;
+
+public class TavernaServerImplTest {
+ private TavernaServer server;
+ private MockPolicy policy;
+ private SimpleNonpersistentRunStore store;
+ @java.lang.SuppressWarnings("unused")
+ private ExampleRun.Builder runFactory;
+ private SimpleListenerFactory lFactory;
+ private TavernaServerSupport support;
+
+ private String lrunname;
+ private String lrunconf;
+
+ Listener makeListener(TavernaRun run, final String config) {
+ lrunname = run.toString();
+ lrunconf = config;
+ return new Listener() {
+ @Override
+ public String getConfiguration() {
+ return config;
+ }
+
+ @Override
+ public String getName() {
+ return "bar";
+ }
+
+ @Override
+ public String getProperty(String propName)
+ throws NoListenerException {
+ throw new NoListenerException();
+ }
+
+ @Override
+ public String getType() {
+ return "foo";
+ }
+
+ @Override
+ public String[] listProperties() {
+ return new String[0];
+ }
+
+ @Override
+ public void setProperty(String propName, String value)
+ throws NoListenerException, BadPropertyValueException {
+ throw new NoListenerException();
+ }
+ };
+ }
+
+ @Before
+ public void wireup() throws Exception {
+ // Wire everything up; ought to be done with Spring, but this works...
+ server = new TavernaServer() {
+ @Override
+ protected RunREST makeRunInterface() {
+ return new RunREST() {
+ @Override
+ protected ListenersREST makeListenersInterface() {
+ return new ListenersREST() {
+ @Override
+ protected SingleListenerREST makeListenerInterface() {
+ return new SingleListenerREST() {
+ @Override
+ protected ListenerPropertyREST makePropertyInterface() {
+ return new ListenerPropertyREST() {
+ };
+ }
+ };
+ }
+ };
+ }
+
+ @Override
+ protected RunSecurityREST makeSecurityInterface() {
+ return new RunSecurityREST() {
+ };
+ }
+
+ @Override
+ protected DirectoryREST makeDirectoryInterface() {
+ return new DirectoryREST() {
+ };
+ }
+
+ @Override
+ protected InputREST makeInputInterface() {
+ return new InputREST() {
+ };
+ }
+
+ @Override
+ protected InteractionFeed makeInteractionFeed() {
+ return null; // TODO...
+ }
+ };
+ }
+
+ @Override
+ public PolicyView getPolicyDescription() {
+ return new PolicyREST();
+ }
+ };
+ support = new TavernaServerSupport();
+ server.setSupport(support);
+ support.setWebapp(server);
+ support.setLogGetPrincipalFailures(false);
+ support.setStateModel(new ManagementModel() {
+ @Override
+ public boolean getAllowNewWorkflowRuns() {
+ return true;
+ }
+
+ @Override
+ public boolean getLogIncomingWorkflows() {
+ return false;
+ }
+
+ @Override
+ public boolean getLogOutgoingExceptions() {
+ return false;
+ }
+
+ @Override
+ public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
+ }
+
+ @Override
+ public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
+ }
+
+ @Override
+ public void setLogOutgoingExceptions(boolean logOutgoingExceptions) {
+ }
+
+ @Override
+ public String getUsageRecordLogFile() {
+ return null;
+ }
+
+ @Override
+ public void setUsageRecordLogFile(String usageRecordLogFile) {
+ }
+ });
+ server.setPolicy(policy = new MockPolicy());
+ support.setPolicy(policy);
+ server.setRunStore(store = new SimpleNonpersistentRunStore());
+ support.setRunStore(store);
+ store.setPolicy(policy);
+ support.setRunFactory(runFactory = new ExampleRun.Builder(1));
+ support.setListenerFactory(lFactory = new SimpleListenerFactory());
+ lFactory.setBuilders(singletonMap(
+ "foo",
+ (SimpleListenerFactory.Builder) new SimpleListenerFactory.Builder() {
+ @Override
+ public Listener build(TavernaRun run, String configuration)
+ throws NoListenerException {
+ return makeListener(run, configuration);
+ }
+ }));
+ }
+
+ @Test
+ public void defaults1() {
+ assertNotNull(server);
+ }
+
+ @Test
+ public void defaults2() {
+ assertEquals(10, server.getServerMaxRuns());
+ }
+
+ @Test
+ public void defaults3() {
+ assertEquals(1, server.getServerListeners().length);
+ }
+
+ @Test
+ public void defaults4() {
+ assertNotNull(support.getPrincipal());
+ }
+
+ @Test
+ public void serverAsksPolicyForMaxRuns() {
+ int oldmax = policy.maxruns;
+ try {
+ policy.maxruns = 1;
+ assertEquals(1, server.getServerMaxRuns());
+ } finally {
+ policy.maxruns = oldmax;
+ }
+ }
+
+ @Test
+ public void makeAndKillARun() throws NoUpdateException, UnknownRunException {
+ RunReference rr = server.submitWorkflow(null);
+ assertNotNull(rr);
+ assertNotNull(rr.name);
+ server.destroyRun(rr.name);
+ }
+
+ @Test
+ public void makeListenKillRun() throws Exception {
+ RunReference run = server.submitWorkflow(null);
+ try {
+ lrunname = lrunconf = null;
+ assertEquals(asList("foo"), asList(server.getServerListeners()));
+ String l = server.addRunListener(run.name, "foo", "foobar");
+ assertEquals("bar", l);
+ assertEquals("foobar", lrunconf);
+ assertEquals(lrunname, support.getRun(run.name).toString());
+ assertEquals(asList("default", "bar"),
+ asList(server.getRunListeners(run.name)));
+ assertEquals(0,
+ server.getRunListenerProperties(run.name, "bar").length);
+ } finally {
+ try {
+ server.destroyRun(run.name);
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java
new file mode 100644
index 0000000..0450317
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/WorkflowSerializationTest.java
@@ -0,0 +1,68 @@
+package org.taverna.server.master;
+
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_NS;
+import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_ROOTNAME;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.taverna.server.master.common.Workflow;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class WorkflowSerializationTest {
+ @Test
+ public void testWorkflowSerialization()
+ throws ParserConfigurationException, IOException,
+ ClassNotFoundException {
+ DocumentBuilder db = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder();
+ Document doc = db.getDOMImplementation().createDocument(null, null,
+ null);
+ Element workflow = doc.createElementNS(T2FLOW_NS, T2FLOW_ROOTNAME);
+ Element foo = doc.createElementNS("urn:foo:bar", "pqr:foo");
+ foo.setTextContent("bar");
+ foo.setAttribute("xyz", "abc");
+ workflow.appendChild(foo);
+ Workflow w = new Workflow(workflow);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ oos.writeObject(w);
+ }
+
+ Object o;
+ try (ObjectInputStream ois = new ObjectInputStream(
+ new ByteArrayInputStream(baos.toByteArray()))) {
+ o = ois.readObject();
+ }
+
+ Assert.assertNotNull(o);
+ Assert.assertEquals(w.getClass(), o.getClass());
+ Workflow w2 = (Workflow) o;
+ Assert.assertNotNull(w2.getT2flowWorkflow());
+ Element e = w2.getT2flowWorkflow();
+ Assert.assertEquals(T2FLOW_ROOTNAME, e.getLocalName());
+ Assert.assertEquals(T2FLOW_NS, e.getNamespaceURI());
+ e = (Element) e.getFirstChild();
+ Assert.assertEquals("foo", e.getLocalName());
+ Assert.assertEquals("pqr", e.getPrefix());
+ Assert.assertEquals("urn:foo:bar", e.getNamespaceURI());
+ Assert.assertEquals("bar", e.getTextContent());
+ Assert.assertEquals(1, e.getChildNodes().getLength());
+ // WARNING: These are dependent on how namespaces are encoded!
+ Assert.assertEquals(2, e.getAttributes().getLength());
+ Assert.assertEquals("xyz", ((Attr) e.getAttributes().item(1)).getLocalName());
+ Assert.assertEquals("abc", e.getAttribute("xyz"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java
new file mode 100644
index 0000000..a2a0791
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/ExampleRun.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.mocks;
+
+import static java.util.Calendar.MINUTE;
+import static java.util.Collections.unmodifiableList;
+import static java.util.UUID.randomUUID;
+import static org.taverna.server.master.common.Status.Initialized;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.xml.ws.handler.MessageContext;
+
+import org.springframework.security.core.context.SecurityContext;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Trust;
+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.InvalidCredentialException;
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.factories.RunFactory;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.Input;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.SecurityContextFactory;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+@SuppressWarnings("serial")
+public class ExampleRun implements TavernaRun, TavernaSecurityContext {
+ String id;
+ List<Listener> listeners;
+ Workflow workflow;
+ Status status;
+ Date expiry;
+ UsernamePrincipal owner;
+ String inputBaclava;
+ String outputBaclava;
+ java.io.File realRoot;
+ List<Input> inputs;
+ String name;
+
+ public ExampleRun(UsernamePrincipal creator, Workflow workflow, Date expiry) {
+ this.id = randomUUID().toString();
+ this.listeners = new ArrayList<>();
+ this.status = Initialized;
+ this.owner = creator;
+ this.workflow = workflow;
+ this.expiry = expiry;
+ this.inputs = new ArrayList<>();
+ listeners.add(new DefaultListener());
+ }
+
+ @Override
+ public void addListener(Listener l) {
+ listeners.add(l);
+ }
+
+ @Override
+ public void destroy() {
+ // This does nothing...
+ }
+
+ @Override
+ public Date getExpiry() {
+ return expiry;
+ }
+
+ @Override
+ public List<Listener> getListeners() {
+ return listeners;
+ }
+
+ @Override
+ public TavernaSecurityContext getSecurityContext() {
+ return this;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public Workflow getWorkflow() {
+ return workflow;
+ }
+
+ @Override
+ public Directory getWorkingDirectory() {
+ // LATER: Implement this!
+ throw new UnsupportedOperationException("not yet implemented");
+ }
+
+ @Override
+ public void setExpiry(Date d) {
+ if (d.after(new Date()))
+ this.expiry = d;
+ }
+
+ @Override
+ public String setStatus(Status s) {
+ this.status = s;
+ return null;
+ }
+
+ @Override
+ public UsernamePrincipal getOwner() {
+ return owner;
+ }
+
+ public static class Builder implements RunFactory {
+ private int lifetime;
+
+ public Builder(int initialLifetimeMinutes) {
+ this.lifetime = initialLifetimeMinutes;
+ }
+
+ @Override
+ public TavernaRun create(UsernamePrincipal creator, Workflow workflow) {
+ Calendar c = GregorianCalendar.getInstance();
+ c.add(MINUTE, lifetime);
+ return new ExampleRun(creator, workflow, c.getTime());
+ }
+
+ @Override
+ public boolean isAllowingRunsToStart() {
+ return true;
+ }
+ }
+
+ static final String[] emptyArray = new String[0];
+
+ class DefaultListener implements Listener {
+ @Override
+ public String getConfiguration() {
+ return "";
+ }
+
+ @Override
+ public String getName() {
+ return "default";
+ }
+
+ @Override
+ public String getType() {
+ return "default";
+ }
+
+ @Override
+ public String[] listProperties() {
+ return emptyArray;
+ }
+
+ @Override
+ public String getProperty(String propName) throws NoListenerException {
+ throw new NoListenerException("no such property");
+ }
+
+ @Override
+ public void setProperty(String propName, String value)
+ throws NoListenerException {
+ throw new NoListenerException("no such property");
+ }
+ }
+
+ @Override
+ public String getInputBaclavaFile() {
+ return inputBaclava;
+ }
+
+ @Override
+ public List<Input> getInputs() {
+ return unmodifiableList(inputs);
+ }
+
+ @Override
+ public String getOutputBaclavaFile() {
+ return outputBaclava;
+ }
+
+ class ExampleInput implements Input {
+ public String name;
+ public String file;
+ public String value;
+ public String delim;
+
+ public ExampleInput(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getFile() {
+ return file;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void setFile(String file) throws FilesystemAccessException,
+ BadStateChangeException {
+ if (status != Status.Initialized)
+ throw new BadStateChangeException();
+ checkBadFilename(file);
+ this.file = file;
+ this.value = null;
+ inputBaclava = null;
+ }
+
+ @Override
+ public void setValue(String value) throws BadStateChangeException {
+ if (status != Status.Initialized)
+ throw new BadStateChangeException();
+ this.value = value;
+ this.file = null;
+ inputBaclava = null;
+ }
+
+ void reset() {
+ this.file = null;
+ this.value = null;
+ }
+
+ @Override
+ public String getDelimiter() {
+ return delim;
+ }
+
+ @Override
+ public void setDelimiter(String delimiter)
+ throws BadStateChangeException {
+ if (status != Status.Initialized)
+ throw new BadStateChangeException();
+ if (delimiter == null)
+ delim = null;
+ else
+ delim = delimiter.substring(0, 1);
+ }
+ }
+
+ @Override
+ public Input makeInput(String name) throws BadStateChangeException {
+ if (status != Status.Initialized)
+ throw new BadStateChangeException();
+ Input i = new ExampleInput(name);
+ inputs.add(i);
+ return i;
+ }
+
+ static void checkBadFilename(String filename)
+ throws FilesystemAccessException {
+ if (filename.startsWith("/"))
+ throw new FilesystemAccessException("filename may not be absolute");
+ if (Arrays.asList(filename.split("/")).contains(".."))
+ throw new FilesystemAccessException(
+ "filename may not refer to parent");
+ }
+
+ @Override
+ public void setInputBaclavaFile(String filename)
+ throws FilesystemAccessException, BadStateChangeException {
+ if (status != Status.Initialized)
+ throw new BadStateChangeException();
+ checkBadFilename(filename);
+ inputBaclava = filename;
+ for (Input i : inputs)
+ ((ExampleInput) i).reset();
+ }
+
+ @Override
+ public void setOutputBaclavaFile(String filename)
+ throws FilesystemAccessException, BadStateChangeException {
+ if (status != Status.Initialized)
+ throw new BadStateChangeException();
+ if (filename != null)
+ checkBadFilename(filename);
+ outputBaclava = filename;
+ }
+
+ private Date created = new Date();
+ @Override
+ public Date getCreationTimestamp() {
+ return created;
+ }
+
+ @Override
+ public Date getFinishTimestamp() {
+ return null;
+ }
+
+ @Override
+ public Date getStartTimestamp() {
+ return null;
+ }
+
+ @Override
+ public Credential[] getCredentials() {
+ return new Credential[0];
+ }
+
+ @Override
+ public void addCredential(Credential toAdd) {
+ }
+
+ @Override
+ public void deleteCredential(Credential toDelete) {
+ }
+
+ @Override
+ public Trust[] getTrusted() {
+ return new Trust[0];
+ }
+
+ @Override
+ public void addTrusted(Trust toAdd) {
+ }
+
+ @Override
+ public void deleteTrusted(Trust toDelete) {
+ }
+
+ @Override
+ public void validateCredential(Credential c)
+ throws InvalidCredentialException {
+ }
+
+ @Override
+ public void validateTrusted(Trust t) throws InvalidCredentialException {
+ }
+
+ @Override
+ public void initializeSecurityFromSOAPContext(MessageContext context) {
+ // Do nothing
+ }
+
+ @Override
+ public void initializeSecurityFromRESTContext(HttpHeaders headers) {
+ // Do nothing
+ }
+
+ @Override
+ public void conveySecurity() throws GeneralSecurityException, IOException {
+ // Do nothing
+ }
+
+ @Override
+ public SecurityContextFactory getFactory() {
+ return null;
+ }
+
+ private Set<String> destroyers = new HashSet<String>();
+ private Set<String> updaters = new HashSet<String>();
+ private Set<String> readers = new HashSet<String>();
+ @Override
+ public Set<String> getPermittedDestroyers() {
+ return destroyers;
+ }
+
+ @Override
+ public void setPermittedDestroyers(Set<String> destroyers) {
+ this.destroyers = destroyers;
+ updaters.addAll(destroyers);
+ readers.addAll(destroyers);
+ }
+
+ @Override
+ public Set<String> getPermittedUpdaters() {
+ return updaters;
+ }
+
+ @Override
+ public void setPermittedUpdaters(Set<String> updaters) {
+ this.updaters = updaters;
+ this.updaters.addAll(destroyers);
+ readers.addAll(updaters);
+ }
+
+ @Override
+ public Set<String> getPermittedReaders() {
+ return readers;
+ }
+
+ @Override
+ public void setPermittedReaders(Set<String> readers) {
+ this.readers = readers;
+ this.readers.addAll(destroyers);
+ this.readers.addAll(updaters);
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public void initializeSecurityFromContext(SecurityContext securityContext)
+ throws Exception {
+ // Do nothing
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void setName(String name) {
+ this.name = (name.length() > 5 ? name.substring(0, 5) : name);
+ }
+
+ @Override
+ public void ping() throws UnknownRunException {
+ // Do nothing
+ }
+
+ @Override
+ public boolean getGenerateProvenance() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void setGenerateProvenance(boolean generateProvenance) {
+ // TODO Auto-generated method stub
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java
new file mode 100644
index 0000000..81dd08c
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/MockPolicy.java
@@ -0,0 +1,59 @@
+package org.taverna.server.master.mocks;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoDestroyException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+public class MockPolicy extends SimpleServerPolicy {
+ public MockPolicy() {
+ super();
+ super.setCleanerInterval(30);
+ }
+
+ public int maxruns = 10;
+ Integer usermaxruns;
+ Set<TavernaRun> denyaccess = new HashSet<>();
+ boolean exnOnUpdate, exnOnCreate, exnOnDelete;
+
+ @Override
+ public int getMaxRuns() {
+ return maxruns;
+ }
+
+ @Override
+ public Integer getMaxRuns(UsernamePrincipal user) {
+ return usermaxruns;
+ }
+
+ @Override
+ public boolean permitAccess(UsernamePrincipal user, TavernaRun run) {
+ return !denyaccess.contains(run);
+ }
+
+ @Override
+ public void permitCreate(UsernamePrincipal user, Workflow workflow)
+ throws NoCreateException {
+ if (this.exnOnCreate)
+ throw new NoCreateException();
+ }
+
+ @Override
+ public void permitDestroy(UsernamePrincipal user, TavernaRun run)
+ throws NoDestroyException {
+ if (this.exnOnDelete)
+ throw new NoDestroyException();
+ }
+
+ @Override
+ public void permitUpdate(UsernamePrincipal user, TavernaRun run)
+ throws NoUpdateException {
+ if (this.exnOnUpdate)
+ throw new NoUpdateException();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java
new file mode 100644
index 0000000..d864214
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleListenerFactory.java
@@ -0,0 +1,64 @@
+package org.taverna.server.master.mocks;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.taverna.server.master.exceptions.NoListenerException;
+import org.taverna.server.master.factories.ListenerFactory;
+import org.taverna.server.master.interfaces.Listener;
+import org.taverna.server.master.interfaces.TavernaRun;
+
+/**
+ * A factory for event listener. The factory is configured using Spring.
+ *
+ * @author Donal Fellows
+ */
+public class SimpleListenerFactory implements ListenerFactory {
+ private Map<String, Builder> builders = new HashMap<>();
+
+ public void setBuilders(Map<String, Builder> builders) {
+ this.builders = builders;
+ }
+
+ @Override
+ public List<String> getSupportedListenerTypes() {
+ return new ArrayList<>(builders.keySet());
+ }
+
+ @Override
+ public Listener makeListener(TavernaRun run, String listenerType,
+ String configuration) throws NoListenerException {
+ Builder b = builders.get(listenerType);
+ if (b == null)
+ throw new NoListenerException("no such listener type");
+ Listener l = b.build(run, configuration);
+ run.addListener(l);
+ return l;
+ }
+
+ /**
+ * How to actually construct a listener.
+ *
+ * @author Donal Fellows
+ */
+ public interface Builder {
+ /**
+ * Make an event listener attached to a run.
+ *
+ * @param run
+ * The run to attach to.
+ * @param configuration
+ * A user-specified configuration document. The constructed
+ * listener <i>should</i> process this configuration document
+ * and be able to return it to the user when requested.
+ * @return The listener object.
+ * @throws NoListenerException
+ * If the listener construction failed or the
+ * <b>configuration</b> document was bad in some way.
+ */
+ public Listener build(TavernaRun run, String configuration)
+ throws NoListenerException;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java
new file mode 100644
index 0000000..a3751e4
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleNonpersistentRunStore.java
@@ -0,0 +1,151 @@
+package org.taverna.server.master.mocks;
+
+import java.lang.ref.WeakReference;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.taverna.server.master.exceptions.NoDestroyException;
+import org.taverna.server.master.exceptions.UnknownRunException;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.RunStore;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Example of a store for Taverna Workflow Runs.
+ *
+ * @author Donal Fellows
+ */
+public class SimpleNonpersistentRunStore implements RunStore {
+ private Map<String, TavernaRun> store = new HashMap<>();
+ private Object lock = new Object();
+
+ Timer timer;
+ private CleanerTask cleaner;
+
+ /**
+ * The connection to the main policy store. Suitable for wiring up with
+ * Spring.
+ *
+ * @param p
+ * The policy to connect to.
+ */
+ public void setPolicy(SimpleServerPolicy p) {
+ p.store = this;
+ cleanerIntervalUpdated(p.getCleanerInterval());
+ }
+
+ public SimpleNonpersistentRunStore() {
+ timer = new Timer("SimpleNonpersistentRunStore.CleanerTimer", true);
+ cleanerIntervalUpdated(300);
+ }
+
+ @Override
+ protected void finalize() {
+ timer.cancel();
+ }
+
+ /**
+ * Remove and destroy all runs that are expired at the moment that this
+ * method starts.
+ */
+ void clean() {
+ Date now = new Date();
+ synchronized (lock) {
+ // Use an iterator so we have access to its remove() method...
+ Iterator<TavernaRun> i = store.values().iterator();
+ while (i.hasNext()) {
+ TavernaRun w = i.next();
+ if (w.getExpiry().before(now)) {
+ i.remove();
+ try {
+ w.destroy();
+ } catch (NoDestroyException e) {
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Reconfigure the cleaner task's call interval. This is called internally
+ * and from the Policy when the interval is set there.
+ *
+ * @param intervalInSeconds
+ * How long between runs of the cleaner task, in seconds.
+ */
+ void cleanerIntervalUpdated(int intervalInSeconds) {
+ if (cleaner != null)
+ cleaner.cancel();
+ cleaner = new CleanerTask(this, intervalInSeconds);
+ }
+
+ @Override
+ public TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
+ throws UnknownRunException {
+ synchronized (lock) {
+ TavernaRun w = store.get(uuid);
+ if (w == null || !p.permitAccess(user, w))
+ throw new UnknownRunException();
+ return w;
+ }
+ }
+
+ @Override
+ public TavernaRun getRun(String uuid) throws UnknownRunException {
+ synchronized (lock) {
+ TavernaRun w = store.get(uuid);
+ if (w == null)
+ throw new UnknownRunException();
+ return w;
+ }
+ }
+
+ @Override
+ public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
+ Map<String, TavernaRun> filtered = new HashMap<>();
+ synchronized (lock) {
+ for (Map.Entry<String, TavernaRun> entry : store.entrySet())
+ if (p.permitAccess(user, entry.getValue()))
+ filtered.put(entry.getKey(), entry.getValue());
+ }
+ return filtered;
+ }
+
+ @Override
+ public String registerRun(TavernaRun run) {
+ synchronized (lock) {
+ store.put(run.getId(), run);
+ return run.getId();
+ }
+ }
+
+ @Override
+ public void unregisterRun(String uuid) {
+ synchronized (lock) {
+ store.remove(uuid);
+ }
+ }
+}
+
+class CleanerTask extends TimerTask {
+ WeakReference<SimpleNonpersistentRunStore> store;
+
+ CleanerTask(SimpleNonpersistentRunStore store, int interval) {
+ this.store = new WeakReference<>(store);
+ int tms = interval * 1000;
+ store.timer.scheduleAtFixedRate(this, tms, tms);
+ }
+
+ @Override
+ public void run() {
+ SimpleNonpersistentRunStore s = store.get();
+ if (s != null) {
+ s.clean();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java
new file mode 100644
index 0000000..1a68d2c
--- /dev/null
+++ b/taverna-server-webapp/src/test/java/org/taverna/server/master/mocks/SimpleServerPolicy.java
@@ -0,0 +1,110 @@
+package org.taverna.server.master.mocks;
+
+import java.net.URI;
+import java.util.List;
+
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoDestroyException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * A very simple (and unsafe) security model. The number of runs is configurable
+ * through Spring (or 10 if unconfigured) with no per-user limits supported, all
+ * workflows are permitted, and all identified users may create a workflow run.
+ * Any user may read off information about any run, but only its owner may
+ * modify or destroy it.
+ * <p>
+ * Note that this is a <i>Policy Enforcement Point</i> for access control to
+ * individual workflows.
+ *
+ * @author Donal Fellows
+ */
+public class SimpleServerPolicy implements Policy {
+ private int maxRuns = 10;
+ private int cleanerInterval;
+ SimpleNonpersistentRunStore store;
+
+ public void setMaxRuns(int maxRuns) {
+ this.maxRuns = maxRuns;
+ }
+
+ @Override
+ public int getMaxRuns() {
+ return maxRuns;
+ }
+
+ @Override
+ public Integer getMaxRuns(UsernamePrincipal p) {
+ return null; // No per-user limits
+ }
+
+ public int getCleanerInterval() {
+ return cleanerInterval;
+ }
+
+ /**
+ * Sets how often the store of workflow runs will try to clean out expired
+ * runs.
+ *
+ * @param intervalInSeconds
+ */
+ public void setCleanerInterval(int intervalInSeconds) {
+ cleanerInterval = intervalInSeconds;
+ if (store != null)
+ store.cleanerIntervalUpdated(intervalInSeconds);
+ }
+
+ @Override
+ public boolean permitAccess(UsernamePrincipal p, TavernaRun run) {
+ // No secrets here!
+ return true;
+ }
+
+ @Override
+ public void permitCreate(UsernamePrincipal p, Workflow workflow)
+ throws NoCreateException {
+ // Only identified users may create
+ if (p == null)
+ throw new NoCreateException();
+ // Global run count limit enforcement
+ if (store.listRuns(p, this).size() >= maxRuns)
+ throw new NoCreateException();
+ // Per-user run count enforcement would come here
+ }
+
+ @Override
+ public void permitDestroy(UsernamePrincipal p, TavernaRun run)
+ throws NoDestroyException {
+ // Only the creator may destroy
+ if (p == null || !p.equals(run.getSecurityContext().getOwner()))
+ throw new NoDestroyException();
+ }
+
+ @Override
+ public void permitUpdate(UsernamePrincipal p, TavernaRun run)
+ throws NoUpdateException {
+ // Only the creator may change
+ if (p == null || !p.equals(run.getSecurityContext().getOwner()))
+ throw new NoUpdateException();
+ }
+
+ @Override
+ public int getOperatingLimit() {
+ return 1;
+ }
+
+ @Override
+ public List<URI> listPermittedWorkflowURIs(UsernamePrincipal user) {
+ return null;
+ }
+
+ @Override
+ public void setPermittedWorkflowURIs(UsernamePrincipal user,
+ List<URI> permitted) {
+ // Ignore
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/resources/example.xml
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/resources/example.xml b/taverna-server-webapp/src/test/resources/example.xml
new file mode 100644
index 0000000..14cc242
--- /dev/null
+++ b/taverna-server-webapp/src/test/resources/example.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
+
+ <bean id="policy" class="org.taverna.server.master.mocks.SimpleServerPolicy"
+ lazy-init="false" scope="singleton">
+ <property name="maxRuns" value="1">
+ <description>
+ Limit on total number of simultaneous runs.
+ </description>
+ </property>
+ <property name="cleanerInterval" value="300">
+ <description>
+ Time between trying to delete expired runs, in seconds.
+ </description>
+ </property>
+ </bean>
+
+ <bean id="runFactory" class="org.taverna.server.master.mocks.ExampleRun$Builder">
+ <constructor-arg type="int" value="10" /> <!-- "initialLifetimeMinutes" -->
+ </bean>
+
+ <bean id="runCatalog" scope="singleton"
+ class="org.taverna.server.master.mocks.SimpleNonpersistentRunStore">
+ <property name="policy" ref="policy" />
+ </bean>
+
+ <bean id="listenerFactory" class="org.taverna.server.master.mocks.SimpleListenerFactory">
+ <property name="builders">
+ <description>
+ This map describes how to build each type of supported
+ event listener that is not installed by default. Any site policy for
+ a listeners should be installed using its properties, as shown. The
+ "key" is the type, the "class" is the builder for actual instances
+ (which must be an instance of
+ org.taverna.server.master.factories.SimpleListenerFactory.Builder)
+ and any policies and installation-specific configurations are
+ characterised by properties such as "sitePolicy" below.
+ </description>
+ <map>
+ <!-- <entry key="exampleListener">-->
+ <!--
+ <bean
+ class="org.taverna.server.master.example.ExampleListener$Builder">
+ -->
+ <!-- <property name="sitePolicy">-->
+ <!-- <value>Just an example!</value>-->
+ <!-- </property>-->
+ <!-- </bean>-->
+ <!-- </entry>-->
+ </map>
+ </property>
+ </bean>
+</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/test/resources/log4j.properties b/taverna-server-webapp/src/test/resources/log4j.properties
new file mode 100644
index 0000000..6707f55
--- /dev/null
+++ b/taverna-server-webapp/src/test/resources/log4j.properties
@@ -0,0 +1,4 @@
+log4j.rootLogger=info, R
+log4j.appender.R=org.apache.log4j.ConsoleAppender
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-server-worker/pom.xml b/taverna-server-worker/pom.xml
new file mode 100644
index 0000000..8006c6d
--- /dev/null
+++ b/taverna-server-worker/pom.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.taverna.server</groupId>
+ <artifactId>taverna-server</artifactId>
+ <version>3.1.0-incubating-SNAPSHOT</version>
+ </parent>
+ <artifactId>taverna-server-worker</artifactId>
+ <name>Apache Taverna Server Workflow Executor/File System Access Process Implementation</name>
+ <description>This is the implementation of the factory process that is started up by the web application to manage executing Taverna Workflow executeworkflow.sh calls. Also provides per-user access to filestore.</description>
+
+ <properties>
+ <workerMainClass>org.taverna.server.localworker.impl.TavernaRunManager</workerMainClass>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-runinterface</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>taverna-server-usagerecord</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.taverna.language</groupId>
+ <artifactId>taverna-scufl2-api</artifactId>
+ <version>${taverna.language.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.taverna.language</groupId>
+ <artifactId>taverna-scufl2-t2flow</artifactId>
+ <version>${taverna.language.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.taverna.language</groupId>
+ <artifactId>taverna-scufl2-wfbundle</artifactId>
+ <version>${taverna.language.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <archive>
+ <manifest>
+ <mainClass>${workerMainClass}</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <versionRange>[2.0,)</versionRange>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/META-INF/MANIFEST.MF b/taverna-server-worker/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/taverna-server-worker/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java
new file mode 100644
index 0000000..600913a
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Constants.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.api;
+
+import static java.nio.charset.Charset.defaultCharset;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * The defaults associated with this worker, together with various other
+ * constants.
+ *
+ * @author Donal Fellows
+ */
+public abstract class Constants {
+ /**
+ * Subdirectories of the working directory to create by default.
+ */
+ public static final String[] SUBDIR_LIST = { "conf", "externaltool", "feed",
+ "interactions", "lib", "logs", "plugins", "repository", "var" };
+
+ /** The name of the default encoding for characters on this machine. */
+ public static final String SYSTEM_ENCODING = defaultCharset().name();
+
+ /**
+ * Password to use to encrypt security information. This default is <7 chars
+ * to work even without Unlimited Strength JCE.
+ */
+ public static final char[] KEYSTORE_PASSWORD = { 'c', 'h', 'a', 'n', 'g', 'e' };
+
+ /**
+ * The name of the directory (in the home directory) where security settings
+ * will be written.
+ */
+ public static final String SECURITY_DIR_NAME = ".taverna-server-security";
+
+ /** The name of the file that will be the created keystore. */
+ public static final String KEYSTORE_FILE = "t2keystore.ubr";
+
+ /** The name of the file that will be the created truststore. */
+ public static final String TRUSTSTORE_FILE = "t2truststore.ubr";
+
+ /**
+ * The name of the file that contains the password to unlock the keystore
+ * and truststore.
+ */
+ public static final String PASSWORD_FILE = "password.txt";
+
+ // --------- UNUSED ---------
+ // /**
+ // * The name of the file that contains the mapping from URIs to keystore
+ // * aliases.
+ // */
+ // public static final String URI_ALIAS_MAP = "urlmap.txt";
+
+ /**
+ * Used to instruct the Taverna credential manager to use a non-default
+ * location for user credentials.
+ */
+ public static final String CREDENTIAL_MANAGER_DIRECTORY = "-cmdir";
+
+ /**
+ * Used to instruct the Taverna credential manager to take its master
+ * password from standard input.
+ */
+ public static final String CREDENTIAL_MANAGER_PASSWORD = "-cmpassword";
+
+ /**
+ * Name of environment variable used to pass HELIO security tokens to
+ * workflows.
+ */
+ // This technique is known to be insecure; bite me.
+ public static final String HELIO_TOKEN_NAME = "HELIO_CIS_TOKEN";
+
+ /**
+ * The name of the standard listener, which is installed by default.
+ */
+ public static final String DEFAULT_LISTENER_NAME = "io";
+
+ /**
+ * Time to wait for the subprocess to wait, in milliseconds.
+ */
+ public static final int START_WAIT_TIME = 1500;
+
+ /**
+ * Time to wait for success or failure of a death-causing activity (i.e.,
+ * sending a signal).
+ */
+ public static final int DEATH_TIME = 333;
+
+ /**
+ * The name of the file (in this code's resources) that provides the default
+ * security policy that we use.
+ */
+ public static final String SECURITY_POLICY_FILE = "security.policy";
+
+ /**
+ * The Java property holding security policy info.
+ */
+ public static final String SEC_POLICY_PROP = "java.security.policy";
+ /**
+ * The Java property to set to make this code not try to enforce security
+ * policy.
+ */
+ public static final String UNSECURE_PROP = "taverna.suppressrestrictions.rmi";
+ /**
+ * The Java property that holds the name of the host name to enforce.
+ */
+ public static final String RMI_HOST_PROP = "java.rmi.server.hostname";
+ /**
+ * The default hostname to require in secure mode. This is the
+ * <i>resolved</i> version of "localhost".
+ */
+ public static final String LOCALHOST;
+ static {
+ String h = "127.0.0.1"; // fallback
+ try {
+ h = InetAddress.getByName("localhost").getHostAddress();
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ } finally {
+ LOCALHOST = h;
+ }
+ }
+
+ /**
+ * Time to wait during closing down this process. In milliseconds.
+ */
+ public static final int DEATH_DELAY = 500;
+ /**
+ * The name of the property describing where shared directories should be
+ * located.
+ */
+ public static final String SHARED_DIR_PROP = "taverna.sharedDirectory";
+
+ public static final String TIME = "/usr/bin/time";
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java
new file mode 100644
index 0000000..3896c06
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/RunAccounting.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.api;
+
+/**
+ *
+ * @author Donal Fellows
+ */
+public interface RunAccounting {
+ /**
+ * Logs that a run has started executing.
+ */
+ void runStarted();
+
+ /**
+ * Logs that a run has finished executing.
+ */
+ void runCeased();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java
new file mode 100644
index 0000000..c513ed8
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/Worker.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.api;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.taverna.server.localworker.impl.LocalWorker;
+import org.taverna.server.localworker.remote.ImplementationException;
+import org.taverna.server.localworker.remote.RemoteListener;
+import org.taverna.server.localworker.remote.RemoteStatus;
+import org.taverna.server.localworker.server.UsageRecordReceiver;
+
+/**
+ * The interface between the connectivity layer and the thunk to the
+ * subprocesses.
+ *
+ * @author Donal Fellows
+ */
+public interface Worker {
+ /**
+ * Fire up the workflow. This causes a transition into the operating state.
+ *
+ * @param local
+ * The reference to the factory class for this worker.
+ * @param executeWorkflowCommand
+ * The command to run to execute the workflow.
+ * @param workflow
+ * The workflow document to execute.
+ * @param workingDir
+ * What directory to use as the working directory.
+ * @param inputBaclavaFile
+ * The baclava file to use for inputs, or <tt>null</tt> to use
+ * the other <b>input*</b> arguments' values.
+ * @param inputRealFiles
+ * A mapping of input names to files that supply them. Note that
+ * we assume that nothing mapped here will be mapped in
+ * <b>inputValues</b>.
+ * @param inputValues
+ * A mapping of input names to values to supply to them. Note
+ * that we assume that nothing mapped here will be mapped in
+ * <b>inputFiles</b>.
+ * @param inputDelimiters
+ * A mapping of input names to characters used to split them into
+ * lists.
+ * @param outputBaclavaFile
+ * What baclava file to write the output from the workflow into,
+ * or <tt>null</tt> to have it written into the <tt>out</tt>
+ * subdirectory.
+ * @param contextDirectory
+ * The directory containing the keystore and truststore. <i>Must
+ * not be <tt>null</tt>.</i>
+ * @param keystorePassword
+ * The password to the keystore and truststore. <i>Must not be
+ * <tt>null</tt>.</i>
+ * @param generateProvenance
+ * Whether to generate a run bundle containing provenance data.
+ * @param environment
+ * Any environment variables that need to be added to the
+ * invokation.
+ * @param masterToken
+ * The internal name of the workflow run.
+ * @param runtimeSettings
+ * List of configuration details for the forked runtime.
+ * @return Whether a successful start happened.
+ * @throws Exception
+ * If any of quite a large number of things goes wrong.
+ */
+ boolean initWorker(LocalWorker local, String executeWorkflowCommand,
+ byte[] workflow, File workingDir, File inputBaclavaFile,
+ Map<String, File> inputRealFiles, Map<String, String> inputValues,
+ Map<String, String> inputDelimiters, File outputBaclavaFile,
+ File contextDirectory, char[] keystorePassword,
+ boolean generateProvenance, Map<String, String> environment,
+ String masterToken, List<String> runtimeSettings) throws Exception;
+
+ /**
+ * Kills off the subprocess if it exists and is alive.
+ *
+ * @throws Exception
+ * if anything goes badly wrong when the worker is being killed
+ * off.
+ */
+ void killWorker() throws Exception;
+
+ /**
+ * Move the worker out of the stopped state and back to operating.
+ *
+ * @throws Exception
+ * if it fails (which it always does; operation currently
+ * unsupported).
+ */
+ void startWorker() throws Exception;
+
+ /**
+ * Move the worker into the stopped state from the operating state.
+ *
+ * @throws Exception
+ * if it fails (which it always does; operation currently
+ * unsupported).
+ */
+ void stopWorker() throws Exception;
+
+ /**
+ * @return The status of the workflow run. Note that this can be an
+ * expensive operation.
+ */
+ RemoteStatus getWorkerStatus();
+
+ /**
+ * @return The listener that is registered by default, in addition to all
+ * those that are explicitly registered by the user.
+ */
+ RemoteListener getDefaultListener();
+
+ /**
+ * @param receiver
+ * The destination where any final usage records are to be
+ * written in order to log them back to the server.
+ */
+ void setURReceiver(UsageRecordReceiver receiver);
+
+ /**
+ * Arrange for the deletion of any resources created during worker process
+ * construction. Guaranteed to be the last thing done before finalization.
+ *
+ * @throws ImplementationException
+ * If anything goes wrong.
+ */
+ void deleteLocalResources() throws ImplementationException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java
new file mode 100644
index 0000000..4ce13a7
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/api/WorkerFactory.java
@@ -0,0 +1,18 @@
+package org.taverna.server.localworker.api;
+
+
+/**
+ * Class that manufactures instances of {@link Worker}.
+ *
+ * @author Donal Fellows
+ */
+public interface WorkerFactory {
+ /**
+ * Create an instance of the low-level worker class.
+ *
+ * @return The worker object.
+ * @throws Exception
+ * If anything goes wrong.
+ */
+ Worker makeInstance() throws Exception;
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java
new file mode 100644
index 0000000..1692856
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/DirectoryDelegate.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl;
+
+import static org.apache.commons.io.FileUtils.forceDelete;
+import static org.apache.commons.io.FileUtils.forceMkdir;
+import static org.apache.commons.io.FileUtils.touch;
+import static org.taverna.server.localworker.impl.utils.FilenameVerifier.getValidatedNewFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.apache.commons.collections.MapIterator;
+import org.apache.commons.collections.map.ReferenceMap;
+import org.taverna.server.localworker.remote.RemoteDirectory;
+import org.taverna.server.localworker.remote.RemoteDirectoryEntry;
+import org.taverna.server.localworker.remote.RemoteFile;
+
+/**
+ * This class acts as a remote-aware delegate for the workflow run's working
+ * directory and its subdirectories.
+ *
+ * @author Donal Fellows
+ * @see FileDelegate
+ */
+@SuppressWarnings("serial")
+public class DirectoryDelegate extends UnicastRemoteObject implements
+ RemoteDirectory {
+ private File dir;
+ private DirectoryDelegate parent;
+ private ReferenceMap localCache;
+
+ /**
+ * @param dir
+ * @param parent
+ * @throws RemoteException
+ * If registration of the directory fails.
+ */
+ public DirectoryDelegate(@Nonnull File dir,
+ @Nonnull DirectoryDelegate parent) throws RemoteException {
+ super();
+ this.localCache = new ReferenceMap();
+ this.dir = dir;
+ this.parent = parent;
+ }
+
+ @Override
+ public Collection<RemoteDirectoryEntry> getContents()
+ throws RemoteException {
+ List<RemoteDirectoryEntry> result = new ArrayList<>();
+ for (String s : dir.list()) {
+ if (s.equals(".") || s.equals(".."))
+ continue;
+ File f = new File(dir, s);
+ RemoteDirectoryEntry entry;
+ synchronized (localCache) {
+ entry = (RemoteDirectoryEntry) localCache.get(s);
+ if (f.isDirectory()) {
+ if (entry == null || !(entry instanceof DirectoryDelegate)) {
+ entry = new DirectoryDelegate(f, this);
+ localCache.put(s, entry);
+ }
+ } else if (f.isFile()) {
+ if (entry == null || !(entry instanceof FileDelegate)) {
+ entry = new FileDelegate(f, this);
+ localCache.put(s, entry);
+ }
+ } else {
+ // not file or dir; skip...
+ continue;
+ }
+ }
+ result.add(entry);
+ }
+ return result;
+ }
+
+ @Override
+ public RemoteFile makeEmptyFile(String name) throws IOException {
+ File f = getValidatedNewFile(dir, name);
+ touch(f);
+ FileDelegate delegate = new FileDelegate(f, this);
+ synchronized (localCache) {
+ localCache.put(name, delegate);
+ }
+ return delegate;
+ }
+
+ @Override
+ public RemoteDirectory makeSubdirectory(String name) throws IOException {
+ File f = getValidatedNewFile(dir, name);
+ forceMkdir(f);
+ DirectoryDelegate delegate = new DirectoryDelegate(f, this);
+ synchronized (localCache) {
+ localCache.put(name, delegate);
+ }
+ return delegate;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void destroy() throws IOException {
+ if (parent == null)
+ throw new IOException("tried to destroy main job working directory");
+ Collection<RemoteDirectoryEntry> values;
+ synchronized (localCache) {
+ values = new ArrayList<>(localCache.values());
+ }
+ for (RemoteDirectoryEntry obj : values) {
+ if (obj == null)
+ continue;
+ try {
+ obj.destroy();
+ } catch (IOException e) {
+ }
+ }
+ forceDelete(dir);
+ parent.forgetEntry(this);
+ }
+
+ @Override
+ public RemoteDirectory getContainingDirectory() {
+ return parent;
+ }
+
+ void forgetEntry(@Nonnull RemoteDirectoryEntry entry) {
+ synchronized (localCache) {
+ MapIterator i = localCache.mapIterator();
+ while (i.hasNext()) {
+ Object key = i.next();
+ if (entry == i.getValue()) {
+ localCache.remove(key);
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String getName() {
+ if (parent == null)
+ return "";
+ return dir.getName();
+ }
+
+ @Override
+ public Date getModificationDate() throws RemoteException {
+ return new Date(dir.lastModified());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java
----------------------------------------------------------------------
diff --git a/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java
new file mode 100644
index 0000000..7e47af9
--- /dev/null
+++ b/taverna-server-worker/src/main/java/org/taverna/server/localworker/impl/FileDelegate.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.localworker.impl;
+
+import static java.lang.System.arraycopy;
+import static java.net.InetAddress.getLocalHost;
+import static org.apache.commons.io.FileUtils.copyFile;
+import static org.apache.commons.io.FileUtils.forceDelete;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Date;
+
+import javax.annotation.Nonnull;
+
+import org.taverna.server.localworker.remote.RemoteDirectory;
+import org.taverna.server.localworker.remote.RemoteFile;
+
+/**
+ * This class acts as a remote-aware delegate for the files in a workflow run's
+ * working directory and its subdirectories.
+ *
+ * @author Donal Fellows
+ * @see DirectoryDelegate
+ */
+@java.lang.SuppressWarnings("serial")
+public class FileDelegate extends UnicastRemoteObject implements RemoteFile {
+ private File file;
+ private DirectoryDelegate parent;
+
+ /**
+ * @param file
+ * @param parent
+ * @throws RemoteException
+ * If registration of the file fails.
+ */
+ public FileDelegate(@Nonnull File file, @Nonnull DirectoryDelegate parent)
+ throws RemoteException {
+ super();
+ this.file = file;
+ this.parent = parent;
+ }
+
+ @Override
+ public byte[] getContents(int offset, int length) throws IOException {
+ if (length == -1)
+ length = (int) (file.length() - offset);
+ if (length < 0 || length > 1024 * 64)
+ length = 1024 * 64;
+ byte[] buffer = new byte[length];
+ int read;
+ try (FileInputStream fis = new FileInputStream(file)) {
+ if (offset > 0 && fis.skip(offset) != offset)
+ throw new IOException("did not move to correct offset in file");
+ read = fis.read(buffer);
+ }
+ if (read <= 0)
+ return new byte[0];
+ if (read < buffer.length) {
+ byte[] shortened = new byte[read];
+ arraycopy(buffer, 0, shortened, 0, read);
+ return shortened;
+ }
+ return buffer;
+ }
+
+ @Override
+ public long getSize() {
+ return file.length();
+ }
+
+ @Override
+ public void setContents(byte[] data) throws IOException {
+ try (FileOutputStream fos = new FileOutputStream(file)) {
+ fos.write(data);
+ }
+ }
+
+ @Override
+ public void appendContents(byte[] data) throws IOException {
+ try (FileOutputStream fos = new FileOutputStream(file, true)) {
+ fos.write(data);
+ }
+ }
+
+ @Override
+ public void destroy() throws IOException {
+ forceDelete(file);
+ parent.forgetEntry(this);
+ parent = null;
+ }
+
+ @Override
+ public RemoteDirectory getContainingDirectory() {
+ return parent;
+ }
+
+ @Override
+ public String getName() {
+ return file.getName();
+ }
+
+ @Override
+ public void copy(RemoteFile sourceFile) throws RemoteException, IOException {
+ String sourceHost = sourceFile.getNativeHost();
+ if (!getNativeHost().equals(sourceHost)) {
+ throw new IOException(
+ "cross-system copy not implemented; cannot copy from "
+ + sourceHost + " to " + getNativeHost());
+ }
+ // Must copy; cannot count on other file to stay unmodified
+ copyFile(new File(sourceFile.getNativeName()), file);
+ }
+
+ @Override
+ public String getNativeName() {
+ return file.getAbsolutePath();
+ }
+
+ @Override
+ public String getNativeHost() {
+ try {
+ return getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(
+ "unexpected failure to resolve local host address", e);
+ }
+ }
+
+ @Override
+ public Date getModificationDate() throws RemoteException {
+ return new Date(file.lastModified());
+ }
+}
[33/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java b/server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
deleted file mode 100644
index 22158d5..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
+++ /dev/null
@@ -1,967 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static java.lang.System.currentTimeMillis;
-import static java.util.Calendar.MINUTE;
-import static java.util.Collections.sort;
-import static java.util.Collections.unmodifiableSet;
-import static java.util.UUID.randomUUID;
-import static org.apache.commons.io.IOUtils.closeQuietly;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.worker.RemoteRunDelegate.checkBadFilename;
-import static org.taverna.server.master.worker.RunConnection.NAME_LENGTH;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.PipedOutputStream;
-import java.rmi.MarshalledObject;
-import java.rmi.RemoteException;
-import java.security.GeneralSecurityException;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-import javax.annotation.Nonnull;
-
-import org.apache.commons.logging.Log;
-import org.taverna.server.localworker.remote.IllegalStateTransitionException;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteDirectoryEntry;
-import org.taverna.server.localworker.remote.RemoteFile;
-import org.taverna.server.localworker.remote.RemoteInput;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.remote.StillWorkingOnItException;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.BadPropertyValueException;
-import org.taverna.server.master.exceptions.BadStateChangeException;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.exceptions.OverloadedException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.SecurityContextFactory;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Bridging shim between the WebApp world and the RMI world.
- *
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-public class RemoteRunDelegate implements TavernaRun {
- private transient Log log = getLog("Taverna.Server.Worker");
- transient TavernaSecurityContext secContext;
- Date creationInstant;
- Workflow workflow;
- Date expiry;
- HashSet<String> readers;
- HashSet<String> writers;
- HashSet<String> destroyers;
- transient String id;
- transient RemoteSingleRun run;
- transient RunDBSupport db;
- transient FactoryBean factory;
- boolean doneTransitionToFinished;
- boolean generateProvenance;// FIXME expose
- String name;
- private static final String ELLIPSIS = "...";
-
- public RemoteRunDelegate(Date creationInstant, Workflow workflow,
- RemoteSingleRun rsr, int defaultLifetime, RunDBSupport db, UUID id,
- boolean generateProvenance, FactoryBean factory) {
- if (rsr == null)
- throw new IllegalArgumentException("remote run must not be null");
- this.creationInstant = creationInstant;
- this.workflow = workflow;
- Calendar c = Calendar.getInstance();
- c.add(MINUTE, defaultLifetime);
- this.expiry = c.getTime();
- this.run = rsr;
- this.db = db;
- this.generateProvenance = generateProvenance;
- this.factory = factory;
- try {
- this.name = "";
- String ci = " " + creationInstant;
- String n = workflow.getName();
- if (n.length() > NAME_LENGTH - ci.length())
- n = n.substring(0,
- NAME_LENGTH - ci.length() - ELLIPSIS.length())
- + ELLIPSIS;
- this.name = n + ci;
- } catch (Exception e) {
- // Ignore; it's just a name, not something important.
- }
- if (id != null)
- this.id = id.toString();
- }
-
- RemoteRunDelegate() {
- }
-
- /**
- * Get the types of listener supported by this run.
- *
- * @return A list of listener type names.
- * @throws RemoteException
- * If anything goes wrong.
- */
- public List<String> getListenerTypes() throws RemoteException {
- return run.getListenerTypes();
- }
-
- @Override
- public void addListener(Listener listener) {
- if (listener instanceof ListenerDelegate)
- try {
- run.addListener(((ListenerDelegate) listener).getRemote());
- } catch (RemoteException e) {
- log.warn("communication problem adding listener", e);
- } catch (ImplementationException e) {
- log.warn("implementation problem adding listener", e);
- }
- else
- log.fatal("bad listener " + listener.getClass()
- + "; not applicable remotely!");
- }
-
- @Override
- public String getId() {
- if (id == null)
- id = randomUUID().toString();
- return id;
- }
-
- /**
- * Attach a listener to a workflow run and return its local delegate.
- *
- * @param type
- * The type of listener to create.
- * @param config
- * The configuration of the listener.
- * @return The local delegate of the listener.
- * @throws NoListenerException
- * If anything goes wrong.
- */
- public Listener makeListener(String type, String config)
- throws NoListenerException {
- try {
- return new ListenerDelegate(run.makeListener(type, config));
- } catch (RemoteException e) {
- throw new NoListenerException("failed to make listener", e);
- }
- }
-
- @Override
- public void destroy() {
- try {
- run.destroy();
- } catch (RemoteException | ImplementationException e) {
- log.warn("failed to destroy run", e);
- }
- }
-
- @Override
- public Date getExpiry() {
- return new Date(expiry.getTime());
- }
-
- @Override
- public List<Listener> getListeners() {
- List<Listener> listeners = new ArrayList<>();
- try {
- for (RemoteListener rl : run.getListeners())
- listeners.add(new ListenerDelegate(rl));
- } catch (RemoteException e) {
- log.warn("failed to get listeners", e);
- }
- return listeners;
- }
-
- @Override
- public TavernaSecurityContext getSecurityContext() {
- return secContext;
- }
-
- @Override
- public Status getStatus() {
- try {
- switch (run.getStatus()) {
- case Initialized:
- return Status.Initialized;
- case Operating:
- return Status.Operating;
- case Stopped:
- return Status.Stopped;
- case Finished:
- return Status.Finished;
- }
- } catch (RemoteException e) {
- log.warn("problem getting remote status", e);
- }
- return Status.Finished;
- }
-
- @Override
- public Workflow getWorkflow() {
- return workflow;
- }
-
- @Override
- public Directory getWorkingDirectory() throws FilesystemAccessException {
- try {
- return new DirectoryDelegate(run.getWorkingDirectory());
- } catch (Throwable e) {
- if (e.getCause() != null)
- e = e.getCause();
- throw new FilesystemAccessException(
- "problem getting main working directory handle", e);
- }
- }
-
- @Override
- public void setExpiry(Date d) {
- if (d.after(new Date()))
- expiry = new Date(d.getTime());
- db.flushToDisk(this);
- }
-
- @Override
- public String setStatus(Status s) throws BadStateChangeException {
- try {
- log.info("setting status of run " + id + " to " + s);
- switch (s) {
- case Initialized:
- run.setStatus(RemoteStatus.Initialized);
- break;
- case Operating:
- if (run.getStatus() == RemoteStatus.Initialized) {
- if (!factory.isAllowingRunsToStart())
- throw new OverloadedException();
- secContext.conveySecurity();
- }
- run.setGenerateProvenance(generateProvenance);
- run.setStatus(RemoteStatus.Operating);
- factory.getMasterEventFeed()
- .started(
- this,
- "started run execution",
- "The execution of run '" + getName()
- + "' has started.");
- break;
- case Stopped:
- run.setStatus(RemoteStatus.Stopped);
- break;
- case Finished:
- run.setStatus(RemoteStatus.Finished);
- break;
- }
- return null;
- } catch (IllegalStateTransitionException e) {
- throw new BadStateChangeException(e.getMessage());
- } catch (RemoteException e) {
- throw new BadStateChangeException(e.getMessage(), e.getCause());
- } catch (GeneralSecurityException | IOException e) {
- throw new BadStateChangeException(e.getMessage(), e);
- } catch (ImplementationException e) {
- if (e.getCause() != null)
- throw new BadStateChangeException(e.getMessage(), e.getCause());
- throw new BadStateChangeException(e.getMessage(), e);
- } catch (StillWorkingOnItException e) {
- log.info("still working on setting status of run " + id + " to "
- + s, e);
- return e.getMessage();
- } catch (InterruptedException e) {
- throw new BadStateChangeException(
- "interrupted while waiting to insert notification into database");
- }
- }
-
- static void checkBadFilename(String filename)
- throws FilesystemAccessException {
- if (filename.startsWith("/"))
- throw new FilesystemAccessException("filename may not be absolute");
- if (Arrays.asList(filename.split("/")).contains(".."))
- throw new FilesystemAccessException(
- "filename may not refer to parent");
- }
-
- @Override
- public String getInputBaclavaFile() {
- try {
- return run.getInputBaclavaFile();
- } catch (RemoteException e) {
- log.warn("problem when fetching input baclava file", e);
- return null;
- }
- }
-
- @Override
- public List<Input> getInputs() {
- ArrayList<Input> inputs = new ArrayList<>();
- try {
- for (RemoteInput ri : run.getInputs())
- inputs.add(new RunInput(ri));
- } catch (RemoteException e) {
- log.warn("problem when fetching list of workflow inputs", e);
- }
- return inputs;
- }
-
- @Override
- public String getOutputBaclavaFile() {
- try {
- return run.getOutputBaclavaFile();
- } catch (RemoteException e) {
- log.warn("problem when fetching output baclava file", e);
- return null;
- }
- }
-
- @Override
- public Input makeInput(String name) throws BadStateChangeException {
- try {
- return new RunInput(run.makeInput(name));
- } catch (RemoteException e) {
- throw new BadStateChangeException("failed to make input", e);
- }
- }
-
- @Override
- public void setInputBaclavaFile(String filename)
- throws FilesystemAccessException, BadStateChangeException {
- checkBadFilename(filename);
- try {
- run.setInputBaclavaFile(filename);
- } catch (RemoteException e) {
- throw new FilesystemAccessException(
- "cannot set input baclava file name", e);
- }
- }
-
- @Override
- public void setOutputBaclavaFile(String filename)
- throws FilesystemAccessException, BadStateChangeException {
- checkBadFilename(filename);
- try {
- run.setOutputBaclavaFile(filename);
- } catch (RemoteException e) {
- throw new FilesystemAccessException(
- "cannot set output baclava file name", e);
- }
- }
-
- @Override
- public Date getCreationTimestamp() {
- return creationInstant == null ? null : new Date(
- creationInstant.getTime());
- }
-
- @Override
- public Date getFinishTimestamp() {
- try {
- return run.getFinishTimestamp();
- } catch (RemoteException e) {
- log.info("failed to get finish timestamp", e);
- return null;
- }
- }
-
- @Override
- public Date getStartTimestamp() {
- try {
- return run.getStartTimestamp();
- } catch (RemoteException e) {
- log.info("failed to get finish timestamp", e);
- return null;
- }
- }
-
- /**
- * @param readers
- * the readers to set
- */
- public void setReaders(Set<String> readers) {
- this.readers = new HashSet<>(readers);
- db.flushToDisk(this);
- }
-
- /**
- * @return the readers
- */
- public Set<String> getReaders() {
- return readers == null ? new HashSet<String>()
- : unmodifiableSet(readers);
- }
-
- /**
- * @param writers
- * the writers to set
- */
- public void setWriters(Set<String> writers) {
- this.writers = new HashSet<>(writers);
- db.flushToDisk(this);
- }
-
- /**
- * @return the writers
- */
- public Set<String> getWriters() {
- return writers == null ? new HashSet<String>()
- : unmodifiableSet(writers);
- }
-
- /**
- * @param destroyers
- * the destroyers to set
- */
- public void setDestroyers(Set<String> destroyers) {
- this.destroyers = new HashSet<>(destroyers);
- db.flushToDisk(this);
- }
-
- /**
- * @return the destroyers
- */
- public Set<String> getDestroyers() {
- return destroyers == null ? new HashSet<String>()
- : unmodifiableSet(destroyers);
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException {
- out.defaultWriteObject();
- out.writeUTF(secContext.getOwner().getName());
- out.writeObject(secContext.getFactory());
- out.writeObject(new MarshalledObject<>(run));
- }
-
- @Override
- public boolean getGenerateProvenance() {
- return generateProvenance;
- }
-
- @Override
- public void setGenerateProvenance(boolean generateProvenance) {
- this.generateProvenance = generateProvenance;
- db.flushToDisk(this);
- }
-
- @SuppressWarnings("unchecked")
- private void readObject(ObjectInputStream in) throws IOException,
- ClassNotFoundException {
- in.defaultReadObject();
- if (log == null)
- log = getLog("Taverna.Server.LocalWorker");
- final String creatorName = in.readUTF();
- SecurityContextFactory factory = (SecurityContextFactory) in
- .readObject();
- try {
- secContext = factory.create(this,
- new UsernamePrincipal(creatorName));
- } catch (RuntimeException | IOException e) {
- throw e;
- } catch (Exception e) {
- throw new SecurityContextReconstructionException(e);
- }
- run = ((MarshalledObject<RemoteSingleRun>) in.readObject()).get();
- }
-
- public void setSecurityContext(TavernaSecurityContext tavernaSecurityContext) {
- secContext = tavernaSecurityContext;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public void setName(@Nonnull String name) {
- if (name.length() > RunConnection.NAME_LENGTH)
- this.name = name.substring(0, RunConnection.NAME_LENGTH);
- else
- this.name = name;
- db.flushToDisk(this);
- }
-
- @Override
- public void ping() throws UnknownRunException {
- try {
- run.ping();
- } catch (RemoteException e) {
- throw new UnknownRunException(e);
- }
- }
-}
-
-abstract class DEDelegate implements DirectoryEntry {
- Log log = getLog("Taverna.Server.Worker");
- private RemoteDirectoryEntry entry;
- private String name;
- private String full;
- private Date cacheModTime;
- private long cacheQueryTime = 0L;
-
- DEDelegate(RemoteDirectoryEntry entry) {
- this.entry = entry;
- }
-
- @Override
- public void destroy() throws FilesystemAccessException {
- try {
- entry.destroy();
- } catch (IOException e) {
- throw new FilesystemAccessException(
- "failed to delete directory entry", e);
- }
- }
-
- @Override
- public String getFullName() {
- if (full != null)
- return full;
- String n = getName();
- RemoteDirectoryEntry re = entry;
- try {
- while (true) {
- RemoteDirectory parent = re.getContainingDirectory();
- if (parent == null)
- break;
- n = parent.getName() + "/" + n;
- re = parent;
- }
- } catch (RemoteException e) {
- log.warn("failed to generate full name", e);
- }
- return (full = n);
- }
-
- @Override
- public String getName() {
- if (name == null)
- try {
- name = entry.getName();
- } catch (RemoteException e) {
- log.error("failed to get name", e);
- }
- return name;
- }
-
- @Override
- public Date getModificationDate() {
- if (cacheModTime == null || currentTimeMillis() - cacheQueryTime < 5000)
- try {
- cacheModTime = entry.getModificationDate();
- cacheQueryTime = currentTimeMillis();
- } catch (RemoteException e) {
- log.error("failed to get modification time", e);
- }
- return cacheModTime;
- }
-
- @Override
- public int compareTo(DirectoryEntry de) {
- return getFullName().compareTo(de.getFullName());
- }
-
- @Override
- public boolean equals(Object o) {
- return o != null && o instanceof DEDelegate
- && getFullName().equals(((DEDelegate) o).getFullName());
- }
-
- @Override
- public int hashCode() {
- return getFullName().hashCode();
- }
-}
-
-class DirectoryDelegate extends DEDelegate implements Directory {
- RemoteDirectory rd;
-
- DirectoryDelegate(RemoteDirectory dir) {
- super(dir);
- rd = dir;
- }
-
- @Override
- public Collection<DirectoryEntry> getContents()
- throws FilesystemAccessException {
- ArrayList<DirectoryEntry> result = new ArrayList<>();
- try {
- for (RemoteDirectoryEntry rde : rd.getContents()) {
- if (rde instanceof RemoteDirectory)
- result.add(new DirectoryDelegate((RemoteDirectory) rde));
- else
- result.add(new FileDelegate((RemoteFile) rde));
- }
- } catch (IOException e) {
- throw new FilesystemAccessException(
- "failed to get directory contents", e);
- }
- return result;
- }
-
- @Override
- public Collection<DirectoryEntry> getContentsByDate()
- throws FilesystemAccessException {
- ArrayList<DirectoryEntry> result = new ArrayList<>(getContents());
- sort(result, new DateComparator());
- return result;
- }
-
- static class DateComparator implements Comparator<DirectoryEntry> {
- @Override
- public int compare(DirectoryEntry a, DirectoryEntry b) {
- return a.getModificationDate().compareTo(b.getModificationDate());
- }
- }
-
- @Override
- public File makeEmptyFile(Principal actor, String name)
- throws FilesystemAccessException {
- try {
- return new FileDelegate(rd.makeEmptyFile(name));
- } catch (IOException e) {
- throw new FilesystemAccessException("failed to make empty file", e);
- }
- }
-
- @Override
- public Directory makeSubdirectory(Principal actor, String name)
- throws FilesystemAccessException {
- try {
- return new DirectoryDelegate(rd.makeSubdirectory(name));
- } catch (IOException e) {
- throw new FilesystemAccessException("failed to make subdirectory",
- e);
- }
- }
-
- @Override
- public ZipStream getContentsAsZip() throws FilesystemAccessException {
- ZipStream zs = new ZipStream();
-
- final ZipOutputStream zos;
- try {
- zos = new ZipOutputStream(new PipedOutputStream(zs));
- } catch (IOException e) {
- throw new FilesystemAccessException("problem building zip stream",
- e);
- }
- Thread t = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- zipDirectory(rd, null, zos);
- } catch (IOException e) {
- log.warn("problem when zipping directory", e);
- } finally {
- closeQuietly(zos);
- }
- }
- });
- t.setDaemon(true);
- t.start();
- return zs;
- }
-
- /**
- * Compresses a directory tree into a ZIP.
- *
- * @param dir
- * The directory to compress.
- * @param base
- * The base name of the directory (or <tt>null</tt> if this is
- * the root directory of the ZIP).
- * @param zos
- * Where to write the compressed data.
- * @throws RemoteException
- * If some kind of problem happens with the remote delegates.
- * @throws IOException
- * If we run into problems with reading or writing data.
- */
- void zipDirectory(RemoteDirectory dir, String base, ZipOutputStream zos)
- throws RemoteException, IOException {
- for (RemoteDirectoryEntry rde : dir.getContents()) {
- String name = rde.getName();
- if (base != null)
- name = base + "/" + name;
- if (rde instanceof RemoteDirectory) {
- RemoteDirectory rd = (RemoteDirectory) rde;
- zipDirectory(rd, name, zos);
- } else {
- RemoteFile rf = (RemoteFile) rde;
- zos.putNextEntry(new ZipEntry(name));
- try {
- int off = 0;
- while (true) {
- byte[] c = rf.getContents(off, 64 * 1024);
- if (c == null || c.length == 0)
- break;
- zos.write(c);
- off += c.length;
- }
- } finally {
- zos.closeEntry();
- }
- }
- }
- }
-}
-
-class FileDelegate extends DEDelegate implements File {
- RemoteFile rf;
-
- FileDelegate(RemoteFile f) {
- super(f);
- this.rf = f;
- }
-
- @Override
- public byte[] getContents(int offset, int length)
- throws FilesystemAccessException {
- try {
- return rf.getContents(offset, length);
- } catch (IOException e) {
- throw new FilesystemAccessException("failed to read file contents",
- e);
- }
- }
-
- @Override
- public long getSize() throws FilesystemAccessException {
- try {
- return rf.getSize();
- } catch (IOException e) {
- throw new FilesystemAccessException("failed to get file length", e);
- }
- }
-
- @Override
- public void setContents(byte[] data) throws FilesystemAccessException {
- try {
- rf.setContents(data);
- } catch (IOException e) {
- throw new FilesystemAccessException(
- "failed to write file contents", e);
- }
- }
-
- @Override
- public void appendContents(byte[] data) throws FilesystemAccessException {
- try {
- rf.appendContents(data);
- } catch (IOException e) {
- throw new FilesystemAccessException(
- "failed to write file contents", e);
- }
- }
-
- @Override
- public void copy(File from) throws FilesystemAccessException {
- FileDelegate fromFile;
- try {
- fromFile = (FileDelegate) from;
- } catch (ClassCastException e) {
- throw new FilesystemAccessException("different types of File?!");
- }
-
- try {
- rf.copy(fromFile.rf);
- } catch (Exception e) {
- throw new FilesystemAccessException("failed to copy file contents",
- e);
- }
- return;
- }
-}
-
-class ListenerDelegate implements Listener {
- private Log log = getLog("Taverna.Server.Worker");
- private RemoteListener r;
- String conf;
-
- ListenerDelegate(RemoteListener l) {
- r = l;
- }
-
- RemoteListener getRemote() {
- return r;
- }
-
- @Override
- public String getConfiguration() {
- try {
- if (conf == null)
- conf = r.getConfiguration();
- } catch (RemoteException e) {
- log.warn("failed to get configuration", e);
- }
- return conf;
- }
-
- @Override
- public String getName() {
- try {
- return r.getName();
- } catch (RemoteException e) {
- log.warn("failed to get name", e);
- return "UNKNOWN NAME";
- }
- }
-
- @Override
- public String getProperty(String propName) throws NoListenerException {
- try {
- return r.getProperty(propName);
- } catch (RemoteException e) {
- throw new NoListenerException("no such property: " + propName, e);
- }
- }
-
- @Override
- public String getType() {
- try {
- return r.getType();
- } catch (RemoteException e) {
- log.warn("failed to get type", e);
- return "UNKNOWN TYPE";
- }
- }
-
- @Override
- public String[] listProperties() {
- try {
- return r.listProperties();
- } catch (RemoteException e) {
- log.warn("failed to list properties", e);
- return new String[0];
- }
- }
-
- @Override
- public void setProperty(String propName, String value)
- throws NoListenerException, BadPropertyValueException {
- try {
- r.setProperty(propName, value);
- } catch (RemoteException e) {
- log.warn("failed to set property", e);
- if (e.getCause() != null
- && e.getCause() instanceof RuntimeException)
- throw new NoListenerException("failed to set property",
- e.getCause());
- if (e.getCause() != null && e.getCause() instanceof Exception)
- throw new BadPropertyValueException("failed to set property",
- e.getCause());
- throw new BadPropertyValueException("failed to set property", e);
- }
- }
-}
-
-class RunInput implements Input {
- private final RemoteInput i;
-
- RunInput(RemoteInput remote) {
- this.i = remote;
- }
-
- @Override
- public String getFile() {
- try {
- return i.getFile();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- @Override
- public String getName() {
- try {
- return i.getName();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- @Override
- public String getValue() {
- try {
- return i.getValue();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- @Override
- public void setFile(String file) throws FilesystemAccessException,
- BadStateChangeException {
- checkBadFilename(file);
- try {
- i.setFile(file);
- } catch (RemoteException e) {
- throw new FilesystemAccessException("cannot set file for input", e);
- }
- }
-
- @Override
- public void setValue(String value) throws BadStateChangeException {
- try {
- i.setValue(value);
- } catch (RemoteException e) {
- throw new BadStateChangeException(e);
- }
- }
-
- @Override
- public String getDelimiter() {
- try {
- return i.getDelimiter();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- @Override
- public void setDelimiter(String delimiter) throws BadStateChangeException {
- try {
- if (delimiter != null)
- delimiter = delimiter.substring(0, 1);
- i.setDelimiter(delimiter);
- } catch (RemoteException e) {
- throw new BadStateChangeException(e);
- }
- }
-}
-
-@SuppressWarnings("serial")
-class SecurityContextReconstructionException extends RuntimeException {
- public SecurityContextReconstructionException(Throwable t) {
- super("failed to rebuild security context", t);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java b/server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
deleted file mode 100644
index cf55ea0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static org.taverna.server.master.worker.RunConnection.COUNT_QUERY;
-import static org.taverna.server.master.worker.RunConnection.NAMES_QUERY;
-import static org.taverna.server.master.worker.RunConnection.SCHEMA;
-import static org.taverna.server.master.worker.RunConnection.TABLE;
-import static org.taverna.server.master.worker.RunConnection.TIMEOUT_QUERY;
-import static org.taverna.server.master.worker.RunConnection.UNTERMINATED_QUERY;
-
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.jdo.annotations.Column;
-import javax.jdo.annotations.Join;
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.PrimaryKey;
-import javax.jdo.annotations.Queries;
-import javax.jdo.annotations.Query;
-
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.interfaces.SecurityContextFactory;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * The representation of the connections to the runs that actually participates
- * in the persistence system.
- *
- * @author Donal Fellows
- */
-@PersistenceCapable(table = TABLE, schema = SCHEMA)
-@Queries({
- @Query(name = "count", language = "SQL", value = COUNT_QUERY, unique = "true", resultClass = Integer.class),
- @Query(name = "names", language = "SQL", value = NAMES_QUERY, unique = "false", resultClass = String.class),
- @Query(name = "unterminated", language = "SQL", value = UNTERMINATED_QUERY, unique = "false", resultClass = String.class),
- @Query(name = "timedout", language = "SQL", value = TIMEOUT_QUERY, unique = "false", resultClass = String.class) })
-public class RunConnection {
- static final String SCHEMA = "TAVERNA";
- static final String TABLE = "RUN_CONNECTION";
- private static final String FULL_NAME = SCHEMA + "." + TABLE;
- static final String COUNT_QUERY = "SELECT count(*) FROM " + FULL_NAME;
- static final String NAMES_QUERY = "SELECT ID FROM " + FULL_NAME;
- static final String TIMEOUT_QUERY = "SELECT ID FROM " + FULL_NAME
- + " WHERE expiry < CURRENT_TIMESTAMP";
- static final String UNTERMINATED_QUERY = "SELECT ID FROM " + FULL_NAME
- + " WHERE doneTransitionToFinished = 0";
- static final int NAME_LENGTH = 48;
-
- @PrimaryKey
- @Column(length = 40)
- private String id;
-
- @Persistent(defaultFetchGroup = "true")
- @Column(length = NAME_LENGTH)
- private String name;
-
- @Persistent(defaultFetchGroup = "true")
- private Date creationInstant;
-
- @Persistent(defaultFetchGroup = "true", serialized = "true")
- @Column(jdbcType = "BLOB", sqlType = "BLOB")
- private Workflow workflow;
-
- @Persistent(defaultFetchGroup = "true")
- private Date expiry;
-
- @Persistent(defaultFetchGroup = "true")
- @Join(table = TABLE + "_READERS", column = "ID")
- private String[] readers;
-
- @Persistent(defaultFetchGroup = "true")
- @Join(table = TABLE + "_WRITERS", column = "ID")
- private String[] writers;
-
- @Persistent(defaultFetchGroup = "true")
- @Join(table = TABLE + "_DESTROYERS", column = "ID")
- private String[] destroyers;
-
- @Persistent(defaultFetchGroup = "true", serialized = "true")
- @Column(jdbcType = "BLOB", sqlType = "BLOB")
- private MarshalledObject<RemoteSingleRun> run;
-
- @Persistent(defaultFetchGroup = "true")
- private int doneTransitionToFinished;
-
- @Persistent(defaultFetchGroup = "true")
- private int generateProvenance;
-
- @Persistent(defaultFetchGroup = "true")
- @Column(length = 128)
- String owner;
-
- @Persistent(defaultFetchGroup = "true")
- @Column(length = 36)
- private String securityToken;
-
- @Persistent(defaultFetchGroup = "true", serialized = "true")
- @Column(jdbcType = "BLOB", sqlType = "BLOB")
- private SecurityContextFactory securityContextFactory;
- @Persistent(defaultFetchGroup = "true", serialized = "true")
- @Column(jdbcType = "BLOB", sqlType = "BLOB")
- private Credential[] credentials;
- @Persistent(defaultFetchGroup = "true", serialized = "true")
- @Column(jdbcType = "BLOB", sqlType = "BLOB")
- private Trust[] trust;
-
- private static final String[] STRING_ARY = new String[0];
-
- public String getId() {
- return id;
- }
-
- public boolean isFinished() {
- return doneTransitionToFinished != 0;
- }
-
- public void setFinished(boolean finished) {
- doneTransitionToFinished = (finished ? 1 : 0);
- }
-
- public boolean isProvenanceGenerated() {
- return generateProvenance != 0;
- }
-
- public void setProvenanceGenerated(boolean generate) {
- generateProvenance = (generate ? 1 : 0);
- }
-
- /**
- * Manufacture a persistent representation of the given workflow run. Must
- * be called within the context of a transaction.
- *
- * @param rrd
- * The remote delegate of the workflow run.
- * @return The persistent object.
- * @throws IOException
- * If serialisation fails.
- */
- @Nonnull
- public static RunConnection toDBform(@Nonnull RemoteRunDelegate rrd)
- throws IOException {
- RunConnection rc = new RunConnection();
- rc.id = rrd.id;
- rc.makeChanges(rrd);
- return rc;
- }
-
- private static List<String> list(String[] ary) {
- if (ary == null)
- return emptyList();
- return asList(ary);
- }
-
- /**
- * Get the remote run delegate for a particular persistent connection. Must
- * be called within the context of a transaction.
- *
- * @param db
- * The database facade.
- * @return The delegate object.
- * @throws Exception
- * If anything goes wrong.
- */
- @Nonnull
- public RemoteRunDelegate fromDBform(@Nonnull RunDBSupport db)
- throws Exception {
- RemoteRunDelegate rrd = new RemoteRunDelegate();
- rrd.id = getId();
- rrd.creationInstant = creationInstant;
- rrd.workflow = workflow;
- rrd.expiry = expiry;
- rrd.readers = new HashSet<>(list(readers));
- rrd.writers = new HashSet<>(list(writers));
- rrd.destroyers = new HashSet<>(list(destroyers));
- rrd.run = run.get();
- rrd.doneTransitionToFinished = isFinished();
- rrd.generateProvenance = isProvenanceGenerated();
- rrd.secContext = securityContextFactory.create(rrd,
- new UsernamePrincipal(owner));
- ((SecurityContextDelegate)rrd.secContext).setCredentialsAndTrust(credentials,trust);
- rrd.db = db;
- rrd.factory = db.getFactory();
- rrd.name = name;
- return rrd;
- }
-
- /**
- * Flush changes from a remote run delegate to the database. Must be called
- * within the context of a transaction.
- *
- * @param rrd
- * The remote run delegate object that has potential changes.
- * @throws IOException
- * If anything goes wrong in serialization.
- */
- public void makeChanges(@Nonnull RemoteRunDelegate rrd) throws IOException {
- // Properties that are set exactly once
- if (creationInstant == null) {
- creationInstant = rrd.getCreationTimestamp();
- workflow = rrd.getWorkflow();
- run = new MarshalledObject<>(rrd.run);
- securityContextFactory = rrd.getSecurityContext().getFactory();
- owner = rrd.getSecurityContext().getOwner().getName();
- securityToken = ((org.taverna.server.master.worker.SecurityContextFactory) securityContextFactory)
- .issueNewPassword();
- }
- // Properties that are set multiple times
- expiry = rrd.getExpiry();
- readers = rrd.getReaders().toArray(STRING_ARY);
- writers = rrd.getWriters().toArray(STRING_ARY);
- destroyers = rrd.getDestroyers().toArray(STRING_ARY);
- credentials = rrd.getSecurityContext().getCredentials();
- trust = rrd.getSecurityContext().getTrusted();
- if (rrd.name.length() > NAME_LENGTH)
- this.name = rrd.name.substring(0, NAME_LENGTH);
- else
- this.name = rrd.name;
- setFinished(rrd.doneTransitionToFinished);
- setProvenanceGenerated(rrd.generateProvenance);
- }
-
- public String getSecurityToken() {
- return securityToken;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java b/server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
deleted file mode 100644
index 2aa7ed1..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.taverna.server.master.notification.NotificationEngine;
-
-/**
- * The interface to the database of runs.
- *
- * @author Donal Fellows
- */
-public interface RunDBSupport {
- /**
- * Scan each run to see if it has finished yet and issue registered
- * notifications if it has.
- */
- void checkForFinishNow();
-
- /**
- * Remove currently-expired runs from this database.
- */
- void cleanNow();
-
- /**
- * How many runs are stored in the database.
- *
- * @return The current size of the run table.
- */
- int countRuns();
-
- /**
- * Ensure that a run gets persisted in the database. It is assumed that the
- * value is already in there.
- *
- * @param run
- * The run to persist.
- */
- void flushToDisk(@Nonnull RemoteRunDelegate run);
-
- /**
- * Select an arbitrary representative run.
- *
- * @return The selected run.
- * @throws Exception
- * If anything goes wrong.
- */
- @Nullable
- RemoteRunDelegate pickArbitraryRun() throws Exception;
-
- /**
- * Get a list of all the run names.
- *
- * @return The names (i.e., UUIDs) of all the runs.
- */
- @Nonnull
- List<String> listRunNames();
-
- /**
- * @param notificationEngine
- * A reference to the notification fabric bean.
- */
- void setNotificationEngine(NotificationEngine notificationEngine);
-
- /**
- * @param notifier
- * A reference to the bean that creates messages about workflow
- * run termination.
- */
- void setNotifier(CompletionNotifier notifier);
-
- /**
- * @return A reference to the actual factory for remote runs.
- */
- FactoryBean getFactory();
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java b/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
deleted file mode 100644
index cedb4b5..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static java.lang.Integer.parseInt;
-import static java.util.UUID.randomUUID;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.RunStore;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.notification.NotificationEngine;
-import org.taverna.server.master.notification.NotificationEngine.Message;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * The main facade bean that interfaces to the database of runs.
- *
- * @author Donal Fellows
- */
-public class RunDatabase implements RunStore, RunDBSupport {
- private Log log = LogFactory.getLog("Taverna.Server.Worker.RunDB");
- RunDatabaseDAO dao;
- CompletionNotifier backupNotifier;
- Map<String, CompletionNotifier> typedNotifiers;
- private NotificationEngine notificationEngine;
- @Autowired
- private FactoryBean factory;
- private Map<String, TavernaRun> cache = new HashMap<>();
-
- @Override
- @Required
- public void setNotifier(CompletionNotifier n) {
- backupNotifier = n;
- }
-
- public void setTypeNotifiers(List<CompletionNotifier> notifiers) {
- typedNotifiers = new HashMap<>();
- for (CompletionNotifier n : notifiers)
- typedNotifiers.put(n.getName(), n);
- }
-
- @Required
- @Override
- public void setNotificationEngine(NotificationEngine notificationEngine) {
- this.notificationEngine = notificationEngine;
- }
-
- @Required
- public void setDao(RunDatabaseDAO dao) {
- this.dao = dao;
- }
-
- @Override
- public void checkForFinishNow() {
- /*
- * Get which runs are actually newly finished; this requires getting the
- * candidates from the database and *then* doing the expensive requests
- * to the back end to find out the status.
- */
- Map<String, RemoteRunDelegate> notifiable = new HashMap<>();
- for (RemoteRunDelegate p : dao.getPotentiallyNotifiable())
- if (p.getStatus() == Status.Finished)
- notifiable.put(p.getId(), p);
-
- // Check if there's nothing more to do
- if (notifiable.isEmpty())
- return;
-
- /*
- * Tell the database about the ones we've got.
- */
- dao.markFinished(notifiable.keySet());
-
- /*
- * Send out the notifications. The notification addresses are stored in
- * the back-end engine, so this is *another* thing that can take time.
- */
- for (RemoteRunDelegate rrd : notifiable.values())
- for (Listener l : rrd.getListeners())
- if (l.getName().equals("io")) {
- try {
- notifyFinished(rrd.id, l, rrd);
- } catch (Exception e) {
- log.warn("failed to do notification of completion", e);
- }
- break;
- }
- }
-
- @Override
- public void cleanNow() {
- List<String> cleaned;
- try {
- cleaned = dao.doClean();
- } catch (Exception e) {
- log.warn("failure during deletion of expired runs", e);
- return;
- }
- synchronized (cache) {
- for (String id : cleaned)
- cache.remove(id);
- }
- }
-
- @Override
- public int countRuns() {
- return dao.countRuns();
- }
-
- @Override
- public void flushToDisk(RemoteRunDelegate run) {
- try {
- dao.flushToDisk(run);
- } catch (IOException e) {
- throw new RuntimeException(
- "unexpected problem when persisting run record in database",
- e);
- }
- }
-
- @Override
- public RemoteRunDelegate pickArbitraryRun() throws Exception {
- return dao.pickArbitraryRun();
- }
-
- @Override
- public List<String> listRunNames() {
- return dao.listRunNames();
- }
-
- @Nullable
- private TavernaRun get(String uuid) {
- TavernaRun run = null;
- synchronized (cache) {
- run = cache.get(uuid);
- }
- try {
- if (run != null)
- run.ping();
- } catch (UnknownRunException e) {
- if (log.isDebugEnabled())
- log.debug("stale mapping in cache?", e);
- // Don't need to flush the cache; this happens when cleaning anyway
- run = null;
- }
- if (run == null)
- run = dao.get(uuid);
- return run;
- }
-
- @Override
- public TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
- throws UnknownRunException {
- // Check first to see if the 'uuid' actually looks like a UUID; if
- // not, throw it out immediately without logging an exception.
- try {
- UUID.fromString(uuid);
- } catch (IllegalArgumentException e) {
- if (log.isDebugEnabled())
- log.debug("run ID does not look like UUID; rejecting...");
- throw new UnknownRunException();
- }
- TavernaRun run = get(uuid);
- if (run != null && (user == null || p.permitAccess(user, run)))
- return run;
- throw new UnknownRunException();
- }
-
- @Override
- public TavernaRun getRun(String uuid) throws UnknownRunException {
- TavernaRun run = get(uuid);
- if (run != null)
- return run;
- throw new UnknownRunException();
- }
-
- @Override
- public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
- synchronized (cache) {
- Map<String, TavernaRun> cached = new HashMap<>();
- for (Entry<String, TavernaRun> e : cache.entrySet()) {
- TavernaRun r = e.getValue();
- if (p.permitAccess(user, r))
- cached.put(e.getKey(), r);
- }
- if (!cached.isEmpty())
- return cached;
- }
- return dao.listRuns(user, p);
- }
-
- private void logLength(String message, Object obj) {
- if (!log.isDebugEnabled())
- return;
- try {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
- oos.writeObject(obj);
- }
- log.debug(message + ": " + baos.size());
- } catch (Exception e) {
- log.warn("oops", e);
- }
- }
-
- @Override
- public String registerRun(TavernaRun run) {
- if (!(run instanceof RemoteRunDelegate))
- throw new IllegalArgumentException(
- "run must be created by localworker package");
- RemoteRunDelegate rrd = (RemoteRunDelegate) run;
- if (rrd.id == null)
- rrd.id = randomUUID().toString();
- logLength("RemoteRunDelegate serialized length", rrd);
- try {
- dao.persistRun(rrd);
- } catch (IOException e) {
- throw new RuntimeException(
- "unexpected problem when persisting run record in database",
- e);
- }
- synchronized (cache) {
- cache.put(rrd.getId(), run);
- }
- return rrd.getId();
- }
-
- @Override
- public void unregisterRun(String uuid) {
- try {
- if (dao.unpersistRun(uuid))
- synchronized (cache) {
- cache.remove(uuid);
- }
- } catch (RuntimeException e) {
- if (log.isDebugEnabled())
- log.debug("problem persisting the deletion of the run " + uuid,
- e);
- }
- }
-
- /**
- * Process the event that a run has finished.
- *
- * @param name
- * The name of the run.
- * @param io
- * The io listener of the run (used to get information about the
- * run).
- * @param run
- * The handle to the run.
- * @throws Exception
- * If anything goes wrong.
- */
- private void notifyFinished(final String name, Listener io,
- final RemoteRunDelegate run) throws Exception {
- String to = io.getProperty("notificationAddress");
- final int code;
- try {
- code = parseInt(io.getProperty("exitcode"));
- } catch (NumberFormatException nfe) {
- // Ignore; not much we can do here...
- return;
- }
-
- notificationEngine.dispatchMessage(run, to, new Message() {
- private CompletionNotifier getNotifier(String type) {
- CompletionNotifier n = typedNotifiers.get(type);
- if (n == null)
- n = backupNotifier;
- return n;
- }
-
- @Override
- public String getContent(String type) {
- return getNotifier(type).makeCompletionMessage(name, run, code);
- }
-
- @Override
- public String getTitle(String type) {
- return getNotifier(type).makeMessageSubject(name, run, code);
- }
- });
- }
-
- @Override
- public FactoryBean getFactory() {
- return factory;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java b/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java
deleted file mode 100644
index 51931c0..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabaseDAO.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static org.taverna.server.master.worker.RunConnection.toDBform;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.jdo.annotations.PersistenceAware;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
-import org.taverna.server.master.utils.JDOSupport;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * This handles storing runs, interfacing with the underlying state engine as
- * necessary.
- *
- * @author Donal Fellows
- */
-@PersistenceAware
-public class RunDatabaseDAO extends JDOSupport<RunConnection> {
- public RunDatabaseDAO() {
- super(RunConnection.class);
- }
-
- private Log log = LogFactory.getLog("Taverna.Server.Worker.RunDB");
- private RunDatabase facade;
-
- @Required
- public void setFacade(RunDatabase facade) {
- this.facade = facade;
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
- @SuppressWarnings("unchecked")
- private List<String> nameRuns() {
- if (log.isDebugEnabled())
- log.debug("fetching all run names");
- return (List<String>) namedQuery("names").execute();
- }
-
- /**
- * @return The number of workflow runs in the database.
- */
- @WithinSingleTransaction
- public int countRuns() {
- if (log.isDebugEnabled())
- log.debug("counting the number of runs");
- return (Integer) namedQuery("count").execute();
- }
-
- @SuppressWarnings("unchecked")
- private List<String> expiredRuns() {
- return (List<String>) namedQuery("timedout").execute();
- }
-
- @SuppressWarnings("unchecked")
- private List<String> unterminatedRuns() {
- return (List<String>) namedQuery("unterminated").execute();
- }
-
- @Nullable
- private RunConnection pickRun(@Nonnull String name) {
- if (log.isDebugEnabled())
- log.debug("fetching the run called " + name);
- try {
- RunConnection rc = getById(name);
- if (rc == null)
- log.warn("no result for " + name);
- return rc;
- } catch (RuntimeException e) {
- log.warn("problem in fetch", e);
- throw e;
- }
- }
-
- @Nullable
- @WithinSingleTransaction
- public String getSecurityToken(@Nonnull String name) {
- RunConnection rc = getById(name);
- if (rc == null)
- return null;
- return rc.getSecurityToken();
- }
-
- private void persist(@Nonnull RemoteRunDelegate rrd) throws IOException {
- persist(toDBform(rrd));
- }
-
- @Nonnull
- private List<RunConnection> allRuns() {
- try {
- List<RunConnection> rcs = new ArrayList<>();
- List<String> names = nameRuns();
- for (String id : names) {
- try {
- if (id != null)
- rcs.add(pickRun(id));
- } catch (RuntimeException e) {
- continue;
- }
- }
- return rcs;
- } catch (RuntimeException e) {
- log.warn("problem in fetch", e);
- throw e;
- }
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
- /**
- * Obtain a workflow run handle.
- *
- * @param name
- * The identifier of the run.
- * @return The run handle, or <tt>null</tt> if there is no such run.
- */
- @Nullable
- @WithinSingleTransaction
- public TavernaRun get(String name) {
- try {
- RunConnection rc = pickRun(name);
- return (rc == null) ? null : rc.fromDBform(facade);
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Get the runs that a user can read things from.
- *
- * @param user
- * Who is asking?
- * @param p
- * The policy that determines what they can see.
- * @return A mapping from run IDs to run handles.
- */
- @Nonnull
- @WithinSingleTransaction
- public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
- Map<String, TavernaRun> result = new HashMap<>();
- for (String id : nameRuns())
- try {
- RemoteRunDelegate rrd = pickRun(id).fromDBform(facade);
- if (p.permitAccess(user, rrd))
- result.put(id, rrd);
- } catch (Exception e) {
- continue;
- }
- return result;
- }
-
- /**
- * @return A list of the IDs for all workflow runs.
- */
- @Nonnull
- @WithinSingleTransaction
- public List<String> listRunNames() {
- List<String> runNames = new ArrayList<>();
- for (RunConnection rc : allRuns())
- if (rc.getId() != null)
- runNames.add(rc.getId());
- return runNames;
- }
-
- /**
- * @return An arbitrary, representative workflow run.
- * @throws Exception
- * If anything goes wrong.
- */
- @Nullable
- @WithinSingleTransaction
- public RemoteRunDelegate pickArbitraryRun() throws Exception {
- for (RunConnection rc : allRuns()) {
- if (rc.getId() == null)
- continue;
- return rc.fromDBform(facade);
- }
- return null;
- }
-
- /**
- * Make a workflow run persistent. Must only be called once per workflow
- * run.
- *
- * @param rrd
- * The workflow run to persist.
- * @throws IOException
- * If anything goes wrong with serialisation of the run.
- */
- @WithinSingleTransaction
- public void persistRun(@Nonnull RemoteRunDelegate rrd) throws IOException {
- persist(rrd);
- }
-
- /**
- * Stop a workflow run from being persistent.
- *
- * @param name
- * The ID of the run.
- * @return Whether a deletion happened.
- */
- @WithinSingleTransaction
- public boolean unpersistRun(String name) {
- RunConnection rc = pickRun(name);
- if (rc != null)
- delete(rc);
- return rc != null;
- }
-
- /**
- * Ensure that the given workflow run is synchronized with the database.
- *
- * @param run
- * The run to synchronise.
- * @throws IOException
- * If serialization of anything fails.
- */
- @WithinSingleTransaction
- public void flushToDisk(@Nonnull RemoteRunDelegate run) throws IOException {
- getById(run.id).makeChanges(run);
- }
-
- /**
- * Remove all workflow runs that have expired.
- *
- * @return The ids of the deleted runs.
- */
- @Nonnull
- @PerfLogged
- @WithinSingleTransaction
- public List<String> doClean() {
- if (log.isDebugEnabled())
- log.debug("deleting runs that timed out before " + new Date());
- List<String> toDelete = expiredRuns();
- if (log.isDebugEnabled())
- log.debug("found " + toDelete.size() + " runs to delete");
- for (String id : toDelete) {
- RunConnection rc = getById(id);
- try {
- rc.fromDBform(facade).run.destroy();
- } catch (Exception e) {
- if (log.isDebugEnabled())
- log.debug("failed to delete execution resource for " + id,
- e);
- }
- delete(rc);
- }
- return toDelete;
- }
-
- /**
- * @return A list of workflow runs that are candidates for doing
- * notification of termination.
- */
- @Nonnull
- @PerfLogged
- @WithinSingleTransaction
- public List<RemoteRunDelegate> getPotentiallyNotifiable() {
- List<RemoteRunDelegate> toNotify = new ArrayList<>();
- for (String id : unterminatedRuns())
- try {
- RunConnection rc = getById(id);
- toNotify.add(rc.fromDBform(facade));
- } catch (Exception e) {
- log.warn("failed to fetch connection token"
- + "for notification of completion check", e);
- }
- return toNotify;
- }
-
- @PerfLogged
- @WithinSingleTransaction
- public void markFinished(@Nonnull Set<String> terminated) {
- for (String id : terminated) {
- RunConnection rc = getById(id);
- if (rc == null)
- continue;
- try {
- rc.fromDBform(facade).doneTransitionToFinished = true;
- rc.setFinished(true);
- } catch (Exception e) {
- log.warn("failed to note termination", e);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java b/server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java
deleted file mode 100644
index 29ac884..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/RunFactoryConfiguration.java
+++ /dev/null
@@ -1,395 +0,0 @@
-package org.taverna.server.master.worker;
-
-import static org.springframework.jmx.support.MetricType.COUNTER;
-import static org.springframework.jmx.support.MetricType.GAUGE;
-import static org.taverna.server.master.TavernaServer.JMX_ROOT;
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.annotation.Order;
-import org.springframework.jmx.export.annotation.ManagedAttribute;
-import org.springframework.jmx.export.annotation.ManagedMetric;
-import org.springframework.jmx.export.annotation.ManagedResource;
-import org.taverna.server.master.factories.ConfigurableRunFactory;
-import org.taverna.server.master.localworker.LocalWorkerState;
-
-@ManagedResource(objectName = JMX_ROOT + "Factory", description = "The factory for runs.")
-public abstract class RunFactoryConfiguration implements ConfigurableRunFactory {
- protected Log log = LogFactory.getLog("Taverna.Server.Worker");
- protected LocalWorkerState state;
- protected RunDBSupport runDB;
- private int totalRuns = 0;
-
- @PreDestroy
- void closeLog() {
- log = null;
- }
-
- @Autowired(required = true)
- @Order(0)
- void setState(LocalWorkerState state) {
- this.state = state;
- }
-
- @Autowired(required = true)
- @Order(0)
- void setRunDB(RunDBSupport runDB) {
- this.runDB = runDB;
- }
-
- /**
- * Drop any current references to the registry of runs, and kill off that
- * process.
- */
- protected abstract void reinitRegistry();
-
- /**
- * Drop any current references to the run factory subprocess and kill it
- * off.
- */
- protected abstract void reinitFactory();
-
- /** Count the number of operating runs. */
- protected abstract int operatingCount() throws Exception;
-
- protected final synchronized void incrementRunCount() {
- totalRuns++;
- }
-
- @Override
- @ManagedAttribute(description = "Whether it is allowed to start a run executing.", currencyTimeLimit = 30)
- public final boolean isAllowingRunsToStart() {
- try {
- return state.getOperatingLimit() > getOperatingCount();
- } catch (Exception e) {
- log.info("failed to get operating run count", e);
- return false;
- }
- }
-
- @Override
- @ManagedAttribute(description = "The host holding the RMI registry to communicate via.")
- public final String getRegistryHost() {
- return state.getRegistryHost();
- }
-
- @Override
- @ManagedAttribute(description = "The host holding the RMI registry to communicate via.")
- public final void setRegistryHost(String host) {
- state.setRegistryHost(host);
- reinitRegistry();
- reinitFactory();
- }
-
- @Override
- @ManagedAttribute(description = "The port number of the RMI registry. Should not normally be set.")
- public final int getRegistryPort() {
- return state.getRegistryPort();
- }
-
- @Override
- @ManagedAttribute(description = "The port number of the RMI registry. Should not normally be set.")
- public final void setRegistryPort(int port) {
- state.setRegistryPort(port);
- reinitRegistry();
- reinitFactory();
- }
-
- @Nonnull
- @Override
- @ManagedAttribute(description = "What JAR do we use to start the RMI registry process?")
- public final String getRmiRegistryJar() {
- return state.getRegistryJar();
- }
-
- @Override
- @ManagedAttribute(description = "What JAR do we use to start the RMI registry process?")
- public final void setRmiRegistryJar(String rmiRegistryJar) {
- state.setRegistryJar(rmiRegistryJar);
- reinitRegistry();
- reinitFactory();
- }
-
- @Override
- @ManagedAttribute(description = "The maximum number of simultaneous runs supported by the server.", currencyTimeLimit = 300)
- public final int getMaxRuns() {
- return state.getMaxRuns();
- }
-
- @Override
- @ManagedAttribute(description = "The maximum number of simultaneous runs supported by the server.", currencyTimeLimit = 300)
- public final void setMaxRuns(int maxRuns) {
- state.setMaxRuns(maxRuns);
- }
-
- /** @return How many minutes should a workflow live by default? */
- @Override
- @ManagedAttribute(description = "How many minutes should a workflow live by default?", currencyTimeLimit = 300)
- public final int getDefaultLifetime() {
- return state.getDefaultLifetime();
- }
-
- /**
- * Set how long a workflow should live by default.
- *
- * @param defaultLifetime
- * Default lifetime, in minutes.
- */
- @Override
- @ManagedAttribute(description = "How many minutes should a workflow live by default?", currencyTimeLimit = 300)
- public final void setDefaultLifetime(int defaultLifetime) {
- state.setDefaultLifetime(defaultLifetime);
- }
-
- /**
- * @return How many milliseconds to wait between checks to see if a worker
- * process has registered.
- */
- @Override
- @ManagedAttribute(description = "How many milliseconds to wait between checks to see if a worker process has registered.", currencyTimeLimit = 300)
- public final int getSleepTime() {
- return state.getSleepMS();
- }
-
- /**
- * @param sleepTime
- * How many milliseconds to wait between checks to see if a
- * worker process has registered.
- */
- @Override
- @ManagedAttribute(description = "How many milliseconds to wait between checks to see if a worker process has registered.", currencyTimeLimit = 300)
- public final void setSleepTime(int sleepTime) {
- state.setSleepMS(sleepTime);
- }
-
- /**
- * @return How many seconds to wait for a worker process to register itself.
- */
- @Override
- @ManagedAttribute(description = "How many seconds to wait for a worker process to register itself.", currencyTimeLimit = 300)
- public final int getWaitSeconds() {
- return state.getWaitSeconds();
- }
-
- /**
- * @param seconds
- * How many seconds to wait for a worker process to register
- * itself.
- */
- @Override
- @ManagedAttribute(description = "How many seconds to wait for a worker process to register itself.", currencyTimeLimit = 300)
- public final void setWaitSeconds(int seconds) {
- state.setWaitSeconds(seconds);
- }
-
- /** @return The script to run to start running a workflow. */
- @Nonnull
- @Override
- @ManagedAttribute(description = "The script to run to start running a workflow.", currencyTimeLimit = 300)
- public final String getExecuteWorkflowScript() {
- return state.getExecuteWorkflowScript();
- }
-
- /**
- * @param executeWorkflowScript
- * The script to run to start running a workflow.
- */
- @Override
- @ManagedAttribute(description = "The script to run to start running a workflow.", currencyTimeLimit = 300)
- public final void setExecuteWorkflowScript(String executeWorkflowScript) {
- state.setExecuteWorkflowScript(executeWorkflowScript);
- reinitFactory();
- }
-
- /** @return The location of the JAR implementing the server worker processes. */
- @Nonnull
- @Override
- @ManagedAttribute(description = "The location of the JAR implementing the server worker processes.")
- public final String getServerWorkerJar() {
- return state.getServerWorkerJar();
- }
-
- /**
- * @param serverWorkerJar
- * The location of the JAR implementing the server worker
- * processes.
- */
- @Override
- @ManagedAttribute(description = "The location of the JAR implementing the server worker processes.")
- public final void setServerWorkerJar(String serverWorkerJar) {
- state.setServerWorkerJar(serverWorkerJar);
- reinitFactory();
- }
-
- /** @return The list of additional arguments used to make a worker process. */
- @Nonnull
- @Override
- @ManagedAttribute(description = "The list of additional arguments used to make a worker process.", currencyTimeLimit = 300)
- public final String[] getExtraArguments() {
- return state.getExtraArgs();
- }
-
- /**
- * @param extraArguments
- * The list of additional arguments used to make a worker
- * process.
- */
- @Override
- @ManagedAttribute(description = "The list of additional arguments used to make a worker process.", currencyTimeLimit = 300)
- public final void setExtraArguments(@Nonnull String[] extraArguments) {
- state.setExtraArgs(extraArguments);
- reinitFactory();
- }
-
- /** @return Which java executable to run. */
- @Nonnull
- @Override
- @ManagedAttribute(description = "Which java executable to run.", currencyTimeLimit = 300)
- public final String getJavaBinary() {
- return state.getJavaBinary();
- }
-
- /**
- * @param javaBinary
- * Which java executable to run.
- */
- @Override
- @ManagedAttribute(description = "Which java executable to run.", currencyTimeLimit = 300)
- public final void setJavaBinary(@Nonnull String javaBinary) {
- state.setJavaBinary(javaBinary);
- reinitFactory();
- }
-
- /**
- * @return A file containing a password to use when running a program as
- * another user (e.g., with sudo).
- */
- @Nullable
- @Override
- @ManagedAttribute(description = "A file containing a password to use when running a program as another user (e.g., with sudo).", currencyTimeLimit = 300)
- public final String getPasswordFile() {
- return state.getPasswordFile();
- }
-
- /**
- * @param passwordFile
- * A file containing a password to use when running a program as
- * another user (e.g., with sudo).
- */
- @Override
- @ManagedAttribute(description = "A file containing a password to use when running a program as another user (e.g., with sudo).", currencyTimeLimit = 300)
- public final void setPasswordFile(@Nullable String passwordFile) {
- state.setPasswordFile(passwordFile);
- reinitFactory();
- }
-
- /**
- * @return The location of the JAR implementing the secure-fork process.
- */
- @Nonnull
- @Override
- @ManagedAttribute(description = "The location of the JAR implementing the secure-fork process.", currencyTimeLimit = 300)
- public final String getServerForkerJar() {
- return state.getServerForkerJar();
- }
-
- /**
- * @param serverForkerJar
- * The location of the JAR implementing the secure-fork process.
- */
- @Override
- @ManagedAttribute(description = "The location of the JAR implementing the secure-fork process.", currencyTimeLimit = 300)
- public final void setServerForkerJar(String forkerJarFilename) {
- state.setServerForkerJar(forkerJarFilename);
- reinitFactory();
- }
-
- /**
- * @return How many times has a workflow run been spawned by this engine.
- * Restarts reset this counter.
- */
- @Override
- @ManagedMetric(description = "How many times has a workflow run been spawned by this engine.", currencyTimeLimit = 10, metricType = COUNTER, category = "throughput")
- public final synchronized int getTotalRuns() {
- return totalRuns;
- }
-
- /**
- * @return How many checks were done for the worker process the last time a
- * spawn was tried.
- */
- @Override
- @ManagedAttribute(description = "How many checks were done for the worker process the last time a spawn was tried.", currencyTimeLimit = 60)
- public abstract int getLastStartupCheckCount();
-
- @Nonnull
- @Override
- @ManagedAttribute(description = "The names of the current runs.", currencyTimeLimit = 5)
- public final String[] getCurrentRunNames() {
- List<String> names = runDB.listRunNames();
- return names.toArray(new String[names.size()]);
- }
-
- @Override
- @ManagedAttribute(description = "What the factory subprocess's main RMI interface is registered as.", currencyTimeLimit = 60)
- public abstract String getFactoryProcessName();
-
- /**
- * @return What was the exit code from the last time the factory subprocess
- * was killed?
- */
- @Override
- @ManagedAttribute(description = "What was the exit code from the last time the factory subprocess was killed?")
- public abstract Integer getLastExitCode();
-
- /**
- * @return The mapping of user names to RMI factory IDs.
- */
- @Override
- @ManagedAttribute(description = "The mapping of user names to RMI factory IDs.", currencyTimeLimit = 60)
- public abstract String[] getFactoryProcessMapping();
-
- @Override
- @ManagedAttribute(description = "The maximum number of simultaneous operating runs supported by the server.", currencyTimeLimit = 300)
- public final void setOperatingLimit(int operatingLimit) {
- state.setOperatingLimit(operatingLimit);
- }
-
- @Override
- @ManagedAttribute(description = "The maximum number of simultaneous operating runs supported by the server.", currencyTimeLimit = 300)
- public final int getOperatingLimit() {
- return state.getOperatingLimit();
- }
-
- /**
- * @return A count of the number of runs believed to actually be in the
- * {@linkplain uk.org.taverna.server.master.common.Status#Operating
- * operating} state.
- * @throws Exception
- * If anything goes wrong.
- */
- @Override
- @ManagedMetric(description = "How many workflow runs are currently actually executing.", currencyTimeLimit = 10, metricType = GAUGE, category = "throughput")
- public final int getOperatingCount() throws Exception {
- return operatingCount();
- }
-
- @Override
- @ManagedAttribute(description="Whether to tell a workflow to generate provenance bundles by default.")
- public final void setGenerateProvenance(boolean genProv) {
- state.setGenerateProvenance(genProv);
- }
-
- @Override
- @ManagedAttribute(description="Whether to tell a workflow to generate provenance bundles by default.")
- public final boolean getGenerateProvenance() {
- return state.getGenerateProvenance();
- }
-}
[13/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
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
[06/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/resources/static/jquery-1.8.0.min.js
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/resources/static/jquery-1.8.0.min.js b/taverna-server-webapp/src/main/resources/static/jquery-1.8.0.min.js
new file mode 100644
index 0000000..f121291
--- /dev/null
+++ b/taverna-server-webapp/src/main/resources/static/jquery-1.8.0.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v@1.8.0 jquery.com | jquery.org/license */
+(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(
a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="scri
pt"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bX(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bV.length;while(e--){b=bV[e]+c;if(b in a)return b}return d}function bY(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function bZ(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bY(c)&&(e[f]=p._data(c,"olddisplay",cb(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b$(a,b,c){
var d=bO.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function b_(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bU[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bU[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bU[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bU[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bU[e]+"Width"))||0));return f}function ca(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bP.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+b_(a,b,c||(f?"border":"content"),e)+"px"}function cb(a){if(bR[a])return bR[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createEle
ment)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cz(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cu;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cz(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cz(a,c,d,e,"*",g)),h}function cA(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c
)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cB(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cC(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"succe
ss",data:b}}function cK(){try{return new a.XMLHttpRequest}catch(b){}}function cL(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cT(){return setTimeout(function(){cM=b},0),cM=p.now()}function cU(a,b){p.each(b,function(b,c){var d=(cS[b]||[]).concat(cS["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cV(a,b,c){var d,e=0,f=0,g=cR.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cM||cT(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cM||cT(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.t
weens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cW(k,j.opts.specialEasing);for(;e<g;e++){d=cR[e].call(j,a,k,j.opts);if(d)return d}return cU(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cW(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cX(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bY(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||
"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cb(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cO.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cY(a,b,c,d,e){return new cY.prototype.init(a,b,c,d,e)}function cZ(a,b){var c,d={height:a},e=0;for(;e<4;e+=2-b)c=bU[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d
.width=a),d}function c_(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=r.test("Â ")?/^[\s\xA0]+|[\s\xA0]+$/g:/^\s+|\s+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:fu
nction(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.0",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return
d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)contin
ue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.p
rototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("In
valid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":a.toString().replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:functi
on(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||f.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if
(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete"||e.readyState!=="loading"&&e.addEventListener)setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;
h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){p.isFunction(c)&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callba
cks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return typeof a=="object"?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.n
otifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length||!d)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkO
n:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).c
loneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display
:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/^(?:\{.*\}|\[.*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQu
ery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||++p.uuid:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];
if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")===0&&(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,
c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.shift(),e=p._queueHooks(a,b),f=function(){p.dequeue(a,b)};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),delete e.stop,d.call(a,f,e)),!c.length&&e&&e.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue
:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)(d=p._data(g[h],a+"queueHooks"))&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.pro
p,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)~f.indexOf(" "+b[g]+" ")||(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>-1)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleCla
ss:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.va
l()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;
if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,""+d),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b
,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:
!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selec
tedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,argu
ments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(
".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join(
"\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[
m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,k,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=[].slice.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click")){g=p(this),g.context=this;for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){i={},k=[],g[0]=f;for(d=0;d<q;d++)l=o[d],m=l.selector,i[m]===b&&(i[m]=g.is(m)),i[m]&&k.push(l);k.length&&u.push({elem:f,matches:k})}}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){j=u[d],c.currentTarget=j.elem;for(e=0;e<j.matches.length&&!c.isImmediatePropagationStopped();e++){l=j.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=
l,h=((p.event.special[l.origType]||{}).handle||l.handler).apply(j.elem,r),h!==b&&(c.result=h,h===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&
&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{ready:{setup:p.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventList
ener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStop
ped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(t
his.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simul
ate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(t
his,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown m
ouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bd(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)Z(a,b[e],c,d)}function be(a,b,c,d,e,f){var g,h=$.setFilters[b.toLowerCase()];return h||Z.error(b),(a||!(g=e))&&bd(a||"*",d,g=[],e),g.length>0?h(g,c,f):[]}function bf(a,c,d,e,f){var g,h,i,j,k,l,m,n,p=0,q=f.length,s=L.POS,t=new RegExp("^"+s.source+"(?!"+r+")","i"),u=function(){var a=1,c=arguments.length-2;for(;a<c;a++)arguments[a]===b&&(g[a]=b)};for(;p<q;p++){s.exec(""),a=f[p],j=[],i=0,k=e;while(g=s.exec(a)){n=s.lastIndex=g.index+g[0].length;if(n>i){m=a.slice(i,g.index),i=n,l=[c],B.test(m)&&(k&&(l=k),k=e);if(h=H.test(m))m=m.slice(0,-5).replace(B,"$&*");g.length>1&&g[0]
.replace(t,u),k=be(m,g[1],g[2],l,k,h)}}k?(j=j.concat(k),(m=a.slice(i))&&m!==")"?B.test(m)?bd(m,j,d,e):Z(m,c,d,e?e.concat(k):k):o.apply(d,j)):Z(a,c,d,e)}return q===1?d:Z.uniqueSort(d)}function bg(a,b,c){var d,e,f,g=[],i=0,j=D.exec(a),k=!j.pop()&&!j.pop(),l=k&&a.match(C)||[""],m=$.preFilter,n=$.filter,o=!c&&b!==h;for(;(e=l[i])!=null&&k;i++){g.push(d=[]),o&&(e=" "+e);while(e){k=!1;if(j=B.exec(e))e=e.slice(j[0].length),k=d.push({part:j.pop().replace(A," "),captures:j});for(f in n)(j=L[f].exec(e))&&(!m[f]||(j=m[f](j,b,c)))&&(e=e.slice(j.shift().length),k=d.push({part:f,captures:j}));if(!k)break}}return k||Z.error(a),g}function bh(a,b,e){var f=b.dir,g=m++;return a||(a=function(a){return a===e}),b.first?function(b,c){while(b=b[f])if(b.nodeType===1)return a(b,c)&&b}:function(b,e){var h,i=g+"."+d,j=i+"."+c;while(b=b[f])if(b.nodeType===1){if((h=b[q])===j)return b.sizset;if(typeof h=="string"&&h.indexOf(i)===0){if(b.sizset)return b}else{b[q]=j;if(a(b,e))return b.sizset=!0,b;b.sizset=!1}}}}func
tion bi(a,b){return a?function(c,d){var e=b(c,d);return e&&a(e===!0?c:e,d)}:b}function bj(a,b,c){var d,e,f=0;for(;d=a[f];f++)$.relative[d.part]?e=bh(e,$.relative[d.part],b):(d.captures.push(b,c),e=bi(e,$.filter[d.part].apply(null,d.captures)));return e}function bk(a){return function(b,c){var d,e=0;for(;d=a[e];e++)if(d(b,c))return!0;return!1}}var c,d,e,f,g,h=a.document,i=h.documentElement,j="undefined",k=!1,l=!0,m=0,n=[].slice,o=[].push,q=("sizcache"+Math.random()).replace(".",""),r="[\\x20\\t\\r\\n\\f]",s="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",t=s.replace("w","w#"),u="([*^$|!~]?=)",v="\\["+r+"*("+s+")"+r+"*(?:"+u+r+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+t+")|)|)"+r+"*\\]",w=":("+s+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)",x=":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)",y=r+"*([\\x20\\t\\r\\n\\f>+~])"+r+"*",z="(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|"+v+"|"+w.replace(2,7)+"|[^\\\\(),])+",A=new RegExp("^"+r+"+|
((?:^|[^\\\\])(?:\\\\.)*)"+r+"+$","g"),B=new RegExp("^"+y),C=new RegExp(z+"?(?="+r+"*,|$)","g"),D=new RegExp("^(?:(?!,)(?:(?:^|,)"+r+"*"+z+")*?|"+r+"*(.*?))(\\)|$)"),E=new RegExp(z.slice(19,-6)+"\\x20\\t\\r\\n\\f>+~])+|"+y,"g"),F=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,G=/[\x20\t\r\n\f]*[+~]/,H=/:not\($/,I=/h\d/i,J=/input|select|textarea|button/i,K=/\\(?!\\)/g,L={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),NAME:new RegExp("^\\[name=['\"]?("+s+")['\"]?\\]"),TAG:new RegExp("^("+s.replace("[-","[-\\*")+")"),ATTR:new RegExp("^"+v),PSEUDO:new RegExp("^"+w),CHILD:new RegExp("^:(only|nth|last|first)-child(?:\\("+r+"*(even|odd|(([+-]|)(\\d*)n|)"+r+"*(?:([+-]|)"+r+"*(\\d+)|))"+r+"*\\)|)","i"),POS:new RegExp(x,"ig"),needsContext:new RegExp("^"+r+"*[>+~]|"+x,"i")},M={},N=[],O={},P=[],Q=function(a){return a.sizzleFilter=!0,a},R=function(a){return function(b){return b.nodeName.toLowerCase()==="input"&&b.type===a}},S=function(a){return function(b){var c=b.nodeName.toLowerCase();return
(c==="input"||c==="button")&&b.type===a}},T=function(a){var b=!1,c=h.createElement("div");try{b=a(c)}catch(d){}return c=null,b},U=T(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),V=T(function(a){a.id=q+0,a.innerHTML="<a name='"+q+"'></a><div name='"+q+"'></div>",i.insertBefore(a,i.firstChild);var b=h.getElementsByName&&h.getElementsByName(q).length===2+h.getElementsByName(q+0).length;return g=!h.getElementById(q),i.removeChild(a),b}),W=T(function(a){return a.appendChild(h.createComment("")),a.getElementsByTagName("*").length===0}),X=T(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==j&&a.firstChild.getAttribute("href")==="#"}),Y=T(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||a.getElementsByClassName("e").length===0?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length!=
=1)}),Z=function(a,b,c,d){c=c||[],b=b||h;var e,f,g,i,j=b.nodeType;if(j!==1&&j!==9)return[];if(!a||typeof a!="string")return c;g=ba(b);if(!g&&!d)if(e=F.exec(a))if(i=e[1]){if(j===9){f=b.getElementById(i);if(!f||!f.parentNode)return c;if(f.id===i)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(i))&&bb(b,f)&&f.id===i)return c.push(f),c}else{if(e[2])return o.apply(c,n.call(b.getElementsByTagName(a),0)),c;if((i=e[3])&&Y&&b.getElementsByClassName)return o.apply(c,n.call(b.getElementsByClassName(i),0)),c}return bm(a,b,c,d,g)},$=Z.selectors={cacheLength:50,match:L,order:["ID","TAG"],attrHandle:{},createPseudo:Q,find:{ID:g?function(a,b,c){if(typeof b.getElementById!==j&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==j&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==j&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:W?function(a,b){if(typeof b.getElementsByTagName!==j)retur
n b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(K,""),a[3]=(a[4]||a[5]||"").replace(K,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||Z.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&Z.error(a[0]),a},PSEUDO:function(a){var b,c=a[4];return L.CHILD.test(a[0])?null:(c&&(b=D.exec(c))&&b.pop()&&(a[0]=a[0].slice(0,b[0].length-c.length-1),c=b[0].slice(0,-1)),a.splice(2,3,c||a[3]),a)}},filter:{ID:g?function(a){return a=a.replace(K,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(K,""),function(b){var c=typeof b.getAttributeNode!==j
&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(K,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=M[a];return b||(b=M[a]=new RegExp("(^|"+r+")"+a+"("+r+"|$)"),N.push(a),N.length>$.cacheLength&&delete M[N.shift()]),function(a){return b.test(a.className||typeof a.getAttribute!==j&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return b?function(d){var e=Z.attr(d,a),f=e+"";if(e==null)return b==="!=";switch(b){case"=":return f===c;case"!=":return f!==c;case"^=":return c&&f.indexOf(c)===0;case"*=":return c&&f.indexOf(c)>-1;case"$=":return c&&f.substr(f.length-c.length)===c;case"~=":return(" "+f+" ").indexOf(c)>-1;case"|=":return f===c||f.substr(0,c.length+1)===c+"-"}}:function(b){return Z.attr(b,a)!=null}},CHILD:function(a,b,c,d){if(a==="nth"){var e=m++;return function(a){var b,f,g=0,h=a;if(c===1&&d===0)return!0;b=a.parentNode;if(b&&(b[q]!==e||!a.sizset)){for(
h=b.firstChild;h;h=h.nextSibling)if(h.nodeType===1){h.sizset=++g;if(h===a)break}b[q]=e}return f=a.sizset-d,c===0?f===0:f%c===0&&f/c>=0}}return function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b,c,d){var e=$.pseudos[a]||$.pseudos[a.toLowerCase()];return e||Z.error("unsupported pseudo: "+a),e.sizzleFilter?e(b,c,d):e}},pseudos:{not:Q(function(a,b,c){var d=bl(a.replace(A,"$1"),b,c);return function(a){return!d(a)}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!$.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.no
deType)===3||b===4)return!1;a=a.nextSibling}return!0},contains:Q(function(a){return function(b){return(b.textContent||b.innerText||bc(b)).indexOf(a)>-1}}),has:Q(function(a){return function(b){return Z(a,b).length>0}}),header:function(a){return I.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:R("radio"),checkbox:R("checkbox"),file:R("file"),password:R("password"),image:R("image"),submit:S("submit"),reset:S("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return J.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b,c){return c?a.slice(1):[a[0]]},last:function(a,b,c){var d=a.pop();return c?a:[d]},even:function(
a,b,c){var d=[],e=c?1:0,f=a.length;for(;e<f;e=e+2)d.push(a[e]);return d},odd:function(a,b,c){var d=[],e=c?0:1,f=a.length;for(;e<f;e=e+2)d.push(a[e]);return d},lt:function(a,b,c){return c?a.slice(+b):a.slice(0,+b)},gt:function(a,b,c){return c?a.slice(0,+b+1):a.slice(+b+1)},eq:function(a,b,c){var d=a.splice(+b,1);return c?a:d}}};$.setFilters.nth=$.setFilters.eq,$.filters=$.pseudos,X||($.attrHandle={href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}}),V&&($.order.push("NAME"),$.find.NAME=function(a,b){if(typeof b.getElementsByName!==j)return b.getElementsByName(a)}),Y&&($.order.splice(1,0,"CLASS"),$.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!==j&&!c)return b.getElementsByClassName(a)});try{n.call(i.childNodes,0)[0].nodeType}catch(_){n=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}var ba=Z.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},bb=Z.contains=i.compa
reDocumentPosition?function(a,b){return!!(a.compareDocumentPosition(b)&16)}:i.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc=Z.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=bc(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=bc(b);return c};Z.attr=function(a,b){var c,d=ba(a);return d||(b=b.toLowerCase()),$.attrHandle[b]?$.attrHandle[b](a):U||d?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},Z.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},[0,0].sort(function(){return l=0}),i.compareDocumentPosition?e=function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPos
ition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:(e=function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],g=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return f(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)g.unshift(j),j=j.parentNode;c=e.length,d=g.length;for(var l=0;l<c&&l<d;l++)if(e[l]!==g[l])return f(e[l],g[l]);return l===c?f(a,g[l],-1):f(e[l],b,1)},f=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),Z.uniqueSort=function(a){var b,c=1;if(e){k=l,a.sort(e);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1)}return a};var bl=Z.compile=function(a,b,c){var d,e,f,g=O[a];if(g&&g.context===b)return g;e=bg(a,b,c);for(f=0;d=e[f];f++)e[f]=bj(d,b,c);return g=O[a]=bk(e),g.context=b,g.runs=g.dirruns=0,P.push(a),P.length>$.cacheLength&&delete O[P.shift()],g};Z.matches=function(a,b){return Z(a,null,null,b)},Z.matchesSel
ector=function(a,b){return Z(b,null,null,[a]).length>0};var bm=function(a,b,e,f,g){a=a.replace(A,"$1");var h,i,j,k,l,m,p,q,r,s=a.match(C),t=a.match(E),u=b.nodeType;if(L.POS.test(a))return bf(a,b,e,f,s);if(f)h=n.call(f,0);else if(s&&s.length===1){if(t.length>1&&u===9&&!g&&(s=L.ID.exec(t[0]))){b=$.find.ID(s[1],b,g)[0];if(!b)return e;a=a.slice(t.shift().length)}q=(s=G.exec(t[0]))&&!s.index&&b.parentNode||b,r=t.pop(),m=r.split(":not")[0];for(j=0,k=$.order.length;j<k;j++){p=$.order[j];if(s=L[p].exec(m)){h=$.find[p]((s[1]||"").replace(K,""),q,g);if(h==null)continue;m===r&&(a=a.slice(0,a.length-r.length)+m.replace(L[p],""),a||o.apply(e,n.call(h,0)));break}}}if(a){i=bl(a,b,g),d=i.dirruns++,h==null&&(h=$.find.TAG("*",G.test(a)&&b.parentNode||b));for(j=0;l=h[j];j++)c=i.runs++,i(l,b)&&e.push(l)}return e};h.querySelectorAll&&function(){var a,b=bm,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[],f=[":active"],g=i.matchesSelector||i.mozMatchesSelector||i.webkitMatchesSelector||i.o
MatchesSelector||i.msMatchesSelector;T(function(a){a.innerHTML="<select><option selected></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+r+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),T(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+r+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=e.length&&new RegExp(e.join("|")),bm=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a)))if(d.nodeType===9)try{return o.apply(f,n.call(d.querySelectorAll(a),0)),f}catch(i){}else if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){var j=d.getAttribute("id"),k=j||q,l=G.test(a)&&d.parentNode||d;j?k=k.replace(c,"\\$&"):d.setAttribute("id",k);try{return o.apply(f,n.call(l.querySelectorAll(a.replace(C,"[id='"+k+"'] $&")),0)),f}catch(i){}finally{j||d.removeAttribute("id")}}return b
(a,d,f,g,h)},g&&(T(function(b){a=g.call(b,"div");try{g.call(b,"[test!='']:sizzle"),f.push($.match.PSEUDO)}catch(c){}}),f=new RegExp(f.join("|")),Z.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!ba(b)&&!f.test(c)&&(!e||!e.test(c)))try{var h=g.call(b,c);if(h||a||b.document&&b.document.nodeType!==11)return h}catch(i){}return Z(c,null,null,[b]).length>0})}(),Z.attr=p.attr,p.find=Z,p.expr=Z.selectors,p.expr[":"]=p.expr.pseudos,p.unique=Z.uniqueSort,p.text=Z.getText,p.isXMLDoc=Z.isXML,p.contains=Z.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice
(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.
merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.
map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new Reg
Exp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[
0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(
a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nod
eType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function()
{p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=(c[0]||c).ownerDocument||c[0]||c,typeof c.createDocumentFragment=="undefined"&&(c=e),a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p
.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return
d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=0,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(g=b===e&&bA;(h=a[s])!=null;s++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{g=g||bk(b),l=l||g.appendChild(b.createElement("div")),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(f=n.length-1;f>=0;--f)p.nodeName(n[f],"tbody")&&!n[f].childNodes.length&&n[f].parentNode.removeChild(n[f])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l=g.lastChild}h.nodeType?t.push(h):t=p.merge(t,h)}l&&(g.removeChild(l),h=l=g=null);if(!p.support.appendChecked)for(s=0;(h=t[s])!=null;s++)p.nodeName(h,"input")?bG(h):type
of h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(s=0;(h=t[s])!=null;s++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[s+1,0].concat(r)),s+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(ms
ie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^margin/,bO=new RegExp("^("+q+")(.*)$","i"),bP=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bQ=new RegExp("^([-+])=("+q+")","i"),bR={},bS={position:"absolute",visibility:"hidden",display:"block"},bT={letterSpacing:0,fontWeight:400,lineHeight:1},bU=["Top","Right","Bottom","Left"],bV=["Webkit","O","Moz","ms"],bW=p.fn.toggle;p.fn.extend({css:funct
ion(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return bZ(this,!0)},hide:function(){return bZ(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bW.apply(this,arguments):this.each(function(){(c?a:bY(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bX(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bQ.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&is
NaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bX(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bT&&(f=bT[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(a,b){var c,d,e,f,g=getComputedStyle(a,null),h=a.style;return g&&(c=g[b],c===""&&!p.contains(a.ownerDocument.documentElement,a)&&(c=p.style(a,b)),bP.test(c)&&bN.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=c,c=g.width,h.width=d,h.minWidth=e,h.maxWidth=f)),c}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bP.test(e)&&!bM.te
st(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0||bH(a,"display")!=="none"?ca(a,b,d):p.swap(a,bS,function(){return ca(a,b,d)})},set:function(a,c,d){return b$(a,c,d?b_(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarg
inRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bP.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bU[d]+b]=e[d]||e[d-2]||e[0];return f}},bN.test(a)||(p.cssHooks[a+b].set=b$)});var cc=/%20/g,cd=/\[\]$/,ce=/\r?\n/g,cf=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,cg=/^(?:select|t
extarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||cg.test(this.nodeName)||cf.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(ce,"\r\n")}}):{name:b.name,value:c.replace(ce,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ch(d,a[d],c,f);return e.join("&").replace(cc,"+")};var ci,cj,ck=/#.*$/,cl=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cm=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,cn=/^(?:GET|HEAD)$/
,co=/^\/\//,cp=/\?/,cq=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cr=/([?&])_=[^&]*/,cs=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,ct=p.fn.load,cu={},cv={},cw=["*/"]+["*"];try{ci=f.href}catch(cx){ci=e.createElement("a"),ci.href="",ci=ci.href}cj=cs.exec(ci.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&ct)return ct.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cq,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({ty
pe:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cA(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cA(a,b),a},ajaxSettings:{url:ci,isLocal:cm.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cw},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cy(cu),ajaxTransport:cy(cv),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cB(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHea
der("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cC(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=""+(c||y),k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cl.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return
c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(ck,"").replace(co,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=cs.exec(l.url.toLowerCase()),l.crossDomain=!(!i||i[1]==cj[1]&&i[2]==cj[2]&&(i[3]||(i[1]==="http:"?80:443))==(cj[3]||(cj[1]==="http:"?80:443)))),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cz(cu,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!cn.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cp.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cr,"$1_="+z);l.url=A+(A===
l.url?(cp.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cw+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cz(cv,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cD=[],cE=/\?/,cF=/(=)\?(?=&|$)|\?\?/,cG=p.now();p.ajaxSetup({j
sonp:"callback",jsonpCallback:function(){var a=cD.pop()||p.expando+"_"+cG++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cF.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cF.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cF,"$1"+f):m?c.data=i.replace(cF,"$1"+f):k&&(c.url+=(cE.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cD.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":fu
nction(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cH,cI=a.ActiveXObject?function(){for(var a in cH)cH[a](0,1)}:!1,cJ=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cK()||cL()}:cK,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){v
ar d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cI&&delete cH[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cJ,cI&&(cH||(cH={},p(a).unload(cI)),cH[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});
var cM,cN,cO=/^(?:toggle|show|hide)$/,cP=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cQ=/queueHooks$/,cR=[cX],cS={"*":[function(a,b){var c,d,e,f=this.createTween(a,b),g=cP.exec(b),h=f.cur(),i=+h||0,j=1;if(g){c=+g[2],d=g[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&i){i=p.css(f.elem,a,!0)||c||1;do e=j=j||".5",i=i/j,p.style(f.elem,a,i+d),j=f.cur()/h;while(j!==1&&j!==e)}f.unit=d,f.start=i,f.end=g[1]?i+(g[1]+1)*c:c}return f}]};p.Animation=p.extend(cV,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cS[c]=cS[c]||[],cS[c].unshift(b)},prefilter:function(a,b){b?cR.unshift(a):cR.push(a)}}),p.Tween=cY,cY.prototype={constructor:cY,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cY.propHooks[this.prop];return a&&a.get?a.get(this):cY.propHooks._default.get(this)},run:function(a){var b,c=cY.prop
Hooks[this.prop];return this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration),this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cY.propHooks._default.set(this),this}},cY.prototype.init.prototype=cY.prototype,cY.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cY.propHooks.scrollTop=cY.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,argum
ents):this.animate(cZ(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bY).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cV(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cQ.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:cZ("show"),slideUp:cZ("hide"),slideToggle:cZ("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.a
nimate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration
<TRUNCATED>
[32/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java b/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java
deleted file mode 100644
index ff14986..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegate.java
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static java.lang.String.format;
-import static java.util.Arrays.fill;
-import static java.util.UUID.randomUUID;
-import static org.taverna.server.master.defaults.Default.CERTIFICATE_FIELD_NAMES;
-import static org.taverna.server.master.defaults.Default.CERTIFICATE_TYPE;
-import static org.taverna.server.master.defaults.Default.CREDENTIAL_FILE_SIZE_LIMIT;
-import static org.taverna.server.master.identity.WorkflowInternalAuthProvider.PREFIX;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.rmi.RemoteException;
-import java.security.GeneralSecurityException;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-import javax.security.auth.x500.X500Principal;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.UriBuilder;
-import javax.xml.ws.handler.MessageContext;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContext;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteSecurityContext;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.InvalidCredentialException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Implementation of a security context.
- *
- * @author Donal Fellows
- */
-public abstract class SecurityContextDelegate implements TavernaSecurityContext {
- Log log = LogFactory.getLog("Taverna.Server.Worker");
- private final UsernamePrincipal owner;
- private final List<Credential> credentials = new ArrayList<>();
- private final List<Trust> trusted = new ArrayList<>();
- private final RemoteRunDelegate run;
- private final Object lock = new Object();
- final SecurityContextFactory factory;
-
- private transient Keystore keystore;
- private transient Map<URI, String> uriToAliasMap;
-
- /**
- * Initialise the context delegate.
- *
- * @param run
- * What workflow run is this for?
- * @param owner
- * Who owns the workflow run?
- * @param factory
- * What class built this object?
- */
- protected SecurityContextDelegate(RemoteRunDelegate run,
- UsernamePrincipal owner, SecurityContextFactory factory) {
- this.run = run;
- this.owner = owner;
- this.factory = factory;
- }
-
- @Override
- public SecurityContextFactory getFactory() {
- return factory;
- }
-
- @Override
- public UsernamePrincipal getOwner() {
- return owner;
- }
-
- @Override
- public Credential[] getCredentials() {
- synchronized (lock) {
- return credentials.toArray(new Credential[credentials.size()]);
- }
- }
-
- /**
- * Get the human-readable name of a principal.
- *
- * @param principal
- * The principal being decoded.
- * @return A name.
- */
- protected final String getPrincipalName(X500Principal principal) {
- return factory.x500Utils.getName(principal, CERTIFICATE_FIELD_NAMES);
- }
-
- /**
- * Cause the current state to be flushed to the database.
- */
- protected final void flushToDB() {
- factory.db.flushToDisk(run);
- }
-
- @Override
- public void addCredential(Credential toAdd) {
- synchronized (lock) {
- int idx = credentials.indexOf(toAdd);
- if (idx != -1)
- credentials.set(idx, toAdd);
- else
- credentials.add(toAdd);
- flushToDB();
- }
- }
-
- @Override
- public void deleteCredential(Credential toDelete) {
- synchronized (lock) {
- credentials.remove(toDelete);
- flushToDB();
- }
- }
-
- @Override
- public Trust[] getTrusted() {
- synchronized (lock) {
- return trusted.toArray(new Trust[trusted.size()]);
- }
- }
-
- @Override
- public void addTrusted(Trust toAdd) {
- synchronized (lock) {
- int idx = trusted.indexOf(toAdd);
- if (idx != -1)
- trusted.set(idx, toAdd);
- else
- trusted.add(toAdd);
- flushToDB();
- }
- }
-
- @Override
- public void deleteTrusted(Trust toDelete) {
- synchronized (lock) {
- trusted.remove(toDelete);
- flushToDB();
- }
- }
-
- @Override
- public abstract void validateCredential(Credential c)
- throws InvalidCredentialException;
-
- @Override
- public void validateTrusted(Trust t) throws InvalidCredentialException {
- InputStream contentsAsStream;
- if (t.certificateBytes != null && t.certificateBytes.length > 0) {
- contentsAsStream = new ByteArrayInputStream(t.certificateBytes);
- t.certificateFile = null;
- } else if (t.certificateFile == null
- || t.certificateFile.trim().isEmpty())
- throw new InvalidCredentialException(
- "absent or empty certificateFile");
- else {
- contentsAsStream = contents(t.certificateFile);
- t.certificateBytes = null;
- }
- t.serverName = null;
- if (t.fileType == null || t.fileType.trim().isEmpty())
- t.fileType = CERTIFICATE_TYPE;
- t.fileType = t.fileType.trim();
- try {
- t.loadedCertificates = CertificateFactory.getInstance(t.fileType)
- .generateCertificates(contentsAsStream);
- t.serverName = new ArrayList<>(t.loadedCertificates.size());
- for (Certificate c : t.loadedCertificates)
- t.serverName.add(getPrincipalName(((X509Certificate) c)
- .getSubjectX500Principal()));
- } catch (CertificateException e) {
- throw new InvalidCredentialException(e);
- } catch (ClassCastException e) {
- // Do nothing; truncates the list of server names
- }
- }
-
- @Override
- public void initializeSecurityFromContext(SecurityContext securityContext)
- throws Exception {
- // This is how to get the info from Spring Security
- Authentication auth = securityContext.getAuthentication();
- if (auth == null)
- return;
- auth.getPrincipal();
- // do nothing else in this implementation
- }
-
- @Override
- public void initializeSecurityFromSOAPContext(MessageContext context) {
- // do nothing in this implementation
- }
-
- @Override
- public void initializeSecurityFromRESTContext(HttpHeaders context) {
- // do nothing in this implementation
- }
-
- private UriBuilder getUB() {
- return factory.uriSource.getRunUriBuilder(run);
- }
-
- private RunDatabaseDAO getDAO() {
- return ((RunDatabase) factory.db).dao;
- }
-
- @Nullable
- private List<X509Certificate> getCerts(URI uri) throws IOException,
- GeneralSecurityException {
- return factory.certFetcher.getTrustsForURI(uri);
- }
-
- private void installLocalPasswordCredential(List<Credential> credentials,
- List<Trust> trusts) throws InvalidCredentialException, IOException,
- GeneralSecurityException {
- Credential.Password pw = new Credential.Password();
- pw.id = "run:self";
- pw.username = PREFIX + run.id;
- pw.password = getDAO().getSecurityToken(run.id);
- UriBuilder ub = getUB().segment("").fragment(factory.httpRealm);
- pw.serviceURI = ub.build();
- validateCredential(pw);
- log.info("issuing self-referential credential for " + pw.serviceURI);
- credentials.add(pw);
- List<X509Certificate> myCerts = getCerts(pw.serviceURI);
- if (myCerts != null && myCerts.size() > 0) {
- Trust t = new Trust();
- t.loadedCertificates = getCerts(pw.serviceURI);
- trusts.add(t);
- }
- }
-
- /**
- * Builds and transfers a keystore with suitable credentials to the back-end
- * workflow execution engine.
- *
- * @throws GeneralSecurityException
- * If the manipulation of the keystore, keys or certificates
- * fails.
- * @throws IOException
- * If there are problems building the data (should not happen).
- * @throws RemoteException
- * If the conveyancing fails.
- */
- @Override
- public final void conveySecurity() throws GeneralSecurityException,
- IOException, ImplementationException {
- RemoteSecurityContext rc = run.run.getSecurityContext();
-
- List<Trust> trusted = new ArrayList<>(this.trusted);
- this.trusted.clear();
- List<Credential> credentials = new ArrayList<>(this.credentials);
- this.credentials.clear();
-
- try {
- installLocalPasswordCredential(credentials, trusted);
- } catch (Exception e) {
- log.warn("failed to construct local credential: "
- + "interaction service will fail", e);
- }
-
- char[] password = null;
- try {
- password = generateNewPassword();
-
- log.info("constructing merged keystore");
- Truststore truststore = new Truststore(password);
- Keystore keystore = new Keystore(password);
- Map<URI, String> uriToAliasMap = new HashMap<>();
- int trustedCount = 0, keyCount = 0;
-
- synchronized (lock) {
- try {
- for (Trust t : trusted) {
- if (t == null || t.loadedCertificates == null)
- continue;
- for (Certificate cert : t.loadedCertificates)
- if (cert != null) {
- truststore.addCertificate(cert);
- trustedCount++;
- }
- }
-
- this.uriToAliasMap = uriToAliasMap;
- this.keystore = keystore;
- for (Credential c : credentials) {
- addCredentialToKeystore(c);
- keyCount++;
- }
- } finally {
- this.uriToAliasMap = null;
- this.keystore = null;
- credentials.clear();
- trusted.clear();
- flushToDB();
- }
- }
-
- byte[] trustbytes = null, keybytes = null;
- try {
- trustbytes = truststore.serialize();
- keybytes = keystore.serialize();
-
- // Now we've built the security information, ship it off...
-
- log.info("transfering merged truststore with " + trustedCount
- + " entries");
- rc.setTruststore(trustbytes);
-
- log.info("transfering merged keystore with " + keyCount
- + " entries");
- rc.setKeystore(keybytes);
- } finally {
- if (trustbytes != null)
- fill(trustbytes, (byte) 0);
- if (keybytes != null)
- fill(keybytes, (byte) 0);
- }
- rc.setPassword(password);
-
- log.info("transferring serviceURL->alias map with "
- + uriToAliasMap.size() + " entries");
- rc.setUriToAliasMap(uriToAliasMap);
- } finally {
- if (password != null)
- fill(password, ' ');
- }
-
- synchronized (lock) {
- conveyExtraSecuritySettings(rc);
- }
- }
-
- /**
- * Hook that allows additional information to be conveyed to the remote run.
- *
- * @param remoteSecurityContext
- * The remote resource that information would be passed to.
- * @throws IOException
- * If anything goes wrong with the communication.
- */
- protected void conveyExtraSecuritySettings(
- RemoteSecurityContext remoteSecurityContext) throws IOException {
- // Does nothing by default; overrideable
- }
-
- /**
- * @return A new password with a reasonable level of randomness.
- */
- protected final char[] generateNewPassword() {
- return randomUUID().toString().toCharArray();
- }
-
- /**
- * Adds a credential to the current keystore.
- *
- * @param alias
- * The alias to create within the keystore.
- * @param c
- * The key-pair.
- * @throws KeyStoreException
- */
- protected final void addKeypairToKeystore(String alias, Credential c)
- throws KeyStoreException {
- if (c.loadedKey == null)
- throw new KeyStoreException("critical: credential was not verified");
- if (uriToAliasMap.containsKey(c.serviceURI))
- log.warn("duplicate URI in alias mapping: " + c.serviceURI);
- keystore.addKey(alias, c.loadedKey, c.loadedTrustChain);
- uriToAliasMap.put(c.serviceURI, alias);
- }
-
- /**
- * Adds a credential to the current keystore.
- *
- * @param c
- * The credential to add.
- * @throws KeyStoreException
- */
- public abstract void addCredentialToKeystore(Credential c)
- throws KeyStoreException;
-
- /**
- * Read a file up to {@value #FILE_SIZE_LIMIT}kB in size.
- *
- * @param name
- * The path name of the file, relative to the context run's
- * working directory.
- * @return A stream of the file's contents.
- * @throws InvalidCredentialException
- * If anything goes wrong.
- */
- final InputStream contents(String name) throws InvalidCredentialException {
- try {
- File f = (File) factory.fileUtils.getDirEntry(run, name);
- long size = f.getSize();
- if (size > CREDENTIAL_FILE_SIZE_LIMIT * 1024)
- throw new InvalidCredentialException(CREDENTIAL_FILE_SIZE_LIMIT
- + "kB limit hit");
- return new ByteArrayInputStream(f.getContents(0, (int) size));
- } catch (NoDirectoryEntryException | FilesystemAccessException e) {
- throw new InvalidCredentialException(e);
- } catch (ClassCastException e) {
- throw new InvalidCredentialException("not a file", e);
- }
- }
-
- @Override
- public Set<String> getPermittedDestroyers() {
- return run.getDestroyers();
- }
-
- @Override
- public void setPermittedDestroyers(Set<String> destroyers) {
- run.setDestroyers(destroyers);
- }
-
- @Override
- public Set<String> getPermittedUpdaters() {
- return run.getWriters();
- }
-
- @Override
- public void setPermittedUpdaters(Set<String> updaters) {
- run.setWriters(updaters);
- }
-
- @Override
- public Set<String> getPermittedReaders() {
- return run.getReaders();
- }
-
- @Override
- public void setPermittedReaders(Set<String> readers) {
- run.setReaders(readers);
- }
-
- /**
- * Reinstall the credentials and the trust extracted from serialization to
- * the database.
- *
- * @param credentials
- * The credentials to reinstall.
- * @param trust
- * The trusted certificates to reinstall.
- */
- void setCredentialsAndTrust(Credential[] credentials, Trust[] trust) {
- synchronized (lock) {
- this.credentials.clear();
- if (credentials != null)
- for (Credential c : credentials)
- try {
- validateCredential(c);
- this.credentials.add(c);
- } catch (InvalidCredentialException e) {
- log.warn("failed to revalidate credential: " + c, e);
- }
- this.trusted.clear();
- if (trust != null)
- for (Trust t : trust)
- try {
- validateTrusted(t);
- this.trusted.add(t);
- } catch (InvalidCredentialException e) {
- log.warn("failed to revalidate trust assertion: " + t,
- e);
- }
- }
- }
-
- static class SecurityStore {
- private KeyStore ks;
- private char[] password;
-
- SecurityStore(char[] password) throws GeneralSecurityException {
- this.password = password.clone();
- ks = KeyStore.getInstance("UBER", "BC");
- try {
- ks.load(null, this.password);
- } catch (IOException e) {
- throw new GeneralSecurityException(
- "problem initializing blank truststore", e);
- }
- }
-
- final synchronized void setCertificate(String alias, Certificate c)
- throws KeyStoreException {
- if (ks == null)
- throw new IllegalStateException("store already written");
- ks.setCertificateEntry(alias, c);
- }
-
- final synchronized void setKey(String alias, Key key, Certificate[] trustChain)
- throws KeyStoreException {
- if (ks == null)
- throw new IllegalStateException("store already written");
- ks.setKeyEntry(alias, key, password, trustChain);
- }
-
- final synchronized byte[] serialize(boolean logIt)
- throws GeneralSecurityException {
- if (ks == null)
- throw new IllegalStateException("store already written");
- try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
- ks.store(stream, password);
- if (logIt)
- LogFactory.getLog("Taverna.Server.Worker").debug(
- "serialized UBER/BC truststore (size: " + ks.size()
- + ") with password \""
- + new String(password) + "\"");
- return stream.toByteArray();
- } catch (IOException e) {
- throw new GeneralSecurityException(
- "problem serializing keystore", e);
- } finally {
- ks = null;
- fill(password, ' ');
- }
- }
-
- @Override
- protected final void finalize() {
- fill(password, ' ');
- ks = null;
- }
- }
-
- /**
- * A trust store that can only be added to or serialized. Only trusted
- * certificates can be placed in it.
- *
- * @author Donal Fellows
- */
- class Truststore extends SecurityStore {
- Truststore(char[] password) throws GeneralSecurityException {
- super(password);
- }
-
- /**
- * Add a trusted certificate to the truststore. No certificates can be
- * added after the truststore is serialized.
- *
- * @param cert
- * The certificate (typically belonging to a root CA) to add.
- * @throws KeyStoreException
- * If anything goes wrong.
- */
- public void addCertificate(Certificate cert) throws KeyStoreException {
- X509Certificate c = (X509Certificate) cert;
- String alias = format("trustedcert#%s#%s#%s",
- getPrincipalName(c.getSubjectX500Principal()),
- getPrincipalName(c.getIssuerX500Principal()),
- factory.x500Utils.getSerial(c));
- setCertificate(alias, c);
- if (log.isDebugEnabled() && factory.logSecurityDetails)
- log.debug("added cert with alias \"" + alias + "\" of type "
- + c.getClass().getCanonicalName());
- }
-
- /**
- * Get the byte serialization of this truststore. This can only be
- * fetched exactly once.
- *
- * @return The serialization.
- * @throws GeneralSecurityException
- * If anything goes wrong.
- */
- public byte[] serialize() throws GeneralSecurityException {
- return serialize(log.isDebugEnabled() && factory.logSecurityDetails);
- }
- }
-
- /**
- * A key store that can only be added to or serialized. Only keys can be
- * placed in it.
- *
- * @author Donal Fellows
- */
- class Keystore extends SecurityStore {
- Keystore(char[] password) throws GeneralSecurityException {
- super(password);
- }
-
- /**
- * Add a key to the keystore. No keys can be added after the keystore is
- * serialized.
- *
- * @param alias
- * The alias of the key.
- * @param key
- * The secret/private key to add.
- * @param trustChain
- * The trusted certificate chain of the key. Should be
- * <tt>null</tt> for secret keys.
- * @throws KeyStoreException
- * If anything goes wrong.
- */
- public void addKey(String alias, Key key, Certificate[] trustChain)
- throws KeyStoreException {
- setKey(alias, key, trustChain);
- if (log.isDebugEnabled() && factory.logSecurityDetails)
- log.debug("added key with alias \"" + alias + "\" of type "
- + key.getClass().getCanonicalName());
- }
-
- /**
- * Get the byte serialization of this keystore. This can only be fetched
- * exactly once.
- *
- * @return The serialization.
- * @throws GeneralSecurityException
- * If anything goes wrong.
- */
- public byte[] serialize() throws GeneralSecurityException {
- return serialize(log.isDebugEnabled() && factory.logSecurityDetails);
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java b/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java
deleted file mode 100644
index d36d2da..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextDelegateImpl.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2010-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static java.lang.String.format;
-import static javax.xml.ws.handler.MessageContext.HTTP_REQUEST_HEADERS;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.rmi.RemoteException;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.List;
-import java.util.Map;
-
-import javax.crypto.spec.SecretKeySpec;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.xml.ws.handler.MessageContext;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.taverna.server.localworker.remote.RemoteSecurityContext;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.exceptions.InvalidCredentialException;
-import org.taverna.server.master.utils.UsernamePrincipal;
-import org.taverna.server.master.utils.X500Utils;
-
-/**
- * Factoring out of the part of the security context handling that actually
- * deals with the different types of credentials.
- *
- * @author Donal Fellows
- */
-class SecurityContextDelegateImpl extends SecurityContextDelegate {
- private static final char USERNAME_PASSWORD_SEPARATOR = '\u0000';
- private static final String USERNAME_PASSWORD_KEY_ALGORITHM = "DUMMY";
- /** What passwords are encoded as. */
- private static final Charset UTF8 = Charset.forName("UTF-8");
-
- private X500Utils x500Utils;
-
- /**
- * Initialise the context delegate.
- *
- * @param run
- * What workflow run is this for?
- * @param owner
- * Who owns the workflow run?
- * @param factory
- * What class built this object?
- */
- protected SecurityContextDelegateImpl(RemoteRunDelegate run,
- UsernamePrincipal owner, SecurityContextFactory factory) {
- super(run, owner, factory);
- this.x500Utils = factory.x500Utils;
- }
-
- @Override
- public void validateCredential(Credential c)
- throws InvalidCredentialException {
- try {
- if (c instanceof Credential.Password)
- validatePasswordCredential((Credential.Password) c);
- else if (c instanceof Credential.KeyPair)
- validateKeyCredential((Credential.KeyPair) c);
- else
- throw new InvalidCredentialException("unknown credential type");
- } catch (InvalidCredentialException e) {
- throw e;
- } catch (Exception e) {
- throw new InvalidCredentialException(e);
- }
- }
-
- @Override
- public void addCredentialToKeystore(Credential c) throws KeyStoreException {
- try {
- if (c instanceof Credential.Password)
- addUserPassToKeystore((Credential.Password) c);
- else if (c instanceof Credential.KeyPair)
- addKeypairToKeystore((Credential.KeyPair) c);
- else
- throw new KeyStoreException("unknown credential type");
- } catch (KeyStoreException e) {
- throw e;
- } catch (Exception e) {
- throw new KeyStoreException(e);
- }
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- /**
- * Tests whether the given username+password credential descriptor is valid.
- * If it is invalid, an exception will be thrown describing what the problem
- * is. Validation mainly consists of listing what the username is.
- *
- * @param passwordDescriptor
- * The credential descriptor to validate.
- * @throws InvalidCredentialException
- * If the username is empty. NB: the password may be empty!
- * That's legal (if unwise).
- */
- protected void validatePasswordCredential(
- Credential.Password passwordDescriptor)
- throws InvalidCredentialException {
- if (passwordDescriptor.username == null
- || passwordDescriptor.username.trim().isEmpty())
- throw new InvalidCredentialException("absent or empty username");
- if (passwordDescriptor.serviceURI == null)
- throw new InvalidCredentialException("absent service URI");
- String keyToSave = passwordDescriptor.username
- + USERNAME_PASSWORD_SEPARATOR + passwordDescriptor.password;
- passwordDescriptor.loadedKey = encodeKey(keyToSave);
- passwordDescriptor.loadedTrustChain = null;
- }
-
- private static Key encodeKey(String key) {
- return new SecretKeySpec(key.getBytes(UTF8),
- USERNAME_PASSWORD_KEY_ALGORITHM);
- }
-
- /**
- * Adds a username/password credential pair to the current keystore.
- *
- * @param userpassCredential
- * The username and password.
- * @throws KeyStoreException
- */
- protected void addUserPassToKeystore(Credential.Password userpassCredential)
- throws KeyStoreException {
- String alias = format("password#%s",
- userpassCredential.serviceURI.toASCIIString());
- addKeypairToKeystore(alias, userpassCredential);
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- /**
- * Tests whether the given key-pair credential descriptor is valid. If it is
- * invalid, an exception will be thrown describing what the problem is.
- *
- * @param keypairDescriptor
- * The descriptor to validate.
- * @throws InvalidCredentialException
- * If the descriptor is invalid
- * @throws KeyStoreException
- * If we don't understand the keystore type or the contents of
- * the keystore
- * @throws NoSuchAlgorithmException
- * If the keystore is of a known type but we can't comprehend
- * its security
- * @throws CertificateException
- * If the keystore does not include enough information about the
- * trust chain of the keypair
- * @throws UnrecoverableKeyException
- * If we can't get the key out of the keystore
- * @throws IOException
- * If we can't read the keystore for prosaic reasons (e.g., file
- * absent)
- */
- protected void validateKeyCredential(Credential.KeyPair keypairDescriptor)
- throws InvalidCredentialException, KeyStoreException,
- NoSuchAlgorithmException, CertificateException, IOException,
- UnrecoverableKeyException {
- if (keypairDescriptor.credentialName == null
- || keypairDescriptor.credentialName.trim().isEmpty())
- throw new InvalidCredentialException(
- "absent or empty credentialName");
-
- InputStream contentsAsStream;
- if (keypairDescriptor.credentialBytes != null
- && keypairDescriptor.credentialBytes.length > 0) {
- contentsAsStream = new ByteArrayInputStream(
- keypairDescriptor.credentialBytes);
- keypairDescriptor.credentialFile = null;
- } else if (keypairDescriptor.credentialFile == null
- || keypairDescriptor.credentialFile.trim().isEmpty())
- throw new InvalidCredentialException(
- "absent or empty credentialFile");
- else {
- contentsAsStream = contents(keypairDescriptor.credentialFile);
- keypairDescriptor.credentialBytes = new byte[0];
- }
- if (keypairDescriptor.fileType == null
- || keypairDescriptor.fileType.trim().isEmpty())
- keypairDescriptor.fileType = KeyStore.getDefaultType();
- keypairDescriptor.fileType = keypairDescriptor.fileType.trim();
-
- KeyStore ks = KeyStore.getInstance(keypairDescriptor.fileType);
- char[] password = keypairDescriptor.unlockPassword.toCharArray();
- ks.load(contentsAsStream, password);
-
- try {
- keypairDescriptor.loadedKey = ks.getKey(
- keypairDescriptor.credentialName, password);
- } catch (UnrecoverableKeyException ignored) {
- keypairDescriptor.loadedKey = ks.getKey(
- keypairDescriptor.credentialName, new char[0]);
- }
- if (keypairDescriptor.loadedKey == null)
- throw new InvalidCredentialException(
- "no such credential in key store");
- keypairDescriptor.loadedTrustChain = ks
- .getCertificateChain(keypairDescriptor.credentialName);
- if (keypairDescriptor.loadedTrustChain == null
- || keypairDescriptor.loadedTrustChain.length == 0)
- throw new InvalidCredentialException(
- "could not establish trust chain for credential");
- }
-
- /**
- * Adds a key-pair to the current keystore.
- *
- * @param c
- * The key-pair.
- * @throws KeyStoreException
- */
- protected void addKeypairToKeystore(Credential.KeyPair c)
- throws KeyStoreException {
- X509Certificate subjectCert = (X509Certificate) c.loadedTrustChain[0];
- String alias = format("keypair#%s#%s#%s",
- getPrincipalName(subjectCert.getSubjectX500Principal()),
- getPrincipalName(subjectCert.getIssuerX500Principal()),
- x500Utils.getSerial(subjectCert));
- addKeypairToKeystore(alias, c);
- }
-}
-
-/**
- * Special subclass that adds support for HELIO project security tokens.
- *
- * @author Donal Fellows
- */
-class HelioSecurityContextDelegateImpl extends SecurityContextDelegateImpl {
- /**
- * Initialise the context delegate.
- *
- * @param run
- * What workflow run is this for?
- * @param owner
- * Who owns the workflow run?
- * @param factory
- * What class built this object?
- */
- protected HelioSecurityContextDelegateImpl(RemoteRunDelegate run,
- UsernamePrincipal owner, SecurityContextFactory factory) {
- super(run, owner, factory);
- }
-
- private Log log = LogFactory.getLog("Taverna.Server.Worker");
- /** The name of the HTTP header holding the CIS token. */
- private static final String HELIO_CIS_TOKEN = "X-Helio-CIS";
- private transient String helioToken;
-
- @Override
- public void initializeSecurityFromSOAPContext(MessageContext context) {
- // does nothing
- @SuppressWarnings("unchecked")
- Map<String, List<String>> headers = (Map<String, List<String>>) context
- .get(HTTP_REQUEST_HEADERS);
- if (factory.supportHelioToken && headers.containsKey(HELIO_CIS_TOKEN))
- helioToken = headers.get(HELIO_CIS_TOKEN).get(0);
- }
-
- @Override
- public void initializeSecurityFromRESTContext(HttpHeaders context) {
- // does nothing
- MultivaluedMap<String, String> headers = context.getRequestHeaders();
- if (factory.supportHelioToken && headers.containsKey(HELIO_CIS_TOKEN))
- helioToken = headers.get(HELIO_CIS_TOKEN).get(0);
- }
-
- @Override
- protected void conveyExtraSecuritySettings(RemoteSecurityContext rc)
- throws RemoteException {
- try {
- if (factory.supportHelioToken && helioToken != null) {
- if (factory.logSecurityDetails)
- log.info("transfering HELIO CIS token: " + helioToken);
- rc.setHelioToken(helioToken);
- }
- } finally {
- helioToken = null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java b/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java
deleted file mode 100644
index cbccf34..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/SecurityContextFactory.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2011-2012 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static java.security.Security.addProvider;
-import static java.security.Security.getProvider;
-import static java.security.Security.removeProvider;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
-
-import java.io.Serializable;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.logging.Log;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.beans.factory.annotation.Value;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-import org.taverna.server.master.utils.CertificateChainFetcher;
-import org.taverna.server.master.utils.FilenameUtils;
-import org.taverna.server.master.utils.UsernamePrincipal;
-import org.taverna.server.master.utils.X500Utils;
-
-/**
- * Singleton factory. Really is a singleton (and is also very trivial); the
- * singleton-ness is just about limiting the number of instances of this around
- * even when lots of serialization is going on.
- *
- * @see Serializable
- * @author Donal Fellows
- */
-public class SecurityContextFactory implements
- org.taverna.server.master.interfaces.SecurityContextFactory {
- private static final long serialVersionUID = 12345678987654321L;
- private static SecurityContextFactory instance;
- transient RunDBSupport db;
- transient FilenameUtils fileUtils;
- transient X500Utils x500Utils;
- transient UriBuilderFactory uriSource;
- transient CertificateChainFetcher certFetcher;
- transient String httpRealm;
- private transient PasswordIssuer passwordIssuer;
- private transient BouncyCastleProvider provider;
-
- /**
- * Whether to support HELIO CIS tokens.
- */
- @Value("${helio.cis.enableTokenPassing}")
- boolean supportHelioToken;
-
- /**
- * Whether to log the details of security (passwords, etc).
- */
- @Value("${log.security.details}")
- boolean logSecurityDetails;
-
- private Log log() {
- return getLog("Taverna.Server.Worker.Security");
- }
-
- private void installAsInstance(SecurityContextFactory handle) {
- instance = handle;
- }
-
- @PreDestroy
- void removeAsSingleton() {
- installAsInstance(null);
- try {
- if (provider != null)
- removeProvider(provider.getName());
- } catch (SecurityException e) {
- log().warn(
- "failed to remove BouncyCastle security provider; "
- + "might be OK if configured in environment", e);
- }
- }
-
- @PostConstruct
- void setAsSingleton() {
- installAsInstance(this);
- if (getProvider(PROVIDER_NAME) == null)
- try {
- provider = new BouncyCastleProvider();
- if (addProvider(provider) == -1)
- provider = null;
- } catch (SecurityException e) {
- log().warn(
- "failed to install BouncyCastle security provider; "
- + "might be OK if already configured", e);
- provider = null;
- }
- }
-
- @Required
- public void setRunDatabase(RunDBSupport db) {
- this.db = db;
- }
-
- @Required
- public void setCertificateFetcher(CertificateChainFetcher fetcher) {
- this.certFetcher = fetcher;
- }
-
- @Required
- public void setFilenameConverter(FilenameUtils fileUtils) {
- this.fileUtils = fileUtils;
- }
-
- @Required
- public void setX500Utils(X500Utils x500Utils) {
- this.x500Utils = x500Utils;
- }
-
- @Required
- public void setUriSource(UriBuilderFactory uriSource) {
- this.uriSource = uriSource;
- }
-
- @Required
- public void setHttpRealm(String realm) {
- this.httpRealm = realm; //${http.realmName}
- }
-
- @Required
- public void setPasswordIssuer(PasswordIssuer issuer) {
- this.passwordIssuer = issuer;
- }
-
- @Override
- public SecurityContextDelegate create(TavernaRun run,
- UsernamePrincipal owner) throws Exception {
- Log log = log();
- if (log.isDebugEnabled())
- log.debug("constructing security context delegate for " + owner);
- RemoteRunDelegate rrd = (RemoteRunDelegate) run;
- return new HelioSecurityContextDelegateImpl(rrd, owner, this);
- }
-
- private Object readResolve() {
- if (instance == null)
- installAsInstance(this);
- return instance;
- }
-
- public String issueNewPassword() {
- return passwordIssuer.issue();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java b/server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java
deleted file mode 100644
index 793d291..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/SimpleFormattedCompletionNotifier.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import static org.taverna.server.master.defaults.Default.NOTIFY_MESSAGE_FORMAT;
-
-import java.text.MessageFormat;
-
-import org.springframework.beans.factory.annotation.Required;
-
-/**
- * Completion notifier that sends messages by email.
- *
- * @author Donal Fellows
- */
-public class SimpleFormattedCompletionNotifier implements CompletionNotifier {
- @Required
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * @param subject
- * The subject of the notification email.
- */
- @Required
- public void setSubject(String subject) {
- this.subject = subject;
- }
-
- /**
- * @param messageFormat
- * The template for the body of the message to send. Parameter #0
- * will be substituted with the ID of the job, and parameter #1
- * will be substituted with the exit code.
- */
- public void setMessageFormat(String messageFormat) {
- this.format = new MessageFormat(messageFormat);
- }
-
- private String name;
- private String subject;
- private MessageFormat format = new MessageFormat(NOTIFY_MESSAGE_FORMAT);
-
- @Override
- public String makeCompletionMessage(String name, RemoteRunDelegate run,
- int code) {
- return format.format(new Object[] { name, code });
- }
-
- @Override
- public String makeMessageSubject(String name, RemoteRunDelegate run,
- int code) {
- return subject;
- }
-
- @Override
- public String getName() {
- return name;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java b/server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java
deleted file mode 100644
index cf67853..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/VelocityCompletionNotifier.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.taverna.server.master.worker;
-
-import java.io.StringWriter;
-
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.VelocityEngine;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.common.version.Version;
-import org.taverna.server.master.exceptions.NoListenerException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-
-public class VelocityCompletionNotifier implements CompletionNotifier {
- private String subject;
- private VelocityEngine engine;
- private Template template;
- private String name;
- private String templateName;
- private UriBuilderFactory ubf;
-
- @Override
- public String getName() {
- return name;
- }
-
- /**
- * @param subject
- * The subject of the notification email.
- */
- @Required
- public void setSubject(String subject) {
- this.subject = subject;
- }
-
- /**
- * @param engine
- * The configured Apache Velocity engine.
- */
- @Required
- public void setVelocityEngine(VelocityEngine engine) {
- this.engine = engine;
- }
-
- /**
- * @param uriBuilderFactory
- * The configured URI builder factory.
- */
- @Required
- public void setUriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
- this.ubf = uriBuilderFactory;
- }
-
- /**
- * @param name
- * The name of the template.
- */
- @Required
- public void setName(String name) {
- this.name = name;
- this.templateName = getClass().getName() + "_" + name + ".vtmpl";
- }
-
- private Template getTemplate() {
- if (template == null)
- synchronized(this) {
- if (template == null)
- template = engine.getTemplate(templateName);
- }
- return template;
- }
-
- @Override
- public String makeCompletionMessage(String name, RemoteRunDelegate run,
- int code) {
- VelocityContext ctxt = new VelocityContext();
- ctxt.put("id", name);
- ctxt.put("uriBuilder", ubf.getRunUriBuilder(run));
- ctxt.put("name", run.getName());
- ctxt.put("creationTime", run.getCreationTimestamp());
- ctxt.put("startTime", run.getStartTimestamp());
- ctxt.put("finishTime", run.getFinishTimestamp());
- ctxt.put("expiryTime", run.getExpiry());
- ctxt.put("serverVersion", Version.JAVA);
- for (Listener l : run.getListeners())
- if (l.getName().equals("io")) {
- for (String p : l.listProperties())
- try {
- ctxt.put("prop_" + p, l.getProperty(p));
- } catch (NoListenerException e) {
- // Ignore...
- }
- break;
- }
- StringWriter sw = new StringWriter();
- getTemplate().merge(ctxt, sw);
- return sw.toString();
- }
-
- @Override
- public String makeMessageSubject(String name, RemoteRunDelegate run,
- int code) {
- return subject;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java b/server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java
deleted file mode 100644
index 1abe617..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/WorkerModel.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2010-2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master.worker;
-
-import java.net.URI;
-import java.util.List;
-
-import org.taverna.server.master.common.Status;
-
-/**
- * Profile of the getters and setters in a worker system. Ensures that the
- * persisted state matches the public view on the state model at least fairly
- * closely.
- *
- * @author Donal Fellows
- */
-public interface WorkerModel extends PolicyLimits {
-
- /**
- * @param defaultLifetime
- * how long a workflow run should live by default, in minutes.
- */
- public abstract void setDefaultLifetime(int defaultLifetime);
-
- /**
- * @return how long a workflow run should live by default, in minutes.
- */
- public abstract int getDefaultLifetime();
-
- /**
- * @param maxRuns
- * the maximum number of extant workflow runs
- */
- public abstract void setMaxRuns(int maxRuns);
-
- /**
- * @param factoryProcessNamePrefix
- * the prefix used for factory processes in RMI
- */
- public abstract void setFactoryProcessNamePrefix(
- String factoryProcessNamePrefix);
-
- /**
- * @return the prefix used for factory processes in RMI
- */
- public abstract String getFactoryProcessNamePrefix();
-
- /**
- * @param executeWorkflowScript
- * the script to run to actually run a workflow
- */
- public abstract void setExecuteWorkflowScript(String executeWorkflowScript);
-
- /**
- * @return the script to run to actually run a workflow
- */
- public abstract String getExecuteWorkflowScript();
-
- /**
- * @param extraArgs
- * the extra arguments to pass into the workflow runner
- */
- public abstract void setExtraArgs(String[] extraArgs);
-
- /**
- * @return the extra arguments to pass into the workflow runner
- */
- public abstract String[] getExtraArgs();
-
- /**
- * @param waitSeconds
- * the number of seconds to wait for subprocesses to start
- */
- public abstract void setWaitSeconds(int waitSeconds);
-
- /**
- * @return the number of seconds to wait for subprocesses to start
- */
- public abstract int getWaitSeconds();
-
- /**
- * @param sleepMS
- * milliseconds to wait between polling for a started
- * subprocess's status
- */
- public abstract void setSleepMS(int sleepMS);
-
- /**
- * @return milliseconds to wait between polling for a started subprocess's
- * status
- */
- public abstract int getSleepMS();
-
- /**
- * @param serverWorkerJar
- * the full path name of the file system access worker
- * subprocess's implementation JAR
- */
- public abstract void setServerWorkerJar(String serverWorkerJar);
-
- /**
- * @return the full path name of the file system access worker subprocess's
- * implementation JAR
- */
- public abstract String getServerWorkerJar();
-
- /**
- * @param javaBinary
- * the full path name to the Java binary to use
- */
- public abstract void setJavaBinary(String javaBinary);
-
- /**
- * @return the full path name to the Java binary to use
- */
- public abstract String getJavaBinary();
-
- /**
- * @param registryPort
- * what port is the RMI registry on
- */
- public abstract void setRegistryPort(int registryPort);
-
- /**
- * @return what port is the RMI registry on
- */
- public abstract int getRegistryPort();
-
- /**
- * @param registryHost
- * what host (network interface) is the RMI registry on
- */
- public abstract void setRegistryHost(String registryHost);
-
- /**
- * @return what host (network interface) is the RMI registry on
- */
- public abstract String getRegistryHost();
-
- /**
- * @param serverForkerJar
- * the full path name of the impersonation engine's
- * implementation JAR
- */
- public abstract void setServerForkerJar(String serverForkerJar);
-
- /**
- * @return the full path name of the impersonation engine's implementation
- * JAR
- */
- public abstract String getServerForkerJar();
-
- /**
- * @param passwordFile
- * the full path name of a file containing a password to use with
- * sudo (or empty for none)
- */
- public abstract void setPasswordFile(String passwordFile);
-
- /**
- * @return the full path name of a file containing a password to use with
- * sudo (or empty for none)
- */
- public abstract String getPasswordFile();
-
- /**
- * @param operatingLimit
- * the maximum number of runs in the
- * {@linkplain Status#Operating operating} state at once
- */
- public abstract void setOperatingLimit(int operatingLimit);
-
- @Override
- void setPermittedWorkflowURIs(List<URI> permittedWorkflows);
-
- /**
- * @return the full path name of the RMI registry subprocess's
- * implementation JAR
- */
- String getRegistryJar();
-
- /**
- * @param rmiRegistryJar
- * the full path name of the RMI registry subprocess's
- * implementation JAR
- */
- void setRegistryJar(String rmiRegistryJar);
-
- /**
- * @return whether a run should generate provenance information by default
- */
- boolean getGenerateProvenance();
-
- /**
- * @param generateProvenance
- * whether a run should generate provenance information by
- * default
- */
- void setGenerateProvenance(boolean generateProvenance);
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java
deleted file mode 100644
index 6007f88..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/worker/package-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2013 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-/**
- * A Taverna Server back-end that works by forking off workflow executors.
- */
-package org.taverna.server.master.worker;
-
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/replacementscripts/executeworkflow.bat
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/replacementscripts/executeworkflow.bat b/server-webapp/src/main/replacementscripts/executeworkflow.bat
deleted file mode 100644
index c678855..0000000
--- a/server-webapp/src/main/replacementscripts/executeworkflow.bat
+++ /dev/null
@@ -1,25 +0,0 @@
-@ECHO OFF
-
-REM Taverna startup script
-
-REM distribution directory
-set TAVERNA_HOME=%~dp0
-
-REM 300 MB memory, 140 MB for classes
-set ARGS=-Xmx300m -XX:MaxPermSize=140m
-
-REM Taverna system properties
-set ARGS=%ARGS% "-Draven.profile=file:%TAVERNA_HOME%conf/current-profile.xml"
-set ARGS=%ARGS% -Djava.system.class.loader=net.sf.taverna.raven.prelauncher.BootstrapClassLoader
-set ARGS=%ARGS% -Draven.launcher.app.main=net.sf.taverna.t2.commandline.CommandLineLauncher
-set ARGS=%ARGS% -Draven.launcher.show_splashscreen=false
-set ARGS=%ARGS% -Djava.awt.headless=true
-set ARGS=%ARGS% "-Dtaverna.startup=%TAVERNA_HOME%."
-IF NOT x%RAVEN_APPHOME%==x SET ARGS=%ARGS% "-Draven.launcher.app.home=%RAVEN_APPHOME%"
-IF NOT x%TAVERNA_RUN_ID%==x SET ARGS=%ARGS% "-Dtaverna.runid=%TAVERNA_RUN_ID%"
-IF NOT x%INTERACTION_HOST%==x SET ARGS=%ARGS% "-Dtaverna.interaction.host=%INTERACTION_HOST%"
-IF NOT x%INTERACTION_PORT%==x SET ARGS=%ARGS% "-Dtaverna.interaction.port=%INTERACTION_PORT%"
-IF NOT x%INTERACTION_WEBDAV%==x SET ARGS=%ARGS% "-Dtaverna.interaction.webdav_path=%INTERACTION_WEBDAV%"
-IF NOT x%INTERACTION_FEED%==x SET ARGS=%ARGS% "-Dtaverna.interaction.feed_path=%INTERACTION_FEED%"
-
-java %ARGS% -jar "%TAVERNA_HOME%lib\prelauncher-2.3.jar" %*
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/replacementscripts/executeworkflow.sh
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/replacementscripts/executeworkflow.sh b/server-webapp/src/main/replacementscripts/executeworkflow.sh
deleted file mode 100644
index e9e1d36..0000000
--- a/server-webapp/src/main/replacementscripts/executeworkflow.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/sh
-
-set -e
-
-# 300 MB memory, 140 MB for classes
-memlimit=-Xmx300m
-permsize=-XX:MaxPermSize=140m
-
-## Parse the command line to extract the pieces to move around to before or
-## after the JAR filename...
-pre=-Djava.awt.headless=true
-post=
-for arg
-do
- case $arg in
- -JXmx*) memlimit=`echo $arg | sed 's/-JX/-X/'` ;;
- -JXX:MaxPermSize=*) permsize=`echo $arg | sed 's/-JXX/-XX/'` ;;
- -J*) pre="$pre `echo $arg | sed 's/-J/-/'`" ;;
- -D*) pre="$pre $arg" ;;
- *) post="$post \"$arg\"" ;;
- esac
-done
-if test "xx" = "x${post}x"; then
- echo "Missing arguments! Bug in argument processing?" >&2
- exit 1
-fi
-eval set x $post
-shift
-
-## resolve links - $0 may be a symlink
-prog="$0"
-
-real_path() {
- readlink -m "$1" 2>/dev/null || python -c 'import os,sys;print os.path.realpath(sys.argv[1])' "$1"
-}
-
-realprog=`real_path "$prog"`
-taverna_home=`dirname "$realprog"`
-javabin=java
-if test -x "$JAVA_HOME/bin/java"; then
- javabin="$JAVA_HOME/bin/java"
-fi
-APPHOME_PROP=
-if test x != "x$TAVERNA_APPHOME"; then
- APPHOME_PROP="-Dtaverna.app.home=$TAVERNA_APPHOME"
-fi
-RUNID_PROP=
-if test x != "x$TAVERNA_RUN_ID"; then
- RUNID_PROP="-Dtaverna.runid=$TAVERNA_RUN_ID"
-fi
-INTERACTION_PROPS=-Dtaverna.interaction.ignore_requests=true
-if test x != "x$INTERACTION_HOST"; then
- INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.host=$INTERACTION_HOST"
- INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.port=$INTERACTION_PORT"
- INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.webdav_path=$INTERACTION_WEBDAV"
- INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.feed_path=$INTERACTION_FEED"
- if test x != "x$INTERACTION_PUBLISH"; then
- INTERACTION_PROPS="$INTERACTION_PROPS -Dtaverna.interaction.publishAddressOverride=$INTERACTION_PUBLISH"
- fi
-fi
-
-MainClass=net.sf.taverna.t2.commandline.CommandLineLauncher
-
-echo "pid:$$"
-exec "$javabin" $memlimit $permsize \
- "-Dlog4j.configuration=file://$taverna_home/conf/log4j.properties " \
- "-Djava.util.logging.config.file=$taverna_home/conf/logging.properties " \
- "-Dtaverna.app.startup=$taverna_home" -Dtaverna.interaction.ignore_requests=true \
- $APPHOME_PROP $RUNID_PROP $INTERACTION_PROPS -Djava.awt.headless=true \
- -Dcom.sun.net.ssl.enableECC=false -Djsse.enableSNIExtension=false $pre \
- -jar "$taverna_home/lib/taverna-command-line-0.1.1.jar" \
- ${1+"$@"}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/admin.html
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/admin.html b/server-webapp/src/main/resources/admin.html
deleted file mode 100644
index a80a783..0000000
--- a/server-webapp/src/main/resources/admin.html
+++ /dev/null
@@ -1,240 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>Taverna Server ${project.version} Administration Interface</title>
-<link id="admin" href="admin" />
-<script type="text/javascript" src="admin/static/jquery-1.8.0.min.js"></script>
-<script type="text/javascript" src="admin/static/jquery-ui-1.8.23.custom.min.js"></script>
-<script type="text/javascript" src="admin/static/admin.js"></script>
-<link href="admin/static/jquery-ui-1.8.23.custom.css" rel="stylesheet" type="text/css" />
-
-</head>
-<body>
-<img height="70" style="float:left" src="admin/static/t2cogs.png">
-<h1>Taverna Server ${project.version} Administration Interface</h1>
-<br clear="left"/>
-<div id="body">
-<ul>
- <li><a href="#t-global">Global Settings</a></li>
- <li><a href="#t-users">Users</a></li>
- <li><a href="#t-workflows">Workflows</a></li>
- <li><a href="#t-usage">Usage Records</a></li>
- <li><a href="#t-worker">Local Worker Configuration</a></li>
-</ul>
-
-<div id="t-global">
-<label title="The number of invocations of the main interface webapp that have been done. Be aware that one service call can result in many invocations due to resource resolution." for="invokationCount">Invocation Count:</label>
-<span title="The number of invocations of the main interface webapp that have been done. Be aware that one service call can result in many invocations due to resource resolution." id="invokationCount">0</span>
-<br>
-<label title="The number of runs that currently exist." for="runCount">Run Count:</label>
-<span title="The number of runs that currently exist." id="runCount">0</span>
-<br>
-<label title="The number of runs that are currently operating." for="operatingCount">Operating Run Count:</label>
-<span title="The number of runs that are currently operating." id="operatingCount">0</span>
-<br>
-<label title="Whether workflow runs should create provenance traces by default. Users can explicitly override this." for="generateProvenance">Generate Provenance by Default</label>
-<input type="checkbox" id="generateProvenance" />
-<br>
-<label title="The time it took for the back-end engine to start up, in seconds. Should usually be short." for="startupTime">Back-End Startup Time (seconds):</label>
-<span title="The time it took for the back-end engine to start up, in seconds. Should usually be short." id="startupTime">0</span>
-<br>
-<label title="The exit code from the last time the back-end was shut down. Blank if the back end has never been shut down while the current webapp instance is running (i.e., since the last boot of the container)." for="lastExitCode">Back-End Last Exit Code:</label>
-<span title="The exit code from the last time the back-end was shut down. Blank if the back end has never been shut down while the current webapp instance is running (i.e., since the last boot of the container)." id="lastExitCode"></span>
-<p>
-<label title="Whether new workflow runs should be created. Disabling this does not prevent existing runs from executing." for="allowNew">Allow New Runs</label>
-<input type="checkbox" id="allowNew" />
-<label title="Whether to record the workflows being run by users. Very noisy due to length of workflow documents, occasionally useful." for="logWorkflows">Log Executed Workflows</label>
-<input type="checkbox" id="logWorkflows" />
-<label title="Whether to record exceptions generated by users in the code (as well as converting them to faults and error responses). Useful for debugging, but noisy." for="logFaults">Log User Exceptions</label>
-<input type="checkbox" id="logFaults" />
-<p>
-<label title="The maximum number of workflow runs that can exist at once, in any state." for="runLimit">Maximum Simultaneous Existing Workflow Runs</label>
-<input title="The maximum number of workflow runs that can exist at once, in any state." id="runLimit" size="3" />
-<br>
-<label title="The maximum number of workflow runs that can be executing at once." for="operatingLimit">Maximum Simultaneous Executing Workflow Runs</label>
-<input title="The maximum number of workflow runs that can be executing at once." id="operatingLimit" size="3" />
-<br>
-<label title="How long to allow a workflow to execute for by default (clients can change this), in minutes." for="defaultLifetime">Default Run Lifetime (minutes)</label>
-<input title="How long to allow a workflow to execute for by default (clients can change this), in minutes." id="defaultLifetime" size="7" />
-</div><!-- t-global -->
-
-<div id="t-users">
-<table id="userList">
- <tr><th>Username<th>System Username</tr>
-</table>
-<h3>Add a user</h3>
-<table border=1>
- <tr>
- <td><label title="The user name to create." for="newUsername">Username</label>
- <td><input title="The user name to create." size=12 id="newUsername" />
- </tr>
- <tr>
- <td><label title="The password to use for the user." for="newPassword">Password</label>
- <td><input title="The password to use for the user." size=12 id="newPassword" type="password"/>
- </tr>
- <tr>
- <td><label title="The system account to run the user's workflows in; leave blank for the default." for="newSysID">System ID</label>
- <td><input title="The system account to run the user's workflows in; leave blank for the default." size=12 id="newSysID" />
- </tr>
- <tr><td colspan=2>
- <label title="Whether to allow this user to log in at all." for="newEnabled">Enabled</label>
- <input type="checkbox" id="newEnabled" />
- <label title="Whether the user has administrative privileges (can see all workflow runs, can access the administration page)." for="newAdmin">Admin</label>
- <input type="checkbox" id="newAdmin" />
- </td></tr>
- <tr><td colspan=2>
- <button id="makeNewUser">Create a new user</button>
- </td></tr>
-</table>
-</div><!-- t-users -->
-
-<div id="t-workflows">
-<label title="Workflow URIs to limit execution to." for="workflows">Workflow URIs (one per line)</label>
-<br>
-<textarea title="Workflow URIs to limit execution to." rows="5" cols="60" id="workflows"></textarea>
-<p>
-<button id="saveWorkflows">Save</button> <button id="refreshWorkflows">Refresh</button> <button id="emptyWorkflows">Empty URIs list</button>
-</div>
-
-<div id="t-usage">
-Download <a href="#" id="ur">usage records</a> (warning: may be slow!)
-<p>
-<label title="The name of a file to write usage records to. Note that this file will end up containing many XML documents concatenated together; it is up to you to split them up as necessary. Each record is only written as it is generated; this does not produce historic data." for="usageRecordDumpFile">Usage Record Dump File</label>
-<input title="The name of a file to write usage records to. Note that this file will end up containing many XML documents concatenated together; it is up to you to split them up as necessary. Each record is only written as it is generated; this does not produce historic data." id="usageRecordDumpFile" size="50" />
-</div><!-- t-usage -->
-
-<div id="t-worker">
- <div id="a-worker">
-
- <h3><a href="#">Subprocess Implementation Control</a></h3>
- <div>
- <table>
- <tr>
- <td> <label title="The full path of the Java executable to use. Normally set correct by default." for="javaBinary">Java Executable (for subprocesses):</label> </td>
- <td> <input title="The full path of the Java executable to use. Normally set correct by default." id="javaBinary" size="80" /> </td>
- </tr>
- <tr>
- <td> <label title="The full path of the secure subprocess fork engine to use. Normally set correct by default." for="serverForkerJar">Subprocess Factory JAR:</label> </td>
- <td> <input title="The full path of the secure subprocess fork engine to use. Normally set correct by default." id="serverForkerJar" size="80" /> </td>
- </tr>
- <tr>
- <td> <label title="The full path of a file containing the credentials to use with sudo. Leave blank to use a password-less connection (see documentation for how to configure)." for="runasPasswordFile">File with password for sudo:</label> </td>
- <td> <input title="The full path of a file containing the credentials to use with sudo. Leave blank to use a password-less connection (see documentation for how to configure)." id="runasPasswordFile" size="80" /> </td>
- </tr>
- <tr>
- <td> <label title="The full path of the user filesystem access and workflow initiation engine to use. Normally set correct by default." for="serverWorkerJar">User Filesystem Access JAR:</label> </td>
- <td> <input title="The full path of the user filesystem access and workflow initiation engine to use. Normally set correct by default." id="serverWorkerJar" size="80" /> </td>
- </tr>
- <tr>
- <td> <label title="The full path of the workflow engine executable. Normally set correctly by default." for="executeWorkflowScript">Workflow Engine Executable:</label> </td>
- <td> <input title="The full path of the workflow engine executable. Normally set correctly by default." id="executeWorkflowScript" size="80" /> </td>
- </tr>
- </table>
- </div>
-
- <h3><a href="#">Worker Registration Control</a></h3>
- <div>
- <label title="The machine hosting the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" for="registryHost">Registry Host</label>
- <input title="The machine hosting the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" id="registryHost" size="20" />
- <label title="The port number the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" for="registryPort">Port</label>
- <input title="The port number the RMI registry. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" id="registryPort" size="5" />
- <br>
- <label title="The full path of the RMI registry implementation JAR file. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" for="registryJar">RMI Registry JAR</label>
- <input title="The full path of the RMI registry implementation JAR file. WARNING: changing this will probably break your configuration! Contact the myGrid team for help before adjusting!" id="registryJar" size="80" />
- <br>
- <label title="The time to wait (in seconds) for the back-end processes to boot and register themselves with the RMI registry. Busy machines may need a longer value here." for="registrationWaitSeconds">Time to wait for registration (seconds)</label>
- <input title="The time to wait (in seconds) for the back-end processes to boot and register themselves with the RMI registry. Busy machines may need a longer value here." id="registrationWaitSeconds" size="5" />
- <br>
- <label title="How long to wait (in milliseconds) between probes to the registry to detect the registration of a back-end process." for="registrationPollMillis">Time to wait between polling to
- detect registration (milliseconds)</label>
- <input title="How long to wait (in milliseconds) between probes to the registry to detect the registration of a back-end process." id="registrationPollMillis" size="5" />
- </div>
-
- <h3><a href="#">System User/Factory ID Mapping</a></h3>
- <div>
- <table title="The mapping of system user IDs to factory identifiers (used in the RMI registry). Note that this is read-only." id="factoryProcessMapping" border="1">
- </table>
- </div>
-
- <h3><a href="#">Extra Workflow Engine Configuration</a></h3>
- <div>
- <h4>System Properties</h4>
- <table id="extraArguments-prop">
- <tr><td></td><td><button title="Add a system property to pass to the back-end engine." id="extra-prop-add">Add System Property</button></td></tr>
- </table>
- <h4>Environment Variables</h4>
- <table id="extraArguments-env">
- <tr><td></td><td><button title="Add an environment variable to pass to the back-end engine." id="extra-env-add">Add Environment Variable</button></td></tr>
- </table>
- <h4>Java Runtime Configuration</h4>
- <table id="extraArguments-runtime">
- <tr><td></td><td><button title="Add a Java runtime parameter (e.g., Xmx=400m to set the memory usage limit to 400MB) to pass to the back-end engine. Note the lack of a leading '-' character!" id="extra-run-add">Add Runtime Configuration</button></td></tr>
- </table>
- </div>
-
- </div><!-- a-worker -->
-</div><!-- t-worker -->
-
-</div>
-
-<hr>
-<address>Donal Fellows / University of Manchester</address>
-
-<!-- DIALOG BOXES -->
-<div id="dialog-confirm" title="Delete user?" style="display: none">
- <p>
- <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
- This user will be permanently deleted from the system. Are you sure?
- </p>
-</div>
-
-<div id="dialog-password" title="Change password?" style="display: none">
- <p>
- <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
- This will permanently change the user's password. Make sure you wish
- to do this.
- </p>
- <p>
- <input title="New password" id="change-password" type="password" size="12" />
- <br>
- Please repeat it to be sure...
- <br>
- <input title="New password (again)" id="change-password2" type="password" size="12" />
- </p>
-</div>
-
-<div id="dialog-environment" title="Set environment variable?" style="display: none">
- <p>
- <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
- Set an environment variable to be passed to the workflow engine.
- </p>
- <p>
- <input title="Environment variable name" id="env-key" size="15" /> =
- <input title="Environment variable value" id="env-value" size="20" />
- </p>
-</div>
-
-<div id="dialog-runtime" title="Set runtime configuration?" style="display: none">
- <p>
- <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
- Set a runtime parameter (e.g., -Xmx400m for a 400MB memory limit) for the Java runtime.
- </p>
- <p>
- <input title="Java runtime configuration parameter" id="runtime-value" size="20" />
- </p>
-</div>
-
-<div id="dialog-property" title="Set runtime property?" style="display: none">
- <p>
- <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
- Set a configuration property for the Java runtime.
- </p>
- <p>
- <input title="System property name" id="prop-key" size="15" /> =
- <input title="System property value" id="prop-value" size="20" />
- </p>
-</div>
-
-</body>
-</html>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/capabilities.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/capabilities.properties b/server-webapp/src/main/resources/capabilities.properties
deleted file mode 100644
index 2b4844f..0000000
--- a/server-webapp/src/main/resources/capabilities.properties
+++ /dev/null
@@ -1,38 +0,0 @@
-# This is currently a hand-curated list. This sucks!
-
-######## --- PLATFORM --- ########
-http\://ns.taverna.org.uk/2013/software/taverna = 2.5
-
-######## --- OUTPUTS/PROVENANCE --- ########
-http\://ns.taverna.org.uk/2013/bundle/run = 1.0
-http\://ns.taverna.org.uk/2013/provenance/prov = 1.0
-
-######## --- ACTIVITIES --- ########
-http\://ns.taverna.org.uk/2010/activity/nested-workflow = 1.5
-http\://ns.taverna.org.uk/2010/activity/apiconsumer = 1.5
-http\://ns.taverna.org.uk/2010/activity/beanshell = 1.5
-http\://ns.taverna.org.uk/2010/activity/localworker = 1.5
-http\://ns.taverna.org.uk/2010/activity/biomart = 1.5
-http\://ns.taverna.org.uk/2010/activity/biomoby/object = 1.5
-http\://ns.taverna.org.uk/2010/activity/biomoby/service = 1.5
-http\://ns.taverna.org.uk/2010/activity/rshell = 1.5
-http\://ns.taverna.org.uk/2010/activity/soaplab = 1.5
-http\://ns.taverna.org.uk/2010/activity/spreadsheet-import = 1.5
-http\://ns.taverna.org.uk/2010/activity/constant = 1.5
-http\://ns.taverna.org.uk/2010/activity/component = 1.5
-http\://ns.taverna.org.uk/2010/activity/wsdl = 1.5
-http\://ns.taverna.org.uk/2010/activity/wsdl/xml-splitter/in = 1.5
-http\://ns.taverna.org.uk/2010/activity/wsdl/xml-splitter/out = 1.5
-http\://ns.taverna.org.uk/2010/activity/tool = 1.5
-http\://ns.taverna.org.uk/2010/activity/rest = 1.5
-http\://ns.taverna.org.uk/2010/activity/xpath = 1.5
-http\://ns.taverna.org.uk/2010/activity/webdav = 1.5
-http\://ns.taverna.org.uk/2010/activity/interaction = 1.5
-
-######## --- DISPATCH LAYERS --- ########
-http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/ErrorBounce = 1.5
-http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Failover = 1.5
-http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Invoke = 1.5
-http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Loop = 1.5
-http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Parallelize = 1.5
-http\://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Retry = 1.5
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/log4j.properties b/server-webapp/src/main/resources/log4j.properties
deleted file mode 100644
index ea0ea12..0000000
--- a/server-webapp/src/main/resources/log4j.properties
+++ /dev/null
@@ -1,39 +0,0 @@
-log4j.rootLogger=info, R
-log4j.category.DataNucleus.Query=warn
-#log4j.category.DataNucleus.Datastore.Schema=debug
-#log4j.logger.org.springframework.security=DEBUG
-#log4j.category.Taverna=debug
-
-log4j.appender.R=org.apache.log4j.RollingFileAppender
-log4j.appender.R.File=${catalina.home}/logs/tavserv.out
-log4j.appender.R.MaxFileSize=10MB
-log4j.appender.R.MaxBackupIndex=30
-log4j.appender.R.layout=org.apache.log4j.PatternLayout
-log4j.appender.R.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
-
-#log4j.category.Taverna=INFO, A1
-#log4j.category.Taverna.Server.LocalWorker.RunDB=INFO
-#log4j.category.Taverna.Server.Webapp=INFO
-#log4j.category.Taverna.Server.LocalWorker.Policy=INFO
-#log4j.category.Taverna.Server.LocalWorker.Security=INFO
-## Swallow Derby's messages
-#log4j.category.Derby=WARN, B2
-## Will you _shut up_, DataNucleus! <hits with rolled-up newspaper>
-#log4j.category.DataNucleus=WARN, B2
-##log4j.category.DataNucleus.SchemaTool=DEBUG
-##log4j.category.DataNucleus.Datastore.Schema=DEBUG
-##log4j.category.DataNucleus.Datastore.Native=DEBUG
-##log4j.logger.org.springframework.security=DEBUG, B2
-#log4j.category.org.springframework=INFO, B2
-#log4j.category.org.apache.cxf=INFO, B2
-#log4j.category.org.apache.cxf.jaxrs.utils.JAXRSUtils=INFO
-#log4j.category.eu.medsea=INFO, B2
-#log4j.category.org.apache.axiom=INFO, B2
-## Appender for Taverna Server components
-#log4j.appender.A1=org.apache.log4j.ConsoleAppender
-#log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-#log4j.appender.A1.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
-## Appender for Framework components
-#log4j.appender.B2=org.apache.log4j.ConsoleAppender
-#log4j.appender.B2.layout=org.apache.log4j.PatternLayout
-#log4j.appender.B2.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} - %m%n
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/security.policy
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/security.policy b/server-webapp/src/main/resources/security.policy
deleted file mode 100644
index 1ec4166..0000000
--- a/server-webapp/src/main/resources/security.policy
+++ /dev/null
@@ -1,3 +0,0 @@
-grant {
- permission java.security.AllPermission "*:*";
-};
[45/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
----------------------------------------------------------------------
diff --git a/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java b/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
deleted file mode 100644
index d12d3d8..0000000
--- a/server-usagerecord/src/main/java/org/ogf/usage/JobUsageRecord.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.ogf.usage;
-
-import static java.util.UUID.randomUUID;
-
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.math.BigInteger;
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlTransient;
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.datatype.DatatypeFactory;
-import javax.xml.transform.dom.DOMSource;
-
-import org.ogf.usage.v1_0.Charge;
-import org.ogf.usage.v1_0.ConsumableResourceType;
-import org.ogf.usage.v1_0.CpuDuration;
-import org.ogf.usage.v1_0.Disk;
-import org.ogf.usage.v1_0.EndTime;
-import org.ogf.usage.v1_0.Host;
-import org.ogf.usage.v1_0.JobName;
-import org.ogf.usage.v1_0.MachineName;
-import org.ogf.usage.v1_0.Memory;
-import org.ogf.usage.v1_0.Network;
-import org.ogf.usage.v1_0.NodeCount;
-import org.ogf.usage.v1_0.Processors;
-import org.ogf.usage.v1_0.ProjectName;
-import org.ogf.usage.v1_0.Queue;
-import org.ogf.usage.v1_0.RecordIdentity;
-import org.ogf.usage.v1_0.ResourceType;
-import org.ogf.usage.v1_0.ServiceLevel;
-import org.ogf.usage.v1_0.StartTime;
-import org.ogf.usage.v1_0.Status;
-import org.ogf.usage.v1_0.SubmitHost;
-import org.ogf.usage.v1_0.Swap;
-import org.ogf.usage.v1_0.TimeDuration;
-import org.ogf.usage.v1_0.TimeInstant;
-import org.ogf.usage.v1_0.UserIdentity;
-import org.ogf.usage.v1_0.WallDuration;
-import org.w3c.dom.Element;
-
-@XmlRootElement(name = "UsageRecord", namespace = "http://schema.ogf.org/urf/2003/09/urf")
-public class JobUsageRecord extends org.ogf.usage.v1_0.UsageRecordType {
- /**
- * Create a new usage record with a random UUID as its identity.
- *
- * @throws DatatypeConfigurationException
- * If the factory for XML-relevant datatypes fails to build; not
- * expected.
- */
- public JobUsageRecord() throws DatatypeConfigurationException {
- datatypeFactory = DatatypeFactory.newInstance();
- RecordIdentity recid = new RecordIdentity();
- recid.setRecordId(randomUUID().toString());
- recid.setCreateTime(datatypeFactory
- .newXMLGregorianCalendar(new GregorianCalendar()));
- setRecordIdentity(recid);
- }
-
- /**
- * Create a new usage record with a random UUID as its identity.
- *
- * @param name
- * The name of the job to which this record pertains.
- * @throws DatatypeConfigurationException
- * If the factory for XML-relevant datatypes fails to build; not
- * expected.
- */
- public JobUsageRecord(String name) throws DatatypeConfigurationException {
- this();
- setJobName(name);
- }
-
- @XmlTransient
- private DatatypeFactory datatypeFactory;
-
- public Status setStatus(String status) {
- Status s = new Status();
- s.setValue(status);
- setStatus(s);
- return s;
- }
-
- public WallDuration addWallDuration(long millis) {
- WallDuration wall = new WallDuration();
- wall.setValue(datatypeFactory.newDuration(millis));
- getWallDurationOrCpuDurationOrNodeCount().add(wall);
- return wall;
- }
-
- public CpuDuration addCpuDuration(long millis) {
- CpuDuration cpu = new CpuDuration();
- cpu.setValue(datatypeFactory.newDuration(millis));
- getWallDurationOrCpuDurationOrNodeCount().add(cpu);
- return cpu;
- }
-
- public NodeCount addNodeCount(int nodes) {
- NodeCount nc = new NodeCount();
- nc.setValue(BigInteger.valueOf(nodes));
- getWallDurationOrCpuDurationOrNodeCount().add(nc);
- return nc;
- }
-
- public Processors addProcessors(int processors) {
- Processors pc = new Processors();
- pc.setValue(BigInteger.valueOf(processors));
- getWallDurationOrCpuDurationOrNodeCount().add(pc);
- return pc;
- }
-
- public SubmitHost addSubmitHost(String host) {
- SubmitHost sh = new SubmitHost();
- sh.setValue(host);
- getWallDurationOrCpuDurationOrNodeCount().add(sh);
- return sh;
- }
-
- public Host addHost(String host) {
- Host h = new Host();
- h.setValue(host);
- getWallDurationOrCpuDurationOrNodeCount().add(h);
- return h;
- }
-
- public MachineName addMachine(String host) {
- MachineName machine = new MachineName();
- machine.setValue(host);
- getWallDurationOrCpuDurationOrNodeCount().add(machine);
- return machine;
- }
-
- public ProjectName addProject(String project) {
- ProjectName p = new ProjectName();
- p.setValue(project);
- getWallDurationOrCpuDurationOrNodeCount().add(p);
- return p;
- }
-
- public void addStartAndEnd(Date start, Date end) {
- GregorianCalendar gc;
-
- gc = new GregorianCalendar();
- gc.setTime(start);
- StartTime st = new StartTime();
- st.setValue(datatypeFactory.newXMLGregorianCalendar(gc));
- getWallDurationOrCpuDurationOrNodeCount().add(st);
-
- gc = new GregorianCalendar();
- gc.setTime(end);
- EndTime et = new EndTime();
- et.setValue(datatypeFactory.newXMLGregorianCalendar(gc));
- getWallDurationOrCpuDurationOrNodeCount().add(et);
- }
-
- public Queue addQueue(String queue) {
- Queue q = new Queue();
- q.setValue(queue);
- getWallDurationOrCpuDurationOrNodeCount().add(q);
- return q;
- }
-
- public void addResource(ConsumableResourceType consumable) {
- getWallDurationOrCpuDurationOrNodeCount().add(consumable);
- }
-
- public ResourceType addResource(ResourceType resource) {
- getWallDurationOrCpuDurationOrNodeCount().add(resource);
- return resource;
- }
-
- public ResourceType addResource(String description, String value) {
- ResourceType resource = new ResourceType();
- resource.setDescription(description);
- resource.setValue(value);
- getWallDurationOrCpuDurationOrNodeCount().add(resource);
- return resource;
- }
-
- public ServiceLevel addServiceLevel(String service) {
- ServiceLevel sl = new ServiceLevel();
- sl.setValue(service);
- getDiskOrMemoryOrSwap().add(sl);
- return sl;
- }
-
- public Memory addMemory(long memory) {
- Memory mem = new Memory();
- mem.setValue(BigInteger.valueOf(memory));
- getDiskOrMemoryOrSwap().add(mem);
- return mem;
- }
-
- public TimeInstant addTimestamp(Date timestamp, String type) {
- TimeInstant instant = new TimeInstant();
- GregorianCalendar gc = new GregorianCalendar();
- gc.setTime(timestamp);
- instant.setValue(datatypeFactory.newXMLGregorianCalendar(gc));
- instant.setType(type);
- getDiskOrMemoryOrSwap().add(instant);
- return instant;
- }
-
- public TimeDuration addDuration(long millis, String type) {
- TimeDuration duration = new TimeDuration();
- duration.setValue(datatypeFactory.newDuration(millis));
- duration.setType(type);
- getDiskOrMemoryOrSwap().add(duration);
- return duration;
- }
-
- public Network addNetwork(long value) {
- Network net = new Network();
- net.setValue(BigInteger.valueOf(value));
- getDiskOrMemoryOrSwap().add(net);
- return net;
- }
-
- public Disk addDisk(long value) {
- Disk disk = new Disk();
- disk.setValue(BigInteger.valueOf(value));
- getDiskOrMemoryOrSwap().add(disk);
- return disk;
- }
-
- public Swap addSwap(long value) {
- Swap net = new Swap();
- net.setValue(BigInteger.valueOf(value));
- getDiskOrMemoryOrSwap().add(net);
- return net;
- }
-
- public UserIdentity addUser(String localUID, String globalName) {
- UserIdentity user = new UserIdentity();
- user.setLocalUserId(localUID);
- user.setGlobalUserName(globalName);
- getUserIdentity().add(user);
- return user;
- }
-
- public JobName setJobName(String name) {
- JobName jn = new JobName();
- jn.setValue(name);
- this.setJobName(jn);
- return jn;
- }
-
- public Charge addCharge(float value) {
- Charge c = new Charge();
- c.setValue(value);
- this.setCharge(c);
- return c;
- }
-
- @SuppressWarnings("unchecked")
- public <T> T getOfType(Class<T> clazz) {
- for (Object o : getWallDurationOrCpuDurationOrNodeCount())
- if (clazz.isInstance(o))
- return (T) o;
- for (Object o : getDiskOrMemoryOrSwap())
- if (clazz.isInstance(o))
- return (T) o;
- return null;
- }
-
- public String marshal() throws JAXBException {
- StringWriter writer = new StringWriter();
- JAXBContext.newInstance(getClass()).createMarshaller()
- .marshal(this, writer);
- return writer.toString();
- }
-
- private static JAXBContext context;
- static {
- try {
- context = JAXBContext.newInstance(JobUsageRecord.class);
- } catch (JAXBException e) {
- throw new RuntimeException("failed to handle JAXB annotated class",
- e);
- }
- }
-
- public static JobUsageRecord unmarshal(String s) throws JAXBException {
- return (JobUsageRecord) context.createUnmarshaller().unmarshal(
- new StringReader(s));
- }
-
- public static JobUsageRecord unmarshal(Element elem) throws JAXBException {
- return context.createUnmarshaller()
- .unmarshal(new DOMSource(elem), JobUsageRecord.class)
- .getValue();
- }
-
- // TODO: Add signing support
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-usagerecord/src/main/xsd/ur.xsd
----------------------------------------------------------------------
diff --git a/server-usagerecord/src/main/xsd/ur.xsd b/server-usagerecord/src/main/xsd/ur.xsd
deleted file mode 100644
index 16344a7..0000000
--- a/server-usagerecord/src/main/xsd/ur.xsd
+++ /dev/null
@@ -1,425 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsd:schema attributeFormDefault="qualified" jaxb:version="2.1"
- elementFormDefault="qualified" targetNamespace="http://schema.ogf.org/urf/2003/09/urf"
- xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:urf="http://schema.ogf.org/urf/2003/09/urf"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
- xsi:schemaLocation="http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd">
- <xsd:annotation>
- <!-- Copyright (c) 2003-2008 Open Grid Forum -->
- <xsd:documentation xml:lang="en">Usage Record Working Group XML Schema definition</xsd:documentation>
- <xsd:appinfo>
- <jaxb:schemaBindings>
- <jaxb:package name="org.ogf.usage.v1_0" />
- </jaxb:schemaBindings>
- </xsd:appinfo>
- </xsd:annotation>
- <xsd:import namespace="http://www.w3.org/2000/09/xmldsig#"
- schemaLocation="xmlds.xsd" /> <!-- http://www.w3.org/TR/xmldsig-core/xmldsig-core-schema.xsd -->
- <xsd:complexType name="UsageRecordType">
- <xsd:sequence>
- <xsd:element ref="urf:RecordIdentity" />
- <xsd:element minOccurs="0" ref="urf:JobIdentity" />
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:UserIdentity" />
- <xsd:element minOccurs="0" ref="urf:JobName" />
- <xsd:element minOccurs="0" ref="urf:Charge" />
- <xsd:element ref="urf:Status" />
- <xsd:choice maxOccurs="unbounded" minOccurs="0">
- <xsd:annotation>
- <xsd:documentation>
- The elements grouped together in this choice may be represented
- within a usage record multiple times. Each of these appearances
- must be differentiated by the metric and/or type associated with
- the element.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:element ref="urf:Disk" />
- <xsd:element ref="urf:Memory" />
- <xsd:element ref="urf:Swap" />
- <xsd:element ref="urf:Network" />
- <xsd:element ref="urf:TimeDuration" />
- <xsd:element ref="urf:TimeInstant" />
- <xsd:element ref="urf:ServiceLevel" />
- </xsd:choice>
- <xsd:choice maxOccurs="unbounded" minOccurs="0">
- <xsd:element minOccurs="0" ref="urf:WallDuration" />
- <xsd:sequence minOccurs="0">
- <xsd:element maxOccurs="2" minOccurs="0" ref="urf:CpuDuration" />
- </xsd:sequence>
- <xsd:element minOccurs="0" ref="urf:NodeCount" />
- <xsd:element minOccurs="0" ref="urf:Processors" />
- <xsd:element minOccurs="0" ref="urf:EndTime" />
- <xsd:element minOccurs="0" ref="urf:StartTime" />
- <xsd:element minOccurs="0" ref="urf:MachineName" />
- <xsd:element minOccurs="0" ref="urf:SubmitHost" />
- <xsd:element minOccurs="0" ref="urf:Queue" />
- <xsd:sequence minOccurs="0">
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:ProjectName" />
- </xsd:sequence>
- <xsd:sequence minOccurs="0">
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:Host" />
- </xsd:sequence>
- <xsd:sequence minOccurs="0">
- <xsd:choice maxOccurs="unbounded" minOccurs="0">
- <xsd:element ref="urf:PhaseResource" />
- <xsd:element ref="urf:VolumeResource" />
- <xsd:element ref="urf:Resource" />
- <xsd:element ref="urf:ConsumableResource" />
- </xsd:choice>
- </xsd:sequence>
- </xsd:choice>
- </xsd:sequence>
- </xsd:complexType>
- <xsd:element abstract="true" name="Usage" type="urf:UsageRecordType" />
- <xsd:element name="UsageRecord" substitutionGroup="urf:Usage"
- type="urf:UsageRecordType" />
- <xsd:element name="JobUsageRecord" substitutionGroup="urf:Usage">
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="urf:UsageRecordType" />
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="UsageRecords">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="0" ref="urf:Usage" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <!-- Common properties that may be measured with several different metrics
- within the same usage record -->
- <xsd:element name="Network">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:positiveInteger">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attributeGroup ref="urf:intervallicVolume" />
- <xsd:attribute default="total" ref="urf:metric" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Disk">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:positiveInteger">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attributeGroup ref="urf:intervallicVolume" />
- <xsd:attribute default="total" ref="urf:metric" use="optional" />
- <xsd:attribute ref="urf:type" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Memory">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:positiveInteger">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attributeGroup ref="urf:intervallicVolume" />
- <xsd:attribute default="total" ref="urf:metric" use="optional" />
- <xsd:attribute ref="urf:type" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Swap">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:positiveInteger">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attributeGroup ref="urf:intervallicVolume" />
- <xsd:attribute default="total" ref="urf:metric" use="optional" />
- <xsd:attribute ref="urf:type" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="NodeCount">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:positiveInteger">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attribute default="total" ref="urf:metric" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Processors">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:positiveInteger">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attribute ref="urf:metric" use="optional" />
- <xsd:attribute name="consumptionRate" type="xsd:float"
- use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="TimeDuration">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:duration">
- <xsd:attribute ref="urf:type" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="TimeInstant">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:dateTime">
- <xsd:attribute ref="urf:type" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ServiceLevel">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:token">
- <xsd:attribute ref="urf:type" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <!-- This element should appear at most twice within a usage record, with
- differing values for usageType for each appearance -->
- <xsd:element name="CpuDuration">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:duration">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attribute name="usageType">
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="user" />
- <xsd:enumeration value="system" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <!-- These common properties should appear at most once within a usage record,
- rather that at most once per metric per usage record -->
- <xsd:element name="WallDuration">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:duration">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="EndTime">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:dateTime">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="StartTime">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:dateTime">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="MachineName">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="urf:domainNameType">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="SubmitHost">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="urf:domainNameType">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Host">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="urf:domainNameType">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attribute default="false" name="primary" type="xsd:boolean" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Queue">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="JobName">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="ProjectName">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Status">
- <xsd:annotation>
- <xsd:documentation>
- Minimum required set = {Aborted, Completed, Failed,
- Held, Queued, Started, Suspended}
- </xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:token">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="Charge">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:float">
- <xsd:attribute ref="urf:description" use="optional" />
- <xsd:attribute ref="urf:unit" use="optional" />
- <xsd:attribute name="formula" type="xsd:string" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <!-- identity elements -->
- <xsd:element name="JobIdentity">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element minOccurs="0" name="GlobalJobId" type="xsd:string" />
- <xsd:element minOccurs="0" name="LocalJobId" type="xsd:string" />
- <xsd:sequence>
- <xsd:element maxOccurs="unbounded" minOccurs="0"
- name="ProcessId" type="xsd:string" />
- </xsd:sequence>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="UserIdentity">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element minOccurs="0" name="LocalUserId" type="xsd:string" />
- <xsd:element minOccurs="0" name="GlobalUserName" type="xsd:string" />
- <xsd:element minOccurs="0" ref="ds:KeyInfo" />
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="RecordIdentity">
- <xsd:complexType>
- <xsd:sequence minOccurs="0">
- <xsd:element ref="ds:KeyInfo" />
- </xsd:sequence>
- <xsd:attribute name="recordId" type="xsd:token" use="required" />
- <xsd:attribute name="createTime" type="xsd:dateTime" use="optional" />
- </xsd:complexType>
- </xsd:element>
- <!-- Extensibility Framework -->
- <xsd:element name="Resource" type="urf:ResourceType" />
- <xsd:element name="ConsumableResource" type="urf:ConsumableResourceType" />
- <xsd:element name="PhaseResource">
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="urf:ConsumableResourceType">
- <xsd:attribute ref="urf:phaseUnit" use="optional" />
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="VolumeResource">
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="urf:ConsumableResourceType">
- <xsd:attribute ref="urf:storageUnit" use="optional" />
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
- <!-- Create a generic consumable resource. Carries the units attribute -->
- <xsd:complexType name="ConsumableResourceType">
- <xsd:simpleContent>
- <xsd:extension base="xsd:float">
- <xsd:attribute name="units" type="xsd:string" use="optional" />
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- <!-- Create a generic resource type -->
- <xsd:complexType name="ResourceType">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute ref="urf:description" use="optional" />
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- <!-- Global Attribute Definitions -->
- <xsd:attribute name="description" type="xsd:string" />
- <!-- Units of measure attribute definitions -->
- <xsd:attribute name="unit" type="xsd:token" />
- <xsd:attribute name="storageUnit">
- <xsd:simpleType>
- <xsd:restriction base="xsd:token">
- <xsd:enumeration value="b" />
- <xsd:enumeration value="B" />
- <xsd:enumeration value="KB" />
- <xsd:enumeration value="MB" />
- <xsd:enumeration value="GB" />
- <xsd:enumeration value="PB" />
- <xsd:enumeration value="EB" />
- <xsd:enumeration value="Kb" />
- <xsd:enumeration value="Mb" />
- <xsd:enumeration value="Gb" />
- <xsd:enumeration value="Pb" />
- <xsd:enumeration value="Eb" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- <xsd:attribute name="phaseUnit" type="xsd:duration" />
- <xsd:attributeGroup name="intervallicVolume">
- <xsd:attribute ref="urf:storageUnit" use="optional" />
- <xsd:attribute ref="urf:phaseUnit" use="optional" />
- </xsd:attributeGroup>
- <!-- End units attributes -->
- <xsd:attribute name="metric" type="xsd:token" />
- <xsd:attribute name="type" type="xsd:token" />
- <!-- Simple type definitions used to constrain values of attributes -->
- <xsd:simpleType name="domainNameType">
- <xsd:restriction base="xsd:string">
- <xsd:pattern
- value="([a-zA-Z0-9][a-zA-Z0-9'\-']*[a-zA-Z0-9]\.)*([a-zA-Z0-9][a-zA-Z0-9'\-']*[a-zA-Z0-9])?" />
- <xsd:maxLength value="255" />
- </xsd:restriction>
- </xsd:simpleType>
-</xsd:schema>
-
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-usagerecord/src/main/xsd/xmlds.xsd
----------------------------------------------------------------------
diff --git a/server-usagerecord/src/main/xsd/xmlds.xsd b/server-usagerecord/src/main/xsd/xmlds.xsd
deleted file mode 100644
index c3421c4..0000000
--- a/server-usagerecord/src/main/xsd/xmlds.xsd
+++ /dev/null
@@ -1,318 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE schema
- PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
- [
- <!ATTLIST schema
- xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
- <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
- <!ENTITY % p ''>
- <!ENTITY % s ''>
- ]>
-
-<!-- Schema for XML Signatures
- http://www.w3.org/2000/09/xmldsig#
- $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
-
- Copyright 2001 The Internet Society and W3C (Massachusetts Institute
- of Technology, Institut National de Recherche en Informatique et en
- Automatique, Keio University). All Rights Reserved.
- http://www.w3.org/Consortium/Legal/
-
- This document is governed by the W3C Software License [1] as described
- in the FAQ [2].
-
- [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
- [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
--->
-
-
-<schema xmlns="http://www.w3.org/2001/XMLSchema"
- xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
- targetNamespace="http://www.w3.org/2000/09/xmldsig#"
- version="0.1" elementFormDefault="qualified">
-
-<!-- Basic Types Defined for Signatures -->
-
-<simpleType name="CryptoBinary">
- <restriction base="base64Binary">
- </restriction>
-</simpleType>
-
-<!-- Start Signature -->
-
-<element name="Signature" type="ds:SignatureType"/>
-<complexType name="SignatureType">
- <sequence>
- <element ref="ds:SignedInfo"/>
- <element ref="ds:SignatureValue"/>
- <element ref="ds:KeyInfo" minOccurs="0"/>
- <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="Id" type="ID" use="optional"/>
-</complexType>
-
- <element name="SignatureValue" type="ds:SignatureValueType"/>
- <complexType name="SignatureValueType">
- <simpleContent>
- <extension base="base64Binary">
- <attribute name="Id" type="ID" use="optional"/>
- </extension>
- </simpleContent>
- </complexType>
-
-<!-- Start SignedInfo -->
-
-<element name="SignedInfo" type="ds:SignedInfoType"/>
-<complexType name="SignedInfoType">
- <sequence>
- <element ref="ds:CanonicalizationMethod"/>
- <element ref="ds:SignatureMethod"/>
- <element ref="ds:Reference" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="Id" type="ID" use="optional"/>
-</complexType>
-
- <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
- <complexType name="CanonicalizationMethodType" mixed="true">
- <sequence>
- <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
- <!-- (0,unbounded) elements from (1,1) namespace -->
- </sequence>
- <attribute name="Algorithm" type="anyURI" use="required"/>
- </complexType>
-
- <element name="SignatureMethod" type="ds:SignatureMethodType"/>
- <complexType name="SignatureMethodType" mixed="true">
- <sequence>
- <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
- <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
- <!-- (0,unbounded) elements from (1,1) external namespace -->
- </sequence>
- <attribute name="Algorithm" type="anyURI" use="required"/>
- </complexType>
-
-<!-- Start Reference -->
-
-<element name="Reference" type="ds:ReferenceType"/>
-<complexType name="ReferenceType">
- <sequence>
- <element ref="ds:Transforms" minOccurs="0"/>
- <element ref="ds:DigestMethod"/>
- <element ref="ds:DigestValue"/>
- </sequence>
- <attribute name="Id" type="ID" use="optional"/>
- <attribute name="URI" type="anyURI" use="optional"/>
- <attribute name="Type" type="anyURI" use="optional"/>
-</complexType>
-
- <element name="Transforms" type="ds:TransformsType"/>
- <complexType name="TransformsType">
- <sequence>
- <element ref="ds:Transform" maxOccurs="unbounded"/>
- </sequence>
- </complexType>
-
- <element name="Transform" type="ds:TransformType"/>
- <complexType name="TransformType" mixed="true">
- <choice minOccurs="0" maxOccurs="unbounded">
- <any namespace="##other" processContents="lax"/>
- <!-- (1,1) elements from (0,unbounded) namespaces -->
- <element name="XPath" type="string"/>
- </choice>
- <attribute name="Algorithm" type="anyURI" use="required"/>
- </complexType>
-
-<!-- End Reference -->
-
-<element name="DigestMethod" type="ds:DigestMethodType"/>
-<complexType name="DigestMethodType" mixed="true">
- <sequence>
- <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="Algorithm" type="anyURI" use="required"/>
-</complexType>
-
-<element name="DigestValue" type="ds:DigestValueType"/>
-<simpleType name="DigestValueType">
- <restriction base="base64Binary"/>
-</simpleType>
-
-<!-- End SignedInfo -->
-
-<!-- Start KeyInfo -->
-
-<element name="KeyInfo" type="ds:KeyInfoType"/>
-<complexType name="KeyInfoType" mixed="true">
- <choice maxOccurs="unbounded">
- <element ref="ds:KeyName"/>
- <element ref="ds:KeyValue"/>
- <element ref="ds:RetrievalMethod"/>
- <element ref="ds:X509Data"/>
- <element ref="ds:PGPData"/>
- <element ref="ds:SPKIData"/>
- <element ref="ds:MgmtData"/>
- <any processContents="lax" namespace="##other"/>
- <!-- (1,1) elements from (0,unbounded) namespaces -->
- </choice>
- <attribute name="Id" type="ID" use="optional"/>
-</complexType>
-
- <element name="KeyName" type="string"/>
- <element name="MgmtData" type="string"/>
-
- <element name="KeyValue" type="ds:KeyValueType"/>
- <complexType name="KeyValueType" mixed="true">
- <choice>
- <element ref="ds:DSAKeyValue"/>
- <element ref="ds:RSAKeyValue"/>
- <any namespace="##other" processContents="lax"/>
- </choice>
- </complexType>
-
- <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
- <complexType name="RetrievalMethodType">
- <sequence>
- <element ref="ds:Transforms" minOccurs="0"/>
- </sequence>
- <attribute name="URI" type="anyURI"/>
- <attribute name="Type" type="anyURI" use="optional"/>
- </complexType>
-
-<!-- Start X509Data -->
-
-<element name="X509Data" type="ds:X509DataType"/>
-<complexType name="X509DataType">
- <sequence maxOccurs="unbounded">
- <choice>
- <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
- <element name="X509SKI" type="base64Binary"/>
- <element name="X509SubjectName" type="string"/>
- <element name="X509Certificate" type="base64Binary"/>
- <element name="X509CRL" type="base64Binary"/>
- <any namespace="##other" processContents="lax"/>
- </choice>
- </sequence>
-</complexType>
-
-<complexType name="X509IssuerSerialType">
- <sequence>
- <element name="X509IssuerName" type="string"/>
- <element name="X509SerialNumber" type="integer"/>
- </sequence>
-</complexType>
-
-<!-- End X509Data -->
-
-<!-- Begin PGPData -->
-
-<element name="PGPData" type="ds:PGPDataType"/>
-<complexType name="PGPDataType">
- <choice>
- <sequence>
- <element name="PGPKeyID" type="base64Binary"/>
- <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
- <any namespace="##other" processContents="lax" minOccurs="0"
- maxOccurs="unbounded"/>
- </sequence>
- <sequence>
- <element name="PGPKeyPacket" type="base64Binary"/>
- <any namespace="##other" processContents="lax" minOccurs="0"
- maxOccurs="unbounded"/>
- </sequence>
- </choice>
-</complexType>
-
-<!-- End PGPData -->
-
-<!-- Begin SPKIData -->
-
-<element name="SPKIData" type="ds:SPKIDataType"/>
-<complexType name="SPKIDataType">
- <sequence maxOccurs="unbounded">
- <element name="SPKISexp" type="base64Binary"/>
- <any namespace="##other" processContents="lax" minOccurs="0"/>
- </sequence>
-</complexType>
-
-<!-- End SPKIData -->
-
-<!-- End KeyInfo -->
-
-<!-- Start Object (Manifest, SignatureProperty) -->
-
-<element name="Object" type="ds:ObjectType"/>
-<complexType name="ObjectType" mixed="true">
- <sequence minOccurs="0" maxOccurs="unbounded">
- <any namespace="##any" processContents="lax"/>
- </sequence>
- <attribute name="Id" type="ID" use="optional"/>
- <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
- <attribute name="Encoding" type="anyURI" use="optional"/>
-</complexType>
-
-<element name="Manifest" type="ds:ManifestType"/>
-<complexType name="ManifestType">
- <sequence>
- <element ref="ds:Reference" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="Id" type="ID" use="optional"/>
-</complexType>
-
-<element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
-<complexType name="SignaturePropertiesType">
- <sequence>
- <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
- </sequence>
- <attribute name="Id" type="ID" use="optional"/>
-</complexType>
-
- <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
- <complexType name="SignaturePropertyType" mixed="true">
- <choice maxOccurs="unbounded">
- <any namespace="##other" processContents="lax"/>
- <!-- (1,1) elements from (1,unbounded) namespaces -->
- </choice>
- <attribute name="Target" type="anyURI" use="required"/>
- <attribute name="Id" type="ID" use="optional"/>
- </complexType>
-
-<!-- End Object (Manifest, SignatureProperty) -->
-
-<!-- Start Algorithm Parameters -->
-
-<simpleType name="HMACOutputLengthType">
- <restriction base="integer"/>
-</simpleType>
-
-<!-- Start KeyValue Element-types -->
-
-<element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
-<complexType name="DSAKeyValueType">
- <sequence>
- <sequence minOccurs="0">
- <element name="P" type="ds:CryptoBinary"/>
- <element name="Q" type="ds:CryptoBinary"/>
- </sequence>
- <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
- <element name="Y" type="ds:CryptoBinary"/>
- <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
- <sequence minOccurs="0">
- <element name="Seed" type="ds:CryptoBinary"/>
- <element name="PgenCounter" type="ds:CryptoBinary"/>
- </sequence>
- </sequence>
-</complexType>
-
-<element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
-<complexType name="RSAKeyValueType">
- <sequence>
- <element name="Modulus" type="ds:CryptoBinary"/>
- <element name="Exponent" type="ds:CryptoBinary"/>
- </sequence>
-</complexType>
-
-<!-- End KeyValue Element-types -->
-
-<!-- End Signature -->
-
-</schema>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-usagerecord/src/test/java/TestUR.java
----------------------------------------------------------------------
diff --git a/server-usagerecord/src/test/java/TestUR.java b/server-usagerecord/src/test/java/TestUR.java
deleted file mode 100644
index 42e9000..0000000
--- a/server-usagerecord/src/test/java/TestUR.java
+++ /dev/null
@@ -1,120 +0,0 @@
-import static java.lang.Runtime.getRuntime;
-
-import java.io.IOException;
-import java.io.StringWriter;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.JAXBIntrospector;
-import javax.xml.bind.SchemaOutputResolver;
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.transform.Result;
-import javax.xml.transform.stream.StreamResult;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.ogf.usage.JobUsageRecord;
-import org.ogf.usage.v1_0.Charge;
-import org.ogf.usage.v1_0.CpuDuration;
-import org.ogf.usage.v1_0.Disk;
-import org.ogf.usage.v1_0.EndTime;
-import org.ogf.usage.v1_0.Host;
-import org.ogf.usage.v1_0.JobIdentity;
-import org.ogf.usage.v1_0.JobName;
-import org.ogf.usage.v1_0.MachineName;
-import org.ogf.usage.v1_0.Memory;
-import org.ogf.usage.v1_0.Network;
-import org.ogf.usage.v1_0.NodeCount;
-import org.ogf.usage.v1_0.PhaseResource;
-import org.ogf.usage.v1_0.Processors;
-import org.ogf.usage.v1_0.ProjectName;
-import org.ogf.usage.v1_0.Queue;
-import org.ogf.usage.v1_0.RecordIdentity;
-import org.ogf.usage.v1_0.ServiceLevel;
-import org.ogf.usage.v1_0.StartTime;
-import org.ogf.usage.v1_0.Status;
-import org.ogf.usage.v1_0.SubmitHost;
-import org.ogf.usage.v1_0.Swap;
-import org.ogf.usage.v1_0.TimeDuration;
-import org.ogf.usage.v1_0.TimeInstant;
-import org.ogf.usage.v1_0.UserIdentity;
-import org.ogf.usage.v1_0.VolumeResource;
-import org.ogf.usage.v1_0.WallDuration;
-
-public class TestUR {
- SchemaOutputResolver sink;
- StringWriter writer;
-
- String result() {
- return writer.toString();
- }
-
- @Before
- public void setUp() throws Exception {
- writer = new StringWriter();
- sink = new SchemaOutputResolver() {
- @Override
- public Result createOutput(String namespaceUri,
- String suggestedFileName) throws IOException {
- StreamResult sr = new StreamResult(writer);
- sr.setSystemId("/dev/null");
- return sr;
- }
- };
- Assert.assertNull(null);// Shut up, Eclipse!
- Assert.assertEquals("", result());
- }
-
- @Test
- public void testSchema() throws JAXBException, IOException {
- JAXBContext.newInstance(JobUsageRecord.class).generateSchema(sink);
- Assert.assertNotSame("", result());
- }
-
- @Test
- public void testSchemaCompleteness() throws JAXBException, DatatypeConfigurationException {
- JAXBIntrospector info = JAXBContext.newInstance(JobUsageRecord.class).createJAXBIntrospector();
- Assert.assertTrue(info.isElement(new Charge()));
- Assert.assertTrue(info.isElement(new CpuDuration()));
- Assert.assertTrue(info.isElement(new Disk()));
- Assert.assertTrue(info.isElement(new EndTime()));
- Assert.assertTrue(info.isElement(new Host()));
- Assert.assertTrue(info.isElement(new JobIdentity()));
- Assert.assertTrue(info.isElement(new JobName()));
- Assert.assertTrue(info.isElement(new JobUsageRecord()));
- Assert.assertTrue(info.isElement(new MachineName()));
- Assert.assertTrue(info.isElement(new Memory()));
- Assert.assertTrue(info.isElement(new Network()));
- Assert.assertTrue(info.isElement(new NodeCount()));
- Assert.assertTrue(info.isElement(new PhaseResource()));
- Assert.assertTrue(info.isElement(new Processors()));
- Assert.assertTrue(info.isElement(new ProjectName()));
- Assert.assertTrue(info.isElement(new Queue()));
- Assert.assertTrue(info.isElement(new RecordIdentity()));
- Assert.assertTrue(info.isElement(new ServiceLevel()));
- Assert.assertTrue(info.isElement(new StartTime()));
- Assert.assertTrue(info.isElement(new Status()));
- Assert.assertTrue(info.isElement(new SubmitHost()));
- Assert.assertTrue(info.isElement(new Swap()));
- Assert.assertTrue(info.isElement(new TimeDuration()));
- Assert.assertTrue(info.isElement(new TimeInstant()));
- Assert.assertTrue(info.isElement(new UserIdentity()));
- Assert.assertTrue(info.isElement(new VolumeResource()));
- Assert.assertTrue(info.isElement(new WallDuration()));
- }
-
- @Test
- public void testGenerate() throws DatatypeConfigurationException,
- JAXBException {
- JobUsageRecord ur = new JobUsageRecord();
- ur.setStatus("Completed");
- ur.addWallDuration(1000 * 65);
- ur.addHost("localhost");
- ur.addMemory(getRuntime().totalMemory() - getRuntime().freeMemory()).setType("vm");
-
- String record = ur.marshal();
- Assert.assertNotSame("", record);
- //System.out.println(record);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/.gitignore
----------------------------------------------------------------------
diff --git a/server-webapp/.gitignore b/server-webapp/.gitignore
deleted file mode 100644
index ea8c4bf..0000000
--- a/server-webapp/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/target
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/.springBeans
----------------------------------------------------------------------
diff --git a/server-webapp/.springBeans b/server-webapp/.springBeans
deleted file mode 100644
index 0b2cbbc..0000000
--- a/server-webapp/.springBeans
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beansProjectDescription>
- <version>1</version>
- <pluginVersion><![CDATA[3.3.0.201307091516-RELEASE]]></pluginVersion>
- <configSuffixes>
- <configSuffix><![CDATA[xml]]></configSuffix>
- </configSuffixes>
- <enableImports><![CDATA[true]]></enableImports>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/test/resources/example.xml</config>
- <config>src/main/webapp/WEB-INF/insecure.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/secure.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- <config>src/main/webapp/WEB-INF/partsecure.xml</config>
- </configs>
- <configSets>
- <configSet>
- <name><![CDATA[Secure Configuration]]></name>
- <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
- <incomplete>false</incomplete>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/secure.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- </configs>
- <profiles>
- </profiles>
- </configSet>
- <configSet>
- <name><![CDATA[Insecure Configuration]]></name>
- <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
- <incomplete>false</incomplete>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/insecure.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- </configs>
- <profiles>
- </profiles>
- </configSet>
- <configSet>
- <name><![CDATA[Semi-Secure Configuration]]></name>
- <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
- <incomplete>false</incomplete>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- <config>src/main/webapp/WEB-INF/partsecure.xml</config>
- </configs>
- <profiles>
- </profiles>
- </configSet>
- </configSets>
-</beansProjectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/pom.xml
----------------------------------------------------------------------
diff --git a/server-webapp/pom.xml b/server-webapp/pom.xml
deleted file mode 100644
index f4cf0ef..0000000
--- a/server-webapp/pom.xml
+++ /dev/null
@@ -1,889 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.apache.taverna.server</groupId>
- <artifactId>taverna-server</artifactId>
- <version>3.1.0-incubating-SNAPSHOT</version>
- </parent>
- <artifactId>taverna-server-webapp</artifactId>
- <packaging>war</packaging>
- <name>Apache Taverna Server Web Application Core</name>
- <description>This is the implementation of the web-app that provides the Taverna Server with its SOAP and REST faces. It relies on the worker process to handle the actual launching of workflow runs.</description>
-
- <properties>
- <version.cxf>2.7.7</version.cxf>
- <version.spring>3.2.5.RELEASE</version.spring>
- <version.spring-security>3.1.4.RELEASE</version.spring-security>
- <version.asm>3.3.1</version.asm>
- <version.smack>3.2.1</version.smack>
- <version.jdoapi>3.0.1</version.jdoapi>
- <forker.module>taverna-server-unix-forker</forker.module>
- <util.dir>${project.build.directory}/${project.build.finalName}/WEB-INF/classes/util</util.dir>
- <cmdline.dir>${util.dir}/taverna-commandline-${edition.commandline}-${version.commandline}</cmdline.dir>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-frontend-jaxws</artifactId>
- <version>${version.cxf}</version>
- <exclusions>
- <exclusion>
- <artifactId>jaxb-impl</artifactId>
- <groupId>com.sun.xml.bind</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-frontend-jaxrs</artifactId>
- <version>${version.cxf}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-transports-http</artifactId>
- <version>${version.cxf}</version>
- </dependency>
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-core</artifactId>
- <version>${version.spring-security}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-web</artifactId>
- <version>${version.spring-security}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- <version>${version.spring-security}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>${version.spring}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId><!--$NO-MVN-MAN-VER$-->
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-port-description</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-runinterface</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-usagerecord</artifactId>
- <version>${project.parent.version}</version>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-worker</artifactId>
- <version>${project.parent.version}</version>
- <classifier>jar-with-dependencies</classifier>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>${forker.module}</artifactId>
- <version>${project.parent.version}</version>
- <classifier>jar-with-dependencies</classifier>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-rmidaemon</artifactId>
- <version>${project.parent.version}</version>
- <classifier>jar-with-dependencies</classifier>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.5</version>
- <scope>provided</scope>
- </dependency>
- <!--
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-annotations</artifactId>
- <version>3.4.0.GA</version>
- <scope>compile</scope>
- </dependency>
- -->
- <!--
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-validator</artifactId>
- <version>4.0.2.GA</version>
- <scope>compile</scope>
- </dependency>
- -->
- <dependency>
- <groupId>org.apache.derby</groupId>
- <artifactId>derby</artifactId>
- <version>10.10.1.1</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>commons-dbcp</groupId>
- <artifactId>commons-dbcp</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.jdo</groupId>
- <artifactId>jdo-api</artifactId>
- <version>3.0.1</version>
- </dependency>
- <dependency>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-api-jdo</artifactId>
- <version>[3.2.0, 3.2.99)</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-core</artifactId>
- <version>3.2.10</version>
- </dependency>
- <dependency>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-rdbms</artifactId>
- <version>[3.2.0, 3.2.99)</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.jdo</groupId>
- <artifactId>jdo2-core</artifactId>
- <version>2.0</version>
- </dependency>
- <dependency>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- </dependency>
- <dependency>
- <groupId>net.sf.mime-util</groupId>
- <artifactId>mime-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.twitter4j</groupId>
- <artifactId>twitter4j-core</artifactId>
- <version>[3.0,)</version>
- </dependency>
- <dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib</artifactId>
- <version>3.0</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.7.4</version>
- </dependency>
- <dependency>
- <groupId>org.igniterealtime.smack</groupId>
- <artifactId>smack</artifactId>
- <version>${version.smack}</version>
- </dependency>
- <dependency>
- <groupId>org.igniterealtime.smack</groupId>
- <artifactId>smackx</artifactId>
- <version>${version.smack}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- </dependency>
- <dependency>
- <groupId>javax.annotation</groupId>
- <artifactId>jsr250-api</artifactId>
- <version>1.0</version>
- </dependency>
- <dependency>
- <groupId>org.apache.abdera</groupId>
- <artifactId>abdera-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.abdera</groupId>
- <artifactId>abdera-parser</artifactId>
- <version>1.1.3</version>
- <scope>runtime</scope>
- <exclusions>
- <exclusion>
- <artifactId>xercesImpl</artifactId>
- <groupId>xerces</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15on</artifactId>
- <version>1.49</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context-support</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.7.4</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>javax.mail</groupId>
- <artifactId>mail</artifactId>
- <version>1.4.4</version>
- <scope>runtime</scope>
- <exclusions>
- <exclusion>
- <groupId>javax.activation</groupId>
- <artifactId>activation</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.velocity</groupId>
- <artifactId>velocity</artifactId>
- <version>1.7</version>
- </dependency>
- <dependency>
- <groupId>org.apache.cxf</groupId>
- <artifactId>cxf-rt-rs-extension-providers</artifactId>
- <version>${version.cxf}</version>
- </dependency>
- <dependency>
- <groupId>org.codehaus.jettison</groupId>
- <artifactId>jettison</artifactId>
- <version>1.3.4</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.taverna.language</groupId>
- <artifactId>taverna-scufl2-api</artifactId>
- <version>${taverna.language.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.taverna.language</groupId>
- <artifactId>taverna-scufl2-t2flow</artifactId>
- <version>${taverna.language.version}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.taverna.language</groupId>
- <artifactId>taverna-scufl2-wfbundle</artifactId>
- <version>${taverna.language.version}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-compress</artifactId>
- <version>1.4.1</version>
- </dependency>
- </dependencies>
-
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-runinterface</artifactId>
- <version>${project.parent.version}</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>asm</groupId>
- <artifactId>asm</artifactId>
- <version>${version.asm}</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>com.sun.xml.bind</groupId>
- <artifactId>jaxb-impl</artifactId>
- <version>2.2.7</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-aop</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-beans</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jdbc</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-tx</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-context</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-expression</artifactId>
- <version>${version.spring}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.abdera</groupId>
- <artifactId>abdera-core</artifactId>
- <version>1.1.3</version>
- </dependency>
- <dependency>
- <groupId>org.codehaus.woodstox</groupId>
- <artifactId>wstx-asl</artifactId>
- <version>4.0.6</version>
- </dependency>
- <dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-javamail_1.4_spec</artifactId>
- <version>1.7.1</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.codehaus.woodstox</groupId>
- <artifactId>woodstox-core-asl</artifactId>
- <version>4.2.0</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>jaxen</groupId>
- <artifactId>jaxen</artifactId>
- <version>1.1.4</version>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
- <build>
- <finalName>TavernaServer.${project.parent.version}</finalName>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>tomcat-maven-plugin</artifactId>
- <version>1.1</version>
- <configuration>
- <server>deployhost</server>
- <path>/taverna-server</path>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <encoding>US-ASCII</encoding>
- <source>1.7</source>
- <target>1.7</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-maven-plugin</artifactId>
- <version>3.3.0-release</version>
- <configuration>
- <jdkLogConfiguration>${project.basedir}/src/build/resources/datanucleus-log.properties</jdkLogConfiguration>
- <log4jConfiguration>${project.basedir}/src/build/resources/datanucleus_log4j.properties</log4jConfiguration>
- <verbose>true</verbose>
- </configuration>
- <dependencies>
- <!-- Sucks that I have to say these explicitly -->
- <dependency>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-core</artifactId>
- <version>3.2.10</version>
- </dependency>
- <dependency>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-enhancer</artifactId>
- <version>3.1.1</version>
- </dependency>
- <dependency>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-api-jdo</artifactId>
- <version>3.2.5</version>
- </dependency>
- <dependency>
- <groupId>javax.jdo</groupId>
- <artifactId>jdo-api</artifactId>
- <version>${version.jdoapi}</version>
- </dependency>
- </dependencies>
- </plugin>
- <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <versionRange>[2.0,)</versionRange>
- <goals>
- <goal>copy-dependencies</goal>
- <goal>unpack</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <ignore />
- </action>
- </pluginExecution>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-maven-plugin</artifactId>
- <versionRange>3.3.0-release</versionRange>
- <goals>
- <goal>enhance</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute />
- </action>
- </pluginExecution>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>pl.project13.maven</groupId>
- <artifactId>git-commit-id-plugin</artifactId>
- <versionRange>[2.1.4,)</versionRange>
- <goals>
- <goal>revision</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute />
- </action>
- </pluginExecution>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-maven-plugin</artifactId>
- <versionRange>3.3.0-release</versionRange>
- <goals>
- <goal>schema-create</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <ignore />
- </action>
- </pluginExecution>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>net.alchim31.maven</groupId>
- <artifactId>yuicompressor-maven-plugin</artifactId>
- <versionRange>[1.0.0,)</versionRange>
- <goals>
- <goal>compress</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <execute/>
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
- </plugins>
- </pluginManagement>
-
- <defaultGoal>package</defaultGoal>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-executable-library-jars</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-worker</artifactId>
- <version>${project.parent.version}</version>
- <classifier>jar-with-dependencies</classifier>
- <overWrite>false</overWrite>
- <destFileName>server.worker.jar</destFileName>
- </artifactItem>
- <artifactItem>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>${forker.module}</artifactId>
- <version>${project.parent.version}</version>
- <classifier>jar-with-dependencies</classifier>
- <overWrite>false</overWrite>
- <destFileName>secure.fork.jar</destFileName>
- </artifactItem>
- <artifactItem>
- <groupId>${project.parent.groupId}</groupId>
- <artifactId>taverna-server-rmidaemon</artifactId>
- <version>${project.parent.version}</version>
- <classifier>jar-with-dependencies</classifier>
- <overWrite>false</overWrite>
- <destFileName>rmi.daemon.jar</destFileName>
- </artifactItem>
- </artifactItems>
- <outputDirectory>${util.dir}</outputDirectory>
- <overWriteReleases>false</overWriteReleases>
- <overWriteSnapshots>true</overWriteSnapshots>
- <excludeTransitive>true</excludeTransitive>
- </configuration>
- </execution>
- <execution>
- <id>unpack-taverna-commandline</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.taverna.commandline</groupId>
- <artifactId>taverna-commandline</artifactId>
- <version>${taverna.commandline.version}</version>
- <classifier>bin</classifier>
- <type>zip</type>
- <classifier>bin</classifier>
- <outputDirectory>${util.dir}</outputDirectory>
- </artifactItem>
- </artifactItems>
- <overWriteReleases>false</overWriteReleases>
- <overWriteSnapshots>true</overWriteSnapshots>
- <excludeTransitive>true</excludeTransitive>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.datanucleus</groupId>
- <artifactId>datanucleus-maven-plugin</artifactId>
- <configuration>
- <fork>false</fork>
- <metadataIncludes>
- org/taverna/server/master/*.class,
- org/taverna/server/master/identity/*.class,
- org/taverna/server/master/localworker/*.class,
- org/taverna/server/master/notification/atom/*.class,
- org/taverna/server/master/usage/*.class,
- org/taverna/server/master/worker/*.class
- </metadataIncludes>
- </configuration>
- <executions>
- <execution>
- <id>enhance</id>
- <phase>process-classes</phase>
- <goals>
- <goal>enhance</goal>
- </goals>
- </execution>
- <!--
- <execution>
- <id>gen-db-schema</id>
- <phase>process-classes</phase>
- <goals>
- <goal>schema-create</goal>
- </goals>
- <configuration>
- <completeDdl>true</completeDdl>
- <ddlFile>${util.dir}/schema.sql</ddlFile>
- </configuration>
- </execution>
- -->
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <encoding>US-ASCII</encoding>
- <source>1.7</source>
- <target>1.7</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>pl.project13.maven</groupId>
- <artifactId>git-commit-id-plugin</artifactId>
- <version>2.1.4</version>
- <executions>
- <execution>
- <id>buildinfo</id>
- <phase>generate-resources</phase>
- <goals>
- <goal>revision</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <dotGitDirectory>${project.basedir}/../.git</dotGitDirectory>
- <prefix>git</prefix>
- <verbose>true</verbose>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <version>2.4</version>
- <configuration>
- <webXml>src/main/webapp/WEB-INF/web-sec.xml</webXml>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-eclipse-plugin</artifactId>
- <configuration>
- <additionalProjectnatures>
- <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
- </additionalProjectnatures>
- <additionalConfig>
- <file>
- <name>.springBeans</name>
- <content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
-<beansProjectDescription>
- <version>1</version>
- <pluginVersion>3.3.0.201307091516-RELEASE</pluginVersion>
- <configSuffixes>
- <configSuffix>xml</configSuffix>
- </configSuffixes>
- <enableImports>true</enableImports>
- <configs>
- <config>src/main/webapp/WEB-INF/partsecure.xml</config>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/insecure.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/secure.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- </configs>
- <configSets>
- <configSet>
- <name>Secure Configuration</name>
- <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
- <incomplete>false</incomplete>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/secure.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- </configs>
- <profiles>
- </profiles>
- </configSet>
- <configSet>
- <name>Insecure Configuration</name>
- <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
- <incomplete>false</incomplete>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/insecure.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- </configs>
- <profiles>
- </profiles>
- </configSet>
- <configSet>
- <name>Semi-Secure Configuration</name>
- <allowBeanDefinitionOverriding>true</allowBeanDefinitionOverriding>
- <incomplete>false</incomplete>
- <configs>
- <config>src/main/webapp/WEB-INF/beans.xml</config>
- <config>src/main/webapp/WEB-INF/providers.xml</config>
- <config>src/main/webapp/WEB-INF/webappBeans.xml</config>
- <config>src/main/webapp/WEB-INF/partsecure.xml</config>
- </configs>
- <profiles>
- </profiles>
- </configSet>
- </configSets>
-</beansProjectDescription>]]></content>
- </file>
- </additionalConfig>
- </configuration>
- </plugin>
- <plugin>
- <groupId>net.alchim31.maven</groupId>
- <artifactId>yuicompressor-maven-plugin</artifactId>
- <version>1.4.0</version>
- <executions>
- <execution>
- <goals>
- <goal>compress</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <excludes>
- <exclude>**/*.min.js</exclude>
- </excludes>
- <nosuffix>true</nosuffix>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <executions>
- <execution>
- <id>override-executeworkflow-scripts</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <outputDirectory>${cmdline.dir}</outputDirectory>
- <resources>
- <resource>
- <directory>src/main/replacementscripts</directory>
- <filtering>false</filtering>
- </resource>
- </resources>
- <overwrite>true</overwrite>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <version>1.2.1</version>
- <executions>
- <execution>
- <id>improve-registry-coverage</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>exec</goal>
- </goals>
- <configuration>
- <executable>/bin/sh</executable>
- <workingDirectory>${cmdline.dir}</workingDirectory>
- <environmentVariables>
- <RAVEN_APPHOME>${cmdline.dir}</RAVEN_APPHOME>
- </environmentVariables>
- <arguments>
- <argument>./executeworkflow.sh</argument>
- <argument>-help</argument>
- </arguments>
- <outputFile>/dev/null</outputFile>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- <resource>
- <directory>src/main/webapp</directory>
- <filtering>false</filtering>
- </resource>
- </resources>
- </build>
-
- <profiles>
- <profile>
- <id>unix</id>
- <properties>
- <forker.module>taverna-server-unix-forker</forker.module>
- </properties>
- </profile>
- <profile>
- <id>win</id>
- <properties>
- <!-- This doesn't exist yet. -->
- <forker.module>taverna-server-win-forker</forker.module>
- </properties>
- </profile>
- <profile>
- <id>nosec</id>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <configuration>
- <webXml>src/main/webapp/WEB-INF/web-nosec.xml</webXml>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- <profile>
- <id>partsec</id>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-war-plugin</artifactId>
- <configuration>
- <webXml>src/main/webapp/WEB-INF/web-partsec.xml</webXml>
- </configuration>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-</project>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/build/resources/datanucleus_log4j.properties
----------------------------------------------------------------------
diff --git a/server-webapp/src/build/resources/datanucleus_log4j.properties b/server-webapp/src/build/resources/datanucleus_log4j.properties
deleted file mode 100644
index 6707f55..0000000
--- a/server-webapp/src/build/resources/datanucleus_log4j.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-log4j.rootLogger=info, R
-log4j.appender.R=org.apache.log4j.ConsoleAppender
-log4j.appender.R.layout=org.apache.log4j.PatternLayout
-log4j.appender.R.layout.ConversionPattern=%d{yyyyMMdd'T'HHmmss.SSS} %-5p %c{1} %C{1} - %m%n
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java b/server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java
deleted file mode 100644
index f5259bd..0000000
--- a/server-webapp/src/main/java/org/taverna/server/master/ContentsDescriptorBuilder.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2010-2011 The University of Manchester
- *
- * See the file "LICENSE" for license terms.
- */
-package org.taverna.server.master;
-
-import static eu.medsea.util.MimeUtil.getMimeType;
-import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM_TYPE;
-import static javax.ws.rs.core.UriBuilder.fromUri;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.taverna.server.master.common.Uri.secure;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-import org.apache.commons.logging.Log;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.exceptions.FilesystemAccessException;
-import org.taverna.server.master.exceptions.NoDirectoryEntryException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.UriBuilderFactory;
-import org.taverna.server.master.utils.FilenameUtils;
-import org.taverna.server.port_description.AbsentValue;
-import org.taverna.server.port_description.AbstractPortDescription;
-import org.taverna.server.port_description.AbstractValue;
-import org.taverna.server.port_description.ErrorValue;
-import org.taverna.server.port_description.InputDescription;
-import org.taverna.server.port_description.InputDescription.InputPort;
-import org.taverna.server.port_description.LeafValue;
-import org.taverna.server.port_description.ListValue;
-import org.taverna.server.port_description.OutputDescription;
-import org.taverna.server.port_description.OutputDescription.OutputPort;
-
-import uk.org.taverna.scufl2.api.container.WorkflowBundle;
-import uk.org.taverna.scufl2.api.core.Workflow;
-import uk.org.taverna.scufl2.api.port.InputWorkflowPort;
-import uk.org.taverna.scufl2.api.port.OutputWorkflowPort;
-
-/**
- * A class that is used to build descriptions of the contents of a workflow
- * run's filesystem.
- *
- * @author Donal Fellows
- */
-public class ContentsDescriptorBuilder {
- private Log log = getLog("Taverna.Server.Webapp");
- private FilenameUtils fileUtils;
- private UriBuilderFactory uriBuilderFactory;
-
- @Required
- public void setUriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
- this.uriBuilderFactory = uriBuilderFactory;
- }
-
- @Required
- public void setFileUtils(FilenameUtils fileUtils) {
- this.fileUtils = fileUtils;
- }
-
- // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- private Workflow fillInFromWorkflow(TavernaRun run, UriBuilder ub,
- AbstractPortDescription portDesc) throws IOException {
- WorkflowBundle bundle = run.getWorkflow().getScufl2Workflow();
- bundle.getMainWorkflow().getInputPorts();
- portDesc.fillInBaseData(bundle.getMainWorkflow()
- .getWorkflowIdentifier().toString(), run.getId(), ub.build());
- return bundle.getMainWorkflow();
- }
-
- /**
- * Computes the depth of value in a descriptor.
- *
- * @param value
- * The value description to characterise.
- * @return Its depth (i.e., the depth of the port outputting the value) or
- * <tt>null</tt> if that is impossible to determine.
- */
- private Integer computeDepth(AbstractValue value) {
- if (value instanceof ListValue) {
- int mv = 1;
- for (AbstractValue v : ((ListValue) value).contents) {
- Integer d = computeDepth(v);
- if (d != null && mv <= d)
- mv = d + 1;
- }
- return mv;
- } else if (value instanceof LeafValue || value instanceof ErrorValue)
- return 0;
- else
- return null;
- }
-
- /**
- * Build a description of a leaf value.
- *
- * @param file
- * The file representing the value.
- * @return A value descriptor.
- * @throws FilesystemAccessException
- * If anything goes wrong.
- */
- private LeafValue constructLeafValue(File file)
- throws FilesystemAccessException {
- LeafValue v = new LeafValue();
- v.fileName = file.getFullName();
- v.byteLength = file.getSize();
- try {
- byte[] head = file.getContents(0, 1024);
- v.contentType = getMimeType(new ByteArrayInputStream(head));
- } catch (Exception e) {
- v.contentType = APPLICATION_OCTET_STREAM_TYPE.toString();
- }
- return v;
- }
-
- /**
- * Build a description of an error value.
- *
- * @param file
- * The file representing the error.
- * @return A value descriptor.
- * @throws FilesystemAccessException
- * If anything goes wrong.
- */
- private ErrorValue constructErrorValue(File file)
- throws FilesystemAccessException {
- ErrorValue v = new ErrorValue();
- v.fileName = file.getFullName();
- v.byteLength = file.getSize();
- return v;
- }
-
- /**
- * Build a description of a list value.
- *
- * @param dir
- * The directory representing the list.
- * @param ub
- * The factory for URIs.
- * @return A value descriptor.
- * @throws FilesystemAccessException
- * If anything goes wrong.
- */
- private ListValue constructListValue(Directory dir, UriBuilder ub)
- throws FilesystemAccessException {
- ListValue v = new ListValue();
- v.length = 0;
- Set<DirectoryEntry> contents = new HashSet<>(dir.getContents());
- Iterator<DirectoryEntry> it = contents.iterator();
- while (it.hasNext())
- if (!it.next().getName().matches("^[0-9]+([.].*)?$"))
- it.remove();
- for (int i = 1; !contents.isEmpty(); i++) {
- String exact = Integer.toString(i);
- AbstractValue subval = constructValue(contents, ub, exact);
- v.contents.add(subval);
- if (!(subval instanceof AbsentValue)) {
- v.length = i;
- String pfx = i + ".";
- for (DirectoryEntry de : contents)
- if (de.getName().equals(exact)
- || de.getName().startsWith(pfx)) {
- contents.remove(de);
- break;
- }
- }
- }
- return v;
- }
-
- /**
- * Build a value description.
- *
- * @param parentContents
- * The contents of the parent directory.
- * @param ub
- * The factory for URIs.
- * @param name
- * The name of the value's file/directory representative.
- * @return A value descriptor.
- * @throws FilesystemAccessException
- * If anything goes wrong.
- */
- private AbstractValue constructValue(
- Collection<DirectoryEntry> parentContents, UriBuilder ub,
- String name) throws FilesystemAccessException {
- String error = name + ".error";
- String prefix = name + ".";
- for (DirectoryEntry entry : parentContents) {
- AbstractValue av;
- if (entry.getName().equals(error) && entry instanceof File) {
- av = constructErrorValue((File) entry);
- } else if (!entry.getName().equals(name)
- && !entry.getName().startsWith(prefix))
- continue;
- else if (entry instanceof File)
- av = constructLeafValue((File) entry);
- else
- av = constructListValue((Directory) entry, ub);
- String fullPath = entry.getFullName().replaceFirst("^/", "");
- av.href = ub.clone().path(fullPath).build();
- return av;
- }
- return new AbsentValue();
- }
-
- /**
- * Construct a description of the outputs of a workflow run.
- *
- * @param run
- * The workflow run whose outputs are to be described.
- * @param ui
- * The origin for URIs.
- * @return The description, which can be serialized to XML.
- * @throws FilesystemAccessException
- * If something goes wrong reading the directories.
- * @throws NoDirectoryEntryException
- * If something goes wrong reading the directories.
- */
- public OutputDescription makeOutputDescriptor(TavernaRun run, UriInfo ui)
- throws FilesystemAccessException, NoDirectoryEntryException {
- OutputDescription descriptor = new OutputDescription();
- try {
- UriBuilder ub = getRunUriBuilder(run, ui);
- Workflow dataflow = fillInFromWorkflow(run, ub, descriptor);
- Collection<DirectoryEntry> outs = null;
- ub = ub.path("wd/{path}");
- for (OutputWorkflowPort output : dataflow.getOutputPorts()) {
- OutputPort p = descriptor.addPort(output.getName());
- if (run.getOutputBaclavaFile() == null) {
- if (outs == null)
- outs = fileUtils.getDirectory(run, "out").getContents();
- p.output = constructValue(outs, ub, p.name);
- p.depth = computeDepth(p.output);
- }
- }
- } catch (IOException e) {
- log.info("failure in conversion to .scufl2", e);
- }
- return descriptor;
- }
-
- private UriBuilder getRunUriBuilder(TavernaRun run, UriInfo ui) {
- if (ui == null)
- return secure(uriBuilderFactory.getRunUriBuilder(run));
- else
- return secure(fromUri(ui.getAbsolutePath().toString()
- .replaceAll("/(out|in)put/?$", "")));
- }
-
- /**
- * Constructs input descriptions.
- *
- * @param run
- * The run to build for.
- * @param ui
- * The mechanism for building URIs.
- * @return The description of the <i>expected</i> inputs of the run.
- */
- public InputDescription makeInputDescriptor(TavernaRun run, UriInfo ui) {
- InputDescription desc = new InputDescription();
- try {
- UriBuilder ub = getRunUriBuilder(run, ui);
- Workflow workflow = fillInFromWorkflow(run, ub, desc);
- ub = ub.path("input/{name}");
- for (InputWorkflowPort port : workflow.getInputPorts()) {
- InputPort in = desc.addPort(port.getName());
- in.href = ub.build(in.name);
- try {
- in.depth = port.getDepth();
- } catch (NumberFormatException ex) {
- in.depth = null;
- }
- }
- } catch (IOException e) {
- log.info("failure in conversion to .scufl2", e);
- }
- return desc;
- }
-}
[28/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js b/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js
deleted file mode 100644
index 7835454..0000000
--- a/server-webapp/src/main/resources/static/jquery-ui-1.8.23.custom.min.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.core.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.23",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number
"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelectio
n:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.cre
atePseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScr
oll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;return b[d]>0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.widget.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){return c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}}),d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;return e=!f&&g.length?a.extend.apply(null,[!0,e
].concat(g)):e,f&&e.charAt(0)==="_"?h:(f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b)return h=f,!1}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))}),h)}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(
this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}return this._setOptions(e),this},_setOptions:function(b){var c=this;return a.each(b,function(a,b){c._setOption(a,b)}),this},_setOption:function(a,b){return this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||
c.isDefaultPrevented())}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.mouse.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent"))return a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(b){if(c)return;this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.del
ay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted)return b.preventDefault(),!0}return!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0,!0},_mouseMove:function(b){return!a.browser.msie||document.documentMode>=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this.
_mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.position.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),
n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left
)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.
curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),a.curCSS||(a.curCSS=a.css),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuer
y);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.draggable.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!this.element.data("draggable"))return;return this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy(),this},_mouseCapture:function(b){var c=this.options;return thi
s.helper||c.disabled||a(b.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(b),this.handle?(c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(b){var c=this.options;return this.helper=this._createHelper(b),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),rel
ative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment(),this._trigger("start",b)===!1?(this._clear(),!1):(this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b),!0)},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1)return this._mouseUp({}),!1;this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!
this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);var d=this.element[0],e=!1;while(d&&(d=d.parentNode))d==document&&(e=!0);if(!e&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var f=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){f._trigger("stop",b)!==!1&&f._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){return this.options.iframeFix===!0&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b),a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(b){var c=!this.options.handle
||!a(this.options.handle,this.element).length?!0:!1;return a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)}),c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute"),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){thi
s.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop")
,10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|wind
ow|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="abs
olute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h
=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.left<h[0]&&(f=h[0]+this.offset.click.left),b.pageY-this.offset.click.top<h[1]&&(g=h[1]+this.offset.click.top),b.pageX-this.offset.click.left>h[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.top<h[1]||j-this.offset.click.top>h[3]?j-this.offset.click.top<h[1]?j+c.grid[1]:j-c.grid[1]:j:j;var k=c.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0]:this.originalPageX;f=h?k-this.offset.click.left<h[0]||k-this.offset.click.left>h[2]?k-this.offset.click.left<h[0]?k+c.grid[0]:k-c.grid[0]:k:k}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&a.browser.version
<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(b,c,d){return d=d||this._uiHash(),a.ui.plugin.call(this,b,[c,d]),b=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),a.Widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(a){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),a.extend(a.ui.draggable,{version:"1.8.23"}),a.ui.plugin.add("draggable","connectToSortable",{start:function(b,c){var d=a(
this).data("draggable"),e=d.options,f=a.extend({},c,{item:d.element});d.sortables=[],a(e.connectToSortable).each(function(){var c=a.data(this,"sortable");c&&!c.options.disabled&&(d.sortables.push({instance:c,shouldRevert:c.options.revert}),c.refreshPositions(),c._trigger("activate",b,f))})},stop:function(b,c){var d=a(this).data("draggable"),e=a.extend({},c,{item:d.element});a.each(d.sortables,function(){this.instance.isOver?(this.instance.isOver=0,d.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(b),this.instance.options.helper=this.instance.options._helper,d.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",b,e))})},drag:function(b,c){var d=a(this).data("draggable"),e=this,f=function(b){var c=this.offset.click.top,d=this.offset.click.left,e=this.positionAbs.top,f=this.positionAbs.left,g
=b.height,h=b.width,i=b.top,j=b.left;return a.ui.isOver(e+c,f+d,i,j,g,h)};a.each(d.sortables,function(f){this.instance.positionAbs=d.positionAbs,this.instance.helperProportions=d.helperProportions,this.instance.offset.click=d.offset.click,this.instance._intersectsWith(this.instance.containerCache)?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=a(e).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return c.helper[0]},b.target=this.instance.currentItem[0],this.instance._mouseCapture(b,!0),this.instance._mouseStart(b,!0,!0),this.instance.offset.click.top=d.offset.click.top,this.instance.offset.click.left=d.offset.click.left,this.instance.offset.parent.left-=d.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=d.offset.parent.top-this.instance.offset.parent.top,d._trigger("toSortable",b),d.dropped=
this.instance.element,d.currentItem=d.element,this.instance.fromOutside=d),this.instance.currentItem&&this.instance._mouseDrag(b)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",b,this.instance._uiHash(this.instance)),this.instance._mouseStop(b,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),d._trigger("fromSortable",b),d.dropped=!1)})}}),a.ui.plugin.add("draggable","cursor",{start:function(b,c){var d=a("body"),e=a(this).data("draggable").options;d.css("cursor")&&(e._cursor=d.css("cursor")),d.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;d._cursor&&a("body").css("cursor",d._cursor)}}),a.ui.plugin.add("draggable","opacity",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("opacity")&&(e._opacity=d.css("opacity")
),d.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;d._opacity&&a(c.helper).css("opacity",d._opacity)}}),a.ui.plugin.add("draggable","scroll",{start:function(b,c){var d=a(this).data("draggable");d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"&&(d.overflowOffset=d.scrollParent.offset())},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=!1;if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"){if(!e.axis||e.axis!="x")d.overflowOffset.top+d.scrollParent[0].offsetHeight-b.pageY<e.scrollSensitivity?d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop+e.scrollSpeed:b.pageY-d.overflowOffset.top<e.scrollSensitivity&&(d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop-e.scrollSpeed);if(!e.axis||e.axis!="y")d.overflowOffset.left+d.scrollParent[0].offsetWidth-b.pageX<e.scrollSensitivity?d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft+e.scrollSpeed:b.pageX-d.overflowOffset.left<e.scrollSensit
ivity&&(d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft-e.scrollSpeed)}else{if(!e.axis||e.axis!="x")b.pageY-a(document).scrollTop()<e.scrollSensitivity?f=a(document).scrollTop(a(document).scrollTop()-e.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<e.scrollSensitivity&&(f=a(document).scrollTop(a(document).scrollTop()+e.scrollSpeed));if(!e.axis||e.axis!="y")b.pageX-a(document).scrollLeft()<e.scrollSensitivity?f=a(document).scrollLeft(a(document).scrollLeft()-e.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<e.scrollSensitivity&&(f=a(document).scrollLeft(a(document).scrollLeft()+e.scrollSpeed))}f!==!1&&a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(d,b)}}),a.ui.plugin.add("draggable","snap",{start:function(b,c){var d=a(this).data("draggable"),e=d.options;d.snapElements=[],a(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var b=a(this),c=b.offset();this!=d.element[0]&&d.snapElements.pu
sh({item:this,width:b.outerWidth(),height:b.outerHeight(),top:c.top,left:c.left})})},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=e.snapTolerance,g=c.offset.left,h=g+d.helperProportions.width,i=c.offset.top,j=i+d.helperProportions.height;for(var k=d.snapElements.length-1;k>=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f<g&&g<m+f&&n-f<i&&i<o+f||l-f<g&&g<m+f&&n-f<j&&j<o+f||l-f<h&&h<m+f&&n-f<i&&i<o+f||l-f<h&&h<m+f&&n-f<j&&j<o+f)){d.snapElements[k].snapping&&d.options.snap.release&&d.options.snap.release.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=!1;continue}if(e.snapMode!="inner"){var p=Math.abs(n-j)<=f,q=Math.abs(o-i)<=f,r=Math.abs(l-h)<=f,s=Math.abs(m-g)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n-d.helperProportions.height,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o,left
:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l-d.helperProportions.width}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m}).left-d.margins.left)}var t=p||q||r||s;if(e.snapMode!="outer"){var p=Math.abs(n-i)<=f,q=Math.abs(o-j)<=f,r=Math.abs(l-g)<=f,s=Math.abs(m-h)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o-d.helperProportions.height,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m-d.helperProportions.width}).left-d.margins.left)}!d.snapElements[k].snapping&&(p||q||r||s||t)&&d.options.snap.snap&&d.options.snap.snap.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=p||q||r||s||t}}}),a.ui.plugin.add("draggable","stack",{st
art:function(b,c){var d=a(this).data("draggable").options,e=a.makeArray(a(d.stack)).sort(function(b,c){return(parseInt(a(b).css("zIndex"),10)||0)-(parseInt(a(c).css("zIndex"),10)||0)});if(!e.length)return;var f=parseInt(e[0].style.zIndex)||0;a(e).each(function(a){this.style.zIndex=f+a}),this[0].style.zIndex=f+e.length}}),a.ui.plugin.add("draggable","zIndex",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("zIndex")&&(e._zIndex=d.css("zIndex")),d.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;d._zIndex&&a(c.helper).css("zIndex",d._zIndex)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.droppable.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var b=this.options,c=b.accept;this.isover=0,this.isout=1,this.accept=a.isFunction(c)?c:function(a){return a.is(c)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},a.ui.ddmanager.droppables[b.scope]=a.ui.ddmanager.droppables[b.scope]||[],a.ui.ddmanager.droppables[b.scope].push(this),b.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++)b[c]==this&&b.splice(c,1);return this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable"),this},_setOption:function(b,c){b=="accept"&&(this.accept=a.isFunction(c)?c:function(a){return a.is(c)}),a.Widget.prototype._setOption.apply(this,arguments)},_activate:function(b){var c=
a.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),c&&this._trigger("activate",b,this.ui(c))},_deactivate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),c&&this._trigger("deactivate",b,this.ui(c))},_over:function(b){var c=a.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return;this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",b,this.ui(c)))},_out:function(b){var c=a.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return;this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;r
eturn this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&&b.accept.call(b.element[0],d.currentItem||d.element)&&a.ui.intersect(d,a.extend(b,{offset:b.element.offset()}),b.options.tolerance))return e=!0,!1}),e?!1:this.accept.call(this.element[0],d.currentItem||d.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",b,this.ui(d)),this.element):!1},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}}),a.extend(a.ui.droppable,{version:"1.8.23"}),a.ui.intersect=function(b,c,d){if(!c.offset)return!1;var e=(b.positionAbs||b.position.absolute).left,f=e+b.helperProportions.width,g=(b.positionAbs||b.position.absolute).top,h=g+b.helperProportions.height,i=c.offset.lef
t,j=i+c.proportions.width,k=c.offset.top,l=k+c.proportions.height;switch(d){case"fit":return i<=e&&f<=j&&k<=g&&h<=l;case"intersect":return i<e+b.helperProportions.width/2&&f-b.helperProportions.width/2<j&&k<g+b.helperProportions.height/2&&h-b.helperProportions.height/2<l;case"pointer":var m=(b.positionAbs||b.position.absolute).left+(b.clickOffset||b.offset.click).left,n=(b.positionAbs||b.position.absolute).top+(b.clickOffset||b.offset.click).top,o=a.ui.isOver(n,m,k,i,c.proportions.height,c.proportions.width);return o;case"touch":return(g>=k&&g<=l||h>=k&&h<=l||g<k&&h>l)&&(e>=i&&e<=j||f>=i&&f<=j||e<i&&f>j);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();g:for(var h=0;h<d.length;h++){if(d[h].options.disabled||b&&!d[h].accept.call(d[h].element[0],b.currentItem||b.element))continue;for(var i=0;i<f.lengt
h;i++)if(f[i]==d[h].element[0]){d[h].proportions.height=0;continue g}d[h].visible=d[h].element.css("display")!="none";if(!d[h].visible)continue;e=="mousedown"&&d[h]._activate.call(d[h],c),d[h].offset=d[h].element.offset(),d[h].proportions={width:d[h].element[0].offsetWidth,height:d[h].element[0].offsetHeight}}},drop:function(b,c){var d=!1;return a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)&&(d=this._drop.call(this,c)||d),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],b.currentItem||b.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,c))}),d},dragStart:function(b,c){b.element.parents(":not(body,html)").bind("scroll.droppable",function(){b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)})},drag:function(b,c){b.options.refreshPositions&&a.ui.ddmanager.prepareOffsets(b,c),a.each(a.ui.ddmanager.droppables[b.opt
ions.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var d=a.ui.intersect(b,this,this.options.tolerance),e=!d&&this.isover==1?"isout":d&&this.isover==0?"isover":null;if(!e)return;var f;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");g.length&&(f=a.data(g[0],"droppable"),f.greedyChild=e=="isover"?1:0)}f&&e=="isover"&&(f.isover=0,f.isout=1,f._out.call(f,c)),this[e]=1,this[e=="isout"?"isover":"isout"]=0,this[e=="isover"?"_over":"_out"].call(this,c),f&&e=="isout"&&(f.isout=0,f.isover=1,f._over.call(f,c))})},dragStop:function(b,c){b.element.parents(":not(body,html)").unbind("scroll.droppable"),b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.resizable.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data(
"resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne
,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e<d.length;e++){var f=a.trim(d[e]),g="ui-resizable-"+f,h=a('<div class="ui-resizable-handle '+g+'"></div>');h.css({zIndex:c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseov
er(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){if(c.disabled)return;a(this).removeClass("ui-resizable-autohide"),b._handles.show()},function(){if(c.disabled)return;b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement),this},_mouseCaptu
re:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalM
ousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");return a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b),!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);return l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigg
er("resize",b,this.ui()),!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}return a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.mi
nHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),e<h.maxWidth&&(h.maxWidth=e),g<h.maxHeight&&(h.maxHeight=g);this._vBoundaries=h},_updateCache:function(a){var b=this.options;this.offset=this.helper.offset(),d(a.left)&&(this.position.left=a.left),d(a.top)&&(this.position.top=a.top),d(a.height)&&(this.size.height=a.height),d(a.width)&&(this.size.width=a.width)},_updateRatio:function(a,b){var c=this.options,e=this.position,f=this.size,g=this.axis;return d(a.height)?a.width=a.height*this.aspectRatio:d(a.width)&&(a.height=a.width/this.aspectRatio),g=="sw"&&(a.left=e.left+(f.width-a.width),a.top=null),g=="nw"&&(a.top=e.top+(f.height-a.height),a.left=e.left+(f.width-a.width)),a},_respectSize:function(a,b){var c=this.helper,e=this._vBoundaries,f=this._aspectRatio||b.shiftKey,g=thi
s.axis,h=d(a.width)&&e.maxWidth&&e.maxWidth<a.width,i=d(a.height)&&e.maxHeight&&e.maxHeight<a.height,j=d(a.width)&&e.minWidth&&e.minWidth>a.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;return p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null),a},_proportionallyResize:function(){var b=this.options;if(!this._proportionallyResizeElements.length)return;var c=this.helper||this.element;for(var d=0;d<this._proportionallyResizeElements.length;d++){var e=this._proportionallyResizeElements[d];if(!this.borderDif){var f=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borde
rLeftWidth")],g=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];this.borderDif=a.map(f,function(a,b){var c=parseInt(a,10)||0,d=parseInt(g[b],10)||0;return c+d})}if(!a.browser.msie||!a(c).is(":hidden")&&!a(c).parents(":hidden").length)e.css({height:c.height()-this.borderDif[0]-this.borderDif[2]||0,width:c.width()-this.borderDif[1]-this.borderDif[3]||0});else continue}},_renderProxy:function(){var b=this.element,c=this.options;this.elementOffset=b.offset();if(this._helper){this.helper=this.helper||a('<div style="overflow:hidden;"></div>');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSiz
e.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:thi
s.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.23"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?[
"width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),1
0),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!i)return;e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i
,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/d.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*d.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d
.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.
originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.
width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.selectable.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("<div class='ui-selectable-helper'></div>")},destroy:function(){return this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy(),this},_mou
seStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(this.options.disabled)return;var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");return d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unsele
cting:d.element}),!1}})},_mouseDrag:function(b){var c=this;this.dragged=!0;if(this.options.disabled)return;var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}return this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!i||i.element==c.element[0])return;var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.right<e||i.top>h||i.bottom<f):d.tolerance=="fit"&&(j=i.left>e&&i.right<g&&i.top>f&&i.bottom<h),j?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,c._trigger("selecting",b,{selecting:i.element}))):(i.selecting&&((b.metaKey||b.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selec
ting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),c._trigger("unselecting",b,{unselecting:i.element}))),i.selected&&!b.metaKey&&!b.ctrlKey&&!i.startselected&&(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,c._trigger("unselecting",b,{unselecting:i.element})))}),!1},_mouseStop:function(b){var c=this;this.dragged=!1;var d=this.options;return a(".ui-unselecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-unselecting"),d.unselecting=!1,d.startselected=!1,c._trigger("unselected",b,{unselected:d.element})}),a(".ui-selecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected"),d.selecting=!1,d.selected=!0,d.startselected=!0,c._trigger("selected",b,{selected:d.element})}),this._trigger("stop",b),this.helper.remove(),!1}}),a.extend(a.ui.selectable,{version:"1.8.23"})})
(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.sortable.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.widget("ui.sortable",a.ui.mouse,{widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return thi
s},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f)return e=a(this),!1});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}return this.currentItem=e,this._removeCurrentsFromItems(),!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset
(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIn
dex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));return a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b),!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY<c.scrollSensitivity?this.scro
llParent[0].scrollTop=d=this.scrollParent[0].scrollTop+c.scrollSpeed:b.pageY-this.overflowOffset.top<c.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-c.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-b.pageX<c.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+c.scrollSpeed:b.pageX-this.overflowOffset.left<c.scrollSensitivity&&(this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft-c.scrollSpeed)):(b.pageY-a(document).scrollTop()<c.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-c.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<c.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+c.scrollSpeed)),b.pageX-a(document).scrollLeft()<c.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-c.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<c.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollL
eft()+c.scrollSpeed))),d!==!1&&a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var e=this.items.length-1;e>=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}return this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseS
top:function(b,c){if(!b)return;a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}return
this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"="),d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];return b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")}),d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top
,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+j<i&&b+k>f&&b+k<g;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?l:f<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<g&&h<d+this.helperProportions.height/2&&e-this.helperProportions.height/2<i},_intersectsWithPointer:function(b){var c=this.options.axis==="x"||a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top,b.height),d=this.options.axis==="y"||a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left,b.width),e=c&&d,f=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();return e?this.floating?g&&g=="right"||f=="down"?2:1:f&&(f=="down"?2:1):!1},_intersectsWithSides:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.c
lick.top,b.top+b.height/2,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left+b.width/2,b.width),e=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:e&&(e=="down"&&c||e=="up"&&!c)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){return this._refreshItems(a),this.refreshPositions(),this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options
.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(b){this.items=[],this.containers=[this];var c=this.items,d=this,e=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]],f=this._connectWith();if(f&&this.ready)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=
a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i<m;i++){var n=a(l[i]);n.data(this.widgetName+"-item",k),c.push({item:n,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var c=this.items.length-1;c>=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.con
tainers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return e||(b.style.visibility="hidden"),b},update:function(a,b){if(e&&!d.forcePlaceholderSize)return;b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft
")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!c)return;if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui
.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.containers[d].floating?this.items[i].item.offset().left:this.items[i].item.offset().top;Math.abs(j-h)<f&&(f=Math.abs(j-h),g=this.items[i],this.direction=j-h>0?"down":"up")}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;return d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]
),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height()),d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.cont
ains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}}
,_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("bo
rderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d
)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(f=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(g=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click
.top<this.containment[1]||h-this.offset.click.top>this.containment[3]?h-this.offset.click.top<this.containment[1]?h+c.grid[1]:h-c.grid[1]:h:h;var i=this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0];f=this.containment?i-this.offset.click.left<this.containment[0]||i-this.offset.click.left>this.containment[2]?i-this.offset.click.left<this.containment[0]?i+c.grid[0]:i-c.grid[0]:i:i}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_rearrange:function(a,b,c,d){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling)
,this.counter=this.counter?++this.counter:1;var e=this,f=this.counter;window.setTimeout(function(){f==e.counter&&e.refreshPositions(!d)},0)},_clear:function(b,c){this.reverting=!1;var d=[],e=this;!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!c&&d.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!c&&d.push(function(a){this._trigger("update",a,this._uiHash())});if(!a.ui.contains(this.element[0],this.currentItem[0])){c||d.push(function(a){this._trigger("remove",a,this._u
iHash())});for(var f=this.containers.length-1;f>=0;f--)a.ui.contains(this.containers[f].element[0],this.currentItem[0])&&!c&&(d.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,this.containers[f])),d.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.containers[f])))}for(var f=this.containers.length-1;f>=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._t
rigger("beforeStop",b,this._uiHash());for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return this.fromOutside=!1,!1}c||this._trigger("beforeStop",b,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!c){for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){a.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(b){var c=b||this;return{helper:c.helper,placeholder:c.placeholder||a([]),position:c.position,originalPosition:c.originalPosition,offset:c.positionAbs,item:c.currentItem,sender:b?b.element:null}}}),a.extend(a.ui.sortable,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
-* https://github.com/jquery/jquery-ui
-* Includes: jquery.ui.accordion.js
-* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
-(function(a,b){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:!0,clearStyle:!1,collapsible:!1,event:"click",fillSpace:!1,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){if(c.disabled)return;a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){if(c.disabled)return;a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){if(c.disabled)return;a(this)
.removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("
tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a("<span></span>").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex
"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");return(b.autoHeight||b.fillHeight)&&c.css("height",""),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(this.options.disabled||b.altKey||b.ctrlKey)return;var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._clickHandler({target:b.target
<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/resources/static/t2cogs.png
----------------------------------------------------------------------
diff --git a/server-webapp/src/main/resources/static/t2cogs.png b/server-webapp/src/main/resources/static/t2cogs.png
deleted file mode 100644
index a93b3bd..0000000
Binary files a/server-webapp/src/main/resources/static/t2cogs.png and /dev/null differ
[10/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java
new file mode 100644
index 0000000..a1ac04a
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimeLogger.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static java.lang.String.format;
+import static java.lang.System.nanoTime;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.taverna.server.master.TavernaServer.JMX_ROOT;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.apache.commons.logging.Log;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedResource;
+import org.taverna.server.master.common.version.Version;
+
+/**
+ * This class is responsible for timing all invocations of publicly-exposed
+ * methods of the webapp. It's connected to the webapp through an AspectJ-style
+ * pointcut that targets a custom annotation.
+ *
+ * @author Donal Fellows
+ */
+@Aspect
+@ManagedResource(objectName = JMX_ROOT + "PerformanceMonitor", description = "The performance monitor for Taverna Server "
+ + Version.JAVA
+ + ". Writes to application log using the category 'Taverna.Server.Performance'.")
+public class CallTimeLogger {
+ private long threshold = 4000000;
+ private Log log = getLog("Taverna.Server.Performance");
+
+ @ManagedAttribute(description = "Threshold beneath which monitored call times are not logged. In nanoseconds.")
+ public long getThreshold() {
+ return threshold;
+ }
+
+ @ManagedAttribute(description = "Threshold beneath which monitored call times are not logged. In nanoseconds.")
+ public void setThreshold(long threshold) {
+ this.threshold = threshold;
+ }
+
+ /**
+ * The timer for this aspect. The wrapped invocation will be timed, and a
+ * log message written if the configured threshold is exceeded.
+ *
+ * @param call
+ * The call being wrapped.
+ * @return The result of the call.
+ * @throws Throwable
+ * If anything goes wrong with the wrapped call.
+ * @see System#nanoTime()
+ */
+ @Around("@annotation(org.taverna.server.master.utils.CallTimeLogger.PerfLogged)")
+ public Object time(ProceedingJoinPoint call) throws Throwable {
+ long fore = nanoTime();
+ try {
+ return call.proceed();
+ } finally {
+ long aft = nanoTime();
+ long elapsed = aft - fore;
+ if (elapsed > threshold)
+ log.info(format("call to %s took %.3fms", call.toShortString(),
+ elapsed / 1000000.0));
+ }
+ }
+
+ /**
+ * Mark methods that should be counted by the invocation counter.
+ *
+ * @author Donal Fellows
+ */
+ @Retention(RUNTIME)
+ @Documented
+ @Target(METHOD)
+ public static @interface PerfLogged {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java
new file mode 100644
index 0000000..aead6fa
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CallTimingFilter.java
@@ -0,0 +1,65 @@
+/**
+ *
+ */
+package org.taverna.server.master.utils;
+
+import static java.lang.String.format;
+import static java.lang.System.nanoTime;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * Logs the time it takes to service HTTP calls into Taverna Server.
+ * <p>
+ * This class is currently not used.
+ *
+ * @author Donal Fellows
+ */
+public class CallTimingFilter implements Filter {
+ private Log log;
+ private String name;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ log = getLog("Taverna.Server.Performance");
+ name = filterConfig.getInitParameter("name");
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ if (request instanceof HttpServletRequest)
+ doFilter((HttpServletRequest) request,
+ (HttpServletResponse) response, chain);
+ else
+ chain.doFilter(request, response);
+ }
+
+ public void doFilter(HttpServletRequest request,
+ HttpServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ long start = nanoTime();
+ chain.doFilter(request, response);
+ long elapsedTime = nanoTime() - start;
+ log.info(format("%s call to %s %s took %.3fms", name,
+ request.getMethod(), request.getRequestURI(),
+ elapsedTime / 1000000.0));
+ }
+
+ @Override
+ public void destroy() {
+ log = null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java
new file mode 100644
index 0000000..54b0420
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CapabilityLister.java
@@ -0,0 +1,44 @@
+package org.taverna.server.master.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import javax.annotation.PostConstruct;
+
+import org.taverna.server.master.common.Capability;
+
+/**
+ * Utility for listing the capabilities supported by this Taverna Server
+ * installation.
+ *
+ * @author Donal Fellows
+ */
+public class CapabilityLister {
+ public static final String CAPABILITY_RESOURCE_FILE = "/capabilities.properties";
+ private Properties properties = new Properties();
+
+ @PostConstruct
+ void loadCapabilities() throws IOException {
+ try (InputStream is = getClass().getResourceAsStream(
+ CAPABILITY_RESOURCE_FILE)) {
+ if (is != null)
+ properties.load(is);
+ }
+ }
+
+ public List<Capability> getCapabilities() {
+ List<Capability> caps = new ArrayList<>();
+ for (Entry<Object, Object> entry : properties.entrySet()) {
+ Capability c = new Capability();
+ c.capability = URI.create(entry.getKey().toString());
+ c.version = entry.getValue().toString();
+ caps.add(c);
+ }
+ return caps;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java
new file mode 100644
index 0000000..c27502f
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/CertificateChainFetcher.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
+
+import java.io.IOException;
+import java.net.URI;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import javax.xml.ws.Holder;
+
+/**
+ * Obtains the certificate chain for an arbitrary SSL service. Maintains a
+ * cache.
+ *
+ * @author Donal Fellows
+ */
+public class CertificateChainFetcher {
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public String getKeystoreType() {
+ return keystoreType;
+ }
+
+ public void setKeystoreType(String keystoreType) {
+ this.keystoreType = keystoreType;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public void setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ public void setSecure(boolean secure) {
+ this.secure = secure;
+ }
+
+ private boolean secure = true;
+ private String protocol = "TLS";
+ private String keystoreType = KeyStore.getDefaultType();
+ private String algorithm = TrustManagerFactory.getDefaultAlgorithm();
+ private int timeout = 10000;
+
+ /**
+ * Get the certificate chain for a service.
+ *
+ * @param host
+ * The host (name or IP address) to contact the service on.
+ * @param port
+ * The port to contact the service on.
+ * @return The certificate chain, or <tt>null</tt> if no credentials are
+ * available.
+ * @throws NoSuchAlgorithmException
+ * If the trust manager cannot be set up because of algorithm
+ * problems.
+ * @throws KeyStoreException
+ * If the trust manager cannot be set up because of problems
+ * with the keystore type.
+ * @throws CertificateException
+ * If a bad certificate is present in the default keystore;
+ * <i>should be impossible</i>.
+ * @throws IOException
+ * If problems happen when trying to contact the service.
+ * @throws KeyManagementException
+ * If the SSL context can't have its special context manager
+ * installed.
+ */
+ private X509Certificate[] getCertificateChainForService(String host,
+ int port) throws NoSuchAlgorithmException, KeyStoreException,
+ CertificateException, IOException, KeyManagementException {
+ KeyStore ks = KeyStore.getInstance(keystoreType);
+ SSLContext context = SSLContext.getInstance(protocol);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+ ks.load(null, null);
+ tmf.init(ks);
+ final Holder<X509Certificate[]> chain = new Holder<>();
+ final X509TrustManager defaultTrustManager = (X509TrustManager) tmf
+ .getTrustManagers()[0];
+ context.init(null, new TrustManager[] { new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] clientChain,
+ String authType) throws CertificateException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] serverChain,
+ String authType) throws CertificateException {
+ chain.value = serverChain;
+ defaultTrustManager.checkServerTrusted(serverChain, authType);
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ throw new UnsupportedOperationException();
+ }
+ } }, null);
+ SSLSocketFactory factory = context.getSocketFactory();
+ try (SSLSocket socket = (SSLSocket) factory.createSocket(host, port)) {
+ socket.setSoTimeout(timeout);
+ socket.startHandshake();
+ } catch (SSLException e) {
+ // Ignore
+ }
+ return chain.value;
+ }
+
+ private Map<URI, List<X509Certificate>> cache = new HashMap<>();
+
+ /**
+ * Gets the certificate chain for a service identified by URI.
+ *
+ * @param uri
+ * The URI of the (secure) service to identify.
+ * @return The certificate chain. Will be <tt>null</tt> if the service is
+ * not secure.
+ * @throws IOException
+ * If the service is unreachable or other connection problems
+ * occur.
+ * @throws GeneralSecurityException
+ * If any of a number of security-related problems occur, such
+ * as an inability to match detailed security protocols.
+ */
+ public List<X509Certificate> getTrustsForURI(URI uri) throws IOException,
+ GeneralSecurityException {
+ if (!secure)
+ return null;
+ synchronized (this) {
+ if (!cache.containsKey(uri)) {
+ int port = uri.getPort();
+ if (port == -1)
+ switch (uri.getScheme()) {
+ case "http":
+ port = 80;
+ break;
+ case "https":
+ port = 443;
+ break;
+ default:
+ return null;
+ }
+ X509Certificate[] chain = getCertificateChainForService(
+ uri.getHost(), port);
+ if (chain != null)
+ cache.put(uri, unmodifiableList(asList(chain)));
+ else
+ cache.put(uri, null);
+ }
+ return cache.get(uri);
+ }
+ }
+
+ /**
+ * Flushes the cache.
+ */
+ public void flushCache() {
+ synchronized (this) {
+ cache.clear();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java
new file mode 100644
index 0000000..884ff94
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/Contextualizer.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import javax.servlet.ServletContext;
+import javax.ws.rs.core.UriInfo;
+
+import org.springframework.web.context.ServletContextAware;
+import org.taverna.server.master.common.version.Version;
+
+/**
+ * Convert a string (URL, etc) to a version that is contextualized to the
+ * web-application.
+ *
+ * @author Donal Fellows
+ */
+public class Contextualizer implements ServletContextAware {
+ static final String ROOT_PLACEHOLDER = "%{WEBAPPROOT}";
+ static final String VERSION_PLACEHOLDER = "%{VERSION}";
+ static final String BASE_PLACEHOLDER = "%{BASEURL}";
+
+ /**
+ * Apply the contextualization operation. This consists of replacing the
+ * string <tt>{@value #ROOT_PLACEHOLDER}</tt> with the real root of the webapp.
+ *
+ * @param input
+ * the string to contextualize
+ * @return the contextualized string
+ */
+ public String contextualize(String input) {
+ // Hack to work around bizarre CXF bug
+ String path = context.getRealPath("/").replace("%2D", "-");
+ return input.replace(ROOT_PLACEHOLDER, path).replace(
+ VERSION_PLACEHOLDER, Version.JAVA);
+ }
+
+ /**
+ * Apply the contextualization operation. This consists of replacing the
+ * string <tt>{@value #ROOT_PLACEHOLDER}</tt> with the real root of the
+ * webapp.
+ *
+ * @param ui
+ * Where to get information about the URL used to access the
+ * webapp.
+ * @param input
+ * the string to contextualize
+ * @return the contextualized string
+ */
+ public String contextualize(UriInfo ui, String input) {
+ // Hack to work around bizarre CXF bug
+ String baseuri = ui.getBaseUri().toString().replace("%2D", "-");
+ if (baseuri.endsWith("/"))
+ baseuri = baseuri.substring(0, baseuri.length() - 1);
+ return contextualize(input).replace(BASE_PLACEHOLDER, baseuri);
+ }
+
+ private ServletContext context;
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ context = servletContext;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java
new file mode 100644
index 0000000..f8b39e3
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/DerbyUtils.java
@@ -0,0 +1,68 @@
+package org.taverna.server.master.utils;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Utility class, used to make Derby less broken.
+ *
+ * @see <a
+ * href="http://stackoverflow.com/questions/1004327/getting-rid-of-derby-log">
+ * Getting rid of derby.log </a>
+ * @see <a
+ * href="http://stackoverflow.com/questions/3339736/set-system-property-with-spring-configuration-file">
+ * Set system property with Spring configuration file </a>
+ */
+public class DerbyUtils {
+ /**
+ * A writer that channels things on to the log.
+ */
+ public static final Writer TO_LOG = new DBLog();
+ // Hack
+ public static final Writer DEV_NULL = TO_LOG;
+}
+
+class DBLog extends Writer {
+ private Log log = LogFactory.getLog("Taverna.Server.Database");
+ private StringBuilder sb = new StringBuilder();
+ private boolean closed = false;
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ if (closed)
+ throw new EOFException();
+ if (!log.isInfoEnabled())
+ return;
+ sb.append(cbuf, off, len);
+ while (!closed) {
+ int idx = sb.indexOf("\n"), realIdx = idx;
+ if (idx < 0)
+ break;
+ char ch;
+ while (idx > 0 && ((ch = sb.charAt(idx - 1)) == '\r' || ch == ' ' || ch == '\t'))
+ idx--;
+ if (idx > 0)
+ log.info(sb.substring(0, idx));
+ sb.delete(0, realIdx + 1);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (sb.length() > 0) {
+ log.info(sb.toString());
+ sb = new StringBuilder();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ flush();
+ closed = true;
+ sb = null;
+ }
+}
\ 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/utils/FilenameUtils.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java
new file mode 100644
index 0000000..19299e2
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FilenameUtils.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import java.util.List;
+
+import javax.ws.rs.core.PathSegment;
+
+import org.taverna.server.master.common.DirEntryReference;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+import org.taverna.server.master.interfaces.Directory;
+import org.taverna.server.master.interfaces.DirectoryEntry;
+import org.taverna.server.master.interfaces.File;
+import org.taverna.server.master.interfaces.TavernaRun;
+
+/**
+ * Utility functions for getting entries from directories.
+ *
+ * @author Donal Fellows
+ */
+public class FilenameUtils {
+ private static final String TYPE_ERROR = "trying to take subdirectory of file";
+ private static final String NO_FILE = "no such directory entry";
+ private static final String NOT_A_FILE = "not a file";
+ private static final String NOT_A_DIR = "not a directory";
+
+ /**
+ * Get a named directory entry from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param name
+ * The name of the directory entry to look up.
+ * @return The directory entry whose name is equal to the last part of the
+ * path; an empty path will retrieve the working directory handle
+ * itself.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ * @throws FilesystemAccessException
+ * If the directory isn't specified or isn't readable.
+ */
+ public DirectoryEntry getDirEntry(TavernaRun run, String name)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ Directory dir = run.getWorkingDirectory();
+ if (name == null || name.isEmpty())
+ return dir;
+ DirectoryEntry found = dir;
+ boolean mustBeLast = false;
+
+ // Must be nested loops; avoids problems with %-encoded "/" chars
+ for (String bit : name.split("/")) {
+ if (mustBeLast)
+ throw new FilesystemAccessException(TYPE_ERROR);
+ found = getEntryFromDir(bit, dir);
+ dir = null;
+ if (found instanceof Directory) {
+ dir = (Directory) found;
+ mustBeLast = false;
+ } else
+ mustBeLast = true;
+ }
+ return found;
+ }
+
+ /**
+ * Get a named directory entry from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param d
+ * The path segments describing what to look up.
+ * @return The directory entry whose name is equal to the last part of the
+ * path; an empty path will retrieve the working directory handle
+ * itself.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ * @throws FilesystemAccessException
+ * If the directory isn't specified or isn't readable.
+ */
+ public DirectoryEntry getDirEntry(TavernaRun run, List<PathSegment> d)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ Directory dir = run.getWorkingDirectory();
+ if (d == null || d.isEmpty())
+ return dir;
+ DirectoryEntry found = dir;
+ boolean mustBeLast = false;
+
+ // Must be nested loops; avoids problems with %-encoded "/" chars
+ for (PathSegment segment : d)
+ for (String bit : segment.getPath().split("/")) {
+ if (mustBeLast)
+ throw new FilesystemAccessException(TYPE_ERROR);
+ found = getEntryFromDir(bit, dir);
+ dir = null;
+ if (found instanceof Directory) {
+ dir = (Directory) found;
+ mustBeLast = false;
+ } else
+ mustBeLast = true;
+ }
+ return found;
+ }
+
+ /**
+ * Get a named directory entry from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param d
+ * The directory reference describing what to look up.
+ * @return The directory entry whose name is equal to the last part of the
+ * path in the directory reference; an empty path will retrieve the
+ * working directory handle itself.
+ * @throws FilesystemAccessException
+ * If the directory isn't specified or isn't readable.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ */
+ public DirectoryEntry getDirEntry(TavernaRun run, DirEntryReference d)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ Directory dir = run.getWorkingDirectory();
+ if (d == null || d.path == null || d.path.isEmpty())
+ return dir;
+ DirectoryEntry found = dir;
+ boolean mustBeLast = false;
+
+ for (String bit : d.path.split("/")) {
+ if (mustBeLast)
+ throw new FilesystemAccessException(TYPE_ERROR);
+ found = getEntryFromDir(bit, dir);
+ dir = null;
+ if (found instanceof Directory) {
+ dir = (Directory) found;
+ mustBeLast = false;
+ } else
+ mustBeLast = true;
+ }
+ return found;
+ }
+
+ /**
+ * Get a named directory entry from a directory.
+ *
+ * @param name
+ * The name of the entry; must be "<tt>/</tt>"-free.
+ * @param dir
+ * The directory to look in.
+ * @return The directory entry whose name is equal to the given name.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ * @throws FilesystemAccessException
+ * If the directory isn't specified or isn't readable.
+ */
+ private DirectoryEntry getEntryFromDir(String name, Directory dir)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ if (dir == null)
+ throw new FilesystemAccessException(NO_FILE);
+ for (DirectoryEntry entry : dir.getContents())
+ if (entry.getName().equals(name))
+ return entry;
+ throw new NoDirectoryEntryException(NO_FILE);
+ }
+
+ /**
+ * Get a named directory from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param d
+ * The directory reference describing what to look up.
+ * @return The directory whose name is equal to the last part of the path in
+ * the directory reference; an empty path will retrieve the working
+ * directory handle itself.
+ * @throws FilesystemAccessException
+ * If the directory isn't specified or isn't readable, or if the
+ * name doesn't refer to a directory.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ */
+ public Directory getDirectory(TavernaRun run, DirEntryReference d)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ DirectoryEntry dirEntry = getDirEntry(run, d);
+ if (dirEntry instanceof Directory)
+ return (Directory) dirEntry;
+ throw new FilesystemAccessException(NOT_A_DIR);
+ }
+
+ /**
+ * Get a named directory from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param name
+ * The name of the directory to look up.
+ * @return The directory.
+ * @throws FilesystemAccessException
+ * If the directory isn't specified or isn't readable, or if the
+ * name doesn't refer to a directory.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ */
+ public Directory getDirectory(TavernaRun run, String name)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ DirectoryEntry dirEntry = getDirEntry(run, name);
+ if (dirEntry instanceof Directory)
+ return (Directory) dirEntry;
+ throw new FilesystemAccessException(NOT_A_DIR);
+ }
+
+ /**
+ * Get a named file from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param d
+ * The directory reference describing what to look up.
+ * @return The file whose name is equal to the last part of the path in the
+ * directory reference; an empty path will retrieve the working
+ * directory handle itself.
+ * @throws FilesystemAccessException
+ * If the file isn't specified or isn't readable, or if the name
+ * doesn't refer to a file.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ */
+ public File getFile(TavernaRun run, DirEntryReference d)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ DirectoryEntry dirEntry = getDirEntry(run, d);
+ if (dirEntry instanceof File)
+ return (File) dirEntry;
+ throw new FilesystemAccessException(NOT_A_FILE);
+ }
+
+ /**
+ * Get a named file from a workflow run.
+ *
+ * @param run
+ * The run whose working directory is to be used as the root of
+ * the search.
+ * @param name
+ * The name of the file to look up.
+ * @return The file whose name is equal to the last part of the path in the
+ * directory reference; an empty path will retrieve the working
+ * directory handle itself.
+ * @throws FilesystemAccessException
+ * If the file isn't specified or isn't readable, or if the name
+ * doesn't refer to a file.
+ * @throws NoDirectoryEntryException
+ * If there is no such entry.
+ */
+ public File getFile(TavernaRun run, String name)
+ throws FilesystemAccessException, NoDirectoryEntryException {
+ DirectoryEntry dirEntry = getDirEntry(run, name);
+ if (dirEntry instanceof File)
+ return (File) dirEntry;
+ throw new FilesystemAccessException(NOT_A_FILE);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java
new file mode 100644
index 0000000..ff52e81
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/FlushThreadLocalCacheInterceptor.java
@@ -0,0 +1,18 @@
+package org.taverna.server.master.utils;
+
+import org.apache.cxf.jaxrs.provider.ProviderFactory;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+import org.apache.cxf.phase.Phase;
+
+public class FlushThreadLocalCacheInterceptor extends
+ AbstractPhaseInterceptor<Message> {
+ public FlushThreadLocalCacheInterceptor() {
+ super(Phase.USER_LOGICAL_ENDING);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ ProviderFactory.getInstance(message).clearThreadLocalProxies();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java
new file mode 100644
index 0000000..55a260b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/InvocationCounter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+
+/**
+ * This class is responsible for counting all invocations of publicly-exposed
+ * methods of the webapp. It's connected to the webapp primarily through an
+ * AspectJ-style pointcut.
+ *
+ * @author Donal Fellows
+ */
+@Aspect
+public class InvocationCounter {
+ private int count;
+
+ @Before("@annotation(org.taverna.server.master.utils.InvocationCounter.CallCounted)")
+ public synchronized void count() {
+ count++;
+ }
+
+ public synchronized int getCount() {
+ return count;
+ }
+
+ /**
+ * Mark methods that should be counted by the invocation counter.
+ *
+ * @author Donal Fellows
+ */
+ @Retention(RUNTIME)
+ @Documented
+ @Target(METHOD)
+ public static @interface CallCounted {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java
new file mode 100644
index 0000000..252e316
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JCECheck.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static java.lang.Integer.MAX_VALUE;
+import static javax.crypto.Cipher.getMaxAllowedKeyLength;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * Trivial bean that checks for whether the JCE policy files that allow
+ * unlimited strength security are present, and warns in the log if not.
+ *
+ * @author Donal Fellows
+ */
+public class JCECheck {
+ /**
+ * Write a message to the log that says whether an unlimited strength
+ * {@linkplain #Cipher cipher} is present. This is the official proxy for
+ * whether the unlimited strength JCE policy files have been installed; if
+ * absent, the message is logged as a warning, otherwise it is just
+ * informational.
+ */
+ @PostConstruct
+ public void checkForUnlimitedJCE() {
+ Log log = getLog("Taverna.Server.Utils");
+
+ try {
+ if (getMaxAllowedKeyLength("AES") < MAX_VALUE)
+ log.warn("maximum key length very short; unlimited "
+ + "strength JCE policy files maybe missing");
+ else
+ log.info("unlimited strength JCE policy in place");
+ } catch (GeneralSecurityException e) {
+ log.warn("problem computing key length limits!", e);
+ }
+ }
+
+ /**
+ * @return Whether the unlimited strength JCE policy files are present (or
+ * rather whether an unlimited strength {@linkplain #Cipher cipher}
+ * is permitted).
+ */
+ public boolean isUnlimitedStrength() {
+ try {
+ return getMaxAllowedKeyLength("AES") == MAX_VALUE;
+ } catch (NoSuchAlgorithmException e) {
+ return false;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java
new file mode 100644
index 0000000..ba9ec81
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/JDOSupport.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.WeakHashMap;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.PreDestroy;
+import javax.jdo.JDOException;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
+import org.apache.commons.logging.Log;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Simple support class that wraps up and provides access to the correct parts
+ * of JDO.
+ *
+ * @author Donal Fellows
+ *
+ * @param <T> The context class that the subclass will be working with.
+ */
+public abstract class JDOSupport<T> {
+ private Class<T> contextClass;
+ private PersistenceManagerBuilder pmb;
+
+ /**
+ * Instantiate this class, supplying it a handle to the class that will be
+ * used to provide context for queries and accesses.
+ *
+ * @param contextClass
+ * Must match the type parameter to the class itself.
+ */
+ protected JDOSupport(@Nonnull Class<T> contextClass) {
+ this.contextClass = contextClass;
+ }
+
+ /**
+ * @param persistenceManagerBuilder
+ * The JDO engine to use for managing persistence.
+ */
+ @Required
+ public void setPersistenceManagerBuilder(
+ PersistenceManagerBuilder persistenceManagerBuilder) {
+ pmb = persistenceManagerBuilder;
+ }
+
+ private PersistenceManager pm() {
+ if (isPersistent())
+ return pmb.getPersistenceManager();
+ return null;
+ }
+
+ /**
+ * Has this class actually been configured with a persistence manager by
+ * Spring?
+ *
+ * @return Whether there is a persistence manager installed.
+ */
+ protected boolean isPersistent() {
+ return pmb != null;
+ }
+
+ /**
+ * Get an instance of a query in JDOQL.
+ *
+ * @param filter
+ * The filter part of the query.
+ * @return The query, which should be executed to retrieve the results.
+ */
+ @Nonnull
+ protected Query query(@Nonnull String filter) {
+ return pm().newQuery(contextClass, filter);
+ }
+
+ /**
+ * Get an instance of a named query attached to the context class (as an
+ * annotation).
+ *
+ * @param name
+ * The name of the query.
+ * @return The query, which should be executed to retrieve the results.
+ * @see javax.jdo.annotations.Query
+ */
+ @Nonnull
+ protected Query namedQuery(@Nonnull String name) {
+ return pm().newNamedQuery(contextClass, name);
+ }
+
+ /**
+ * Make an instance of the context class persist in the database. It's
+ * identity must not already exist.
+ *
+ * @param value
+ * The instance to persist.
+ * @return The persistence-coupled instance.
+ */
+ @Nullable
+ protected T persist(@Nullable T value) {
+ if (value == null)
+ return null;
+ return pm().makePersistent(value);
+ }
+
+ /**
+ * Make a non-persistent (i.e., will hold its value past the end of the
+ * transaction) copy of a persistence-coupled instance of the context class.
+ *
+ * @param value
+ * The value to decouple.
+ * @return The non-persistent copy.
+ */
+ @Nullable
+ protected T detach(@Nullable T value) {
+ if (value == null)
+ return null;
+ return pm().detachCopy(value);
+ }
+
+ /**
+ * Look up an instance of the context class by its identity.
+ *
+ * @param id
+ * The identity of the object.
+ * @return The instance, which is persistence-coupled.
+ */
+ @Nullable
+ protected T getById(Object id) {
+ try {
+ return pm().getObjectById(contextClass, id);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Delete a persistence-coupled instance of the context class.
+ *
+ * @param value
+ * The value to delete.
+ */
+ protected void delete(@Nullable T value) {
+ if (value != null)
+ pm().deletePersistent(value);
+ }
+
+ /**
+ * Manages integration of JDO transactions with Spring.
+ *
+ * @author Donal Fellows
+ */
+ @Aspect
+ public static class TransactionAspect {
+ private Object lock = new Object();
+ private Log log = getLog("Taverna.Server.Utils");
+ private volatile int txid;
+
+ @Around(value = "@annotation(org.taverna.server.master.utils.JDOSupport.WithinSingleTransaction) && target(support)", argNames = "support")
+ Object applyTransaction(ProceedingJoinPoint pjp, JDOSupport<?> support)
+ throws Throwable {
+ synchronized (lock) {
+ PersistenceManager pm = support.pm();
+ int id = ++txid;
+ Transaction tx = (pm == null) ? null : pm.currentTransaction();
+ if (tx != null && tx.isActive())
+ tx = null;
+ if (tx != null) {
+ if (log.isDebugEnabled())
+ log.debug("starting transaction #" + id);
+ tx.begin();
+ }
+ try {
+ Object result = pjp.proceed();
+ if (tx != null) {
+ tx.commit();
+ if (log.isDebugEnabled())
+ log.debug("committed transaction #" + id);
+ }
+ tx = null;
+ return result;
+ } catch (Throwable t) {
+ try {
+ if (tx != null) {
+ tx.rollback();
+ if (log.isDebugEnabled())
+ log.debug("rolled back transaction #" + id);
+ }
+ } catch (JDOException e) {
+ log.warn("rollback failed unexpectedly", e);
+ }
+ throw t;
+ }
+ }
+ }
+ }
+
+ /**
+ * Mark a method (of a subclass of {@link JDOSupport}) as having a
+ * transaction wrapped around it. The transactions are managed correctly in
+ * the multi-threaded case.
+ *
+ * @author Donal Fellows
+ */
+ @Target(METHOD)
+ @Retention(RUNTIME)
+ @Documented
+ public @interface WithinSingleTransaction {
+ }
+
+ /**
+ * Manages {@linkplain PersistenceManager persistence managers} in a way
+ * that doesn't cause problems when the web application is unloaded.
+ *
+ * @author Donal Fellows
+ */
+ public static class PersistenceManagerBuilder {
+ private PersistenceManagerFactory pmf;
+ private WeakHashMap<Thread, PersistenceManager> cache = new WeakHashMap<>();
+
+ /**
+ * @param persistenceManagerFactory
+ * The JDO engine to use for managing persistence.
+ */
+ @Required
+ public void setPersistenceManagerFactory(
+ PersistenceManagerFactory persistenceManagerFactory) {
+ pmf = persistenceManagerFactory;
+ }
+
+ @Nonnull
+ public PersistenceManager getPersistenceManager() {
+ if (cache == null)
+ return pmf.getPersistenceManager();
+ Thread t = Thread.currentThread();
+ PersistenceManager pm = cache.get(t);
+ if (pm == null && pmf != null) {
+ pm = pmf.getPersistenceManager();
+ cache.put(t, pm);
+ }
+ return pm;
+ }
+
+ @PreDestroy
+ void clearThreadCache() {
+ WeakHashMap<Thread, PersistenceManager> cache = this.cache;
+ this.cache = null;
+ for (PersistenceManager pm : cache.values())
+ if (pm != null)
+ pm.close();
+ cache.clear();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java
new file mode 100644
index 0000000..a8aa937
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/LoggingDerbyAdapter.java
@@ -0,0 +1,138 @@
+package org.taverna.server.master.utils;
+
+import static java.lang.System.currentTimeMillis;
+import static java.lang.Thread.sleep;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.sql.DatabaseMetaData;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.datanucleus.store.rdbms.adapter.DerbyAdapter;
+import org.datanucleus.store.rdbms.identifier.IdentifierFactory;
+import org.datanucleus.store.rdbms.key.CandidateKey;
+import org.datanucleus.store.rdbms.key.ForeignKey;
+import org.datanucleus.store.rdbms.key.Index;
+import org.datanucleus.store.rdbms.key.PrimaryKey;
+import org.datanucleus.store.rdbms.sql.SQLTable;
+import org.datanucleus.store.rdbms.table.Column;
+import org.datanucleus.store.rdbms.table.Table;
+import org.datanucleus.store.rdbms.table.TableImpl;
+import org.datanucleus.store.rdbms.table.ViewImpl;
+
+/**
+ * Evil hack to allow logging of the DDL spat out to Derby.
+ *
+ * @author Donal Fellows
+ */
+public class LoggingDerbyAdapter extends DerbyAdapter {
+ Log log = getLog("Taverna.Server.SQL");
+
+ private StringBuilder ddl = new StringBuilder();
+ private volatile long timeout;
+ private Thread timer;
+
+ private synchronized void logDDL() {
+ if (ddl.length() > 0) {
+ log.info("Data definition language:\n" + ddl);
+ ddl.setLength(0);
+ }
+ timer = null;
+ }
+
+ private synchronized void doLog(String item) {
+ ddl.append(item);
+ if (!item.endsWith("\n"))
+ ddl.append('\n');
+ timeout = currentTimeMillis() + 5000;
+ if (timer == null)
+ timer = new OneShotThread("DDL logger timeout", new Runnable() {
+ @Override
+ public void run() {
+ try {
+ while (timeout > currentTimeMillis())
+ sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ logDDL();
+ }
+ });
+ }
+
+ /**
+ * Creates an Apache Derby adapter based on the given metadata which logs
+ * the DDL it creates.
+ */
+ public LoggingDerbyAdapter(DatabaseMetaData metadata) {
+ super(metadata);
+ }
+
+ @Override
+ public String getCreateTableStatement(TableImpl table, Column[] columns,
+ Properties props, IdentifierFactory factory) {
+ String statement = super.getCreateTableStatement(table, columns, props,
+ factory);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getCreateIndexStatement(Index index, IdentifierFactory factory) {
+ String statement = super.getCreateIndexStatement(index, factory);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getAddCandidateKeyStatement(CandidateKey ck,
+ IdentifierFactory factory) {
+ String statement = super.getAddCandidateKeyStatement(ck, factory);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getAddPrimaryKeyStatement(PrimaryKey pk,
+ IdentifierFactory factory) {
+ String statement = super.getAddPrimaryKeyStatement(pk, factory);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getAddColumnStatement(Table table, Column col) {
+ String statement = super.getAddColumnStatement(table, col);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getAddForeignKeyStatement(ForeignKey fk,
+ IdentifierFactory factory) {
+ String statement = super.getAddForeignKeyStatement(fk, factory);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getDeleteTableStatement(SQLTable tbl) {
+ String statement = super.getDeleteTableStatement(tbl);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getDropTableStatement(Table table) {
+ String statement = super.getDropTableStatement(table);
+ doLog(statement);
+ return statement;
+ }
+
+ @Override
+ public String getDropViewStatement(ViewImpl view) {
+ String statement = super.getDropViewStatement(view);
+ doLog(statement);
+ return statement;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java
new file mode 100644
index 0000000..68b813d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/OneShotThread.java
@@ -0,0 +1,10 @@
+package org.taverna.server.master.utils;
+
+public class OneShotThread extends Thread {
+ public OneShotThread(String name, Runnable target) {
+ super(target, name);
+ setContextClassLoader(null);
+ setDaemon(true);
+ start();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java
new file mode 100644
index 0000000..a892b52
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RestUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.core.Response;
+
+/**
+ * Utilities that make it easier to write REST services.
+ *
+ * @author Donal Fellows
+ */
+public class RestUtils {
+ /**
+ * Generate a response to an HTTP OPTIONS request.
+ *
+ * @param methods
+ * The state-changing methods supported, if any.
+ * @return the required response
+ * @see OPTIONS
+ */
+ public static Response opt(String... methods) {
+ StringBuilder sb = new StringBuilder("GET,");
+ for (String m : methods)
+ sb.append(m).append(",");
+ sb.append("HEAD,OPTIONS");
+ return Response.ok().header("Allow", sb.toString()).entity("").build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java
new file mode 100644
index 0000000..0b2d4ea
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/RuntimeExceptionWrapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.taverna.server.master.exceptions.GeneralFailureException;
+
+/**
+ * Aspect used to convert {@linkplain RuntimeException runtime exceptions} into
+ * a form that can be nicely conveyed to the outside world as HTTP errors.
+ *
+ * @author Donal Fellows
+ */
+@Aspect
+public class RuntimeExceptionWrapper {
+ /**
+ * Map an unexpected exception to one that can be correctly reported as a
+ * problem.
+ *
+ * @param exn
+ * The runtime exception being trapped.
+ * @throws GeneralFailureException
+ * The known exception type that it is mapped to.
+ */
+ @AfterThrowing(pointcut = "execution(* org.taverna.server.master.rest..*(..)) && !bean(*Provider.*)", throwing = "exn")
+ public void wrapRuntimeException(RuntimeException exn)
+ throws GeneralFailureException {
+ // Exclude security-related exceptions
+ if (exn.getClass().getName().startsWith("org.springframework.security."))
+ return;
+ throw new GeneralFailureException(exn);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java
new file mode 100644
index 0000000..9bbcc2f
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/UsernamePrincipal.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * A simple serializable principal that just records the name.
+ *
+ * @author Donal Fellows
+ */
+public class UsernamePrincipal implements Principal, Serializable {
+ private static final long serialVersionUID = 2703493248562435L;
+ public UsernamePrincipal(String username) {
+ this.name = username;
+ }
+
+ public UsernamePrincipal(Principal other) {
+ this.name = other.getName();
+ }
+
+ public UsernamePrincipal(Authentication auth) {
+ this(auth.getPrincipal());
+ }
+
+ public UsernamePrincipal(Object principal) {
+ if (principal instanceof Principal)
+ this.name = ((Principal) principal).getName();
+ else if (principal instanceof String)
+ this.name = (String) principal;
+ else if (principal instanceof UserDetails)
+ this.name = ((UserDetails) principal).getUsername();
+ else
+ this.name = principal.toString();
+ }
+
+ private String name;
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "Principal<" + name + ">";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Principal) {
+ Principal p = (Principal) o;
+ return name.equals(p.getName());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
new file mode 100644
index 0000000..96cdc6d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
@@ -0,0 +1,65 @@
+package org.taverna.server.master.utils;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+import static org.apache.cxf.common.util.UrlUtils.parseQueryString;
+import static org.apache.cxf.message.Message.HTTP_REQUEST_METHOD;
+import static org.apache.cxf.message.Message.QUERY_STRING;
+import static org.apache.cxf.message.Message.REQUEST_URL;
+import static org.apache.cxf.phase.Phase.READ;
+
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.cxf.binding.soap.interceptor.EndpointSelectionInterceptor;
+import org.apache.cxf.interceptor.Fault;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
+
+
+/**
+ * Thunk for TAVSERV-293.
+ *
+ * @author Donal Fellows (based on work by Daniel Hagen)
+ */
+public class WSDLHeadOptionsInterceptor extends
+ AbstractPhaseInterceptor<Message> {
+ public static final Log log = getLog("Taverna.Server.Utils");
+
+ public WSDLHeadOptionsInterceptor() {
+ super(READ);
+ getAfter().add(EndpointSelectionInterceptor.class.getName());
+ }
+
+ @Override
+ public void handleMessage(Message message) throws Fault {
+ String method = (String) message.get(HTTP_REQUEST_METHOD);
+ String query = (String) message.get(QUERY_STRING);
+
+ if (("HEAD".equals(method) || "OPTIONS".equals(method))
+ && query != null && !query.trim().isEmpty()
+ && isRecognizedQuery(query)) {
+ log.debug("adjusting message request method " + method + " for "
+ + message.get(REQUEST_URL) + " to GET");
+ message.put(HTTP_REQUEST_METHOD, "GET");
+ }
+ }
+
+ /*
+ * Stolen from http://permalink.gmane.org/gmane.comp.apache.cxf.user/20037
+ * which is itself in turn stolen from
+ * org.apache.cxf.frontend.WSDLGetInterceptor.isRecognizedQuery
+ */
+ /**
+ * Is this a query for WSDL or XSD relating to it?
+ *
+ * @param query
+ * The query string to check
+ * @return If the query is one to handle.
+ * @see org.apache.cxf.frontend.WSDLGetInterceptor#isRecognizedQuery(Map,String,String,org.apache.cxf.service.model.EndpointInfo)
+ * WSDLGetInterceptor
+ */
+ private boolean isRecognizedQuery(String query) {
+ Map<String, String> map = parseQueryString(query);
+ return map.containsKey("wsdl") || map.containsKey("xsd");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
new file mode 100644
index 0000000..03fc749
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static java.lang.Thread.currentThread;
+import static java.sql.DriverManager.deregisterDriver;
+import static java.sql.DriverManager.getDrivers;
+import static org.taverna.server.master.utils.Contextualizer.ROOT_PLACEHOLDER;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Enumeration;
+
+import javax.annotation.PreDestroy;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+
+/**
+ * Add some awareness of the context so that we can locate databases internally
+ * to the webapp.
+ *
+ * @author Donal Fellows
+ */
+public class WebappAwareDataSource extends BasicDataSource {
+ Log log = LogFactory.getLog("Taverna.Server.Utils");
+ private transient boolean init;
+ private Contextualizer ctxt;
+ private String shutdownUrl;
+
+ @Required
+ public void setContextualizer(Contextualizer ctxt) {
+ this.ctxt = ctxt;
+ }
+
+ /**
+ * A JDBC connection URL to use on shutting down the database. If not set,
+ * do nothing special.
+ *
+ * @param url
+ */
+ public void setShutdownUrl(String url) {
+ shutdownUrl = url;
+ }
+
+ private void doInit() {
+ synchronized (this) {
+ if (!init) {
+ setDriverClassLoader(currentThread().getContextClassLoader());
+ String url = getUrl();
+ if (url.contains(ROOT_PLACEHOLDER)) {
+ String newurl = ctxt.contextualize(url);
+ setUrl(newurl);
+ log.info("mapped " + url + " to " + newurl);
+ } else {
+ log.info("did not find " + ROOT_PLACEHOLDER + " in " + url);
+ }
+ init = true;
+ }
+ }
+ }
+
+ // -=-=-=-=-=-=-=-=-=-=- HOOKS -=-=-=-=-=-=-=-=-=-=-
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ doInit();
+ return super.getConnection();
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter pw) throws SQLException {
+ doInit();
+ super.setLogWriter(pw);
+ }
+
+ @Override
+ public void setLoginTimeout(int num) throws SQLException {
+ doInit();
+ super.setLoginTimeout(num);
+ }
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ doInit();
+ return super.getLogWriter();
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ doInit();
+ return super.getLoginTimeout();
+ }
+
+ @PreDestroy
+ void realClose() {
+ try {
+ close();
+ } catch (SQLException e) {
+ log.warn("problem shutting down DB connection", e);
+ }
+ try {
+ if (shutdownUrl != null)
+ DriverManager.getConnection(ctxt.contextualize(shutdownUrl));
+ } catch (SQLException e) {
+ // Expected; ignore it
+ }
+ log = null;
+ dropDriver();
+ }
+
+ private void dropDriver() {
+ Enumeration<Driver> drivers = getDrivers();
+ while (drivers.hasMoreElements()) {
+ Driver d = drivers.nextElement();
+ if (d.getClass().getClassLoader() == getDriverClassLoader()
+ && d.getClass().getName().equals(getDriverClassName())) {
+ try {
+ deregisterDriver(d);
+ } catch (SQLException e) {
+ }
+ break;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
new file mode 100644
index 0000000..da4cff0
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.utils;
+
+import static javax.security.auth.x500.X500Principal.RFC2253;
+
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.PreDestroy;
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Support class that factors out some of the messier parts of working with
+ * X.500 identities and X.509 certificates.
+ *
+ * @author Donal Fellows
+ */
+public class X500Utils {
+ private Log log = LogFactory.getLog("Taverna.Server.Utils");
+
+ @PreDestroy
+ void closeLog() {
+ log = null;
+ }
+
+ private static final char DN_SEPARATOR = ',';
+ private static final char DN_ESCAPE = '\\';
+ private static final char DN_QUOTE = '"';
+
+ /**
+ * Parse the DN from the Principal and extract the CN field.
+ *
+ * @param id
+ * The identity to extract the distinguished name from.
+ * @param fields
+ * The names to look at when finding the field to return. Each
+ * should be an upper-cased string.
+ * @return The common-name part of the distinguished name, or the literal
+ * string "<tt>none</tt>" if there is no CN.
+ */
+ public String getName(X500Principal id, String... fields) {
+ String dn = id.getName(RFC2253);
+
+ int i = 0;
+ int startIndex = 0;
+ boolean ignoreThisChar = false;
+ boolean inQuotes = false;
+ Map<String, String> tokenized = new HashMap<>();
+
+ for (i = 0; i < dn.length(); i++)
+ if (ignoreThisChar)
+ ignoreThisChar = false;
+ else if (dn.charAt(i) == DN_QUOTE)
+ inQuotes = !inQuotes;
+ else if (inQuotes)
+ continue;
+ else if (dn.charAt(i) == DN_ESCAPE)
+ ignoreThisChar = true;
+ else if ((dn.charAt(i) == DN_SEPARATOR) && !ignoreThisChar) {
+ storeDNField(tokenized, dn.substring(startIndex, i).trim()
+ .split("=", 2));
+ startIndex = i + 1;
+ }
+ if (inQuotes || ignoreThisChar)
+ log.warn("was parsing invalid DN format");
+ // Add last token - after the last delimiter
+ storeDNField(tokenized, dn.substring(startIndex).trim().split("=", 2));
+
+ for (String field : fields) {
+ String value = tokenized.get(field);
+ if (value != null)
+ return value;
+ }
+ return "none";
+ }
+
+ private void storeDNField(Map<String, String> container, String[] split) {
+ if (split == null || split.length != 2)
+ return;
+ String key = split[0].toUpperCase();
+ if (container.containsKey(key))
+ log.warn("duplicate field in DN: " + key);
+ // LATER: Should the field be de-quoted?
+ container.put(key, split[1]);
+ }
+
+ /**
+ * Get the serial number from a certificate as a hex string.
+ *
+ * @param cert
+ * The certificate to extract from.
+ * @return A hex string, in upper-case.
+ */
+ public String getSerial(X509Certificate cert) {
+ return new BigInteger(1, cert.getSerialNumber().toByteArray())
+ .toString(16).toUpperCase();
+ }
+}
\ 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/utils/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
new file mode 100644
index 0000000..612e61c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Miscellaneous utility classes. Includes aspects that might be attached
+ * for purposes such as transaction management and invocation tracking.
+ */
+package org.taverna.server.master.utils;
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
new file mode 100644
index 0000000..10b3830
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+
+/**
+ * How to convert a notification about the completion of a job into a message.
+ *
+ * @author Donal Fellows
+ */
+public interface CompletionNotifier {
+ /**
+ * @return The name of this notifier.
+ */
+ String getName();
+
+ /**
+ * Called to get the content of a message that a workflow run has finished.
+ *
+ * @param name
+ * The name of the run.
+ * @param run
+ * What run are we talking about.
+ * @param code
+ * What the exit code was.
+ * @return The plain-text content of the message.
+ */
+ String makeCompletionMessage(String name, RemoteRunDelegate run, int code);
+
+ /**
+ * Called to get the subject of the message to dispatch.
+ *
+ * @param name
+ * The name of the run.
+ * @param run
+ * What run are we talking about.
+ * @param code
+ * What the exit code was.
+ * @return The plain-text subject of the message.
+ */
+ String makeMessageSubject(String name, RemoteRunDelegate run, int code);
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
new file mode 100644
index 0000000..5d0f371
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import org.taverna.server.master.notification.atom.EventDAO;
+
+/**
+ * What the remote run really needs of its factory.
+ *
+ * @author Donal Fellows
+ */
+public interface FactoryBean {
+ /**
+ * @return Whether a run can actually be started at this time.
+ */
+ boolean isAllowingRunsToStart();
+
+ /**
+ * @return a handle to the master Atom event feed (<i>not</i> the per-run
+ * feed)
+ */
+ EventDAO getMasterEventFeed();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
new file mode 100644
index 0000000..d3c5b8a
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
@@ -0,0 +1,57 @@
+package org.taverna.server.master.worker;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A simple password issuing bean.
+ *
+ * @author Donal Fellows
+ */
+public class PasswordIssuer {
+ private static final char[] ALPHABET = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+ 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '0', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
+ ',', '.', '<', '>', '/', '?', ':', ';', '-', '_', '+', '[', ']',
+ '{', '}', '`', '~' };
+ private Log log = LogFactory.getLog("Taverna.Server.Worker");
+ private SecureRandom r;
+ private int length;
+
+ public PasswordIssuer() {
+ r = new SecureRandom();
+ log.info("constructing passwords with " + r.getAlgorithm());
+ setLength(8);
+ }
+
+ public PasswordIssuer(String algorithm) throws NoSuchAlgorithmException {
+ r = SecureRandom.getInstance(algorithm);
+ log.info("constructing passwords with " + r.getAlgorithm());
+ setLength(8);
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ log.info("issued password will be " + this.length
+ + " symbols chosen from " + ALPHABET.length);
+ }
+
+ /**
+ * Issue a password.
+ *
+ * @return The new password.
+ */
+ public String issue() {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; i++)
+ sb.append(ALPHABET[r.nextInt(ALPHABET.length)]);
+ log.info("issued new password of length " + sb.length());
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
new file mode 100644
index 0000000..f5613c7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import static org.taverna.server.master.identity.WorkflowInternalAuthProvider.PREFIX;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Required;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.taverna.server.master.common.Roles;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoDestroyException;
+import org.taverna.server.master.exceptions.NoUpdateException;
+import org.taverna.server.master.interfaces.Policy;
+import org.taverna.server.master.interfaces.TavernaRun;
+import org.taverna.server.master.interfaces.TavernaSecurityContext;
+import org.taverna.server.master.utils.UsernamePrincipal;
+
+/**
+ * Basic policy implementation that allows any workflow to be instantiated by
+ * any user, but which does not permit users to access each others workflow
+ * runs. It also imposes a global limit on the number of workflow runs at once.
+ *
+ * @author Donal Fellows
+ */
+class PolicyImpl implements Policy {
+ Log log = LogFactory.getLog("Taverna.Server.Worker.Policy");
+ private PolicyLimits limits;
+ private RunDBSupport runDB;
+
+ @Required
+ public void setLimits(PolicyLimits limits) {
+ this.limits = limits;
+ }
+
+ @Required
+ public void setRunDB(RunDBSupport runDB) {
+ this.runDB = runDB;
+ }
+
+ @Override
+ public int getMaxRuns() {
+ return limits.getMaxRuns();
+ }
+
+ @Override
+ public Integer getMaxRuns(UsernamePrincipal user) {
+ return null;
+ }
+
+ @Override
+ public int getOperatingLimit() {
+ return limits.getOperatingLimit();
+ }
+
+ @Override
+ public List<URI> listPermittedWorkflowURIs(UsernamePrincipal user) {
+ return limits.getPermittedWorkflowURIs();
+ }
+
+ private boolean isSelfAccess(String runId) {
+ Authentication auth = SecurityContextHolder.getContext()
+ .getAuthentication();
+ boolean self = false;
+ String id = null;
+ for (GrantedAuthority a : auth.getAuthorities()) {
+ String aa = a.getAuthority();
+ if (aa.equals(Roles.SELF)) {
+ self = true;
+ continue;
+ }
+ if (!aa.startsWith(PREFIX))
+ continue;
+ id = aa.substring(PREFIX.length());
+ }
+ return self && runId.equals(id);
+ }
+
+ @Override
+ public boolean permitAccess(UsernamePrincipal user, TavernaRun run) {
+ String username = user.getName();
+ TavernaSecurityContext context = run.getSecurityContext();
+ if (context.getOwner().getName().equals(username)) {
+ if (log.isDebugEnabled())
+ log.debug("granted access by " + user.getName() + " to "
+ + run.getId());
+ return true;
+ }
+ if (isSelfAccess(run.getId())) {
+ if (log.isDebugEnabled())
+ log.debug("access by workflow to itself: " + run.getId());
+ return true;
+ }
+ if (log.isDebugEnabled())
+ log.debug("considering access by " + user.getName() + " to "
+ + run.getId());
+ return context.getPermittedReaders().contains(username);
+ }
+
+ @Override
+ public void permitCreate(UsernamePrincipal user, Workflow workflow)
+ throws NoCreateException {
+ if (user == null)
+ throw new NoCreateException(
+ "anonymous workflow creation not allowed");
+ if (runDB.countRuns() >= getMaxRuns())
+ throw new NoCreateException("server load exceeded; please wait");
+ }
+
+ @Override
+ public synchronized void permitDestroy(UsernamePrincipal user, TavernaRun run)
+ throws NoDestroyException {
+ if (user == null)
+ throw new NoDestroyException();
+ String username = user.getName();
+ TavernaSecurityContext context = run.getSecurityContext();
+ if (context.getOwner() == null
+ || context.getOwner().getName().equals(username))
+ return;
+ if (!context.getPermittedDestroyers().contains(username))
+ throw new NoDestroyException();
+ }
+
+ @Override
+ public void permitUpdate(UsernamePrincipal user, TavernaRun run)
+ throws NoUpdateException {
+ if (user == null)
+ throw new NoUpdateException(
+ "workflow run not owned by you and you're not granted access");
+ TavernaSecurityContext context = run.getSecurityContext();
+ if (context.getOwner().getName().equals(user.getName()))
+ return;
+ if (isSelfAccess(run.getId())) {
+ if (log.isDebugEnabled())
+ log.debug("update access by workflow to itself: " + run.getId());
+ return;
+ }
+ if (!context.getPermittedUpdaters().contains(user.getName()))
+ throw new NoUpdateException(
+ "workflow run not owned by you and you're not granted access");
+ }
+
+ @Override
+ public void setPermittedWorkflowURIs(UsernamePrincipal user,
+ List<URI> permitted) {
+ limits.setPermittedWorkflowURIs(permitted);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
new file mode 100644
index 0000000..8cbc7ea
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.worker;
+
+import java.net.URI;
+import java.util.List;
+
+import org.taverna.server.master.common.Status;
+
+/**
+ * The worker policy delegates certain limits to the state model of the
+ * particular worker.
+ *
+ * @author Donal Fellows
+ */
+public interface PolicyLimits {
+ /**
+ * @return the maximum number of extant workflow runs in any state
+ */
+ int getMaxRuns();
+
+ /**
+ * @return the maximum number of workflow runs in the
+ * {@linkplain Status#Operating operating} state.
+ */
+ int getOperatingLimit();
+
+ /**
+ * @return the list of URIs to workflows that may be used to create workflow
+ * runs. If empty or <tt>null</tt>, no restriction is present.
+ */
+ List<URI> getPermittedWorkflowURIs();
+
+ /**
+ * @param permitted
+ * the list of URIs to workflows that may be used to create
+ * workflow runs.
+ */
+ void setPermittedWorkflowURIs(List<URI> permitted);
+}
[11/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java
new file mode 100644
index 0000000..e175bf8
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/TavernaServerSOAP.java
@@ -0,0 +1,1553 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.soap;
+
+import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
+import static org.taverna.server.master.common.Roles.USER;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+
+import javax.annotation.security.RolesAllowed;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebResult;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.apache.cxf.annotations.WSDLDocumentation;
+import org.ogf.usage.JobUsageRecord;
+import org.taverna.server.master.common.Capability;
+import org.taverna.server.master.common.Credential;
+import org.taverna.server.master.common.DirEntryReference;
+import org.taverna.server.master.common.InputDescription;
+import org.taverna.server.master.common.Permission;
+import org.taverna.server.master.common.ProfileList;
+import org.taverna.server.master.common.RunReference;
+import org.taverna.server.master.common.Status;
+import org.taverna.server.master.common.Trust;
+import org.taverna.server.master.common.Workflow;
+import org.taverna.server.master.common.version.Version;
+import org.taverna.server.master.exceptions.BadPropertyValueException;
+import org.taverna.server.master.exceptions.BadStateChangeException;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+import org.taverna.server.master.exceptions.NoCreateException;
+import org.taverna.server.master.exceptions.NoCredentialException;
+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.exceptions.UnknownRunException;
+import org.taverna.server.master.rest.TavernaServerREST;
+import org.taverna.server.port_description.OutputDescription;
+
+/**
+ * The SOAP service interface to Taverna 3 Server.
+ *
+ * @author Donal Fellows
+ * @see TavernaServerREST
+ */
+@RolesAllowed(USER)
+@WebService(name = "tavernaService", targetNamespace = SERVER_SOAP)
+@WSDLDocumentation("The SOAP service interface to Taverna " + Version.JAVA
+ + " Server.")
+public interface TavernaServerSOAP {
+ /**
+ * Make a run for a particular workflow.
+ *
+ * @param workflow
+ * The workflow to instantiate.
+ * @return Annotated handle for created run.
+ * @throws NoUpdateException
+ * @throws NoCreateException
+ */
+ @WebResult(name = "Run")
+ @WSDLDocumentation("Make a run for a particular workflow.")
+ RunReference submitWorkflow(
+ @WebParam(name = "workflow") @XmlElement(required = true) Workflow workflow)
+ throws NoUpdateException, NoCreateException;
+
+ /**
+ * Make a run for a particular workflow.
+ *
+ * @param workflow
+ * The workflow to instantiate.
+ * @return Annotated handle for created run.
+ * @throws NoUpdateException
+ * @throws NoCreateException
+ */
+ @WebResult(name = "Run")
+ @WSDLDocumentation("Make a run for a particular workflow.")
+ RunReference submitWorkflowMTOM(
+ @WebParam(name = "workflow") @XmlElement(required = true) WrappedWorkflow workflow)
+ throws NoUpdateException;
+
+ /**
+ * Make a run for a particular workflow, where that workflow will be
+ * downloaded from elsewhere. The URI <i>must</i> be publicly readable.
+ *
+ * @param workflowURI
+ * The URI to the workflow to instantiate.
+ * @return Annotated handle for created run.
+ * @throws NoUpdateException
+ * @throws NoCreateException
+ */
+ @WebResult(name = "Run")
+ @WSDLDocumentation("Make a run for a particular workflow where that "
+ + "workflow is given by publicly readable URI.")
+ RunReference submitWorkflowByURI(
+ @WebParam(name = "workflowURI") @XmlElement(required = true) URI workflowURI)
+ throws NoCreateException, NoUpdateException;
+
+ /**
+ * Get the list of existing runs owned by the user.
+ *
+ * @return Annotated handle list.
+ */
+ @WebResult(name = "Run")
+ @WSDLDocumentation("Get the list of existing runs owned by the user.")
+ RunReference[] listRuns();
+
+ /**
+ * Get the upper limit on the number of runs that the user may create at
+ * once.
+ *
+ * @return The limit. <b>NB:</b> the number currently operating may be
+ * larger, but in that case no further runs can be made until some
+ * of the old ones are destroyed.
+ */
+ @WebResult(name = "MaxSimultaneousRuns")
+ @WSDLDocumentation("Get the upper limit on the number of runs that the user may create at once.")
+ int getServerMaxRuns();
+
+ /**
+ * Get the list of allowed workflows. If the list is empty, <i>any</i>
+ * workflow may be used.
+ *
+ * @return A list of workflow documents.
+ */
+ @WebMethod(operationName = "getPermittedWorkflowURIs")
+ @WebResult(name = "PermittedWorkflowURI")
+ @WSDLDocumentation("Get the list of URIs to allowed workflows. If the list is empty, any workflow may be used including those not submitted via URI.")
+ URI[] getServerWorkflows();
+
+ /**
+ * Get the list of allowed event listeners.
+ *
+ * @return A list of listener names.
+ */
+ @WebMethod(operationName = "getPermittedListenerTypes")
+ @WebResult(name = "PermittedListenerType")
+ @WSDLDocumentation("Get the list of allowed types of event listeners.")
+ String[] getServerListeners();
+
+ /**
+ * Get the list of notification fabrics.
+ *
+ * @return A list of listener names.
+ */
+ @WebMethod(operationName = "getEnabledNotificationFabrics")
+ @WebResult(name = "EnabledNotifierFabric")
+ @WSDLDocumentation("Get the list of notification fabrics. Each is a URI scheme.")
+ String[] getServerNotifiers();
+
+ @WebMethod(operationName = "getCapabilities")
+ @WebResult(name = "Capabilities")
+ @WSDLDocumentation("Get the workflow execution capabilities of this "
+ + "Taverna Server instance.")
+ List<Capability> getServerCapabilities();
+
+ /**
+ * Destroy a run immediately. This might or might not actually relinquish
+ * resources; that's up to the service implementation and deployment.
+ *
+ * @param runName
+ * The handle of the run.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the lifetime of the
+ * run.
+ */
+ @WSDLDocumentation("Destroy a run immediately.")
+ void destroyRun(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException, NoUpdateException;
+
+ /**
+ * Get the workflow document used to create the given run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The workflow document.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "CreationWorkflow")
+ @WSDLDocumentation("Get the workflow document used to create the given run.")
+ Workflow getRunWorkflow(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get the workflow document used to create the given run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The workflow document.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "CreationWorkflow")
+ @WSDLDocumentation("Get the workflow document used to create the given run.")
+ WrappedWorkflow getRunWorkflowMTOM(
+ @WebParam(name = "runName") String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get a description of the profiles supported by the workflow document used
+ * to create the given run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return A description of the supported profiles.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "Profiles")
+ @WSDLDocumentation("Get a description of the profiles supported by the workflow document used to create the given run.")
+ ProfileList getRunWorkflowProfiles(
+ @WebParam(name = "runName") String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get the descriptive name of the workflow run. The descriptive name
+ * carries no deep information.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The descriptive name of the run.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "DescriptiveName")
+ @WSDLDocumentation("Get the descriptive name of the workflow run. Carries no deep information.")
+ String getRunDescriptiveName(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Set the descriptive name of the workflow run. The descriptive name
+ * carries no deep information.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param descriptiveName
+ * The new descriptive name to set. Note that the implementation
+ * is allowed to arbitrarily truncate this value.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not permitted to update this run.
+ */
+ @WSDLDocumentation("Set the descriptive name of the workflow run. Carries no deep information.")
+ void setRunDescriptiveName(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "descriptiveName") @XmlElement(required = true) String descriptiveName)
+ throws UnknownRunException, NoUpdateException;
+
+ /**
+ * Get the description of the inputs to the workflow run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The input description
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "RunInputDescription")
+ @WSDLDocumentation("Get the description of the inputs currently set up for the given workflow run.")
+ InputDescription getRunInputs(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get a description of what inputs the workflow run <i>expects</i> to
+ * receive.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The description document.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "RunInputDescriptor")
+ @WSDLDocumentation("Get a description of what inputs the given workflow run expects to receive.")
+ org.taverna.server.port_description.InputDescription getRunInputDescriptor(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Tells the run to use the given Baclava file for all inputs.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param fileName
+ * The name of the file to use. Must not start with a <tt>/</tt>
+ * or contain a <tt>..</tt> element.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws FilesystemAccessException
+ * If the filename is illegal.
+ * @throws BadStateChangeException
+ * If the run is not in the {@link Status#Initialized
+ * Initialized} state
+ */
+ @WSDLDocumentation("Tells the given run to use the given already-uploaded Baclava file for all inputs.")
+ void setRunInputBaclavaFile(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "baclavaFileName") String fileName)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, BadStateChangeException;
+
+ /**
+ * Tells the run to use the given file for input on the given port. This
+ * overrides any previously set file or value on the port and causes the
+ * server to forget about using a Baclava file for all inputs.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param portName
+ * The port to use the file for.
+ * @param portFilename
+ * The file to use on the port. Must not start with a <tt>/</tt>
+ * or contain a <tt>..</tt> element.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws FilesystemAccessException
+ * If the filename is illegal.
+ * @throws BadStateChangeException
+ * If the run is not in the {@link Status#Initialized
+ * Initialized} state.
+ * @throws BadPropertyValueException
+ * If the input port may not be changed to the contents of the
+ * given file.
+ */
+ @WSDLDocumentation("Tells the given run to use the given file for input on the given port.")
+ void setRunInputPortFile(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "portName") @XmlElement(required = true) String portName,
+ @WebParam(name = "portFileName") @XmlElement(required = true) String portFilename)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, BadStateChangeException,
+ BadPropertyValueException;
+
+ /**
+ * Tells the run to use the given value for input on the given port. This
+ * overrides any previously set file or value on the port and causes the
+ * server to forget about using a Baclava file for all inputs. Note that
+ * this is wholly unsuitable for use with binary data.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param portName
+ * The port to use the file for.
+ * @param portValue
+ * The literal value to use on the port.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws BadStateChangeException
+ * If the run is not in the {@link Status#Initialized
+ * Initialized} state.
+ * @throws BadPropertyValueException
+ * If the input port may not be changed to the given literal
+ * value.
+ */
+ @WSDLDocumentation("Tells the given run to use the given literal string value for input on the given port.")
+ void setRunInputPortValue(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "portName") @XmlElement(required = true) String portName,
+ @WebParam(name = "portValue") @XmlElement(required = true) String portValue)
+ throws UnknownRunException, NoUpdateException,
+ BadStateChangeException, BadPropertyValueException;
+
+ /**
+ * Tells the given run to use the given list delimiter (a single-character
+ * string value) for splitting the input on the given port. Note that
+ * nullability of the delimiter is supported here.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param portName
+ * The port to set the list delimiter for.
+ * @param delimiter
+ * The single-character value (in range U+00001..U+0007F) to use
+ * as the delimiter, or <tt>null</tt> for no delimiter at all.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws BadStateChangeException
+ * If the run is not in the {@link Status#Initialized
+ * Initialized} state.
+ * @throws BadPropertyValueException
+ * If the delimiter may not be changed to the given literal
+ * value.
+ */
+ @WSDLDocumentation("Tells the given run to use the given list delimiter (a single-character string value) for splitting the input on the given port. Note that nullability of the delimiter is supported here.")
+ void setRunInputPortListDelimiter(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "portName") @XmlElement(required = true) String portName,
+ @WebParam(name = "delimiter") String delimiter)
+ throws UnknownRunException, NoUpdateException,
+ BadStateChangeException, BadPropertyValueException;
+
+ /**
+ * Get the Baclava file where the output of the run will be written.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The filename, or <tt>null</tt> if the results will be written to
+ * a subdirectory <tt>out</tt> of the run's working directory.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "OutputBaclavaFile")
+ @WSDLDocumentation("Get the Baclava file where the output of the run will be written.")
+ String getRunOutputBaclavaFile(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Set the Baclava file where the output of the run will be written.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param outputFile
+ * The filename for the Baclava file, or <tt>null</tt> or the
+ * empty string to indicate that the results are to be written to
+ * the subdirectory <tt>out</tt> of the run's working directory.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws FilesystemAccessException
+ * If the filename is illegal (starts with a <tt>/</tt> or
+ * contains a <tt>..</tt> element.
+ * @throws BadStateChangeException
+ * If the run is not in the {@link Status#Initialized
+ * Initialized} state
+ */
+ @WSDLDocumentation("Set the Baclava file where the output of the run will be written.")
+ void setRunOutputBaclavaFile(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "baclavaFileName") String outputFile)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, BadStateChangeException;
+
+ /**
+ * Return a description of the outputs of a run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return Description document (higher level than filesystem traverse).
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws BadStateChangeException
+ * If the run is in the {@link Status#Initialized Initialized}
+ * state
+ * @throws FilesystemAccessException
+ * If there is an exception when accessing the filesystem.
+ * @throws NoDirectoryEntryException
+ * If things are odd in the filesystem.
+ */
+ @WebResult(name = "OutputDescription")
+ @WSDLDocumentation("Return a description of the outputs of a run. Only known during/after the run.")
+ OutputDescription getRunOutputDescription(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException, BadStateChangeException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Get the time when the run will be eligible to be automatically deleted.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return A date at which the expiry will be scheduled. The actual deletion
+ * will happen an arbitrary amount of time later (depending on
+ * system policy).
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "Expiry")
+ @WSDLDocumentation("Get the time when the run will be eligible to be automatically deleted.")
+ Date getRunExpiry(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Set when the run will be eligible to be automatically deleted.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param expiry
+ * A date at which the expiry will be scheduled. The actual
+ * deletion will happen an arbitrary amount of time later
+ * (depending on system policy).
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the lifetime of the
+ * run.
+ */
+ @WSDLDocumentation("Set when the run will be eligible to be automatically deleted.")
+ void setRunExpiry(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "expiry") @XmlElement(required = true) Date expiry)
+ throws UnknownRunException, NoUpdateException;
+
+ /**
+ * Get the time when the run was created.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The moment when the run was created (modulo some internal
+ * overhead).
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "CreationTime")
+ @WSDLDocumentation("Get the time when the run was created.")
+ Date getRunCreationTime(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get the time when the run was started.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The moment when the run was started (modulo some internal
+ * overhead) or <tt>null</tt> to indicate that it has never started.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "StartTime")
+ @WSDLDocumentation("Get the time when the run was started.")
+ Date getRunStartTime(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get the time when the run was detected as having finished.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The moment when the run was believed stopped. Note that this may
+ * not be when the run <i>actually</i> finished; promptness of
+ * detection depends on many factors.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "FinishTime")
+ @WSDLDocumentation("Get the time when the run was detected as having finished.")
+ Date getRunFinishTime(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get the current status of the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The status code.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "Status")
+ @WSDLDocumentation("Get the current status of the given workflow run.")
+ Status getRunStatus(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Set the status of a run. This is used to start it executing, make it stop
+ * executing, etc. Note that changing the status of a run can <i>never</i>
+ * cause the run to be destroyed.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param status
+ * The status to change to. Changing to the current status will
+ * always have no effect.
+ * @return An empty string if the state change was completed, or a
+ * description (never empty) of why the state change is ongoing.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws BadStateChangeException
+ * If the state change requested is impossible.
+ */
+ @WebResult(name = "PartialityReason")
+ @WSDLDocumentation("Set the status of a given workflow run.")
+ String setRunStatus(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "status") @XmlElement(required = true) Status status)
+ throws UnknownRunException, NoUpdateException,
+ BadStateChangeException;
+
+ /**
+ * Get the names of the event listeners attached to the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The listener names.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "ListenerName")
+ @WSDLDocumentation("Get the names of the event listeners attached to the run.")
+ String[] getRunListeners(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Adds an event listener to the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param listenerType
+ * The type of event listener to add. Must be one of the names
+ * returned by the {@link #getServerListeners()} operation.
+ * @param configuration
+ * The configuration document for the event listener; the
+ * interpretation of the configuration is up to the listener.
+ * @return The actual name of the listener.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user isn't allowed to manipulate the run.
+ * @throws NoListenerException
+ * If the listener construction fails (<i>e.g.</i>, due to an
+ * unsupported <b>listenerType</b> or a problem with the
+ * <b>configuration</b>).
+ */
+ @WebResult(name = "ListenerName")
+ @WSDLDocumentation("Adds an event listener to the run.")
+ String addRunListener(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "listenerType") @XmlElement(required = true) String listenerType,
+ @WebParam(name = "configuration") @XmlElement(required = true) String configuration)
+ throws UnknownRunException, NoUpdateException, NoListenerException;
+
+ /**
+ * Returns the standard output of the workflow run. Unstarted runs return
+ * the empty string.
+ * <p>
+ * The equivalent thing can also be fetched from the relevant listener
+ * property (i.e., io/stdout).
+ *
+ * @param runName
+ * The handle of the run.
+ * @return Whatever the run engine printed on its stdout.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "StandardOutput")
+ @WSDLDocumentation("Returns the stdout from the run engine.")
+ String getRunStdout(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Returns the standard error of the workflow run. Unstarted runs return the
+ * empty string.
+ * <p>
+ * The equivalent thing can also be fetched from the relevant listener
+ * property (i.e., io/stderr).
+ *
+ * @param runName
+ * The handle of the run.
+ * @return Whatever the run engine printed on its stderr.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "StandardError")
+ @WSDLDocumentation("Returns the stderr from the run engine.")
+ String getRunStderr(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Returns the usage record for the workflow run. Unfinished runs return
+ * <tt>null</tt>.
+ * <p>
+ * The equivalent thing can also be fetched from the relevant listener
+ * property (i.e., io/usage).
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The usage record, or <tt>null</tt>.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "ResourceUsage")
+ @WSDLDocumentation("Returns the resource usage from the run engine.")
+ JobUsageRecord getRunUsageRecord(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Returns the log of the workflow run. Unstarted runs return the empty
+ * string.
+ * <p>
+ * This can also be fetched from the appropriate file (i.e.,
+ * <tt>logs/detail.log</tt>).
+ *
+ * @param runName
+ * The handle of the run.
+ * @return Whatever the run engine wrote to its log.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "Log")
+ @WSDLDocumentation("Returns the detailed log from the run engine.")
+ String getRunLog(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Returns the run bundle of a run. The run must be <i>finished</i> for this
+ * to be guaranteed to be present, and must <i>not</i> have had its output
+ * generated as Baclava.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The contents of the run bundle.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If there was a problem reading the bundle.
+ * @throws NoDirectoryEntryException
+ * If the bundle doesn't exist currently.
+ */
+ @WebResult(name = "RunBundle")
+ @WSDLDocumentation("Gets the run bundle of a finished run. MTOM support recommended!")
+ FileContents getRunBundle(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Gets whether to generate provenance (in a run bundle) for a run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return Whether provenance will be generated.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "GenerateProvenance")
+ @WSDLDocumentation("Gets whether a run generates provenance.")
+ boolean getRunGenerateProvenance(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Sets whether to generate provenance (in a run bundle) for a run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param generateProvenance
+ * Whether to generate provenance.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to manipulate the run.
+ */
+ @WSDLDocumentation("Sets whether a run generates provenance. "
+ + "Only usefully settable before the run is started.")
+ void setRunGenerateProvenance(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "generateProvenance") @XmlElement(required = true) boolean generateProvenance)
+ throws UnknownRunException, NoUpdateException;
+
+ /**
+ * Get the owner of the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The status code.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ */
+ @WebResult(name = "Owner")
+ @WSDLDocumentation("Get the owner of the given workflow run.")
+ String getRunOwner(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException;
+
+ /**
+ * Get the list of permissions associated with a workflow run.
+ *
+ * @param runName
+ * The name of the run whose permissions are to be obtained.
+ * @return A description of the non-<tt>none</tt> permissions.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the current
+ * user is not permitted to see it.
+ * @throws NotOwnerException
+ * If asked to provide this information about a run that the
+ * current user may see but where they are not the owner of it.
+ */
+ @WebResult(name = "PermissionList")
+ @WSDLDocumentation("Get the list of permissions associated with a given workflow run.")
+ PermissionList listRunPermissions(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException, NotOwnerException;
+
+ /**
+ * Set the permission for a user to access and update a particular workflow
+ * run.
+ *
+ * @param runName
+ * The name of the run whose permissions are to be updated.
+ * @param userName
+ * The name of the user about whom this call is talking.
+ * @param permission
+ * The permission level to set.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the current
+ * user is not permitted to see it.
+ * @throws NotOwnerException
+ * If asked to provide this information about a run that the
+ * current user may see but where they are not the owner of it.
+ */
+ @WSDLDocumentation("Set the permission for a user to access and update a given workflow run.")
+ void setRunPermission(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "userName") @XmlElement(required = true) String userName,
+ @WebParam(name = "permission") @XmlElement(required = true) Permission permission)
+ throws UnknownRunException, NotOwnerException;
+
+ /**
+ * Get the credentials associated with the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The collection of credentials.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NotOwnerException
+ * If the user is permitted to see the run, but isn't the owner;
+ * only the owner may see the credentials.
+ */
+ @WebResult(name = "Credentials")
+ @WSDLDocumentation("Get the credentials (passwords, private keys) associated with the given workflow run. Only the owner may do this.")
+ Credential[] getRunCredentials(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException, NotOwnerException;
+
+ /**
+ * Set a credential associated with the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param credentialID
+ * The handle of the credential to set. If empty, a new
+ * credential will be created.
+ * @param credential
+ * The credential to set.
+ * @return The handle of the credential that was created or updated.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NotOwnerException
+ * If the user is permitted to see the run, but isn't the owner;
+ * only the owner may manipulate the credentials.
+ * @throws InvalidCredentialException
+ * If the <b>credential</b> fails its checks.
+ * @throws NoCredentialException
+ * If the <b>credentialID</b> is not empty but does not
+ * correspond to an existing credential.
+ * @throws BadStateChangeException
+ * If an attempt to manipulate the credentials is done after the
+ * workflow has started running.
+ */
+ @WebResult(name = "credentialID")
+ @WSDLDocumentation("Set a credential (password, private key, etc.) associated with the given run. Only the owner may do this.")
+ String setRunCredential(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "credentialID") @XmlElement(required = true) String credentialID,
+ @WebParam(name = "credential") @XmlElement(required = true) Credential credential)
+ throws UnknownRunException, NotOwnerException,
+ InvalidCredentialException, NoCredentialException,
+ BadStateChangeException;
+
+ /**
+ * Delete a credential associated with the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param credentialID
+ * The handle of the credential to delete. If empty, a new
+ * credential will be created.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NotOwnerException
+ * If the user is permitted to see the run, but isn't the owner;
+ * only the owner may manipulate the credentials.
+ * @throws NoCredentialException
+ * If the given credentialID does not exist.
+ * @throws BadStateChangeException
+ * If an attempt to manipulate the credentials is done after the
+ * workflow has started running.
+ */
+ @WSDLDocumentation("Delete a credential associated with the given run. Only the owner may do this.")
+ void deleteRunCredential(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "credentialID") @XmlElement(required = true) String credentialID)
+ throws UnknownRunException, NotOwnerException,
+ NoCredentialException, BadStateChangeException;
+
+ /**
+ * Get the certificate collections associated with the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @return The collection of credentials.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NotOwnerException
+ * If the user is permitted to see the run, but isn't the owner;
+ * only the owner may see the credentials.
+ */
+ @WebResult(name = "CertificateCollections")
+ @WSDLDocumentation("Get the trusted (server or CA) certificates associated with the run. Only the owner may do this.")
+ Trust[] getRunCertificates(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName)
+ throws UnknownRunException, NotOwnerException;
+
+ /**
+ * Set a certificate collection associated with the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param certificateID
+ * The handle of the certificate collection to set. If empty, a
+ * new certificate collection will be created.
+ * @param certificate
+ * The certificate collection to set.
+ * @return The handle of the certificate set that was created or updated.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NotOwnerException
+ * If the user is permitted to see the run, but isn't the owner;
+ * only the owner may manipulate the certificates.
+ * @throws InvalidCredentialException
+ * If the <b>certificate</b> fails its checks.
+ * @throws NoCredentialException
+ * If the <b>credentialID</b> is not empty but does not
+ * correspond to an existing certificate collection.
+ * @throws BadStateChangeException
+ * If an attempt to manipulate the credentials is done after the
+ * workflow has started running.
+ */
+ @WebResult(name = "certificateID")
+ @WSDLDocumentation("Set a trusted (server or CA) certificate associated with the run. Only the owner may do this.")
+ String setRunCertificates(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "certificateID") String certificateID,
+ @WebParam(name = "certificate") @XmlElement(required = true) Trust certificate)
+ throws UnknownRunException, NotOwnerException,
+ InvalidCredentialException, NoCredentialException,
+ BadStateChangeException;
+
+ /**
+ * Delete a certificate collection associated with the run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param certificateID
+ * The handle of the credential to delete.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NotOwnerException
+ * If the user is permitted to see the run, but isn't the owner;
+ * only the owner may manipulate the certificates.
+ * @throws NoCredentialException
+ * If the given certificateID does not exist.
+ * @throws BadStateChangeException
+ * If an attempt to manipulate the credentials is done after the
+ * workflow has started running.
+ */
+ @WSDLDocumentation("Delete a trusted (server or CA) certificate associated with the run. Only the owner may do this.")
+ void deleteRunCertificates(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "certificateID") @XmlElement(required = true) String certificateID)
+ throws UnknownRunException, NotOwnerException,
+ NoCredentialException, BadStateChangeException;
+
+ /**
+ * Get the contents of any directory at/under the run's working directory.
+ * Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param directory
+ * The name of the directory to fetch; the main working directory
+ * is <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return A list of entries. They are assumed to be all directories or
+ * files.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the contents of
+ * a file).
+ * @throws NoDirectoryEntryException
+ * If the name of the directory can't be looked up.
+ */
+ @WebResult(name = "DirectoryEntry")
+ @WSDLDocumentation("Get the contents of any directory at/under the run's working directory.")
+ DirEntry[] getRunDirectoryContents(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "directory") @XmlElement(required = true) DirEntry directory)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Get the contents of any directory (and its subdirectories) at/under the
+ * run's working directory, returning it as a compressed ZIP file. Runs do
+ * not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param directory
+ * The name of the directory to fetch; the main working directory
+ * is <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return A serialized ZIP file.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the contents of
+ * a file).
+ * @throws NoDirectoryEntryException
+ * If the name of the directory can't be looked up.
+ */
+ @WebResult(name = "ZipFile")
+ @WSDLDocumentation("Get the contents of any directory (and its subdirectories) at/under the run's working directory, returning it as a compressed ZIP file.")
+ byte[] getRunDirectoryAsZip(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "directory") @XmlElement(required = true) DirEntry directory)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Get the contents of any directory (and its subdirectories) at/under the
+ * run's working directory, returning it as a compressed ZIP file that is
+ * streamed via MTOM. Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param directory
+ * The name of the directory to fetch; the main working directory
+ * is <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return An MTOM-streamable ZIP file reference.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the contents of
+ * a file).
+ * @throws NoDirectoryEntryException
+ * If the name of the directory can't be looked up.
+ */
+ @WebResult(name = "ZipStream")
+ @WSDLDocumentation("Get the contents of any directory (and its subdirectories) at/under the run's working directory, returning it as a compressed ZIP file that is streamed by MTOM.")
+ ZippedDirectory getRunDirectoryAsZipMTOM(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "directory") @XmlElement(required = true) DirEntry directory)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Make a new empty directory beneath an existing one, which must be the
+ * run's working directory or a directory beneath it. Runs do not share
+ * working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param parent
+ * The parent directory that will have the new directory added
+ * beneath it.
+ * @param name
+ * The name of the directory to create. Must not be the same as
+ * any other file or directory in the <i>parent</i> directory.
+ * The name <i>must not</i> consist of <tt>..</tt> or have a
+ * <tt>/</tt> in it.
+ * @return A reference to the created directory.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., making something with
+ * the same name as something that already exists).
+ * @throws NoDirectoryEntryException
+ * If the name of the containing directory can't be looked up.
+ */
+ @WebResult(name = "CreatedDirectory")
+ @WSDLDocumentation("Make a new empty directory beneath an existing one, all relative to the given run's main working directory.")
+ DirEntry makeRunDirectory(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "parentDirectory") @XmlElement(required = true) DirEntry parent,
+ @WebParam(name = "directoryName") @XmlElement(required = true) String name)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Make a new empty file in an existing directory, which may be the run's
+ * working directory or any directory beneath it. Runs do not share working
+ * directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param parent
+ * The parent directory that will have the new file added to it.
+ * @param name
+ * The name of the file to create. Must not be the same as any
+ * other file or directory in the <i>parent</i> directory. The
+ * name <i>must not</i> consist of <tt>..</tt> or have a
+ * <tt>/</tt> in it.
+ * @return A reference to the created file. The file will be empty.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., making something with
+ * the same name as something that already exists).
+ * @throws NoDirectoryEntryException
+ * If the name of the containing directory can't be looked up.
+ */
+ @WebResult(name = "CreatedFile")
+ @WSDLDocumentation("Make a new empty file in an existing directory, which may be the run's working directory or any directory beneath it.")
+ DirEntry makeRunFile(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "parentDirectory") @XmlElement(required = true) DirEntry parent,
+ @WebParam(name = "fileNameTail") @XmlElement(required = true) String name)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Destroy an entry (file or directory) in or beneath a run's working
+ * directory. Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param dirEntry
+ * Reference to an existing item in a directory that will be
+ * destroyed. May be a reference to either a file or a directory.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., deleting something
+ * which doesn't exist or attempting to delete the main working
+ * directory).
+ * @throws NoDirectoryEntryException
+ * If the name of the file or directory can't be looked up.
+ */
+ @WSDLDocumentation("Destroy an entry (file or directory) in or beneath a run's working directory.")
+ void destroyRunDirectoryEntry(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "directoryEntry") @XmlElement(required = true) DirEntry dirEntry)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Get the contents of a file under the run's working directory. Runs do not
+ * share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to fetch; the main working directory is
+ * <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return The literal byte contents of the file.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the contents of
+ * a directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WebResult(name = "FileContents")
+ @WSDLDocumentation("Get the contents of a file under the run's working directory.")
+ byte[] getRunFileContents(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Get the contents of a file under the run's working directory via MTOM.
+ * Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to fetch; the main working directory is
+ * <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return The contents, described for transfer via MTOM.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the contents of
+ * a directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WebResult(name = "FileContentsMTOM")
+ @WSDLDocumentation("Get the contents of a file via MTOM.")
+ FileContents getRunFileContentsMTOM(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Set the contents of a file under the run's working directory. Runs do not
+ * share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to update; the main working directory is
+ * <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @param newContents
+ * The literal bytes to set the file contents to.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., writing the contents of
+ * a directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WSDLDocumentation("Set the contents of a file under the run's working directory.")
+ void setRunFileContents(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file,
+ @WebParam(name = "contents") @XmlElement(required = true) byte[] newContents)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Set the contents of a file under the run's working directory. Runs do not
+ * share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param newContents
+ * The description of what file to set, and what to the file
+ * contents should be set to.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., writing the contents of
+ * a directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WSDLDocumentation("Set the contents of a file under the run's working directory.")
+ void setRunFileContentsMTOM(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "contents") @XmlElement(required = true) FileContents newContents)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Set the contents of a file under the run's working directory to the
+ * contents of a publicly readable URI. Runs do not share working
+ * directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to update; the main working directory is
+ * <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @param reference
+ * The publicly readable URI whose contents are to become the
+ * literal bytes of the file's contents.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., writing the contents of
+ * a directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WSDLDocumentation("Set the contents of a file under the run's working directory from the contents of a publicly readable URI.")
+ void setRunFileContentsFromURI(@WebParam(name = "runName") String runName,
+ @WebParam(name = "fileName") DirEntryReference file,
+ @WebParam(name = "contents") URI reference)
+ throws UnknownRunException, NoUpdateException,
+ FilesystemAccessException, NoDirectoryEntryException;
+
+ /**
+ * Get the length of any file (in bytes) at/under the run's working
+ * directory. Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to get the length of; the main working
+ * directory is <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return The number of bytes in the file.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the length of a
+ * directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WebResult(name = "FileLength")
+ @WSDLDocumentation("Get the length of any file (in bytes) at/under the run's working directory.")
+ long getRunFileLength(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Get the time that the file or directory (at/under the run's working
+ * directory) was last modified. Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to get the modification date of; the main
+ * working directory is <tt>/</tt> and <tt>..</tt> is always
+ * disallowed.
+ * @return The modification date of the file or directory, as understood by
+ * the underlying operating system.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated.
+ * @throws NoDirectoryEntryException
+ * If the file or directory doesn't exist.
+ */
+ @WebResult(name = "FileModified")
+ @WSDLDocumentation("Get the length of any file (in bytes) at/under the run's working directory.")
+ Date getRunFileModified(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Get the content type of any file at/under the run's working directory.
+ * Runs do not share working directories.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param file
+ * The name of the file to get the length of; the main working
+ * directory is <tt>/</tt> and <tt>..</tt> is always disallowed.
+ * @return The content type of the file.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws FilesystemAccessException
+ * If some assumption is violated (e.g., reading the length of a
+ * directory).
+ * @throws NoDirectoryEntryException
+ * If the file doesn't exist.
+ */
+ @WebResult(name = "FileContentType")
+ @WSDLDocumentation("Get the content type of any file at/under the run's working directory.")
+ String getRunFileType(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "fileName") @XmlElement(required = true) DirEntry file)
+ throws UnknownRunException, FilesystemAccessException,
+ NoDirectoryEntryException;
+
+ /**
+ * Get the configuration document for an event listener attached to a run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param listenerName
+ * The name of the listener attached.
+ * @return The configuration document.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoListenerException
+ * If no such listener exists.
+ */
+ @WebResult(name = "ListenerConfiguration")
+ @WSDLDocumentation("Get the configuration document for an event listener attached to a run.")
+ String getRunListenerConfiguration(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName)
+ throws UnknownRunException, NoListenerException;
+
+ /**
+ * Get the list of properties supported by an event listener attached to a
+ * run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param listenerName
+ * The name of the listener attached.
+ * @return The list of property names.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoListenerException
+ * If no such listener exists.
+ */
+ @WebResult(name = "ListenerPropertyName")
+ @WSDLDocumentation("Get the list of properties supported by an event listener attached to a run.")
+ String[] getRunListenerProperties(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName)
+ throws UnknownRunException, NoListenerException;
+
+ /**
+ * Get the value of a property for an event listener attached to a run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param listenerName
+ * The name of the listener attached.
+ * @param propertyName
+ * The name of the property to read.
+ * @return The configuration document.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoListenerException
+ * If no such listener exists or if the listener has no such
+ * property.
+ */
+ @WebResult(name = "ListenerPropertyValue")
+ @WSDLDocumentation("Get the value of a property for an event listener attached to a run.")
+ String getRunListenerProperty(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName,
+ @WebParam(name = "propertyName") @XmlElement(required = true) String propertyName)
+ throws UnknownRunException, NoListenerException;
+
+ /**
+ * Set the value of a property for an event listener attached to a run.
+ *
+ * @param runName
+ * The handle of the run.
+ * @param listenerName
+ * The name of the listener attached.
+ * @param propertyName
+ * The name of the property to write.
+ * @param value
+ * The value to set the property to.
+ * @throws UnknownRunException
+ * If the server doesn't know about the run or if the user is
+ * not permitted to see it.
+ * @throws NoListenerException
+ * If no such listener exists, the listener has no such
+ * property, or the value is considered "unacceptable" in some
+ * way.
+ * @throws NoUpdateException
+ * If the user is not allowed to make modifications to the run.
+ */
+ @WSDLDocumentation("Set the value of a property for an event listener attached to a run.")
+ void setRunListenerProperty(
+ @WebParam(name = "runName") @XmlElement(required = true) String runName,
+ @WebParam(name = "listenerName") @XmlElement(required = true) String listenerName,
+ @WebParam(name = "propertyName") @XmlElement(required = true) String propertyName,
+ @WebParam(name = "propertyValue") @XmlElement(required = true) String value)
+ throws UnknownRunException, NoUpdateException, NoListenerException;
+
+ /**
+ * Gets the status of the server. Follows the HELIO Monitoring Service
+ * protocol.
+ *
+ * @return A status string.
+ */
+ @WSDLDocumentation("A simple way to get the status of the overall server.")
+ @WebResult(name = "ServerStatus")
+ String getServerStatus();
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java
new file mode 100644
index 0000000..cd06115
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/WrappedWorkflow.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE.txt" for license terms.
+ */
+package org.taverna.server.master.soap;
+
+import static javax.xml.bind.annotation.XmlAccessType.NONE;
+import static org.apache.commons.io.IOUtils.closeQuietly;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlMimeType;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.common.Workflow;
+
+import uk.org.taverna.scufl2.api.io.ReaderException;
+import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
+import uk.org.taverna.scufl2.api.io.WriterException;
+
+/**
+ * An MTOM-capable description of how to transfer the contents of a file.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "WorkflowReference")
+@XmlAccessorType(NONE)
+public class WrappedWorkflow {
+ @XmlMimeType("application/octet-stream")
+ // JAXB bug: must be this
+ public DataHandler workflowData;
+ Workflow workflow;
+
+ /**
+ * Initialize the contents of this descriptor from the given file and
+ * content type.
+ *
+ * @param workflow
+ * The workflow that is to be reported.
+ */
+ public void setWorkflow(Workflow workflow) {
+ workflowData = new DataHandler(new WorkflowSource(workflow));
+ }
+
+ @XmlTransient
+ public Workflow getWorkflow() throws IOException {
+ if (workflow != null)
+ return workflow;
+ try {
+ return new Workflow(new WorkflowBundleIO().readBundle(
+ workflowData.getInputStream(), null));
+ } catch (ReaderException e) {
+ throw new IOException("problem converting to scufl2 bundle", e);
+ }
+ }
+}
+
+/**
+ * A data source that knows how to deliver a workflow.
+ *
+ * @author Donal Fellows
+ */
+class WorkflowSource implements DataSource {
+ WorkflowSource(Workflow workflow) {
+ this.wf = workflow;
+ this.io = new WorkflowBundleIO();
+ }
+
+ Workflow wf;
+ final WorkflowBundleIO io;
+
+ @Override
+ public String getContentType() {
+ return wf.getPreferredContentType().getContentType();
+ }
+
+ @Override
+ public String getName() {
+ switch (wf.getPreferredContentType()) {
+ case SCUFL2:
+ return "workflow.scufl2";
+ case T2FLOW:
+ return "workflow.t2flow";
+ default:
+ return "workflow";
+ }
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ PipedInputStream is = new PipedInputStream();
+ final OutputStream os = new PipedOutputStream(is);
+ new Worker() {
+ @Override
+ public void doWork() throws WriterException, IOException {
+ io.writeBundle(wf.getScufl2Workflow(), os, wf
+ .getPreferredContentType().getContentType());
+ }
+
+ @Override
+ public void doneWork() {
+ closeQuietly(os);
+ }
+ };
+ return is;
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ final PipedInputStream is = new PipedInputStream();
+ OutputStream os = new PipedOutputStream(is);
+ new Worker() {
+ @Override
+ public void doWork() throws IOException, ReaderException {
+ wf = new Workflow(io.readBundle(is, null));
+ }
+
+ @Override
+ public void doneWork() {
+ closeQuietly(is);
+ }
+ };
+ return os;
+ }
+
+ static abstract class Worker extends Thread {
+ public Worker() {
+ setDaemon(true);
+ start();
+ }
+
+ public abstract void doWork() throws Exception;
+
+ public abstract void doneWork();
+
+ @Override
+ public void run() {
+ try {
+ doWork();
+ } catch (Exception e) {
+ // do nothing.
+ } finally {
+ doneWork();
+ }
+ }
+ }
+}
\ 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/soap/ZippedDirectory.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java
new file mode 100644
index 0000000..90fe51b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/ZippedDirectory.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.soap;
+
+import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.activation.UnsupportedDataTypeException;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlMimeType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.Directory;
+
+/**
+ * An MTOM-capable description of how to transfer the zipped contents of a
+ * directory.
+ *
+ * @author Donal Fellows
+ * @see Directory#getContentsAsZip()
+ */
+@XmlType(name = "ZippedDirectory")
+public class ZippedDirectory {
+ @XmlElement
+ public String name;
+ @XmlMimeType("application/octet-stream")
+ // JAXB bug: must be this
+ public DataHandler fileData;
+
+ public ZippedDirectory() {
+ }
+
+ /**
+ * Initialise the contents of this descriptor from the given directory.
+ *
+ * @param dir
+ * The directory that is to be reported.
+ */
+ public ZippedDirectory(Directory dir) {
+ name = dir.getFullName();
+ fileData = new DataHandler(new ZipSource(dir));
+ }
+}
+
+/**
+ * A data source that knows how to communicate with the Taverna Server back-end.
+ *
+ * @author Donal Fellows
+ */
+class ZipSource implements DataSource {
+ ZipSource(Directory d) {
+ this.d = d;
+ }
+
+ private final Directory d;
+
+ @Override
+ public String getContentType() {
+ return APPLICATION_ZIP_TYPE.toString();
+ }
+
+ @Override
+ public String getName() {
+ return d.getName();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ try {
+ return d.getContentsAsZip();
+ } catch (FilesystemAccessException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ throw new UnsupportedDataTypeException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java
new file mode 100644
index 0000000..51d9b69
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains the SOAP interface to Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER_SOAP, 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 = "port", namespaceURI = DATA),
+ @XmlNs(prefix = "feed", namespaceURI = FEED),
+ @XmlNs(prefix = "admin", namespaceURI = ADMIN) })
+package org.taverna.server.master.soap;
+
+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.XLINK;
+import static org.taverna.server.port_description.Namespaces.DATA;
+
+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/usage/UsageRecord.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java
new file mode 100644
index 0000000..487dbd0
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecord.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.usage;
+
+import java.util.Date;
+
+import javax.jdo.annotations.Column;
+import javax.jdo.annotations.Index;
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Persistent;
+import javax.jdo.annotations.PrimaryKey;
+import javax.jdo.annotations.Queries;
+import javax.jdo.annotations.Query;
+import javax.xml.bind.JAXBException;
+
+import org.ogf.usage.JobUsageRecord;
+
+/**
+ * A usage record as recorded in the database.
+ *
+ * @author Donal Fellows
+ */
+@PersistenceCapable(table = "USAGE_RECORD_LOG", schema = "UR", cacheable = "true")
+@Queries({ @Query(name = "allByDate", value = "SELECT USAGE_RECORD FROM UR.USAGE_RECORD_LOG ORDER BY CREATE_DATE", resultClass = String.class, unmodifiable = "true", unique = "false", language = "SQL") })
+public class UsageRecord {
+ /**
+ * Create an empty usage record database entry.
+ */
+ public UsageRecord() {
+ }
+
+ /**
+ * Create a usage record database entry that is populated from the given UR.
+ *
+ * @param usageRecord
+ * The originating usage record.
+ * @throws JAXBException
+ * If deserialization of the record fails.
+ */
+ public UsageRecord(String usageRecord) throws JAXBException {
+ JobUsageRecord jur = JobUsageRecord.unmarshal(usageRecord);
+ setUsageRecord(usageRecord);
+ setCreateDate(jur.getRecordIdentity().getCreateTime()
+ .toGregorianCalendar().getTime());
+ setId(jur.getRecordIdentity().getRecordId());
+ setUserid(jur.getUserIdentity().get(0).getLocalUserId());
+ }
+
+ /**
+ * Create a usage record database entry that is populated from the given UR.
+ *
+ * @param usageRecord
+ * The originating usage record.
+ * @throws JAXBException
+ * If serialization of the record fails.
+ */
+ public UsageRecord(JobUsageRecord usageRecord) throws JAXBException {
+ setUsageRecord(usageRecord.marshal());
+ setCreateDate(usageRecord.getRecordIdentity().getCreateTime()
+ .toGregorianCalendar().getTime());
+ setId(usageRecord.getRecordIdentity().getRecordId());
+ setUserid(usageRecord.getUserIdentity().get(0).getLocalUserId());
+ }
+
+ @PrimaryKey
+ @Column(name = "ID", length = 40)
+ private String id;
+
+ @Persistent
+ @Index(name = "USERID_IDX")
+ @Column(name = "USERID", length = 24)
+ private String userid;
+
+ @Persistent
+ @Index(name = "CREATE_IDX")
+ @Column(name = "CREATE_DATE")
+ private Date createDate;
+
+ @Persistent
+ @Column(name = "USAGE_RECORD", length = 32000)
+ // TODO Consider moving to BLOB (CLOB?) type
+ private String usageRecord;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUserid() {
+ return userid;
+ }
+
+ public void setUserid(String userid) {
+ this.userid = userid;
+ }
+
+ public Date getCreateDate() {
+ return createDate;
+ }
+
+ public void setCreateDate(Date createDate) {
+ this.createDate = createDate;
+ }
+
+ public String getUsageRecord() {
+ return usageRecord;
+ }
+
+ public void setUsageRecord(String usageRecord) {
+ this.usageRecord = usageRecord;
+ }
+}
\ 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/usage/UsageRecordRecorder.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java
new file mode 100644
index 0000000..12de304
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/UsageRecordRecorder.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.usage;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.annotation.PreDestroy;
+import javax.xml.bind.JAXBException;
+
+import org.apache.commons.logging.Log;
+import org.ogf.usage.JobUsageRecord;
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.api.ManagementModel;
+import org.taverna.server.master.utils.Contextualizer;
+import org.taverna.server.master.utils.JDOSupport;
+
+/**
+ * A simple state-aware writer of usage records. It just appends them, one by
+ * one, to the file whose name is stored in the state.
+ *
+ * @author Donal Fellows
+ */
+public class UsageRecordRecorder extends JDOSupport<UsageRecord> {
+ private Log log = getLog("Taverna.Server.Webapp");
+ public UsageRecordRecorder() {
+ super(UsageRecord.class);
+ }
+
+ private String logFile = null;
+ private boolean disableDB = false;
+ private ManagementModel state;
+ private Contextualizer contextualizer;
+ private String logDestination;
+ private PrintWriter writer;
+ private Object lock = new Object();
+ private UsageRecordRecorder self;
+
+ /**
+ * @param state
+ * the state to set
+ */
+ @Required
+ public void setState(ManagementModel state) {
+ this.state = state;
+ }
+
+ @Required
+ public void setSelf(UsageRecordRecorder self) {
+ this.self = self;
+ }
+
+ public void setLogFile(String logFile) {
+ this.logFile = (logFile == null || logFile.equals("none")) ? null : logFile;
+ }
+
+ public void setDisableDB(String disable) {
+ disableDB = "yes".equalsIgnoreCase(disable);
+ }
+
+ /**
+ * @param contextualizer
+ * the system's contextualizer, used to allow making the UR dump
+ * file be placed relative to the webapp.
+ */
+ @Required
+ public void setContextualizer(Contextualizer contextualizer) {
+ this.contextualizer = contextualizer;
+ }
+
+ /**
+ * Accept a usage record for recording.
+ *
+ * @param usageRecord
+ * The serialized usage record to record.
+ */
+ public void storeUsageRecord(String usageRecord) {
+ String logfile = state.getUsageRecordLogFile();
+ if (logfile == null)
+ logfile = this.logFile;
+ if (logfile != null) {
+ logfile = contextualizer.contextualize(logfile);
+ synchronized (lock) {
+ if (!logfile.equals(logDestination)) {
+ if (writer != null) {
+ writer.close();
+ writer = null;
+ }
+ try {
+ writer = new PrintWriter(new FileWriter(logfile));
+ logDestination = logfile;
+ } catch (IOException e) {
+ log.warn("failed to open usage record log file", e);
+ }
+ }
+ if (writer != null) {
+ writer.println(usageRecord);
+ writer.flush();
+ }
+ }
+ }
+
+ if (!disableDB)
+ saveURtoDB(usageRecord);
+ }
+
+ /**
+ * How to save a usage record to the database.
+ *
+ * @param usageRecord
+ * The serialized usage record to save.
+ */
+ protected void saveURtoDB(String usageRecord) {
+ UsageRecord ur;
+ try {
+ ur = new UsageRecord(usageRecord);
+ } catch (JAXBException e) {
+ log.warn("failed to deserialize usage record", e);
+ return;
+ }
+
+ try {
+ self.saveURtoDB(ur);
+ } catch (RuntimeException e) {
+ log.warn("failed to save UR to database", e);
+ }
+ }
+
+ @WithinSingleTransaction
+ public void saveURtoDB(UsageRecord ur) {
+ persist(ur);
+ }
+
+ @WithinSingleTransaction
+ public List<JobUsageRecord> getUsageRecords() {
+ @SuppressWarnings("unchecked")
+ Collection<String> urs = (Collection<String>) namedQuery("allByDate")
+ .execute();
+ List<JobUsageRecord> result = new ArrayList<>();
+ for (String ur : urs)
+ try {
+ result.add(JobUsageRecord.unmarshal(ur));
+ } catch (JAXBException e) {
+ log.warn("failed to unmarshal UR", e);
+ }
+ return result;
+ }
+
+ @PreDestroy
+ public void close() {
+ if (writer != null)
+ writer.close();
+ }
+}
\ 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/usage/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java
new file mode 100644
index 0000000..13e14cd
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/usage/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * Resource usage recording mechanism.
+ */
+package org.taverna.server.master.usage;
[12/49] incubator-taverna-server git commit: taverna-* module names
Posted by st...@apache.org.
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/EntryHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java
new file mode 100644
index 0000000..20d9f56
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java
@@ -0,0 +1,131 @@
+package org.taverna.server.master.rest.handler;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonMap;
+import static javax.ws.rs.core.Response.notAcceptable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Variant;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.writer.Writer;
+import org.springframework.beans.factory.annotation.Required;
+
+@Provider
+@Produces({ "application/atom+xml", "application/atom+xml;type=entry" })
+@Consumes({ "application/atom+xml", "application/atom+xml;type=entry" })
+public class EntryHandler implements MessageBodyWriter<Entry>,
+ MessageBodyReader<Entry> {
+ private static final String ENC = "UTF-8";
+ private static final MediaType ENTRY = new MediaType("application",
+ "atom+xml", singletonMap("type", "entry"));
+ private static final Variant VARIANT = new Variant(ENTRY, (String) null,
+ ENC);
+ private static final Charset UTF8 = Charset.forName(ENC);
+
+ @Required
+ public void setAbdera(Abdera abdera) {
+ parser = abdera.getParser();
+ writer = abdera.getWriterFactory().getWriter("prettyxml");
+ }
+
+ private Parser parser;
+ private Writer writer;
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (!Entry.class.isAssignableFrom(type))
+ return false;
+ if (!ENTRY.isCompatible(mediaType))
+ return false;
+ if (mediaType.getParameters().containsKey("type"))
+ return "entry".equalsIgnoreCase(mediaType.getParameters().get(
+ "type"));
+ return true;
+ }
+
+ @Override
+ public Entry readFrom(Class<Entry> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ Charset cs = UTF8;
+ try {
+ String charset = mediaType.getParameters().get("charset");
+ if (charset != null)
+ cs = Charset.forName(charset);
+ } catch (IllegalCharsetNameException e) {
+ throw new WebApplicationException(notAcceptable(asList(VARIANT))
+ .entity("bad charset name").build());
+ } catch (UnsupportedCharsetException e) {
+ throw new WebApplicationException(notAcceptable(asList(VARIANT))
+ .entity("unsupportd charset name").build());
+ }
+ try {
+ Document<Entry> doc = parser.parse(new InputStreamReader(
+ entityStream, cs));
+ if (!Entry.class.isAssignableFrom(doc.getRoot().getClass())) {
+ throw new WebApplicationException(
+ notAcceptable(asList(VARIANT)).entity(
+ "not really a feed entry").build());
+ }
+ return doc.getRoot();
+ } catch (ClassCastException e) {
+ throw new WebApplicationException(notAcceptable(asList(VARIANT))
+ .entity("not really a feed entry").build());
+
+ }
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (!Entry.class.isAssignableFrom(type))
+ return false;
+ if (!ENTRY.isCompatible(mediaType))
+ return false;
+ if (mediaType.getParameters().containsKey("type"))
+ return "entry".equalsIgnoreCase(mediaType.getParameters().get(
+ "type"));
+ return true;
+ }
+
+ @Override
+ public long getSize(Entry t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Entry t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ httpHeaders.putSingle("Content-Type", ENTRY.toString() + ";charset="
+ + ENC);
+ writer.writeTo(t, new OutputStreamWriter(entityStream, UTF8));
+ }
+}
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/FeedHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java
new file mode 100644
index 0000000..7c17f5c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java
@@ -0,0 +1,66 @@
+package org.taverna.server.master.rest.handler;
+
+import static java.util.Collections.singletonMap;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.writer.Writer;
+import org.springframework.beans.factory.annotation.Required;
+
+@Provider
+@Produces({ "application/atom+xml", "application/atom+xml;type=feed" })
+public class FeedHandler implements MessageBodyWriter<Feed> {
+ private static final MediaType FEED = new MediaType("application",
+ "atom+xml", singletonMap("type", "feed"));
+ private static final String ENC = "UTF-8";
+
+ @Required
+ public void setAbdera(Abdera abdera) {
+ writer = abdera.getWriterFactory().getWriter("prettyxml");
+ }
+
+ private Writer writer;
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (!Feed.class.isAssignableFrom(type))
+ return false;
+ if (!FEED.isCompatible(mediaType))
+ return false;
+ if (mediaType.getParameters().containsKey("type"))
+ return "feed".equalsIgnoreCase(mediaType.getParameters()
+ .get("type"));
+ return true;
+ }
+
+ @Override
+ public long getSize(Feed t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Feed t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ httpHeaders.putSingle("Content-Type", FEED.toString() + ";charset="
+ + ENC);
+ writer.writeTo(t, new OutputStreamWriter(entityStream, ENC));
+ }
+}
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/FileConcatenationHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java
new file mode 100644
index 0000000..ab18d73
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java
@@ -0,0 +1,61 @@
+package org.taverna.server.master.rest.handler;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.springframework.beans.factory.annotation.Required;
+import org.taverna.server.master.FileConcatenation;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.File;
+
+public class FileConcatenationHandler implements
+ MessageBodyWriter<FileConcatenation> {
+ /** How much to pull from the worker in one read. */
+ private int maxChunkSize;
+
+ /**
+ * @param maxChunkSize
+ * How much to pull from the worker in one read.
+ */
+ @Required
+ public void setMaxChunkSize(int maxChunkSize) {
+ this.maxChunkSize = maxChunkSize;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return type.isAssignableFrom(FileConcatenation.class);
+ }
+
+ @Override
+ public long getSize(FileConcatenation fc, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return fc.size();
+ }
+
+ @Override
+ public void writeTo(FileConcatenation fc, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ for (File f : fc)
+ try {
+ byte[] buffer;
+ for (int off = 0; true ; off += buffer.length) {
+ buffer = f.getContents(off, maxChunkSize);
+ if (buffer == null || buffer.length == 0)
+ break;
+ entityStream.write(buffer);
+ }
+ } catch (FilesystemAccessException e) {
+ // Ignore/skip to next 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/FileMessageHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java
new file mode 100644
index 0000000..0aeb816
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010-2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.commons.logging.Log;
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.File;
+
+/**
+ * How to write out a File object with JAX-RS.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+public class FileMessageHandler implements MessageBodyWriter<File> {
+ private Log log = getLog("Taverna.Server.Webapp");
+ /** How much to pull from the worker in one read. */
+ private int maxChunkSize;
+
+ /**
+ * @param maxChunkSize
+ * How much to pull from the worker in one read.
+ */
+ public void setMaxChunkSize(int maxChunkSize) {
+ this.maxChunkSize = maxChunkSize;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return File.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(File t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ try {
+ return t.getSize(); // Is it really raw bytes?
+ } catch (FilesystemAccessException e) {
+ log.info("failed to get file length", e);
+ return -1;
+ }
+ }
+
+ @Override
+ public void writeTo(File t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ try {
+ int off = 0;
+ while (true) {
+ byte[] buffer = t.getContents(off, maxChunkSize);
+ if (buffer == null || buffer.length == 0)
+ break;
+ entityStream.write(buffer);
+ off += buffer.length;
+ }
+ } catch (FilesystemAccessException e) {
+ throw new IOException("problem when reading file", e);
+ }
+ }
+}
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/FileSegmentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java
new file mode 100644
index 0000000..f387cf6
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static java.lang.Math.min;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.rest.FileSegment;
+
+/**
+ * How to write out a segment of a file with JAX-RS.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+public class FileSegmentHandler implements MessageBodyWriter<FileSegment> {
+ /** How much to pull from the worker in one read. */
+ private int maxChunkSize;
+
+ /**
+ * @param maxChunkSize
+ * How much to pull from the worker in one read.
+ */
+ public void setMaxChunkSize(int maxChunkSize) {
+ this.maxChunkSize = maxChunkSize;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return FileSegment.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public long getSize(FileSegment t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return t.to - t.from;
+ }
+
+ @Override
+ public void writeTo(FileSegment t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ try {
+ int off = t.from;
+ while (off < t.to) {
+ byte[] buffer = t.file.getContents(off,
+ min(maxChunkSize, t.to - off));
+ if (buffer == null || buffer.length == 0)
+ break;
+ entityStream.write(buffer);
+ off += buffer.length;
+ }
+ } catch (FilesystemAccessException e) {
+ throw new IOException("problem when reading file", e);
+ }
+ }
+}
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/FilesystemAccessHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java
new file mode 100644
index 0000000..12c137e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.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.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+
+@Provider
+public class FilesystemAccessHandler extends HandlerCore implements
+ ExceptionMapper<FilesystemAccessException> {
+ @Override
+ public Response toResponse(FilesystemAccessException exn) {
+ return respond(FORBIDDEN, 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/GeneralFailureHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java
new file mode 100644
index 0000000..775805b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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.INTERNAL_SERVER_ERROR;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.taverna.server.master.exceptions.GeneralFailureException;
+
+public class GeneralFailureHandler extends HandlerCore implements
+ ExceptionMapper<GeneralFailureException> {
+ @Override
+ public Response toResponse(GeneralFailureException exception) {
+ return respond(INTERNAL_SERVER_ERROR, 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/HandlerCore.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java
new file mode 100644
index 0000000..0e3fb51
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java
@@ -0,0 +1,71 @@
+/*
+ * 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.MediaType.TEXT_PLAIN_TYPE;
+import static javax.ws.rs.core.Response.status;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.logging.Log;
+import org.taverna.server.master.api.ManagementModel;
+
+/**
+ * Base class for handlers that grants Spring-enabled access to the management
+ * model.
+ *
+ * @author Donal Fellows
+ */
+public class HandlerCore {
+ private Log log = getLog("Taverna.Server.Webapp");
+ private ManagementModel managementModel;
+
+ /**
+ * @param managementModel
+ * the managementModel to set
+ */
+ public void setManagementModel(ManagementModel managementModel) {
+ this.managementModel = managementModel;
+ }
+
+ /**
+ * Simplified interface for building responses.
+ *
+ * @param status
+ * What status code to use?
+ * @param exception
+ * What exception to report on?
+ * @return The build response.
+ */
+ protected Response respond(Response.Status status, Exception exception) {
+ if (managementModel.getLogOutgoingExceptions()
+ || status.getStatusCode() >= 500)
+ log.info("converting exception to response", exception);
+ return status(status).type(TEXT_PLAIN_TYPE)
+ .entity(exception.getMessage()).build();
+ }
+
+ /**
+ * Simplified interface for building responses.
+ *
+ * @param status
+ * What status code to use?
+ * @param partialMessage
+ * The prefix to the message.
+ * @param exception
+ * What exception to report on?
+ * @return The build response.
+ */
+ protected Response respond(Response.Status status, String partialMessage,
+ Exception exception) {
+ if (managementModel.getLogOutgoingExceptions()
+ || status.getStatusCode() >= 500)
+ log.info("converting exception to response", exception);
+ return status(status).type(TEXT_PLAIN_TYPE)
+ .entity(partialMessage + "\n" + exception.getMessage()).build();
+ }
+}
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/IllegalArgumentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java
new file mode 100644
index 0000000..ac02015
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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.UNSUPPORTED_MEDIA_TYPE;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class IllegalArgumentHandler extends HandlerCore implements
+ ExceptionMapper<IllegalArgumentException> {
+ @Override
+ public Response toResponse(IllegalArgumentException exn) {
+ return respond(UNSUPPORTED_MEDIA_TYPE, exn);
+ }
+}
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/ImplementationProblemHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java
new file mode 100644
index 0000000..1458667
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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.INTERNAL_SERVER_ERROR;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.taverna.server.localworker.remote.ImplementationException;
+
+public class ImplementationProblemHandler extends HandlerCore implements
+ ExceptionMapper<ImplementationException> {
+ @Override
+ public Response toResponse(ImplementationException exception) {
+ return respond(INTERNAL_SERVER_ERROR, 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/InputStreamMessageHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java
new file mode 100644
index 0000000..2c0c092
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010-2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static java.lang.Long.parseLong;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * Maps a stream from a client into a bounded ordinary input stream that the
+ * webapp can work with more easily.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+@Consumes(APPLICATION_OCTET_STREAM)
+public class InputStreamMessageHandler implements
+ MessageBodyReader<InputStream> {
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return InputStream.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public InputStream readFrom(Class<InputStream> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ return new TransferStream(entityStream,
+ httpHeaders.get("Content-Length"));
+ }
+}
+
+/**
+ * The actual transfer thunk.
+ *
+ * @author Donal Fellows
+ */
+class TransferStream extends InputStream {
+ private Log log = getLog("Taverna.Server.Handlers");
+
+ public TransferStream(InputStream entityStream, List<String> contentLength) {
+ this.entityStream = new BufferedInputStream(entityStream);
+ if (contentLength != null && contentLength.size() > 0) {
+ this.limit = parseLong(contentLength.get(0));
+ if (log.isDebugEnabled())
+ log.debug("will attempt to transfer " + this.limit + " bytes");
+ } else {
+ this.limit = -1;
+ if (log.isDebugEnabled())
+ log.debug("will attempt to transfer until EOF");
+ }
+ }
+
+ InputStream entityStream;
+ long limit;
+ long doneBytes = 0;
+
+ @Override
+ public int read() throws IOException {
+ if (limit >= 0 && doneBytes >= limit)
+ return -1;
+ int result = entityStream.read();
+ if (result >= 0)
+ doneBytes++;
+ return result;
+ }
+
+ @Override
+ public int read(byte[] ary, int off, int len) throws IOException {
+ if (limit >= 0) {
+ if (doneBytes >= limit)
+ return -1;
+ if (doneBytes + len > limit)
+ len = (int) (limit - doneBytes);
+ }
+ int readBytes = entityStream.read(ary, off, len);
+ if (readBytes >= 0)
+ doneBytes += readBytes;
+ return readBytes;
+ }
+
+ @Override
+ public void close() throws IOException {
+ entityStream.close();
+ }
+}
\ 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/InvalidCredentialHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java
new file mode 100644
index 0000000..fe11de8
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 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.InvalidCredentialException;
+
+@Provider
+public class InvalidCredentialHandler extends HandlerCore implements
+ ExceptionMapper<InvalidCredentialException> {
+ @Override
+ public Response toResponse(InvalidCredentialException 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/JAXBExceptionHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java
new file mode 100644
index 0000000..33ac6a0
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 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 javax.xml.bind.JAXBException;
+
+@Provider
+public class JAXBExceptionHandler extends HandlerCore implements
+ ExceptionMapper<JAXBException> {
+ @Override
+ public Response toResponse(JAXBException exn) {
+ return respond(BAD_REQUEST, "APIEpicFail: " + exn.getErrorCode(), exn);
+ }
+}
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/NegotiationFailedHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java
new file mode 100644
index 0000000..47153e7
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static javax.ws.rs.core.Response.notAcceptable;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.rest.TavernaServerDirectoryREST.NegotiationFailedException;
+
+@Provider
+public class NegotiationFailedHandler implements
+ ExceptionMapper<NegotiationFailedException> {
+ @Override
+ public Response toResponse(NegotiationFailedException exn) {
+ return notAcceptable(exn.accepted).type(TEXT_PLAIN)
+ .entity(exn.getMessage()).build();
+ }
+}
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/NoCreateHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java
new file mode 100644
index 0000000..e4215a1
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.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.SERVICE_UNAVAILABLE;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoCreateException;
+
+@Provider
+public class NoCreateHandler extends HandlerCore implements
+ ExceptionMapper<NoCreateException> {
+ @Override
+ public Response toResponse(NoCreateException exn) {
+ return respond(SERVICE_UNAVAILABLE, 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/NoCredentialHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java
new file mode 100644
index 0000000..d81f6ba
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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 org.taverna.server.master.exceptions.NoCredentialException;
+
+public class NoCredentialHandler extends HandlerCore implements
+ ExceptionMapper<NoCredentialException> {
+ @Override
+ public Response toResponse(NoCredentialException exn) {
+ return respond(NOT_FOUND, exn);
+ }
+}
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/NoDestroyHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java
new file mode 100644
index 0000000..927af4b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.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.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoDestroyException;
+
+@Provider
+public class NoDestroyHandler extends HandlerCore implements
+ ExceptionMapper<NoDestroyException> {
+ @Override
+ public Response toResponse(NoDestroyException exn) {
+ return respond(FORBIDDEN, 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/NoDirectoryEntryHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
new file mode 100644
index 0000000..ab2e54d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.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.NoDirectoryEntryException;
+
+@Provider
+public class NoDirectoryEntryHandler extends HandlerCore implements
+ ExceptionMapper<NoDirectoryEntryException> {
+ @Override
+ public Response toResponse(NoDirectoryEntryException 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/NoListenerHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java
new file mode 100644
index 0000000..36e3053
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.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.NoListenerException;
+
+@Provider
+public class NoListenerHandler extends HandlerCore implements
+ ExceptionMapper<NoListenerException> {
+ @Override
+ public Response toResponse(NoListenerException 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/NoUpdateHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java
new file mode 100644
index 0000000..61a89d4
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.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.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoUpdateException;
+
+@Provider
+public class NoUpdateHandler extends HandlerCore implements
+ ExceptionMapper<NoUpdateException> {
+ @Override
+ public Response toResponse(NoUpdateException exn) {
+ return respond(FORBIDDEN, 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/NotOwnerHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java
new file mode 100644
index 0000000..44de871
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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.taverna.server.master.exceptions.NotOwnerException;
+
+public class NotOwnerHandler extends HandlerCore implements
+ ExceptionMapper<NotOwnerException> {
+ @Override
+ public Response toResponse(NotOwnerException exn) {
+ return respond(FORBIDDEN, exn);
+ }
+}
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/OverloadedHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java
new file mode 100644
index 0000000..21e5e68
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.SERVICE_UNAVAILABLE;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.OverloadedException;
+
+@Provider
+public class OverloadedHandler extends HandlerCore implements
+ ExceptionMapper<OverloadedException> {
+ @Override
+ public Response toResponse(OverloadedException exn) {
+ return respond(SERVICE_UNAVAILABLE, 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/PermissionHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java
new file mode 100644
index 0000000..03a4dd4
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 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.MediaType.TEXT_PLAIN_TYPE;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.taverna.server.master.common.Permission;
+
+/**
+ * Handler that allows CXF to send and receive {@linkplain Permission
+ * permissions} as plain text directly.
+ *
+ * @author Donal Fellows
+ */
+public class PermissionHandler implements MessageBodyReader<Permission>,
+ MessageBodyWriter<Permission> {
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return type.isAssignableFrom(Permission.class)
+ && mediaType.isCompatible(TEXT_PLAIN_TYPE);
+ }
+
+ @Override
+ public long getSize(Permission t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return t.toString().length();
+ }
+
+ @Override
+ public void writeTo(Permission t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ new OutputStreamWriter(entityStream).write(t.toString());
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return type.isAssignableFrom(Permission.class)
+ && mediaType.isCompatible(TEXT_PLAIN_TYPE);
+ }
+
+ @Override
+ public Permission readFrom(Class<Permission> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ char[] cbuf = new char[7];
+ int len = new InputStreamReader(entityStream).read(cbuf);
+ if (len < 0)
+ throw new IllegalArgumentException("no entity supplied");
+ return Permission.valueOf(new String(cbuf, 0, len));
+ }
+}
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/Scufl2DocumentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
new file mode 100644
index 0000000..edeac63
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE.txt" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.common.Workflow;
+
+import uk.org.taverna.scufl2.api.io.ReaderException;
+import uk.org.taverna.scufl2.api.io.WorkflowBundleIO;
+import uk.org.taverna.scufl2.api.io.WriterException;
+
+/**
+ * Handler that allows a .scufl2 document to be read from and written to a REST
+ * message directly.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+public class Scufl2DocumentHandler implements MessageBodyReader<Workflow>,
+ MessageBodyWriter<Workflow> {
+ private static final MediaType SCUFL2_TYPE = new MediaType("application",
+ "vnd.taverna.scufl2.workflow-bundle");
+ public static final String SCUFL2 = "application/vnd.taverna.scufl2.workflow-bundle";
+ private WorkflowBundleIO io = new WorkflowBundleIO();
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (type.isAssignableFrom(Workflow.class))
+ return mediaType.isCompatible(SCUFL2_TYPE);
+ return false;
+ }
+
+ @Override
+ public Workflow readFrom(Class<Workflow> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ try {
+ return new Workflow(io.readBundle(entityStream, SCUFL2));
+ } catch (ReaderException e) {
+ throw new WebApplicationException(e, 403);
+ }
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (Workflow.class.isAssignableFrom(type))
+ return mediaType.isCompatible(SCUFL2_TYPE);
+ return false;
+ }
+
+ @Override
+ public long getSize(Workflow workflow, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Workflow workflow, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ try {
+ io.writeBundle(workflow.getScufl2Workflow(), entityStream, SCUFL2);
+ } catch (WriterException e) {
+ throw new WebApplicationException(e);
+ }
+ }
+}
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/T2FlowDocumentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
new file mode 100644
index 0000000..4227d80
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.taverna.server.master.common.Workflow;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * Handler that allows a .t2flow document to be read from and written to a REST
+ * message directly.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+public class T2FlowDocumentHandler implements MessageBodyReader<Workflow>,
+ MessageBodyWriter<Workflow> {
+ private static final MediaType T2FLOW_TYPE = new MediaType("application",
+ "vnd.taverna.t2flow+xml");
+ public static final String T2FLOW = "application/vnd.taverna.t2flow+xml";
+ public static final String T2FLOW_ROOTNAME = "workflow";
+ public static final String T2FLOW_NS = "http://taverna.sf.net/2008/xml/t2flow";
+ private DocumentBuilderFactory db;
+ private TransformerFactory transformer;
+
+ public T2FlowDocumentHandler() throws ParserConfigurationException,
+ TransformerConfigurationException {
+ db = DocumentBuilderFactory.newInstance();
+ db.setNamespaceAware(true);
+ transformer = TransformerFactory.newInstance();
+ }
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (type.isAssignableFrom(Workflow.class))
+ return mediaType.isCompatible(T2FLOW_TYPE);
+ return false;
+ }
+
+ @Override
+ public Workflow readFrom(Class<Workflow> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ Document doc;
+ try {
+ doc = db.newDocumentBuilder().parse(entityStream);
+ } catch (SAXException e) {
+ throw new WebApplicationException(e, 403);
+ } catch (ParserConfigurationException e) {
+ throw new WebApplicationException(e);
+ }
+ Workflow workflow = new Workflow(doc.getDocumentElement());
+ if (doc.getDocumentElement().getNamespaceURI().equals(T2FLOW_NS)
+ && doc.getDocumentElement().getNodeName()
+ .equals(T2FLOW_ROOTNAME))
+ return workflow;
+ throw new WebApplicationException(Response.status(403)
+ .entity("invalid T2flow document; bad root element")
+ .type("text/plain").build());
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ if (Workflow.class.isAssignableFrom(type))
+ return mediaType.isCompatible(T2FLOW_TYPE);
+ return false;
+ }
+
+ @Override
+ public long getSize(Workflow workflow, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(Workflow workflow, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ try {
+ transformer.newTransformer().transform(
+ new DOMSource(workflow.getT2flowWorkflow()),
+ new StreamResult(entityStream));
+ } catch (TransformerException e) {
+ if (e.getCause() != null && e.getCause() instanceof IOException)
+ throw (IOException) e.getCause();
+ throw new WebApplicationException(e);
+ }
+ }
+}
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/URIListHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java
new file mode 100644
index 0000000..a90a229
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 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;
+import static org.taverna.server.master.rest.handler.URIListHandler.URI_LIST;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Deserialization and serialization engine for the <tt>{@value #URI_LIST}</tt>
+ * content type.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+@Consumes(URI_LIST)
+public class URIListHandler implements MessageBodyReader<List<URI>>,
+ MessageBodyWriter<List<URI>> {
+ /** The content type we handle. */
+ public static final String URI_LIST = "text/uri-list";
+ private static final MediaType URILIST = new MediaType("text", "uri-list");
+
+ @Override
+ public boolean isReadable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return type.isAssignableFrom(ArrayList.class)
+ && genericType instanceof ParameterizedType
+ && ((Class<?>) ((ParameterizedType) genericType)
+ .getActualTypeArguments()[0])
+ .isAssignableFrom(URI.class)
+ && URILIST.isCompatible(mediaType);
+ }
+
+ @Override
+ public List<URI> readFrom(Class<List<URI>> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+ throws IOException, WebApplicationException {
+ String enc = mediaType.getParameters().get("encoding");
+ Charset c = (enc == null) ? Charset.defaultCharset() : Charset
+ .forName(enc);
+ BufferedReader br = new BufferedReader(new InputStreamReader(
+ entityStream, c));
+ ArrayList<URI> uris = new ArrayList<>();
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (line.startsWith("#"))
+ continue;
+ try {
+ uris.add(new URI(line));
+ } catch (URISyntaxException e) {
+ throw new WebApplicationException(e, status(422).entity(
+ "ill-formed URI").build());
+ }
+ }
+ return uris;
+ }
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return List.class.isAssignableFrom(type)
+ && genericType instanceof ParameterizedType
+ && ((ParameterizedType) genericType).getActualTypeArguments()[0] == URI.class
+ && URILIST.isCompatible(mediaType);
+ }
+
+ @Override
+ public long getSize(List<URI> list, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ private static final String PREFERRED_ENCODING = "UTF-8";
+
+ @Override
+ public void writeTo(List<URI> list, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException {
+ String encoding = mediaType.getParameters().get("encoding");
+ if (encoding == null) {
+ encoding = PREFERRED_ENCODING;
+ httpHeaders.putSingle("Content-Type", URI_LIST + ";encoding="
+ + encoding);
+ }
+ BufferedWriter w = new BufferedWriter(new OutputStreamWriter(
+ entityStream, encoding));
+ for (URI uri : list) {
+ w.write(uri.toString());
+ w.newLine();
+ }
+ w.flush();
+ }
+}
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/UnknownRunHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java
new file mode 100644
index 0000000..4542237
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.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.UnknownRunException;
+
+@Provider
+public class UnknownRunHandler extends HandlerCore implements
+ ExceptionMapper<UnknownRunException> {
+ @Override
+ public Response toResponse(UnknownRunException 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/ZipStreamHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java
new file mode 100644
index 0000000..2241220
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.rest.handler;
+
+import static org.apache.commons.io.IOUtils.copy;
+import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.interfaces.Directory.ZipStream;
+
+/**
+ * How to write a ZIP file as the result entity of a request.
+ *
+ * @author Donal Fellows
+ */
+@Provider
+@Produces("application/zip")
+public class ZipStreamHandler implements MessageBodyWriter<ZipStream> {
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return ZipStream.class.isAssignableFrom(type)
+ && mediaType.equals(APPLICATION_ZIP_TYPE);
+ }
+
+ @Override
+ public long getSize(ZipStream t, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType) {
+ return -1;
+ }
+
+ @Override
+ public void writeTo(ZipStream zipStream, Class<?> type, Type genericType,
+ Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders,
+ OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ copy(zipStream, entityStream);
+ }
+}
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/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java
new file mode 100644
index 0000000..e72af22
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains type handlers for the RESTful interface to Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER_REST, 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 = "port", namespaceURI = DATA),
+ @XmlNs(prefix = "feed", namespaceURI = FEED),
+ @XmlNs(prefix = "admin", namespaceURI = ADMIN) })
+package org.taverna.server.master.rest.handler;
+
+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.XLINK;
+import static org.taverna.server.port_description.Namespaces.DATA;
+
+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/rest/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java
new file mode 100644
index 0000000..0a0b069
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+/**
+ * This package contains the RESTful interface to Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER_REST, 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 = "port", namespaceURI = DATA),
+ @XmlNs(prefix = "feed", namespaceURI = FEED),
+ @XmlNs(prefix = "admin", namespaceURI = ADMIN) })
+package org.taverna.server.master.rest;
+
+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.XLINK;
+import static org.taverna.server.port_description.Namespaces.DATA;
+
+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/soap/DirEntry.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java
new file mode 100644
index 0000000..bb8d73f
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.soap;
+
+import static org.taverna.server.master.common.Namespaces.XLINK;
+
+import java.net.URI;
+
+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.XmlType;
+
+import org.taverna.server.master.common.DirEntryReference;
+
+/**
+ * A more Taverna-friendly version of the directory entry descriptor classes.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "DirectoryEntry")
+@XmlRootElement(name = "entry")
+@XmlSeeAlso({ DirEntry.File.class, DirEntry.Directory.class })
+public class DirEntry {
+ /** A link to the entry. Ignored on input. */
+ @XmlAttribute(name = "href", namespace = XLINK)
+ @XmlSchemaType(name = "anyURI")
+ public URI link;
+ @XmlAttribute
+ public String name;
+ @XmlElement(required = true)
+ public String path;
+
+ /**
+ * A file in a directory.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "FileDirEntry")
+ @XmlRootElement(name = "file")
+ public static class File extends DirEntry {
+ }
+
+ /**
+ * A directory in a directory. That is, a sub-directory.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "DirectoryDirEntry")
+ @XmlRootElement(name = "dir")
+ public static class Directory extends DirEntry {
+ }
+
+ /**
+ * Converts from the "common" format to the subclasses of this class.
+ *
+ * @param deref
+ * The "common" format handle to convert.
+ * @return The converted handle
+ */
+ public static DirEntry convert(DirEntryReference deref) {
+ DirEntry result;
+ if (deref instanceof DirEntryReference.DirectoryReference)
+ result = new Directory();
+ else if (deref instanceof DirEntryReference.FileReference)
+ result = new File();
+ else
+ result = new DirEntry();
+ result.link = deref.link;
+ result.name = deref.name;
+ result.path = deref.path;
+ return result;
+ }
+
+ /**
+ * Converts to the "common" format from the subclasses of this class.
+ *
+ * @param deref
+ * The subclass of this class to convert.
+ * @return The converted reference.
+ */
+ public static DirEntryReference convert(DirEntry de) {
+ DirEntryReference result;
+ if (de instanceof Directory)
+ result = new DirEntryReference.DirectoryReference();
+ else if (de instanceof File)
+ result = new DirEntryReference.FileReference();
+ else
+ result = new DirEntryReference();
+ result.link = de.link;
+ result.name = de.name;
+ result.path = de.path;
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java
new file mode 100644
index 0000000..7ebc991
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.soap;
+
+import static java.lang.Math.min;
+import static java.lang.System.arraycopy;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlMimeType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.File;
+
+/**
+ * An MTOM-capable description of how to transfer the contents of a file.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "FileContents")
+public class FileContents {
+ @XmlElement
+ public String name;
+ @XmlMimeType("application/octet-stream") // JAXB bug: must be this
+ public DataHandler fileData;
+
+ /**
+ * Initialize the contents of this descriptor from the given file and
+ * content type.
+ *
+ * @param file
+ * The file that is to be reported.
+ * @param contentType
+ * The estimated content type of the file.
+ */
+ public void setFile(File file, String contentType) {
+ name = file.getFullName();
+ fileData = new DataHandler(new TavernaFileSource(file, contentType));
+ }
+
+ /**
+ * Write the content described by this class to the specified file.
+ * @param file The file to write to; must already exist.
+ * @throws IOException
+ * @throws FilesystemAccessException
+ */
+ public void writeToFile(File file) throws IOException,
+ FilesystemAccessException {
+ try (InputStream is = fileData.getInputStream()) {
+ byte[] buf = new byte[65536];
+ file.setContents(new byte[0]);
+ while (true) {
+ int len = is.read(buf);
+ if (len <= 0)
+ return;
+ if (len == buf.length)
+ file.appendContents(buf);
+ else {
+ byte[] shortbuf = new byte[len];
+ arraycopy(buf, 0, shortbuf, 0, len);
+ file.appendContents(shortbuf);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * A data source that knows how to communicate with the Taverna Server back-end.
+ *
+ * @author Donal Fellows
+ */
+class TavernaFileSource implements DataSource {
+ TavernaFileSource(File f, String type) {
+ this.f = f;
+ this.type = type;
+ }
+
+ private final File f;
+ private final String type;
+
+ @Override
+ public String getContentType() {
+ return type;
+ }
+
+ @Override
+ public String getName() {
+ return f.getName();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ final File f = this.f;
+ return new InputStream() {
+ private int idx;
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ byte[] r;
+ try {
+ r = f.getContents(idx, len);
+ } catch (FilesystemAccessException e) {
+ throw new IOException(e);
+ }
+ if (r == null)
+ return -1;
+ len = min(len, r.length);
+ arraycopy(r, 0, b, off, len);
+ idx += len;
+ return len;
+ }
+
+ @Override
+ public int read() throws IOException {
+ byte[] r;
+ try {
+ r = f.getContents(idx, 1);
+ } catch (FilesystemAccessException e) {
+ throw new IOException(e);
+ }
+ if (r == null)
+ return -1;
+ idx++;
+ return r[0];
+ }
+ };
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ final File f = this.f;
+ return new OutputStream() {
+ private boolean append = false;
+
+ @Override
+ public void write(int b) throws IOException {
+ write(new byte[] { (byte) b });
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ try {
+ if (append)
+ f.appendContents(b);
+ else
+ f.setContents(b);
+ append = true;
+ } catch (FilesystemAccessException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ byte[] ary = new byte[len];
+ arraycopy(b, off, ary, 0, len);
+ write(ary);
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java
new file mode 100644
index 0000000..3ab6d0c
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The University of Manchester
+ *
+ * See the file "LICENSE" for license terms.
+ */
+package org.taverna.server.master.soap;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.common.Permission;
+
+/**
+ * The list of permissions to access a workflow run of users <i>other than the
+ * owner</i>. This class exists to support the JAXB mapping.
+ *
+ * @author Donal Fellows
+ */
+@XmlType(name = "PermissionList")
+@XmlRootElement(name = "permissionList")
+public class PermissionList {
+ /**
+ * The type of a single mapped permission. This class exists to support the
+ * JAXB mapping.
+ *
+ * @author Donal Fellows
+ */
+ @XmlType(name = "")
+ public static class SinglePermissionMapping {
+ public SinglePermissionMapping() {
+ }
+
+ public SinglePermissionMapping(String user, Permission permission) {
+ this.userName = user;
+ this.permission = permission;
+ }
+
+ /** The name of the user that this talks about. */
+ public String userName;
+ /** The permission level that the user is granted. */
+ public Permission permission;
+ }
+
+ /** The list of (non-default) permissions granted. */
+ @XmlElement
+ public List<SinglePermissionMapping> permission;
+}
\ No newline at end of file