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

import static eu.medsea.util.MimeUtil.UNKNOWN_MIME_TYPE;
import static eu.medsea.util.MimeUtil.getExtensionMimeTypes;
import static eu.medsea.util.MimeUtil.getMimeType;
import static java.lang.Math.min;
import static org.apache.commons.logging.LogFactory.getLog;
import static org.springframework.jmx.support.MetricType.COUNTER;
import static org.springframework.jmx.support.MetricType.GAUGE;
import static org.taverna.server.master.TavernaServer.JMX_ROOT;
import static org.taverna.server.master.common.Roles.ADMIN;
import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.activation.DataHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.PreDestroy;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.JAXBException;

import org.apache.commons.logging.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedMetric;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.taverna.server.master.api.ManagementModel;
import org.taverna.server.master.api.TavernaServerBean;
import org.taverna.server.master.common.Capability;
import org.taverna.server.master.common.Permission;
import org.taverna.server.master.common.ProfileList;
import org.taverna.server.master.common.VersionedElement;
import org.taverna.server.master.common.Workflow;
import org.taverna.server.master.common.version.Version;
import org.taverna.server.master.exceptions.FilesystemAccessException;
import org.taverna.server.master.exceptions.NoCreateException;
import org.taverna.server.master.exceptions.NoDestroyException;
import org.taverna.server.master.exceptions.NoDirectoryEntryException;
import org.taverna.server.master.exceptions.NoListenerException;
import org.taverna.server.master.exceptions.NoUpdateException;
import org.taverna.server.master.exceptions.UnknownRunException;
import org.taverna.server.master.factories.ListenerFactory;
import org.taverna.server.master.factories.RunFactory;
import org.taverna.server.master.identity.WorkflowInternalAuthProvider.WorkflowSelfAuthority;
import org.taverna.server.master.interfaces.File;
import org.taverna.server.master.interfaces.Input;
import org.taverna.server.master.interfaces.Listener;
import org.taverna.server.master.interfaces.LocalIdentityMapper;
import org.taverna.server.master.interfaces.Policy;
import org.taverna.server.master.interfaces.RunStore;
import org.taverna.server.master.interfaces.TavernaRun;
import org.taverna.server.master.interfaces.TavernaSecurityContext;
import org.taverna.server.master.rest.handler.T2FlowDocumentHandler;
import org.taverna.server.master.utils.CapabilityLister;
import org.taverna.server.master.utils.FilenameUtils;
import org.taverna.server.master.utils.InvocationCounter;
import org.taverna.server.master.utils.UsernamePrincipal;

import org.apache.taverna.scufl2.api.profiles.Profile;

/**
 * Web application support utilities.
 * 
 * @author Donal Fellows
 */
@ManagedResource(objectName = JMX_ROOT + "Webapp", description = "The main Taverna Server "
		+ Version.JAVA + " web-application interface.")
public class TavernaServerSupport {
	/** The main webapp log. */
	private Log log = getLog("Taverna.Server.Webapp");
	private Log accessLog = getLog("Taverna.Server.Webapp.Access");;
	/** Bean used to log counts of external calls. */
	private InvocationCounter counter;
	/** A storage facility for workflow runs. */
	private RunStore runStore;
	/** Encapsulates the policies applied by this server. */
	private Policy policy;
	/** Connection to the persistent state of this service. */
	private ManagementModel stateModel;
	/** A factory for event listeners to attach to workflow runs. */
	private ListenerFactory listenerFactory;
	/** A factory for workflow runs. */
	private RunFactory runFactory;
	/** How to map the user ID to who to run as. */
	private LocalIdentityMapper idMapper;
	/** The code that is coupled to CXF. */
	private TavernaServerBean webapp;
	/** How to handle files. */
	private FilenameUtils fileUtils;
	/** How to get the server capabilities. */
	private CapabilityLister capabilitySource;
	/**
	 * Whether to log failures during principal retrieval. Should be normally on
	 * as it indicates a serious problem, but can be switched off for testing.
	 */
	private boolean logGetPrincipalFailures = true;
	private Map<String, String> contentTypeMap;
	/** Number of bytes to read when guessing the MIME type. */
	private static final int SAMPLE_SIZE = 1024;
	/** Number of bytes to ask for when copying a stream to a file. */
	private static final int TRANSFER_SIZE = 32768;

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

