/*
 */
package org.taverna.server.master;

import static java.lang.Math.min;
import static java.util.Collections.emptyMap;
import static java.util.Collections.sort;
import static java.util.UUID.randomUUID;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.UriBuilder.fromUri;
import static javax.xml.ws.handler.MessageContext.HTTP_REQUEST_HEADERS;
import static javax.xml.ws.handler.MessageContext.PATH_INFO;
import static org.apache.commons.io.IOUtils.toByteArray;
import static org.apache.commons.logging.LogFactory.getLog;
import static org.taverna.server.master.TavernaServerSupport.PROV_BUNDLE;
import static org.taverna.server.master.common.DirEntryReference.newInstance;
import static org.taverna.server.master.common.Namespaces.SERVER_SOAP;
import static org.taverna.server.master.common.Roles.ADMIN;
import static org.taverna.server.master.common.Roles.SELF;
import static org.taverna.server.master.common.Roles.USER;
import static org.taverna.server.master.common.Status.Initialized;
import static org.taverna.server.master.common.Uri.secure;
import static org.taverna.server.master.soap.DirEntry.convert;
import static org.taverna.server.master.utils.RestUtils.opt;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.jws.WebService;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBException;
import javax.xml.ws.WebServiceContext;

import org.apache.commons.logging.Log;
import org.apache.cxf.annotations.WSDLDocumentation;
import org.ogf.usage.JobUsageRecord;
import org.springframework.beans.factory.annotation.Required;
import org.taverna.server.master.api.SupportAware;
import org.taverna.server.master.api.TavernaServerBean;
import org.taverna.server.master.common.Capability;
import org.taverna.server.master.common.Credential;
import org.taverna.server.master.common.DirEntryReference;
import org.taverna.server.master.common.InputDescription;
import org.taverna.server.master.common.Permission;
import org.taverna.server.master.common.ProfileList;
import org.taverna.server.master.common.RunReference;
import org.taverna.server.master.common.Status;
import org.taverna.server.master.common.Trust;
import org.taverna.server.master.common.Workflow;
import org.taverna.server.master.common.version.Version;
import org.taverna.server.master.exceptions.BadPropertyValueException;
import org.taverna.server.master.exceptions.BadStateChangeException;
import org.taverna.server.master.exceptions.FilesystemAccessException;
import org.taverna.server.master.exceptions.InvalidCredentialException;
import org.taverna.server.master.exceptions.NoCreateException;
import org.taverna.server.master.exceptions.NoCredentialException;
import org.taverna.server.master.exceptions.NoDirectoryEntryException;
import org.taverna.server.master.exceptions.NoListenerException;
import org.taverna.server.master.exceptions.NoUpdateException;
import org.taverna.server.master.exceptions.NotOwnerException;
import org.taverna.server.master.exceptions.OverloadedException;
import org.taverna.server.master.exceptions.UnknownRunException;
import org.taverna.server.master.factories.ListenerFactory;
import org.taverna.server.master.interfaces.Directory;
import org.taverna.server.master.interfaces.DirectoryEntry;
import org.taverna.server.master.interfaces.File;
import org.taverna.server.master.interfaces.Input;
import org.taverna.server.master.interfaces.Listener;
import org.taverna.server.master.interfaces.Policy;
import org.taverna.server.master.interfaces.RunStore;
import org.taverna.server.master.interfaces.TavernaRun;
import org.taverna.server.master.interfaces.TavernaSecurityContext;
import org.taverna.server.master.notification.NotificationEngine;
import org.taverna.server.master.notification.atom.EventDAO;
import org.taverna.server.master.rest.TavernaServerREST;
import org.taverna.server.master.rest.TavernaServerREST.EnabledNotificationFabrics;
import org.taverna.server.master.rest.TavernaServerREST.PermittedListeners;
import org.taverna.server.master.rest.TavernaServerREST.PermittedWorkflows;
import org.taverna.server.master.rest.TavernaServerREST.PolicyView;
import org.taverna.server.master.rest.TavernaServerRunREST;
import org.taverna.server.master.soap.DirEntry;
import org.taverna.server.master.soap.FileContents;
import org.taverna.server.master.soap.PermissionList;
import org.taverna.server.master.soap.TavernaServerSOAP;
import org.taverna.server.master.soap.WrappedWorkflow;
import org.taverna.server.master.soap.ZippedDirectory;
import org.taverna.server.master.utils.CallTimeLogger.PerfLogged;
import org.taverna.server.master.utils.FilenameUtils;
import org.taverna.server.master.utils.InvocationCounter.CallCounted;
import org.taverna.server.port_description.OutputDescription;

