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 2018/01/09 23:30:35 UTC

[19/42] incubator-taverna-server git commit: package org.taverna -> org.apache.taverna

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/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
deleted file mode 100644
index b800c1c..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/DirectoryREST.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index 4ccb033..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/FileConcatenation.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index b9c8f55..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/InputREST.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index 6dfa3e2..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/InteractionFeed.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index 26a8982..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenerPropertyREST.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index 3cc0d73..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/ListenersREST.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index c65a334..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/ManagementState.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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<WebappState> q = query("id == " + KEY);
-		q.setUnique(true);
-		return q.executeUnique();
-	}
-
-	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/00397eff/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
deleted file mode 100644
index a04de46..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/RunREST.java
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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.apache.taverna.server.usagerecord.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/00397eff/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
deleted file mode 100644
index 9dc69d7..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/RunSecurityREST.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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/00397eff/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
deleted file mode 100644
index 2c841cc..0000000
--- a/taverna-server-webapp/src/main/java/org/taverna/server/master/SingleListenerREST.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- */
-package org.taverna.server.master;
-/*
- * 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.
- */
-
-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();
-	}
-}