	/**
	 * @return Count of the number of external calls into this webapp.
	 */
	@ManagedMetric(description = "Count of the number of external calls into this webapp.", metricType = COUNTER, category = "throughput")
	public int getInvocationCount() {
		return counter.getCount();
	}

	/**
	 * @return Current number of runs.
	 */
	@ManagedMetric(description = "Current number of runs.", metricType = GAUGE, category = "utilization")
	public int getCurrentRunCount() {
		return runStore.listRuns(null, policy).size();
	}

	/**
	 * @return Whether to write submitted workflows to the log.
	 */
	@ManagedAttribute(description = "Whether to write submitted workflows to the log.")
	public boolean getLogIncomingWorkflows() {
		return stateModel.getLogIncomingWorkflows();
	}

	/**
	 * @param logIncomingWorkflows
	 *            Whether to write submitted workflows to the log.
	 */
	@ManagedAttribute(description = "Whether to write submitted workflows to the log.")
	public void setLogIncomingWorkflows(boolean logIncomingWorkflows) {
		stateModel.setLogIncomingWorkflows(logIncomingWorkflows);
	}

	/**
	 * @return Whether outgoing exceptions should be logged before being
	 *         converted to responses.
	 */
	@ManagedAttribute(description = "Whether outgoing exceptions should be logged before being converted to responses.")
	public boolean getLogOutgoingExceptions() {
		return stateModel.getLogOutgoingExceptions();
	}

	/**
	 * @param logOutgoing
	 *            Whether outgoing exceptions should be logged before being
	 *            converted to responses.
	 */
	@ManagedAttribute(description = "Whether outgoing exceptions should be logged before being converted to responses.")
	public void setLogOutgoingExceptions(boolean logOutgoing) {
		stateModel.setLogOutgoingExceptions(logOutgoing);
	}

	/**
	 * @return Whether to permit any new workflow runs to be created.
	 */
	@ManagedAttribute(description = "Whether to permit any new workflow runs to be created; has no effect on existing runs.")
	public boolean getAllowNewWorkflowRuns() {
		return stateModel.getAllowNewWorkflowRuns();
	}

	/**
	 * @param allowNewWorkflowRuns
	 *            Whether to permit any new workflow runs to be created.
	 */
	@ManagedAttribute(description = "Whether to permit any new workflow runs to be created; has no effect on existing runs.")
	public void setAllowNewWorkflowRuns(boolean allowNewWorkflowRuns) {
		stateModel.setAllowNewWorkflowRuns(allowNewWorkflowRuns);
	}

	/**
	 * @return The server's version identifier.
	 */
	@ManagedAttribute(description = "The installed version of the server.")
	public String getServerVersion() {
		return VersionedElement.VERSION + " " + VersionedElement.REVISION + " "
				+ VersionedElement.TIMESTAMP;
	}

	@ManagedAttribute(description = "The URIs of the workfows that this server will allow to be instantiated.")
	public URI[] getPermittedWorkflowURIs() {
		List<URI> pw = policy.listPermittedWorkflowURIs(null);
		if (pw == null)
			return new URI[0];
		return pw.toArray(new URI[pw.size()]);
	}

	@ManagedAttribute(description = "The URIs of the workfows that this server will allow to be instantiated.")
	public void setPermittedWorkflowURIs(URI[] pw) {
		if (pw == null)
			policy.setPermittedWorkflowURIs(null, new ArrayList<URI>());
		else
			policy.setPermittedWorkflowURIs(null, Arrays.asList(pw));
	}

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

	@Autowired
	private T2FlowDocumentHandler t2flowHandler;

	public Workflow getWorkflowDocumentFromURI(URI uri)
			throws WebApplicationException, IOException {
		URLConnection conn = uri.toURL().openConnection();
		conn.setRequestProperty("Accept", T2FLOW);
		conn.connect();
		// Tricky point: we know the reader part of the handler only cares
		// about the stream argument.
		return t2flowHandler.readFrom(null, null, null, null, null,
				conn.getInputStream());
	}

