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/17 21:55:04 UTC

[15/26] incubator-taverna-server git commit: temporarily empty repository

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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/27cbb9cb/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));
-		}
-	}
-}