/**
 * The core implementation of the web application.
 * 
 * @author Donal Fellows
 */
@Path("/")
@DeclareRoles({ USER, ADMIN })
@WebService(endpointInterface = "org.taverna.server.master.soap.TavernaServerSOAP", serviceName = "TavernaServer", targetNamespace = SERVER_SOAP)
@WSDLDocumentation("An instance of Taverna " + Version.JAVA + " Server.")
public abstract class TavernaServer implements TavernaServerSOAP,
		TavernaServerREST, TavernaServerBean {
	/**
	 * The root of descriptions of the server in JMX.
	 */
	public static final String JMX_ROOT = "Taverna:group=Server-"
			+ Version.JAVA + ",name=";

	/** The logger for the server framework. */
	public Log log = getLog("Taverna.Server.Webapp");

	@PreDestroy
	void closeLog() {
		log = null;
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// CONNECTIONS TO JMX, SPRING AND CXF

	@Resource
	WebServiceContext jaxws;
	@Context
	private HttpHeaders jaxrsHeaders;

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// STATE VARIABLES AND SPRING SETTERS

	/**
	 * For building descriptions of the expected inputs and actual outputs of a
	 * workflow.
	 */
	private ContentsDescriptorBuilder cdBuilder;
	/**
	 * Utilities for accessing files on the local-worker.
	 */
	private FilenameUtils fileUtils;
	/** How notifications are dispatched. */
	private NotificationEngine notificationEngine;
	/** Main support class. */
	private TavernaServerSupport support;
	/** A storage facility for workflow runs. */
	private RunStore runStore;
	/** Encapsulates the policies applied by this server. */
	private Policy policy;
	/** Where Atom events come from. */
	EventDAO eventSource;
	/** Reference to the main interaction feed. */
	private String interactionFeed;

	@Override
	@Required
	public void setFileUtils(FilenameUtils converter) {
		this.fileUtils = converter;
	}

	@Override
	@Required
	public void setContentsDescriptorBuilder(ContentsDescriptorBuilder cdBuilder) {
		this.cdBuilder = cdBuilder;
	}

	@Override
	@Required
	public void setNotificationEngine(NotificationEngine notificationEngine) {
		this.notificationEngine = notificationEngine;
	}

	/**
	 * @param support
	 *            the support to set
	 */
	@Override
	@Required
	public void setSupport(TavernaServerSupport support) {
		this.support = support;
	}

	@Override
	@Required
	public void setRunStore(RunStore runStore) {
		this.runStore = runStore;
	}

	@Override
	@Required
	public void setPolicy(Policy policy) {
		this.policy = policy;
	}

	@Override
	@Required
	public void setEventSource(EventDAO eventSource) {
		this.eventSource = eventSource;
	}

	/**
	 * The location of a service-wide interaction feed, derived from a
	 * properties file. Expected to be <i>actually</i> not set (to a real
	 * value).
	 * 
	 * @param interactionFeed
	 *            The URL, which will be resolved relative to the location of
	 *            the webapp, or the string "<tt>none</tt>" (which corresponds
	 *            to a <tt>null</tt>).
	 */
	public void setInteractionFeed(String interactionFeed) {
		if ("none".equals(interactionFeed))
			interactionFeed = null;
		else if (interactionFeed != null && interactionFeed.startsWith("${"))
			interactionFeed = null;
		this.interactionFeed = interactionFeed;
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// REST INTERFACE

	@Override
	@CallCounted
	@PerfLogged
	public ServerDescription describeService(UriInfo ui) {
		jaxrsUriInfo.set(new WeakReference<>(ui));
		return new ServerDescription(ui, resolve(interactionFeed));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public RunList listUsersRuns(UriInfo ui) {
		jaxrsUriInfo.set(new WeakReference<>(ui));
		return new RunList(runs(), secure(ui).path("{name}"));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Response submitWorkflow(Workflow workflow, UriInfo ui)
			throws NoUpdateException {
		jaxrsUriInfo.set(new WeakReference<>(ui));
		checkCreatePolicy(workflow);
		String name = support.buildWorkflow(workflow);
		return created(secure(ui).path("{uuid}").build(name)).build();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Response submitWorkflowByURL(List<URI> referenceList, UriInfo ui)
			throws NoCreateException {
		jaxrsUriInfo.set(new WeakReference<>(ui));
		if (referenceList == null || referenceList.size() == 0)
			throw new NoCreateException("no workflow URI supplied");
		URI workflowURI = referenceList.get(0);
		checkCreatePolicy(workflowURI);
		Workflow workflow;
		try {
			workflow = support.getWorkflowDocumentFromURI(workflowURI);
		} catch (IOException e) {
			throw new NoCreateException("could not read workflow", e);
		}
		String name = support.buildWorkflow(workflow);
		return created(secure(ui).path("{uuid}").build(name)).build();
	}

	@Override
	@CallCounted
	@PerfLogged
	public int getServerMaxRuns() {
		return support.getMaxSimultaneousRuns();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed({ USER, SELF })
	public TavernaServerRunREST getRunResource(String runName, UriInfo ui)
			throws UnknownRunException {
		jaxrsUriInfo.set(new WeakReference<>(ui));
		RunREST rr = makeRunInterface();
		rr.setRun(support.getRun(runName));
		rr.setRunName(runName);
		return rr;
	}

	private ThreadLocal<Reference<UriInfo>> jaxrsUriInfo = new InheritableThreadLocal<>();

	private UriInfo getUriInfo() {
		if (jaxrsUriInfo.get() == null)
			return null;
		return jaxrsUriInfo.get().get();
	}

	@Override
	@CallCounted
	public abstract PolicyView getPolicyDescription();

	@Override
	@CallCounted
	public Response serviceOptions() {
		return opt();
	}

	@Override
	@CallCounted
	public Response runsOptions() {
		return opt("POST");
	}

	/**
	 * Construct a RESTful interface to a run.
	 * 
	 * @return The handle to the interface, as decorated by Spring.
	 */
	protected abstract RunREST makeRunInterface();

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// SOAP INTERFACE

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public RunReference[] listRuns() {
		ArrayList<RunReference> ws = new ArrayList<>();
		UriBuilder ub = getRunUriBuilder();
		for (String runName : runs().keySet())
			ws.add(new RunReference(runName, ub));
		return ws.toArray(new RunReference[ws.size()]);
	}

	private void checkCreatePolicy(Workflow workflow) throws NoCreateException {
		List<URI> pwu = policy
				.listPermittedWorkflowURIs(support.getPrincipal());
		if (pwu == null || pwu.size() == 0)
			return;
		throw new NoCreateException("server policy: will only start "
				+ "workflows sourced from permitted URI list");
	}

	private void checkCreatePolicy(URI workflowURI) throws NoCreateException {
		List<URI> pwu = policy
				.listPermittedWorkflowURIs(support.getPrincipal());
		if (pwu == null || pwu.size() == 0 || pwu.contains(workflowURI))
			return;
		throw new NoCreateException("workflow URI not on permitted list");
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public RunReference submitWorkflow(Workflow workflow)
			throws NoUpdateException {
		checkCreatePolicy(workflow);
		String name = support.buildWorkflow(workflow);
		return new RunReference(name, getRunUriBuilder());
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public RunReference submitWorkflowMTOM(WrappedWorkflow workflow)
			throws NoUpdateException {
		Workflow wf;
		try {
			wf = workflow.getWorkflow();
		} catch (IOException e) {
			throw new NoCreateException(e.getMessage(), e);
		}
		checkCreatePolicy(wf);
		String name = support.buildWorkflow(wf);
		return new RunReference(name, getRunUriBuilder());
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public RunReference submitWorkflowByURI(URI workflowURI)
			throws NoCreateException {
		checkCreatePolicy(workflowURI);
		Workflow workflow;
		try {
			workflow = support.getWorkflowDocumentFromURI(workflowURI);
		} catch (IOException e) {
			throw new NoCreateException("could not read workflow", e);
		}
		String name = support.buildWorkflow(workflow);
		return new RunReference(name, getRunUriBuilder());
	}

	@Override
	@CallCounted
	@PerfLogged
	public URI[] getServerWorkflows() {
		return support.getPermittedWorkflowURIs();
	}

	@Override
	@CallCounted
	@PerfLogged
	public String[] getServerListeners() {
		List<String> types = support.getListenerTypes();
		return types.toArray(new String[types.size()]);
	}

	@Override
	@CallCounted
	@PerfLogged
	public String[] getServerNotifiers() {
		List<String> dispatchers = notificationEngine
				.listAvailableDispatchers();
		return dispatchers.toArray(new String[dispatchers.size()]);
	}

	@Override
	@CallCounted
	@PerfLogged
	public List<Capability> getServerCapabilities() {
		return support.getCapabilities();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void destroyRun(String runName) throws UnknownRunException,
			NoUpdateException {
		support.unregisterRun(runName, null);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunDescriptiveName(String runName)
			throws UnknownRunException {
		return support.getRun(runName).getName();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunDescriptiveName(String runName, String descriptiveName)
			throws UnknownRunException, NoUpdateException {
		TavernaRun run = support.getRun(runName);
		support.permitUpdate(run);
		run.setName(descriptiveName);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Workflow getRunWorkflow(String runName) throws UnknownRunException {
		return support.getRun(runName).getWorkflow();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public WrappedWorkflow getRunWorkflowMTOM(String runName)
			throws UnknownRunException {
		WrappedWorkflow ww = new WrappedWorkflow();
		ww.setWorkflow(support.getRun(runName).getWorkflow());
		return ww;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public ProfileList getRunWorkflowProfiles(String runName)
			throws UnknownRunException {
		return support.getProfileDescriptor(support.getRun(runName)
				.getWorkflow());
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Date getRunExpiry(String runName) throws UnknownRunException {
		return support.getRun(runName).getExpiry();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunExpiry(String runName, Date d)
			throws UnknownRunException, NoUpdateException {
		support.updateExpiry(support.getRun(runName), d);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Date getRunCreationTime(String runName) throws UnknownRunException {
		return support.getRun(runName).getCreationTimestamp();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Date getRunFinishTime(String runName) throws UnknownRunException {
		return support.getRun(runName).getFinishTimestamp();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Date getRunStartTime(String runName) throws UnknownRunException {
		return support.getRun(runName).getStartTimestamp();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Status getRunStatus(String runName) throws UnknownRunException {
		return support.getRun(runName).getStatus();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String setRunStatus(String runName, Status s)
			throws UnknownRunException, NoUpdateException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		if (s == Status.Operating && w.getStatus() == Status.Initialized) {
			if (!support.getAllowStartWorkflowRuns())
				throw new OverloadedException();
			try {
				String issue = w.setStatus(s);
				if (issue == null)
					return "";
				if (issue.isEmpty())
					return "unknown reason for partial change";
				return issue;
			} catch (RuntimeException | NoUpdateException e) {
				log.info("failed to start run " + runName, e);
				throw e;
			}
		} else {
			w.setStatus(s);
			return "";
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunStdout(String runName) throws UnknownRunException {
		try {
			return support.getProperty(runName, "io", "stdout");
		} catch (NoListenerException e) {
			return "";
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunStderr(String runName) throws UnknownRunException {
		try {
			return support.getProperty(runName, "io", "stderr");
		} catch (NoListenerException e) {
			return "";
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public JobUsageRecord getRunUsageRecord(String runName)
			throws UnknownRunException {
		try {
			String ur = support.getProperty(runName, "io", "usageRecord");
			if (ur.isEmpty())
				return null;
			return JobUsageRecord.unmarshal(ur);
		} catch (NoListenerException e) {
			return null;
		} catch (JAXBException e) {
			log.info("failed to deserialize non-empty usage record", e);
			return null;
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunLog(String runName) throws UnknownRunException {
		try {
			return support.getLogs(support.getRun(runName)).get("UTF-8");
		} catch (UnsupportedEncodingException e) {
			log.warn("unexpected encoding problem", e);
			return "";
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public FileContents getRunBundle(String runName)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		File f = fileUtils.getFile(support.getRun(runName), PROV_BUNDLE);
		FileContents fc = new FileContents();
		// We *know* the content type, by definition
		fc.setFile(f, "application/vnd.wf4ever.robundle+zip");
		return fc;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public boolean getRunGenerateProvenance(String runName)
			throws UnknownRunException {
		return support.getRun(runName).getGenerateProvenance();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunGenerateProvenance(String runName, boolean generate)
			throws UnknownRunException, NoUpdateException {
		TavernaRun run = support.getRun(runName);
		support.permitUpdate(run);
		run.setGenerateProvenance(generate);
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// SOAP INTERFACE - Security

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunOwner(String runName) throws UnknownRunException {
		return support.getRun(runName).getSecurityContext().getOwner()
				.getName();
	}

	/**
	 * Look up a security context, applying access control rules for access to
	 * the parts of the context that are only open to the owner.
	 * 
	 * @param runName
	 *            The name of the workflow run.
	 * @param initialOnly
	 *            Whether to check if we're in the initial state.
	 * @return The security context. Never <tt>null</tt>.
	 * @throws UnknownRunException
	 * @throws NotOwnerException
	 * @throws BadStateChangeException
	 */
	private TavernaSecurityContext getRunSecurityContext(String runName,
			boolean initialOnly) throws UnknownRunException, NotOwnerException,
			BadStateChangeException {
		TavernaRun run = support.getRun(runName);
		TavernaSecurityContext c = run.getSecurityContext();
		if (!c.getOwner().equals(support.getPrincipal()))
			throw new NotOwnerException();
		if (initialOnly && run.getStatus() != Initialized)
			throw new BadStateChangeException();
		return c;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Credential[] getRunCredentials(String runName)
			throws UnknownRunException, NotOwnerException {
		try {
			return getRunSecurityContext(runName, false).getCredentials();
		} catch (BadStateChangeException e) {
			Error e2 = new Error("impossible");
			e2.initCause(e);
			throw e2;
		}
	}

	private Credential findCredential(TavernaSecurityContext c, String id)
			throws NoCredentialException {
		for (Credential t : c.getCredentials())
			if (t.id.equals(id))
				return t;
		throw new NoCredentialException();
	}

	private Trust findTrust(TavernaSecurityContext c, String id)
			throws NoCredentialException {
		for (Trust t : c.getTrusted())
			if (t.id.equals(id))
				return t;
		throw new NoCredentialException();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String setRunCredential(String runName, String credentialID,
			Credential credential) throws UnknownRunException,
			NotOwnerException, InvalidCredentialException,
			NoCredentialException, BadStateChangeException {
		TavernaSecurityContext c = getRunSecurityContext(runName, true);
		if (credentialID == null || credentialID.isEmpty()) {
			credential.id = randomUUID().toString();
		} else {
			credential.id = findCredential(c, credentialID).id;
		}
		URI uri = getRunUriBuilder().path("security/credentials/{credid}")
				.build(runName, credential.id);
		credential.href = uri.toString();
		c.validateCredential(credential);
		c.addCredential(credential);
		return credential.id;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void deleteRunCredential(String runName, String credentialID)
			throws UnknownRunException, NotOwnerException,
			NoCredentialException, BadStateChangeException {
		getRunSecurityContext(runName, true).deleteCredential(
				new Credential.Dummy(credentialID));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Trust[] getRunCertificates(String runName)
			throws UnknownRunException, NotOwnerException {
		try {
			return getRunSecurityContext(runName, false).getTrusted();
		} catch (BadStateChangeException e) {
			Error e2 = new Error("impossible");
			e2.initCause(e);
			throw e2;
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String setRunCertificates(String runName, String certificateID,
			Trust certificate) throws UnknownRunException, NotOwnerException,
			InvalidCredentialException, NoCredentialException,
			BadStateChangeException {
		TavernaSecurityContext c = getRunSecurityContext(runName, true);
		if (certificateID == null || certificateID.isEmpty()) {
			certificate.id = randomUUID().toString();
		} else {
			certificate.id = findTrust(c, certificateID).id;
		}
		URI uri = getRunUriBuilder().path("security/trusts/{certid}").build(
				runName, certificate.id);
		certificate.href = uri.toString();
		c.validateTrusted(certificate);
		c.addTrusted(certificate);
		return certificate.id;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void deleteRunCertificates(String runName, String certificateID)
			throws UnknownRunException, NotOwnerException,
			NoCredentialException, BadStateChangeException {
		TavernaSecurityContext c = getRunSecurityContext(runName, true);
		Trust toDelete = new Trust();
		toDelete.id = certificateID;
		c.deleteTrusted(toDelete);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public PermissionList listRunPermissions(String runName)
			throws UnknownRunException, NotOwnerException {
		PermissionList pl = new PermissionList();
		pl.permission = new ArrayList<>();
		Map<String, Permission> perm;
		try {
			perm = support.getPermissionMap(getRunSecurityContext(runName,
					false));
		} catch (BadStateChangeException e) {
			log.error("unexpected error from internal API", e);
			perm = emptyMap();
		}
		List<String> users = new ArrayList<>(perm.keySet());
		sort(users);
		for (String user : users)
			pl.permission.add(new PermissionList.SinglePermissionMapping(user,
					perm.get(user)));
		return pl;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunPermission(String runName, String userName,
			Permission permission) throws UnknownRunException,
			NotOwnerException {
		try {
			support.setPermission(getRunSecurityContext(runName, false),
					userName, permission);
		} catch (BadStateChangeException e) {
			log.error("unexpected error from internal API", e);
		}
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// SOAP INTERFACE - Filesystem connection

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public OutputDescription getRunOutputDescription(String runName)
			throws UnknownRunException, BadStateChangeException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun run = support.getRun(runName);
		if (run.getStatus() == Initialized)
			throw new BadStateChangeException(
					"may not get output description in initial state");
		return cdBuilder.makeOutputDescriptor(run, null);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public DirEntry[] getRunDirectoryContents(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		List<DirEntry> result = new ArrayList<>();
		for (DirectoryEntry e : fileUtils.getDirectory(support.getRun(runName),
				convert(d)).getContents())
			result.add(convert(newInstance(null, e)));
		return result.toArray(new DirEntry[result.size()]);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public byte[] getRunDirectoryAsZip(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		try {
			return toByteArray(fileUtils.getDirectory(support.getRun(runName),
					convert(d)).getContentsAsZip());
		} catch (IOException e) {
			throw new FilesystemAccessException("problem serializing ZIP data",
					e);
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public ZippedDirectory getRunDirectoryAsZipMTOM(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		return new ZippedDirectory(fileUtils.getDirectory(
				support.getRun(runName), convert(d)));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public DirEntry makeRunDirectory(String runName, DirEntry parent,
			String name) throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		Directory dir = fileUtils.getDirectory(w, convert(parent))
				.makeSubdirectory(support.getPrincipal(), name);
		return convert(newInstance(null, dir));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public DirEntry makeRunFile(String runName, DirEntry parent, String name)
			throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		File f = fileUtils.getDirectory(w, convert(parent)).makeEmptyFile(
				support.getPrincipal(), name);
		return convert(newInstance(null, f));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void destroyRunDirectoryEntry(String runName, DirEntry d)
			throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		fileUtils.getDirEntry(w, convert(d)).destroy();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public byte[] getRunFileContents(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		File f = fileUtils.getFile(support.getRun(runName), convert(d));
		return f.getContents(0, -1);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunFileContents(String runName, DirEntry d,
			byte[] newContents) throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		fileUtils.getFile(w, convert(d)).setContents(newContents);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public FileContents getRunFileContentsMTOM(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		File f = fileUtils.getFile(support.getRun(runName), convert(d));
		FileContents fc = new FileContents();
		fc.setFile(f, support.getEstimatedContentType(f));
		return fc;
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunFileContentsFromURI(String runName,
			DirEntryReference file, URI reference)
			throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun run = support.getRun(runName);
		support.permitUpdate(run);
		File f = fileUtils.getFile(run, file);
		try {
			support.copyDataToFile(reference, f);
		} catch (IOException e) {
			throw new FilesystemAccessException(
					"problem transferring data from URI", e);
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunFileContentsMTOM(String runName, FileContents newContents)
			throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, NoDirectoryEntryException {
		TavernaRun run = support.getRun(runName);
		support.permitUpdate(run);
		File f = fileUtils.getFile(run, newContents.name);
		f.setContents(new byte[0]);
		support.copyDataToFile(newContents.fileData, f);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunFileType(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		return support.getEstimatedContentType(fileUtils.getFile(
				support.getRun(runName), convert(d)));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public long getRunFileLength(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		return fileUtils.getFile(support.getRun(runName), convert(d)).getSize();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public Date getRunFileModified(String runName, DirEntry d)
			throws UnknownRunException, FilesystemAccessException,
			NoDirectoryEntryException {
		return fileUtils.getFile(support.getRun(runName), convert(d))
				.getModificationDate();
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// SOAP INTERFACE - Run listeners

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String[] getRunListeners(String runName) throws UnknownRunException {
		TavernaRun w = support.getRun(runName);
		List<String> result = new ArrayList<>();
		for (Listener l : w.getListeners())
			result.add(l.getName());
		return result.toArray(new String[result.size()]);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String addRunListener(String runName, String listenerType,
			String configuration) throws UnknownRunException,
			NoUpdateException, NoListenerException {
		return support.makeListener(support.getRun(runName), listenerType,
				configuration).getName();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunListenerConfiguration(String runName,
			String listenerName) throws UnknownRunException,
			NoListenerException {
		return support.getListener(runName, listenerName).getConfiguration();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String[] getRunListenerProperties(String runName, String listenerName)
			throws UnknownRunException, NoListenerException {
		return support.getListener(runName, listenerName).listProperties()
				.clone();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunListenerProperty(String runName, String listenerName,
			String propName) throws UnknownRunException, NoListenerException {
		return support.getListener(runName, listenerName).getProperty(propName);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunListenerProperty(String runName, String listenerName,
			String propName, String value) throws UnknownRunException,
			NoUpdateException, NoListenerException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		Listener l = support.getListener(w, listenerName);
		try {
			l.getProperty(propName); // sanity check!
			l.setProperty(propName, value);
		} catch (RuntimeException e) {
			throw new NoListenerException("problem setting property: "
					+ e.getMessage(), e);
		}
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public InputDescription getRunInputs(String runName)
			throws UnknownRunException {
		return new InputDescription(support.getRun(runName));
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getRunOutputBaclavaFile(String runName)
			throws UnknownRunException {
		return support.getRun(runName).getOutputBaclavaFile();
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunInputBaclavaFile(String runName, String fileName)
			throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, BadStateChangeException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		w.setInputBaclavaFile(fileName);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunInputPortFile(String runName, String portName,
			String portFilename) throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, BadStateChangeException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		Input i = support.getInput(w, portName);
		if (i == null)
			i = w.makeInput(portName);
		i.setFile(portFilename);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunInputPortValue(String runName, String portName,
			String portValue) throws UnknownRunException, NoUpdateException,
			BadStateChangeException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		Input i = support.getInput(w, portName);
		if (i == null)
			i = w.makeInput(portName);
		i.setValue(portValue);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunInputPortListDelimiter(String runName, String portName,
			String delimiter) throws UnknownRunException, NoUpdateException,
			BadStateChangeException, BadPropertyValueException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		Input i = support.getInput(w, portName);
		if (i == null)
			i = w.makeInput(portName);
		if (delimiter != null && delimiter.isEmpty())
			delimiter = null;
		if (delimiter != null) {
			if (delimiter.length() > 1)
				throw new BadPropertyValueException("delimiter too long");
			if (delimiter.charAt(0) < 1 || delimiter.charAt(0) > 127)
				throw new BadPropertyValueException(
						"delimiter character must be non-NUL ASCII");
		}
		i.setDelimiter(delimiter);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public void setRunOutputBaclavaFile(String runName, String outputFile)
			throws UnknownRunException, NoUpdateException,
			FilesystemAccessException, BadStateChangeException {
		TavernaRun w = support.getRun(runName);
		support.permitUpdate(w);
		w.setOutputBaclavaFile(outputFile);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public org.taverna.server.port_description.InputDescription getRunInputDescriptor(
			String runName) throws UnknownRunException {
		return cdBuilder.makeInputDescriptor(support.getRun(runName), null);
	}

	@Override
	@CallCounted
	@PerfLogged
	@RolesAllowed(USER)
	public String getServerStatus() {
		return support.getAllowNewWorkflowRuns() ? "operational" : "suspended";
	}

	// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	// SUPPORT METHODS

	@Override
	public boolean initObsoleteSOAPSecurity(TavernaSecurityContext c) {
		try {
			javax.xml.ws.handler.MessageContext msgCtxt = (jaxws == null ? null
					: jaxws.getMessageContext());
			if (msgCtxt == null)
				return true;
			c.initializeSecurityFromSOAPContext(msgCtxt);
			return false;
		} catch (IllegalStateException e) {
			/* ignore; not much we can do */
			return true;
		}
	}

	@Override
	public boolean initObsoleteRESTSecurity(TavernaSecurityContext c) {
		if (jaxrsHeaders == null)
			return true;
		c.initializeSecurityFromRESTContext(jaxrsHeaders);
		return false;
	}

	/**
	 * A creator of substitute {@link URI} builders.
	 * 
	 * @return A URI builder configured so that it takes a path parameter that
	 *         corresponds to the run ID (but with no such ID applied).
	 */
	UriBuilder getRunUriBuilder() {
		return getBaseUriBuilder().path("runs/{uuid}");
	}

	@Override
	public UriBuilder getRunUriBuilder(TavernaRun run) {
		return fromUri(getRunUriBuilder().build(run.getId()));
	}

	private final String DEFAULT_HOST = "localhost:8080"; // Crappy default

	private String getHostLocation() {
		@java.lang.SuppressWarnings("unchecked")
		Map<String, List<String>> headers = (Map<String, List<String>>) jaxws
				.getMessageContext().get(HTTP_REQUEST_HEADERS);
		if (headers != null) {
			List<String> host = headers.get("HOST");
			if (host != null && !host.isEmpty())
				return host.get(0);
		}
		return DEFAULT_HOST;
	}

	@Nonnull
	private URI getPossiblyInsecureBaseUri() {
		// See if JAX-RS can supply the info
		UriInfo ui = getUriInfo();
		if (ui != null && ui.getBaseUri() != null)
			return ui.getBaseUri();
		// See if JAX-WS *cannot* supply the info
		if (jaxws == null || jaxws.getMessageContext() == null)
			// Hack to make the test suite work
			return URI.create("http://" + DEFAULT_HOST
					+ "/taverna-server/rest/");
		String pathInfo = (String) jaxws.getMessageContext().get(PATH_INFO);
		pathInfo = pathInfo.replaceFirst("/soap$", "/rest/");
		pathInfo = pathInfo.replaceFirst("/rest/.+$", "/rest/");
		return URI.create("http://" + getHostLocation() + pathInfo);
	}

	@Override
	public UriBuilder getBaseUriBuilder() {
		return secure(fromUri(getPossiblyInsecureBaseUri()));
	}

	@Override
	@Nullable
	public String resolve(@Nullable String uri) {
		if (uri == null)
			return null;
		return secure(getPossiblyInsecureBaseUri(), uri).toString();
	}

	private Map<String, TavernaRun> runs() {
		return runStore.listRuns(support.getPrincipal(), policy);
	}
}

/**
 * RESTful interface to the policies of a Taverna Server installation.
 * 
 * @author Donal Fellows
 */
class PolicyREST implements PolicyView, SupportAware {
	private TavernaServerSupport support;
	private Policy policy;
	private ListenerFactory listenerFactory;
	private NotificationEngine notificationEngine;

	@Override
	public void setSupport(TavernaServerSupport support) {
		this.support = support;
	}

	@Required
	public void setPolicy(Policy policy) {
		this.policy = policy;
	}

	@Required
	public void setListenerFactory(ListenerFactory listenerFactory) {
		this.listenerFactory = listenerFactory;
	}

	@Required
	public void setNotificationEngine(NotificationEngine notificationEngine) {
		this.notificationEngine = notificationEngine;
	}

	@Override
	@CallCounted
	@PerfLogged
	public PolicyDescription getDescription(UriInfo ui) {
		return new PolicyDescription(ui);
	}

	@Override
	@CallCounted
	@PerfLogged
	public int getMaxSimultaneousRuns() {
		Integer limit = policy.getMaxRuns(support.getPrincipal());
		if (limit == null)
			return policy.getMaxRuns();
		return min(limit.intValue(), policy.getMaxRuns());
	}

	@Override
	@CallCounted
	@PerfLogged
	public PermittedListeners getPermittedListeners() {
		return new PermittedListeners(
				listenerFactory.getSupportedListenerTypes());
	}

	@Override
	@CallCounted
	@PerfLogged
	public PermittedWorkflows getPermittedWorkflows() {
		return new PermittedWorkflows(policy.listPermittedWorkflowURIs(support
				.getPrincipal()));
	}

	@Override
	@CallCounted
	@PerfLogged
	public EnabledNotificationFabrics getEnabledNotifiers() {
		return new EnabledNotificationFabrics(
				notificationEngine.listAvailableDispatchers());
	}

	@Override
	@CallCounted
	@PerfLogged
	public int getMaxOperatingRuns() {
		return policy.getOperatingLimit();
	}

	@Override
	@CallCounted
	@PerfLogged
	public CapabilityList getCapabilities() {
		CapabilityList cl = new CapabilityList();
		cl.capability.addAll(support.getCapabilities());
		return cl;
	}
}