	public List<String> getListenerTypes() {
		return listenerFactory.getSupportedListenerTypes();
	}

	/**
	 * @param policy
	 *            The policy being installed by Spring.
	 */
	@Required
	public void setPolicy(Policy policy) {
		this.policy = policy;
	}

	/**
	 * @param listenerFactory
	 *            The listener factory being installed by Spring.
	 */
	@Required
	public void setListenerFactory(ListenerFactory listenerFactory) {
		this.listenerFactory = listenerFactory;
	}

	/**
	 * @param runFactory
	 *            The run factory being installed by Spring.
	 */
	@Required
	public void setRunFactory(RunFactory runFactory) {
		this.runFactory = runFactory;
	}

	/**
	 * @param runStore
	 *            The run store being installed by Spring.
	 */
	@Required
	public void setRunStore(RunStore runStore) {
		this.runStore = runStore;
	}

	/**
	 * @param stateModel
	 *            The state model engine being installed by Spring.
	 */
	@Required
	public void setStateModel(ManagementModel stateModel) {
		this.stateModel = stateModel;
	}

	/**
	 * @param mapper
	 *            The identity mapper being installed by Spring.
	 */
	@Required
	public void setIdMapper(LocalIdentityMapper mapper) {
		this.idMapper = mapper;
	}

	/**
	 * @param counter
	 *            The object whose job it is to manage the counting of
	 *            invocations. Installed by Spring.
	 */
	@Required
	public void setInvocationCounter(InvocationCounter counter) {
		this.counter = counter;
	}

	/**
	 * @param webapp
	 *            The web-app being installed by Spring.
	 */
	@Required
	public void setWebapp(TavernaServerBean webapp) {
		this.webapp = webapp;
	}

	/**
	 * @param fileUtils
	 *            The file handling utilities.
	 */
	@Required
	public void setFileUtils(FilenameUtils fileUtils) {
		this.fileUtils = fileUtils;
	}

	/**
	 * @param logthem
	 *            Whether to log failures relating to principals.
	 */
	public void setLogGetPrincipalFailures(boolean logthem) {
		logGetPrincipalFailures = logthem;
	}

	public Map<String, String> getContentTypeMap() {
		return contentTypeMap;
	}

	/**
	 * Mapping from filename suffixes (e.g., "baclava") to content types.
	 * 
	 * @param contentTypeMap
	 *            The mapping to install.
	 */
	@Required
	public void setContentTypeMap(Map<String, String> contentTypeMap) {
		this.contentTypeMap = contentTypeMap;
	}

	@Required
	public void setCapabilitySource(CapabilityLister capabilitySource) {
		this.capabilitySource = capabilitySource;
	}

	/**
	 * Test whether the current user can do updates to the given run.
	 * 
	 * @param run
	 *            The workflow run to do the test on.
	 * @throws NoUpdateException
	 *             If the current user is not permitted to update the run.
	 */
	public void permitUpdate(@Nonnull TavernaRun run) throws NoUpdateException {
		if (isSuperUser()) {
			accessLog
					.warn("check for admin powers passed; elevated access rights granted for update");
			return; // Superusers are fully authorized to access others things
		}
		if (getSelfAuthority() != null) {
			// At this point, must already be accessing self as that is checked
			// in getRun().
			return;
		}
		policy.permitUpdate(getPrincipal(), run);
	}

	/**
	 * Test whether the current user can destroy or control the lifespan of the
	 * given run.
	 * 
	 * @param run
	 *            The workflow run to do the test on.
	 * @throws NoDestroyException
	 *             If the current user is not permitted to destroy the run.
	 */
	public void permitDestroy(TavernaRun run) throws NoDestroyException {
		if (isSuperUser()) {
			accessLog
					.warn("check for admin powers passed; elevated access rights granted for destroy");
			return; // Superusers are fully authorized to access others things
		}
		if (getSelfAuthority() != null)
			throw new NoDestroyException();
		policy.permitDestroy(getPrincipal(), run);
	}

	/**
	 * Gets the identity of the user currently accessing the webapp, which is
	 * stored in a thread-safe way in the webapp's container's context.
	 * 
	 * @return The identity of the user accessing the webapp.
	 */
	@Nonnull
	public UsernamePrincipal getPrincipal() {
		try {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			if (auth == null || !auth.isAuthenticated()) {
				if (logGetPrincipalFailures)
					log.warn("failed to get auth; going with <NOBODY>");
				return new UsernamePrincipal("<NOBODY>");
			}
			return new UsernamePrincipal(auth);
		} catch (RuntimeException e) {
			if (logGetPrincipalFailures)
				log.info("failed to map principal", e);
			throw e;
		}
	}

	private WorkflowSelfAuthority getSelfAuthority() {
		try {
			Authentication a = SecurityContextHolder.getContext()
					.getAuthentication();
			for (GrantedAuthority ga : a.getAuthorities())
				if (ga instanceof WorkflowSelfAuthority)
					return (WorkflowSelfAuthority) ga;
		} catch (RuntimeException e) {
		}
		return null;
	}

	/**
	 * Obtain the workflow run with a particular name.
	 * 
	 * @param name
	 *            The name of the run to look up.
	 * @return A workflow run handle that the current user has at least
	 *         permission to read.
	 * @throws UnknownRunException
	 *             If the workflow run doesn't exist or the current user doesn't
	 *             have permission to see it.
	 */
	@Nonnull
	public TavernaRun getRun(@Nonnull String name) throws UnknownRunException {
		if (isSuperUser()) {
			accessLog
					.info("check for admin powers passed; elevated access rights granted for read");
			return runStore.getRun(name);
		}
		WorkflowSelfAuthority wsa = getSelfAuthority();
		if (wsa != null) {
			if (wsa.getWorkflowID().equals(name))
				return runStore.getRun(name);
			throw new UnknownRunException();
		}
		return runStore.getRun(getPrincipal(), policy, name);
	}

	/**
	 * Construct a listener attached to the given run.
	 * 
	 * @param run
	 *            The workflow run to attach the listener to.
	 * @param type
	 *            The name of the type of run to create.
	 * @param configuration
	 *            The configuration description to pass into the listener. The
	 *            format of this string is up to the listener to define.
	 * @return A handle to the listener which can be used to further configure
	 *         any properties.
	 * @throws NoListenerException
	 *             If the listener type is unrecognized or the configuration is
	 *             invalid.
	 * @throws NoUpdateException
	 *             If the run does not permit the current user to add listeners
	 *             (or perform other types of update).
	 */
	@Nonnull
	public Listener makeListener(@Nonnull TavernaRun run, @Nonnull String type,
			@Nonnull String configuration) throws NoListenerException,
			NoUpdateException {
		permitUpdate(run);
		return listenerFactory.makeListener(run, type, configuration);
	}

	/**
	 * Obtain a listener that is already attached to a workflow run.
	 * 
	 * @param run
	 *            The workflow run to search.
	 * @param listenerName
	 *            The name of the listener to look up.
	 * @return The listener instance interface.
	 * @throws NoListenerException
	 *             If no listener with that name exists.
	 */
	@Nonnull
	public Listener getListener(TavernaRun run, String listenerName)
			throws NoListenerException {
		for (Listener l : run.getListeners())
			if (l.getName().equals(listenerName))
				return l;
		throw new NoListenerException();
	}

	/**
	 * Obtain a property from a listener that is already attached to a workflow
	 * run.
	 * 
	 * @param runName
	 *            The ID of the workflow run to search.
	 * @param listenerName
	 *            The name of the listener to look up in.
	 * @param propertyName
	 *            The name of the property to fetch.
	 * @return The property value.
	 * @throws NoListenerException
	 *             If no listener with that name exists, or no property with
	 *             that name exists.
	 * @throws UnknownRunException
	 *             If no run with that name exists.
	 */
	@Nonnull
	public String getProperty(String runName, String listenerName,
			String propertyName) throws NoListenerException,
			UnknownRunException {
		return getListener(runName, listenerName).getProperty(propertyName);
	}

	/**
	 * Obtain a property from a listener that is already attached to a workflow
	 * run.
	 * 
	 * @param run
	 *            The workflow run to search.
	 * @param listenerName
	 *            The name of the listener to look up in.
	 * @param propertyName
	 *            The name of the property to fetch.
	 * @return The property value.
	 * @throws NoListenerException
	 *             If no listener with that name exists, or no property with
	 *             that name exists.
	 */
	@Nonnull
	public String getProperty(TavernaRun run, String listenerName,
			String propertyName) throws NoListenerException {
		return getListener(run, listenerName).getProperty(propertyName);
	}

	/**
	 * Get the permission description for the given user.
	 * 
	 * @param context
	 *            A security context associated with a particular workflow run.
	 *            Note that only the owner of a workflow run may get the
	 *            security context in the first place.
	 * @param userName
	 *            The name of the user to look up the permission for.
	 * @return A permission description.
	 */
	@Nonnull
	public Permission getPermission(@Nonnull TavernaSecurityContext context,
			@Nonnull String userName) {
		if (context.getPermittedDestroyers().contains(userName))
			return Permission.Destroy;
		if (context.getPermittedUpdaters().contains(userName))
			return Permission.Update;
		if (context.getPermittedReaders().contains(userName))
			return Permission.Read;
		return Permission.None;
	}

	/**
	 * Set the permissions for the given user.
	 * 
	 * @param context
	 *            A security context associated with a particular workflow run.
	 *            Note that only the owner of a workflow run may get the
	 *            security context in the first place.
	 * @param userName
	 *            The name of the user to set the permission for.
	 * @param permission
	 *            The description of the permission to grant. Note that the
	 *            owner of a workflow run always has the equivalent of
	 *            {@link Permission#Destroy}; this is always enforced before
	 *            checking for other permissions.
	 */
	public void setPermission(TavernaSecurityContext context, String userName,
			Permission permission) {
		Set<String> permSet;
		boolean doRead = false, doWrite = false, doKill = false;

		switch (permission) {
		case Destroy:
			doKill = true;
		case Update:
			doWrite = true;
		case Read:
			doRead = true;
		default:
			break;
		}

		permSet = context.getPermittedReaders();
		if (doRead) {
			if (!permSet.contains(userName)) {
				permSet = new HashSet<>(permSet);
				permSet.add(userName);
				context.setPermittedReaders(permSet);
			}
		} else if (permSet.contains(userName)) {
			permSet = new HashSet<>(permSet);
			permSet.remove(userName);
			context.setPermittedReaders(permSet);
		}

		permSet = context.getPermittedUpdaters();
		if (doWrite) {
			if (!permSet.contains(userName)) {
				permSet = new HashSet<>(permSet);
				permSet.add(userName);
				context.setPermittedUpdaters(permSet);
			}
		} else if (permSet.contains(userName)) {
			permSet = new HashSet<>(permSet);
			permSet.remove(userName);
			context.setPermittedUpdaters(permSet);
		}

		permSet = context.getPermittedDestroyers();
		if (doKill) {
			if (!permSet.contains(userName)) {
				permSet = new HashSet<>(permSet);
				permSet.add(userName);
				context.setPermittedDestroyers(permSet);
			}
		} else if (permSet.contains(userName)) {
			permSet = new HashSet<>(permSet);
			permSet.remove(userName);
			context.setPermittedDestroyers(permSet);
		}
	}

	public Map<String, Permission> getPermissionMap(
			TavernaSecurityContext context) {
		Map<String, Permission> perm = new HashMap<>();
		for (String u : context.getPermittedReaders())
			perm.put(u, Permission.Read);
		for (String u : context.getPermittedUpdaters())
			perm.put(u, Permission.Update);
		for (String u : context.getPermittedDestroyers())
			perm.put(u, Permission.Destroy);
		return perm;
	}

	/**
	 * Stops a run from being possible to be looked up and destroys it.
	 * 
	 * @param runName
	 *            The name of the run.
	 * @param run
	 *            The workflow run. <i>Must</i> correspond to the name.
	 * @throws NoDestroyException
	 *             If the user is not permitted to destroy the workflow run.
	 * @throws UnknownRunException
	 *             If the run is unknown (e.g., because it is already
	 *             destroyed).
	 */
	public void unregisterRun(@Nonnull String runName, @Nonnull TavernaRun run)
			throws NoDestroyException, UnknownRunException {
		if (run == null)
			run = getRun(runName);
		permitDestroy(run);
		runStore.unregisterRun(runName);
		run.destroy();
	}

	/**
	 * Changes the expiry date of a workflow run. The expiry date is when the
	 * workflow run becomes eligible for automated destruction.
	 * 
	 * @param run
	 *            The handle to the workflow run.
	 * @param date
	 *            When the workflow run should be expired.
	 * @return When the workflow run will actually be expired.
	 * @throws NoDestroyException
	 *             If the user is not permitted to destroy the workflow run.
	 *             (Note that lifespan management requires the ability to
	 *             destroy.)
	 */
	@Nonnull
	public Date updateExpiry(@Nonnull TavernaRun run, @Nonnull Date date)
			throws NoDestroyException {
		permitDestroy(run);
		run.setExpiry(date);
		return run.getExpiry();
	}

	/**
	 * Manufacture a workflow run instance.
	 * 
	 * @param workflow
	 *            The workflow document (t2flow, scufl2?) to instantiate.
	 * @return The ID of the created workflow run.
	 * @throws NoCreateException
	 *             If the user is not permitted to create workflows.
	 */
	public String buildWorkflow(Workflow workflow) throws NoCreateException {
		UsernamePrincipal p = getPrincipal();
		if (getSelfAuthority() != null)
			throw new NoCreateException(
					"runs may not create workflows on their host server");
		if (!stateModel.getAllowNewWorkflowRuns())
			throw new NoCreateException("run creation not currently enabled");
		try {
			if (stateModel.getLogIncomingWorkflows()) {
				log.info(workflow.marshal());
			}
		} catch (JAXBException e) {
			log.warn("problem when logging workflow", e);
		}

		// Security checks
		policy.permitCreate(p, workflow);
		if (idMapper != null && idMapper.getUsernameForPrincipal(p) == null) {
			log.error("cannot map principal to local user id");
			throw new NoCreateException(
					"failed to map security token to local user id");
		}

		TavernaRun run;
		try {
			run = runFactory.create(p, workflow);
			TavernaSecurityContext c = run.getSecurityContext();
			c.initializeSecurityFromContext(SecurityContextHolder.getContext());
			/*
			 * These next pieces of security initialisation are (hopefully)
			 * obsolete now that we use Spring Security, but we keep them Just
			 * In Case.
			 */
			boolean doRESTinit = webapp.initObsoleteSOAPSecurity(c);
			if (doRESTinit)
				webapp.initObsoleteRESTSecurity(c);
		} catch (Exception e) {
			log.error("failed to build workflow run worker", e);
			throw new NoCreateException("failed to build workflow run worker");
		}

		return runStore.registerRun(run);
	}

	private boolean isSuperUser() {
		try {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			if (auth == null || !auth.isAuthenticated())
				return false;
			UserDetails details = (UserDetails) auth.getPrincipal();
			if (log.isDebugEnabled())
				log.debug("checking for admin role for user <" + auth.getName()
						+ "> in collection " + details.getAuthorities());
			return details.getAuthorities().contains(ADMIN);
		} catch (ClassCastException e) {
			return false;
		}
	}

	/**
	 * Get a particular input to a workflow run.
	 * 
	 * @param run
	 *            The workflow run to search.
	 * @param portName
	 *            The name of the input.
	 * @return The handle of the input, or <tt>null</tt> if no such handle
	 *         exists.
	 */
	@Nullable
	public Input getInput(TavernaRun run, String portName) {
		for (Input i : run.getInputs())
			if (i.getName().equals(portName))
				return i;
		return null;
	}

	/**
	 * Get a listener attached to a run.
	 * 
	 * @param runName
	 *            The name of the run to look up
	 * @param listenerName
	 *            The name of the listener.
	 * @return The handle of the listener.
	 * @throws NoListenerException
	 *             If no such listener exists.
	 * @throws UnknownRunException
	 *             If no such workflow run exists, or if the user does not have
	 *             permission to access it.
	 */
	public Listener getListener(String runName, String listenerName)
			throws NoListenerException, UnknownRunException {
		return getListener(getRun(runName), listenerName);
	}

	/**
	 * Given a file, produce a guess at its content type. This uses the content
	 * type map property, and if that search fails it falls back on the Medsea
	 * mime type library.
	 * 
	 * @param f
	 *            The file handle.
	 * @return The content type. If all else fails, produces good old
	 *         "application/octet-stream".
	 */
	@Nonnull
	public String getEstimatedContentType(@Nonnull File f) {
		String name = f.getName();
		for (int idx = name.indexOf('.'); idx != -1; idx = name.indexOf('.',
				idx + 1)) {
			String mt = contentTypeMap.get(name.substring(idx + 1));
			if (mt != null)
				return mt;
		}
		@Nonnull
		String type = getExtensionMimeTypes(name);
		if (!type.equals(UNKNOWN_MIME_TYPE))
			return type;
		try {
			return getMimeType(new ByteArrayInputStream(f.getContents(0,
					SAMPLE_SIZE)));
		} catch (FilesystemAccessException e) {
			return type;
		}
	}

	public void copyDataToFile(DataHandler handler, File file)
			throws FilesystemAccessException {
		try {
			copyStreamToFile(handler.getInputStream(), file);
		} catch (IOException e) {
			throw new FilesystemAccessException(
					"problem constructing stream from data source", e);
		}
	}

	public void copyDataToFile(URI uri, File file)
			throws MalformedURLException, FilesystemAccessException,
			IOException {
		copyStreamToFile(uri.toURL().openStream(), file);
	}

	public void copyStreamToFile(InputStream stream, File file)
			throws FilesystemAccessException {
		String name = file.getFullName();
		long total = 0;
		try {
			byte[] buffer = new byte[TRANSFER_SIZE];
			boolean first = true;
			while (true) {
				int len = stream.read(buffer);
				if (len < 0)
					break;
				total += len;
				if (log.isDebugEnabled())
					log.debug("read " + len
							+ " bytes from source stream (total: " + total
							+ ") bound for " + name);
				if (len == buffer.length) {
					if (first)
						file.setContents(buffer);
					else
						file.appendContents(buffer);
				} else {
					byte[] newBuf = new byte[len];
					System.arraycopy(buffer, 0, newBuf, 0, len);
					if (first)
						file.setContents(newBuf);
					else
						file.appendContents(newBuf);
				}
				first = false;
			}
		} catch (IOException exn) {
			throw new FilesystemAccessException("failed to transfer bytes", exn);
		}
	}

	/**
	 * Build a description of the profiles supported by a workflow. Note that we
	 * expect the set of profiles to be fairly small.
	 * 
	 * @param workflow
	 *            The workflow to describe the profiles of.
	 * @return The descriptor (which might be empty).
	 */
	public ProfileList getProfileDescriptor(Workflow workflow) {
		ProfileList result = new ProfileList();
		String main = workflow.getMainProfileName();
		for (Profile p : workflow.getProfiles()) {
			ProfileList.Info i = new ProfileList.Info();
			i.name = p.getName();
			if (main != null && main.equals(i.name))
				i.main = true;
			result.profile.add(i);
		}
		return result;
	}

	public boolean getAllowStartWorkflowRuns() {
		return runFactory.isAllowingRunsToStart();
	}

	/**
	 * The list of filenames that logs may occupy.
	 */
	private static final String[] LOGS = { "logs/detail.log.4",
			"logs/detail.log.3", "logs/detail.log.2", "logs/detail.log.1",
			"logs/detail.log" };

	public FileConcatenation getLogs(TavernaRun run) {
		FileConcatenation fc = new FileConcatenation();
		for (String name : LOGS) {
			try {
				fc.add(fileUtils.getFile(run, name));
			} catch (FilesystemAccessException | NoDirectoryEntryException e) {
				// Ignore
			}
		}
		return fc;
	}

	@Nonnull
	public List<Capability> getCapabilities() {
		return capabilitySource.getCapabilities();
	}

	static final String PROV_BUNDLE = "out.bundle.zip";

	public FileConcatenation getProv(TavernaRun run) {
		FileConcatenation fc = new FileConcatenation();
		try {
			fc.add(fileUtils.getFile(run, PROV_BUNDLE));
		} catch (FilesystemAccessException | NoDirectoryEntryException e) {
			// Ignore
		}
		return fc;
	}
}
