http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java new file mode 100644 index 0000000..69c3622 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/ProfileList.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 The University of Manchester + * + * See the file "LICENSE.txt" for license terms. + */ +package org.taverna.server.master.common; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** + * Description of the profiles that can apply to a workflow. + * + * @author Donal K. Fellows + */ +@XmlRootElement(name = "profiles") +@XmlType(name = "ProfileList") +public class ProfileList { + public List<ProfileList.Info> profile = new ArrayList<ProfileList.Info>(); + + /** + * Description of a single workflow profile. + * + * @author Donal Fellows + */ + @XmlRootElement(name = "profile") + @XmlType(name = "Profile") + public static class Info { + @XmlValue + public String name; + /** + * Whether this is the main profile. + */ + @XmlAttribute(name = "isMain") + public Boolean main; + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java new file mode 100644 index 0000000..8079b1c --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Roles.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +/** + * The roles defined in this webapp. + * + * @author Donal Fellows + */ +public interface Roles { + /** The role of a normal user. */ + static final String USER = "ROLE_tavernauser"; + /** + * The role of an administrator. Administrators <i>should</i> have the + * normal user role as well. + */ + static final String ADMIN = "ROLE_tavernasuperuser"; + /** + * The role of a workflow accessing itself. Do not give users this role. + */ + static final String SELF = "ROLE_tavernaworkflow"; +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java new file mode 100644 index 0000000..3486bf7 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/RunReference.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static org.taverna.server.master.common.Namespaces.SERVER; +import static org.taverna.server.master.common.Namespaces.XLINK; +import static org.taverna.server.master.common.VersionedElement.VERSION; + +import java.net.URI; + +import javax.ws.rs.core.UriBuilder; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +/** + * A reference to a single workflow run, described using JAXB. + * + * @author Donal Fellows + * @see org.taverna.server.master.interfaces.TavernaRun TavernaRun + */ +@XmlRootElement +@XmlType(name = "TavernaRun") +@XmlSeeAlso( { Workflow.class, DirEntryReference.class }) +public class RunReference { + /** + * Where to get information about the run. For REST. + */ + @XmlAttribute(name = "href", namespace = XLINK) + @XmlSchemaType(name = "anyURI") + public URI link; + /** What version of server produced this element? */ + @XmlAttribute(namespace = SERVER) + public String serverVersion; + /** + * The name of the run. For SOAP. + */ + @XmlValue + public String name; + + /** + * Make a blank run reference. + */ + public RunReference() { + } + + /** + * Make a reference to the given workflow run. + * + * @param name + * The name of the run. + * @param ub + * A factory for URIs, or <tt>null</tt> if none is to be made. + */ + public RunReference(String name, UriBuilder ub) { + this.serverVersion = VERSION; + this.name = name; + if (ub != null) + this.link = ub.build(name); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java new file mode 100644 index 0000000..8e360dc --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Status.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + +/** + * States of a workflow run. They are {@link #Initialized Initialized}, + * {@link #Operating Operating}, {@link #Stopped Stopped}, and {@link #Finished + * Finished}. Conceptually, there is also a <tt>Destroyed</tt> state, but the + * workflow run does not exist (and hence can't have its state queried or set) + * in that case. + * + * @author Donal Fellows + */ +@XmlEnum +@XmlType(name = "Status") +public enum Status { + /** + * The workflow run has been created, but is not yet running. The run will + * need to be manually moved to {@link #Operating Operating} when ready. + */ + Initialized, + /** + * The workflow run is going, reading input, generating output, etc. Will + * eventually either move automatically to {@link #Finished Finished} or can + * be moved manually to {@link #Stopped Stopped} (where supported). + */ + Operating, + /** + * The workflow run is paused, and will need to be moved back to + * {@link #Operating Operating} manually. + */ + Stopped, + /** + * The workflow run has ceased; data files will continue to exist until the + * run is destroyed (which may be manual or automatic). + */ + Finished +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java new file mode 100644 index 0000000..6d77aa7 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Trust.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011-2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static org.taverna.server.master.common.Namespaces.XLINK; + +import java.io.Serializable; +import java.security.cert.Certificate; +import java.util.Collection; +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * A description of a trusted identity or identities. This description is + * characterised by a file visible to the workflow run that contains one or more + * certificates. + * + * @author Donal Fellows + */ +@XmlType(name = "TrustDescriptor") +@XmlRootElement(name = "trustedIdentity") +@SuppressWarnings("serial") +public final class Trust implements Serializable { + /** The location of this descriptor in the REST world. */ + @XmlAttribute(namespace = XLINK) + public String href; + /** + * The location of this descriptor in the SOAP world. Must match corrected + * with the {@link #href} field. + */ + @XmlTransient + public String id; + /** + * The file containing the certificate(s). This is resolved with respect to + * the workflow run working directory. + */ + @XmlElement + public String certificateFile; + /** + * The type of certificate file. Defaults to <tt>X.509</tt> if unspecified. + */ + @XmlElement + public String fileType; + /** + * The encoded serialized keystore containing the certificate(s). + */ + @XmlElement + public byte[] certificateBytes; + /** + * The names of the server(s) identified by this trust. + */ + @XmlElement + public List<String> serverName; + /** + * The collection of certificates loaded from the specified file. This is + * always <tt>null</tt> before validation. + */ + public transient Collection<? extends Certificate> loadedCertificates; + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof Trust)) + return false; + return id.equals(((Trust) o).id); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java new file mode 100644 index 0000000..d6d057c --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Uri.java @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static javax.ws.rs.core.UriBuilder.fromUri; +import static org.apache.commons.logging.LogFactory.getLog; +import static org.taverna.server.master.common.Namespaces.XLINK; + +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Map; + +import javax.annotation.PreDestroy; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriBuilderException; +import javax.ws.rs.core.UriInfo; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + +import org.apache.commons.logging.Log; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.web.PortMapper; + +import javax.annotation.Nonnull; + +/** + * A class that makes it simpler to work with an element with a {@link URI} in + * an <tt>href</tt> attribute. Done with JAXB. + * + * @author Donal Fellows + */ +@XmlType(name = "Location") +public class Uri { + static Log log = getLog("Taverna.Server.UriRewriter"); + private static final String SECURE_SCHEME = "https"; + /** + * This type is characterised by an attribute that is the reference to some + * other element. + */ + @XmlAttribute(name = "href", namespace = XLINK) + @XmlSchemaType(name = "anyURI") + public URI ref; + + /** Make a reference that points nowhere. */ + public Uri() { + } + + /** + * Make a reference to the given location. + * + * @param ref + * Where to point to. + */ + public Uri(@Nonnull URI ref) { + this.ref = secure(ref); + } + + /** + * Make a reference from the factory with the given parameters. + * + * @param ub + * The configured factory. + * @param strings + * The parameters to the factory. + */ + public Uri(@Nonnull UriBuilder ub, String... strings) { + ref = secure(ub).build((Object[]) strings); + } + + /** + * Make a reference from the factory with the given parameters. + * + * @param ui + * The factory factory. + * @param path + * The path to configure the factory with. + * @param strings + * The parameters to the factory. + */ + public Uri(@Nonnull UriInfo ui, @Nonnull String path, String... strings) { + this(ui, true, path, strings); + } + + /** + * Make a reference from the factory with the given parameters. + * + * @param ui + * The factory factory. + * @param secure + * Whether the URI should be required to use HTTPS. + * @param path + * The path to configure the factory with. + * @param strings + * The parameters to the factory. + */ + public Uri(@Nonnull UriInfo ui, boolean secure, @Nonnull String path, + String... strings) { + UriBuilder ub = ui.getAbsolutePathBuilder(); + if (secure) { + ub = secure(ub); + } + ref = ub.path(path).build((Object[]) strings); + } + + public static UriBuilder secure(UriBuilder ub) { + return Rewriter.getInstance().getSecuredUriBuilder(ub); + } + + public static UriBuilder secure(UriInfo ui) { + return secure(ui.getAbsolutePathBuilder()); + } + + public static URI secure(URI uri) { + URI newURI = secure(fromUri(uri)).build(); + if (log.isDebugEnabled()) + log.debug("rewrote " + uri + " to " + newURI); + return newURI; + } + + public static URI secure(URI base, String uri) { + URI newURI = secure(fromUri(base.resolve(uri))).build(); + if (log.isDebugEnabled()) + log.debug("rewrote " + uri + " to " + newURI); + return newURI; + } + + /** + * A bean that allows configuration of how to rewrite generated URIs to be + * secure. + * + * @author Donal Fellows + */ + public static class Rewriter { + private static Rewriter instance; + private PortMapper portMapper; + private boolean suppress; + private String rewriteRE = "://[^/]+/[^/]+"; + private String rewriteTarget; + + static Rewriter getInstance() { + if (instance == null) + new Rewriter(); + return instance; + } + + @Autowired + public void setPortMapper(PortMapper portMapper) { + this.portMapper = portMapper; + } + + /** + * Whether to suppress rewriting of URIs to be secure. + * + * @param suppressSecurity + * True if no rewriting should be done. + */ + public void setSuppressSecurity(boolean suppressSecurity) { + suppress = suppressSecurity; + } + + public void setRewriteRegexp(String rewriteRegexp) { + this.rewriteRE = rewriteRegexp; + } + + /** + * What to rewrite the host, port and web-app name to be. + * + * @param rewriteTarget + * What to rewrite to, or "<tt>NONE</tt>" for no rewrite. + */ + public void setRewriteTarget(String rewriteTarget) { + if (rewriteTarget.isEmpty()) + this.rewriteTarget = null; + else if (rewriteTarget.equals("NONE")) + this.rewriteTarget = null; + else if (rewriteTarget.startsWith("${")) + this.rewriteTarget = null; + else + this.rewriteTarget = "://" + rewriteTarget; + } + + private Integer lookupHttpsPort(URI uri) { + if (portMapper != null) + return portMapper.lookupHttpsPort(uri.getPort()); + return null; + } + + public Rewriter() { + instance = this; + } + + @PreDestroy + public void done() { + instance = null; + Uri.log = null; + } + + @Nonnull + URI rewrite(@Nonnull String url) { + if (rewriteTarget != null) + url = url.replaceFirst(rewriteRE, rewriteTarget); + return URI.create(url); + } + + @Nonnull + public UriBuilder getSecuredUriBuilder(@Nonnull UriBuilder uribuilder) { + if (suppress) + return uribuilder.clone(); + UriBuilder ub = new RewritingUriBuilder(uribuilder); + Integer secPort = null; + try { + secPort = lookupHttpsPort(ub.build()); + } catch (Exception e) { + /* + * Do not log this; we know why it happens and don't actually + * care to do anything about it. All it does is fill up the log + * with pointless scariness! + */ + + // log.debug("failed to extract current URI port", e); + } + if (secPort == null || secPort.intValue() == -1) + return ub.scheme(SECURE_SCHEME); + return ub.scheme(SECURE_SCHEME).port(secPort); + } + + /** + * {@link UriBuilder} that applies a rewrite rule to the URIs produced + * by the wrapped builder. + * + * @author Donal Fellows + */ + class RewritingUriBuilder extends UriBuilder { + private UriBuilder wrapped; + + RewritingUriBuilder(UriBuilder builder) { + wrapped = builder.clone(); + } + + private URI rewrite(URI uri) { + return Rewriter.this.rewrite(uri.toString()); + } + + @Override + public UriBuilder clone() { + return new RewritingUriBuilder(wrapped); + } + + @Override + public URI buildFromMap(Map<String, ?> values) + throws IllegalArgumentException, UriBuilderException { + return rewrite(wrapped.buildFromMap(values)); + } + + @Override + public URI buildFromEncodedMap(Map<String, ? extends Object> values) + throws IllegalArgumentException, UriBuilderException { + return rewrite(wrapped.buildFromEncodedMap(values)); + } + + @Override + public URI build(Object... values) throws IllegalArgumentException, + UriBuilderException { + return rewrite(wrapped.build(values)); + } + + @Override + public URI build(Object[] values, boolean encodeSlashInPath) + throws IllegalArgumentException, UriBuilderException { + return rewrite(wrapped.build(values, encodeSlashInPath)); + } + + @Override + public URI buildFromEncoded(Object... values) + throws IllegalArgumentException, UriBuilderException { + return rewrite(wrapped.buildFromEncoded(values)); + } + + @Override + public URI buildFromMap(Map<String, ?> values, + boolean encodeSlashInPath) throws IllegalArgumentException, + UriBuilderException { + return rewrite(wrapped.buildFromEncoded(values, + encodeSlashInPath)); + } + + @Override + public UriBuilder uri(URI uri) throws IllegalArgumentException { + wrapped.uri(uri); + return this; + } + + @Override + public UriBuilder uri(String uriTemplate) + throws IllegalArgumentException { + wrapped.uri(uriTemplate); + return this; + } + + @Override + public String toTemplate() { + return wrapped.toTemplate(); + } + + @Override + public UriBuilder scheme(String scheme) + throws IllegalArgumentException { + wrapped.scheme(scheme); + return this; + } + + @Override + public UriBuilder schemeSpecificPart(String ssp) + throws IllegalArgumentException { + wrapped.schemeSpecificPart(ssp); + return this; + } + + @Override + public UriBuilder userInfo(String ui) { + wrapped.userInfo(ui); + return this; + } + + @Override + public UriBuilder host(String host) throws IllegalArgumentException { + wrapped.host(host); + return this; + } + + @Override + public UriBuilder port(int port) throws IllegalArgumentException { + wrapped.port(port); + return this; + } + + @Override + public UriBuilder replacePath(String path) { + wrapped.replacePath(path); + return this; + } + + @Override + public UriBuilder path(String path) throws IllegalArgumentException { + wrapped.path(path); + return this; + } + + @Override + public UriBuilder path( + @java.lang.SuppressWarnings("rawtypes") Class resource) + throws IllegalArgumentException { + wrapped.path(resource); + return this; + } + + @Override + public UriBuilder path( + @java.lang.SuppressWarnings("rawtypes") Class resource, + String method) throws IllegalArgumentException { + wrapped.path(resource, method); + return this; + } + + @Override + public UriBuilder path(Method method) + throws IllegalArgumentException { + wrapped.path(method); + return this; + } + + @Override + public UriBuilder segment(String... segments) + throws IllegalArgumentException { + wrapped.segment(segments); + return this; + } + + @Override + public UriBuilder replaceMatrix(String matrix) + throws IllegalArgumentException { + wrapped.replaceMatrix(matrix); + return this; + } + + @Override + public UriBuilder matrixParam(String name, Object... values) + throws IllegalArgumentException { + wrapped.matrixParam(name, values); + return this; + } + + @Override + public UriBuilder replaceMatrixParam(String name, Object... values) + throws IllegalArgumentException { + wrapped.replaceMatrixParam(name, values); + return this; + } + + @Override + public UriBuilder replaceQuery(String query) + throws IllegalArgumentException { + wrapped.replaceQuery(query); + return this; + } + + @Override + public UriBuilder queryParam(String name, Object... values) + throws IllegalArgumentException { + wrapped.queryParam(name, values); + return this; + } + + @Override + public UriBuilder replaceQueryParam(String name, Object... values) + throws IllegalArgumentException { + wrapped.replaceQueryParam(name, values); + return this; + } + + @Override + public UriBuilder fragment(String fragment) { + wrapped.fragment(fragment); + return this; + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java new file mode 100644 index 0000000..6eddf2d --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/VersionedElement.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static org.apache.commons.logging.LogFactory.getLog; +import static org.taverna.server.master.common.Namespaces.SERVER; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + +import org.apache.commons.logging.Log; + +/** + * The type of an element that declares the version of the server that produced + * it. + * + * @author Donal Fellows + */ +@XmlType(name = "VersionedElement", namespace = SERVER) +public abstract class VersionedElement { + /** What version of server produced this element? */ + @XmlAttribute(namespace = SERVER) + public String serverVersion; + /** What revision of server produced this element? Derived from SCM commit. */ + @XmlAttribute(namespace = SERVER) + public String serverRevision; + /** When was the server built? */ + @XmlAttribute(namespace = SERVER) + public String serverBuildTimestamp; + public static final String VERSION, REVISION, TIMESTAMP; + static { + Log log = getLog("Taverna.Server.Webapp"); + Properties p = new Properties(); + try { + try (InputStream is = VersionedElement.class + .getResourceAsStream("/version.properties")) { + p.load(is); + } + } catch (IOException e) { + log.warn("failed to read /version.properties", e); + } + VERSION = p.getProperty("tavernaserver.version", "unknownVersion"); + REVISION = String.format("%s (tag: %s)", + p.getProperty("tavernaserver.branch", "unknownRevision"), + p.getProperty("tavernaserver.revision.describe", "unknownTag")); + TIMESTAMP = p + .getProperty("tavernaserver.timestamp", "unknownTimestamp"); + } + + public VersionedElement() { + } + + protected VersionedElement(boolean ignored) { + serverVersion = VERSION; + serverRevision = REVISION; + serverBuildTimestamp = TIMESTAMP; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java new file mode 100644 index 0000000..ba6a68c --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/Workflow.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2010-2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common; + +import static javax.xml.bind.Marshaller.JAXB_ENCODING; +import static javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT; +import static javax.xml.bind.annotation.XmlAccessType.NONE; +import static org.apache.commons.logging.LogFactory.getLog; +import static org.taverna.server.master.rest.handler.Scufl2DocumentHandler.SCUFL2; +import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW; +import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_NS; +import static org.taverna.server.master.rest.handler.T2FlowDocumentHandler.T2FLOW_ROOTNAME; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.URL; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.taverna.server.master.rest.handler.Scufl2DocumentHandler; +import org.taverna.server.master.rest.handler.T2FlowDocumentHandler; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import uk.org.taverna.scufl2.api.common.NamedSet; +import uk.org.taverna.scufl2.api.container.WorkflowBundle; +import uk.org.taverna.scufl2.api.io.ReaderException; +import uk.org.taverna.scufl2.api.io.WorkflowBundleIO; +import uk.org.taverna.scufl2.api.io.WriterException; +import uk.org.taverna.scufl2.api.profiles.Profile; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Encapsulation of a T2flow or Scufl2 document. + * + * @author Donal K. Fellows + */ +@XmlRootElement(name = "workflow") +@XmlType(name = "Workflow") +@XmlAccessorType(NONE) +public class Workflow implements Serializable, Externalizable { + /** Literal document, if present. */ + @XmlAnyElement(lax = true) + private Element content; + /** SCUFL2 bundle, if present. */ + @XmlTransient + private WorkflowBundle bundle; + /** Which came first, the bundle or the t2flow document. */ + @XmlTransient + private boolean isBundleFirst; + + private static Marshaller marshaller; + private static Unmarshaller unmarshaller; + private final static String ENCODING = "UTF-8"; + private final static WorkflowBundleIO io; + static { + try { + JAXBContext context = JAXBContext.newInstance(Workflow.class); + marshaller = context.createMarshaller(); + unmarshaller = context.createUnmarshaller(); + marshaller.setProperty(JAXB_ENCODING, ENCODING); + marshaller.setProperty(JAXB_FORMATTED_OUTPUT, false); + } catch (JAXBException e) { + getLog("Taverna.Server.Webapp").fatal( + "failed to build JAXB context for working with " + + Workflow.class, e); + } + io = new WorkflowBundleIO(); + } + + public enum ContentType { + T2FLOW(T2FlowDocumentHandler.T2FLOW), SCUFL2( + Scufl2DocumentHandler.SCUFL2); + private String type; + + ContentType(String type) { + this.type = type; + } + + public String getContentType() { + return type; + } + } + + public Workflow() { + } + + public Workflow(Element element) { + this.content = element; + this.isBundleFirst = false; + } + + public Workflow(WorkflowBundle bundle) { + this.bundle = bundle; + this.isBundleFirst = true; + } + + public Workflow(URL url) throws ReaderException, IOException { + this(io.readBundle(url, null)); + } + + /** + * What content type would this workflow "prefer" to be? + */ + public ContentType getPreferredContentType() { + if (isBundleFirst) + return ContentType.SCUFL2; + else + return ContentType.T2FLOW; + } + + /** + * Retrieves the workflow as a SCUFL2 document, converting it if necessary. + * + * @return The SCUFL2 document. + * @throws IOException + * If anything goes wrong. + */ + public WorkflowBundle getScufl2Workflow() throws IOException { + try { + if (bundle == null) + bundle = io.readBundle(new ByteArrayInputStream(getAsT2Flow()), + T2FLOW); + return bundle; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException("problem when converting to SCUFL2", e); + } + } + + /** + * Get the bytes of the serialized SCUFL2 workflow. + * + * @return Array of bytes. + * @throws IOException + * If serialization fails. + * @throws WriterException + * If conversion fails. + */ + public byte[] getScufl2Bytes() throws IOException, WriterException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + io.writeBundle(getScufl2Workflow(), baos, SCUFL2); + return baos.toByteArray(); + } + + /** + * Retrieves the workflow as a T2Flow document, converting it if necessary. + * + * @return The T2Flow document. + * @throws IOException + * If anything goes wrong. + */ + public Element getT2flowWorkflow() throws IOException { + try { + if (content != null) + return content; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + io.writeBundle(bundle, baos, T2FLOW); + Document doc; + try { + DocumentBuilderFactory dbf = DocumentBuilderFactory + .newInstance(); + dbf.setNamespaceAware(true); + doc = dbf.newDocumentBuilder().parse( + new ByteArrayInputStream(baos.toByteArray())); + } catch (SAXException e) { + throw new IOException("failed to convert to DOM tree", e); + } + Element e = doc.getDocumentElement(); + if (e.getNamespaceURI().equals(T2FLOW_NS) + && e.getNodeName().equals(T2FLOW_ROOTNAME)) + return content = e; + throw new IOException( + "unexpected element when converting to T2Flow: {" + + e.getNamespaceURI() + "}" + e.getNodeName()); + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new IOException("problem when converting to SCUFL2", e); + } + } + + /** + * @return The name of the main workflow profile, or <tt>null</tt> if there + * is none. + */ + public String getMainProfileName() { + try { + return getScufl2Workflow().getMainProfile().getName(); + } catch (IOException e) { + return null; + } + } + + /** + * @return The set of profiles supported over this workflow. + */ + public NamedSet<Profile> getProfiles() { + try { + return getScufl2Workflow().getProfiles(); + } catch (IOException e) { + return new NamedSet<Profile>(); + } + } + + /** + * Convert from marshalled form. + * + * @throws JAXBException + * If the conversion fails. + */ + public static Workflow unmarshal(String representation) + throws JAXBException { + StringReader sr = new StringReader(representation); + return (Workflow) unmarshaller.unmarshal(sr); + } + + /** + * Convert to marshalled form. + */ + public String marshal() throws JAXBException { + StringWriter sw = new StringWriter(); + marshaller.marshal(this, sw); + return sw.toString(); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, + ClassNotFoundException { + try { + ByteArrayInputStream bytes = readbytes(in); + if (bytes != null) + try (Reader r = new InputStreamReader(bytes, ENCODING)) { + content = ((Workflow) unmarshaller.unmarshal(r)).content; + } + bytes = readbytes(in); + if (bytes != null) + bundle = io.readBundle(bytes, SCUFL2); + isBundleFirst = in.readBoolean(); + return; + } catch (JAXBException e) { + throw new IOException("failed to unmarshal", e); + } catch (ClassCastException e) { + throw new IOException("bizarre result of unmarshalling", e); + } catch (ReaderException e) { + throw new IOException("failed to unmarshal", e); + } + } + + private byte[] getAsT2Flow() throws IOException, JAXBException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OutputStreamWriter w = new OutputStreamWriter(baos, ENCODING); + marshaller.marshal(this, w); + w.close(); + return baos.toByteArray(); + } + + private byte[] getAsScufl2() throws IOException, WriterException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + io.writeBundle(bundle, baos, SCUFL2); + baos.close(); + return baos.toByteArray(); + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + try { + writebytes(out, (content != null) ? getAsT2Flow() : null); + } catch (JAXBException e) { + throw new IOException("failed to marshal t2flow", e); + } + try { + writebytes(out, (bundle != null) ? getAsScufl2() : null); + } catch (WriterException e) { + throw new IOException("failed to marshal scufl2", e); + } + out.writeBoolean(isBundleFirst); + } + + private ByteArrayInputStream readbytes(ObjectInput in) throws IOException { + int len = in.readInt(); + if (len > 0) { + byte[] bytes = new byte[len]; + in.readFully(bytes); + return new ByteArrayInputStream(bytes); + } + return null; + } + + private void writebytes(ObjectOutput out, byte[] data) throws IOException { + out.writeInt(data == null ? 0 : data.length); + if (data != null && data.length > 0) + out.write(data); + } + + /** + * Make up for the lack of an integrated XPath engine. + * + * @param name + * The element names to look up from the root of the contained + * document. + * @return The looked up element, or <tt>null</tt> if it doesn't exist. + */ + private Element getEl(String... name) { + Element el = content; + boolean skip = true; + for (String n : name) { + if (skip) { + skip = false; + continue; + } + if (el == null) + return null; + NodeList nl = el.getElementsByTagNameNS(T2FLOW_NS, n); + if (nl.getLength() == 0) + return null; + Node node = nl.item(0); + if (node instanceof Element) + el = (Element) node; + else + return null; + } + return el; + } + + /** + * @return The content of the embedded + * <tt><workflow><dataflow><name></tt> element. + */ + @XmlTransient + public String getName() { + return getEl("workflow", "dataflow", "name").getTextContent(); + } + + /** + * @return The embedded <tt><workflow></tt> element. + */ + @XmlTransient + public Element getWorkflowRoot() { + return getEl("workflow"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java new file mode 100644 index 0000000..fd040de --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/package-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * This package contains the common XML elements used throughout Taverna Server's various interfaces. + * @author Donal Fellows + */ +@XmlSchema(namespace = SERVER, elementFormDefault = QUALIFIED, attributeFormDefault = QUALIFIED, xmlns = { + @XmlNs(prefix = "xlink", namespaceURI = XLINK), + @XmlNs(prefix = "ts", namespaceURI = SERVER), + @XmlNs(prefix = "ts-rest", namespaceURI = SERVER_REST), + @XmlNs(prefix = "ts-soap", namespaceURI = SERVER_SOAP), + @XmlNs(prefix = "feed", namespaceURI = FEED), + @XmlNs(prefix = "admin", namespaceURI = ADMIN) }) +package org.taverna.server.master.common; + +import static javax.xml.bind.annotation.XmlNsForm.QUALIFIED; +import static org.taverna.server.master.common.Namespaces.ADMIN; +import static org.taverna.server.master.common.Namespaces.FEED; +import static org.taverna.server.master.common.Namespaces.SERVER; +import static org.taverna.server.master.common.Namespaces.SERVER_REST; +import static org.taverna.server.master.common.Namespaces.SERVER_SOAP; +import static org.taverna.server.master.common.Namespaces.XLINK; + +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlSchema; + http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java new file mode 100644 index 0000000..e9c58a9 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/common/version/Version.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.common.version; + +import static org.taverna.server.master.common.version.Constants.PATCH; +import static org.taverna.server.master.common.version.Constants.VERSION; + +/** + * Common location for describing the version of the server. + * + * @author Donal Fellows + */ +public interface Version { + public static final String JAVA = VERSION + Constants.releaseChar + PATCH; + public static final String HTML = VERSION + Constants.releaseHEnt + PATCH; + public static final String XML = VERSION + Constants.releaseXEnt + PATCH; +} + +/** + * The pieces of a version string. + * + * @author Donal Fellows + */ +interface Constants { + static final String MAJOR = "2"; + static final String MINOR = "5"; + static final String PATCH = "4"; + + static final char alphaChar = '\u03b1'; + static final char betaChar = '\u03b2'; + static final char releaseChar = '.'; + static final String alphaHEnt = "α"; + static final String betaHEnt = "β"; + static final String releaseHEnt = "."; + static final String alphaXEnt = "α"; + static final String betaXEnt = "β"; + static final String releaseXEnt = "."; + + static final String VERSION = MAJOR + "." + MINOR; +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java new file mode 100644 index 0000000..c2a2bc9 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/Default.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.defaults; + +import org.taverna.server.master.common.Status; +import org.taverna.server.master.localworker.LocalWorkerState; + +/** + * This defines a collection of default values, collecting them from various + * parts of the server. + * + * @author Donal Fellows + */ +public interface Default { + /** The default value of the <tt>prefix</tt> property. */ + static final String AUTHORITY_PREFIX = "LOCALUSER_"; + + /** + * The name of the resource that is the implementation of the subprocess + * that this class will fork off. + */ + static final String SERVER_WORKER_IMPLEMENTATION_JAR = "util/server.worker.jar"; + + /** + * The name of the resource that is the implementation of the subprocess + * that manages secure forking. + */ + static final String SECURE_FORK_IMPLEMENTATION_JAR = "util/secure.fork.jar"; + + /** + * The name of the resource that is the implementation of the subprocess + * that acts as the RMI registry. + */ + static final String REGISTRY_JAR = "util/rmi.daemon.jar"; + + /** Initial lifetime of runs, in minutes. */ + static final int RUN_LIFE_MINUTES = 20; + + /** + * Maximum number of runs to exist at once. Note that this includes when + * they are just existing for the purposes of file transfer ( + * {@link Status#Initialized}/{@link Status#Finished} states). + */ + static final int RUN_COUNT_MAX = 5; + + /** + * Prefix to use for RMI names. + */ + static final String RMI_PREFIX = "ForkRunFactory."; + + /** Default value for {@link LocalWorkerState#passwordFile}. */ + static final String PASSWORD_FILE = null; + + /** + * The extra arguments to pass to the subprocess. + */ + static final String[] EXTRA_ARGUMENTS = new String[0]; + + /** + * How long to wait for subprocess startup, in seconds. + */ + static final int SUBPROCESS_START_WAIT = 40; + + /** + * Polling interval to use during startup, in milliseconds. + */ + static final int SUBPROCESS_START_POLL_SLEEP = 1000; + + /** + * Maximum number of {@link Status#Operating} runs at any time. + */ + static final int RUN_OPERATING_LIMIT = 10; + + /** + * What fields of a certificate we look at when understanding who it is + * talking about, in the order that we look. + */ + static final String[] CERTIFICATE_FIELD_NAMES = { "CN", "COMMONNAME", + "COMMON NAME", "COMMON_NAME", "OU", "ORGANIZATIONALUNITNAME", + "ORGANIZATIONAL UNIT NAME", "O", "ORGANIZATIONNAME", + "ORGANIZATION NAME" }; + + /** The type of certificates that are processed if we don't say otherwise. */ + static final String CERTIFICATE_TYPE = "X.509"; + + /** Max size of credential file, in kiB. */ + static final int CREDENTIAL_FILE_SIZE_LIMIT = 20; + + /** + * The notification message format to use if none is configured. + */ + public static final String NOTIFY_MESSAGE_FORMAT = "Your job with ID={0} has finished with exit code {1,number,integer}."; + + /** The address of the SMS gateway service used. */ + public static final String SMS_GATEWAY_URL = "https://www.intellisoftware.co.uk/smsgateway/sendmsg.aspx"; +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java new file mode 100644 index 0000000..239b260 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/defaults/package-info.java @@ -0,0 +1,5 @@ +/** + * This package contains information about the various default values supported by the server. + * @author Donal Fellows + */ +package org.taverna.server.master.defaults; http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java new file mode 100644 index 0000000..0b6247e --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadInputPortNameException.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * Indicates that the port name was not recognized. + * + * @author Donal Fellows + */ +@WebFault(name = "BadInputPortNameFault") +@SuppressWarnings("serial") +public class BadInputPortNameException extends Exception { + public BadInputPortNameException(String msg) { + super(msg); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java new file mode 100644 index 0000000..303b19b --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadPropertyValueException.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * Indicates a bad property value. + * + * @author Donal Fellows + */ +@WebFault(name = "BadPropertyValueFault") +public class BadPropertyValueException extends NoListenerException { + private static final long serialVersionUID = -8459491388504556875L; + + public BadPropertyValueException(String msg) { + super(msg); + } + + public BadPropertyValueException(String msg, Throwable e) { + super(msg, e); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java new file mode 100644 index 0000000..4b843e2 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/BadStateChangeException.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * Exception that is thrown to indicate that the state change requested for a + * run is impossible. + * + * @author Donal Fellows + */ +@WebFault(name = "NoUpdateFault") +public class BadStateChangeException extends NoUpdateException { + private static final long serialVersionUID = -4490826388447601775L; + + public BadStateChangeException() { + super("cannot do that state change"); + } + + public BadStateChangeException(Throwable t) { + super("cannot do that state change", t); + } + + public BadStateChangeException(String msg, Throwable t) { + super(msg, t); + } + + public BadStateChangeException(String message) { + super(message); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java new file mode 100644 index 0000000..0b6cf07 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/FilesystemAccessException.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import java.rmi.RemoteException; + +import javax.xml.ws.WebFault; + +/** + * An exception that happened when the underlying filesystem was accessed. + * @author Donal Fellows + */ +@WebFault(name = "FilesystemAccessFault") +public class FilesystemAccessException extends Exception { + private static final long serialVersionUID = 8715937300989820318L; + + public FilesystemAccessException(String msg) { + super(msg); + } + + public FilesystemAccessException(String string, Throwable cause) { + super(string, getRealCause(cause)); + } + + private static Throwable getRealCause(Throwable t) { + if (t instanceof RemoteException) { + RemoteException remote = (RemoteException) t; + if (remote.detail != null) + return remote.detail; + } + if (t.getCause() != null) + return t.getCause(); + return t; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java new file mode 100644 index 0000000..11d47c7 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/GeneralFailureException.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import static org.taverna.server.master.common.Namespaces.SERVER_SOAP; + +import javax.xml.ws.WebFault; + +/** + * Some sort of exception that occurred which we can't map any other way. This + * is generally indicative of a problem server-side. + * + * @author Donal Fellows + */ +@WebFault(name = "GeneralFailureFault", targetNamespace = SERVER_SOAP) +@SuppressWarnings("serial") +public class GeneralFailureException extends RuntimeException { + public GeneralFailureException(Throwable cause) { + super(cause.getMessage(), cause); + } + + public GeneralFailureException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java new file mode 100644 index 0000000..67ba551 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/InvalidCredentialException.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +/** + * An exception that is thrown to indicate that a credential-descriptor or + * trust-descriptor supplied as part of a credential or trust management + * operation is invalid. + * + * @author Donal Fellows + * + */ +@SuppressWarnings("serial") +public class InvalidCredentialException extends Exception { + private static final String MSG = "that credential is invalid"; + + public InvalidCredentialException() { + super(MSG); + } + + public InvalidCredentialException(String reason) { + super(MSG + ": " + reason); + } + + public InvalidCredentialException(String reason, Throwable cause) { + this(reason); + initCause(cause); + } + + public InvalidCredentialException(Throwable cause) { + this(cause.getMessage(), cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java new file mode 100644 index 0000000..e2ddf4c --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCreateException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + + +/** + * Exception that is thrown to indicate that the user is not permitted to + * create something. + * + * @author Donal Fellows + */ +@WebFault(name = "NoCreateFault") +public class NoCreateException extends NoUpdateException { + private static final long serialVersionUID = 270413810410167235L; + + public NoCreateException() { + super("not permitted to create"); + } + + public NoCreateException(String string) { + super(string); + } + + public NoCreateException(String string, Throwable e) { + super(string, e); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java new file mode 100644 index 0000000..7077fc4 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoCredentialException.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +/** + * Exception that indicates the absence of an expected credential. + * + * @author Donal Fellows + */ +@SuppressWarnings("serial") +public class NoCredentialException extends Exception { + public NoCredentialException() { + super("no such credential"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java new file mode 100644 index 0000000..d7b0d29 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDestroyException.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + + +/** + * Exception that is thrown to indicate that the user is not permitted to + * destroy something. + * + * @author Donal Fellows + */ +@WebFault(name = "NoDestroyFault") +public class NoDestroyException extends NoUpdateException { + private static final long serialVersionUID = 6207448533265237933L; + + public NoDestroyException() { + super("not permitted to destroy"); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java new file mode 100644 index 0000000..0d6ca63 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoDirectoryEntryException.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * Indicates that the file or directory name was not recognized. + * + * @author Donal Fellows + */ +@WebFault(name = "NoDirectoryEntryFault") +@SuppressWarnings("serial") +public class NoDirectoryEntryException extends Exception { + public NoDirectoryEntryException(String msg) { + super(msg); + } + public NoDirectoryEntryException(String msg,Exception cause) { + super(msg, cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java new file mode 100644 index 0000000..f4b8e81 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoListenerException.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.ws.WebFault; + +/** + * Exception thrown to indicate that no listener by that name exists, or that + * some other problem with listeners has occurred. + * + * @author Donal Fellows + */ +@WebFault(name = "NoListenerFault") +@XmlSeeAlso(BadPropertyValueException.class) +public class NoListenerException extends Exception { + private static final long serialVersionUID = -2550897312787546547L; + + public NoListenerException() { + super("no such listener"); + } + + public NoListenerException(String msg) { + super(msg); + } + + public NoListenerException(String msg, Throwable t) { + super(msg, t); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java new file mode 100644 index 0000000..c49d111 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NoUpdateException.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.ws.WebFault; + +/** + * Exception that is thrown to indicate that the user is not permitted to update + * something. + * + * @author Donal Fellows + */ +@WebFault(name = "NoUpdateFault") +@XmlSeeAlso( { NoCreateException.class, NoDestroyException.class, BadStateChangeException.class }) +public class NoUpdateException extends Exception { + private static final long serialVersionUID = 4230987102653846379L; + + public NoUpdateException() { + super("not permitted to update"); + } + + public NoUpdateException(String msg) { + super(msg); + } + + public NoUpdateException(String string, Throwable e) { + super(string, e); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java new file mode 100644 index 0000000..6e1f792 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/NotOwnerException.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * An exception thrown when an operation is attempted which only the owner is + * permitted to do. Notably, permissions may <i>only</i> be manipulated by the + * owner. + * + * @author Donal Fellows + */ +@WebFault(name = "NotOwnerFault") +@SuppressWarnings("serial") +public class NotOwnerException extends Exception { + public NotOwnerException() { + super("not permitted; not the owner"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java new file mode 100644 index 0000000..dda371e --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/OverloadedException.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * Exception that is thrown to indicate that the state change requested for a + * run is currently impossible due to excessive server load. + * + * @author Donal Fellows + */ +@WebFault(name = "OverloadedFault") +public class OverloadedException extends BadStateChangeException { + private static final long serialVersionUID = 490826388447601776L; + + public OverloadedException() { + super("server too busy; try later please"); + } + + public OverloadedException(Throwable t) { + super("server too busy; try later please", t); + } + + public OverloadedException(String msg, Throwable t) { + super(msg, t); + } + + public OverloadedException(String message) { + super(message); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java new file mode 100644 index 0000000..4632d4a --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/UnknownRunException.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.exceptions; + +import javax.xml.ws.WebFault; + +/** + * Exception thrown to indicate that the handle of the run is unknown (or + * unacceptable to the current user). + * + * @author Donal Fellows + */ +@WebFault(name = "UnknownRunFault") +public class UnknownRunException extends Exception { + private static final long serialVersionUID = -3028749401786242841L; + + public UnknownRunException() { + super("unknown run UUID"); + } + + public UnknownRunException(Throwable t) { + super("implementation problems", t); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java new file mode 100644 index 0000000..29ccacd --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/exceptions/package-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * This package contains the exceptions/faults thrown by Taverna Server. + * @author Donal Fellows + */ +@XmlSchema(namespace = SERVER, elementFormDefault = QUALIFIED, attributeFormDefault = QUALIFIED, xmlns = { + @XmlNs(prefix = "xlink", namespaceURI = XLINK), + @XmlNs(prefix = "ts", namespaceURI = SERVER), + @XmlNs(prefix = "ts-rest", namespaceURI = SERVER_REST), + @XmlNs(prefix = "ts-soap", namespaceURI = SERVER_SOAP), + @XmlNs(prefix = "feed", namespaceURI = FEED), + @XmlNs(prefix = "admin", namespaceURI = ADMIN) }) +package org.taverna.server.master.exceptions; + +import static javax.xml.bind.annotation.XmlNsForm.QUALIFIED; +import static org.taverna.server.master.common.Namespaces.ADMIN; +import static org.taverna.server.master.common.Namespaces.FEED; +import static org.taverna.server.master.common.Namespaces.SERVER; +import static org.taverna.server.master.common.Namespaces.SERVER_REST; +import static org.taverna.server.master.common.Namespaces.SERVER_SOAP; +import static org.taverna.server.master.common.Namespaces.XLINK; + +import javax.xml.bind.annotation.XmlNs; +import javax.xml.bind.annotation.XmlSchema; + http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java new file mode 100644 index 0000000..0015754 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/Facade.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.facade; + +import static javax.ws.rs.core.MediaType.TEXT_HTML_TYPE; +import static javax.ws.rs.core.Response.ok; + +import java.io.IOException; +import java.net.URL; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Required; +import org.taverna.server.master.utils.Contextualizer; + +/** + * This is a simple class that is used to serve up a file (with a simple + * substitution applied) as the root of the T2Server webapp. + * + * @author Donal Fellows + */ +@Path("/") +public class Facade { + private Log log = LogFactory.getLog("Taverna.Server.Utils"); + private String welcome; + private Contextualizer contextualizer; + + /** + * Set what resource file to use as the template for the response. + * + * @param file + * The file from which to load the data (presumed HTML) to serve + * up as the root content. + * @throws IOException + * If the file doesn't exist. + */ + public void setFile(String file) throws IOException { + URL full = Facade.class.getResource(file); + log.info("setting " + full + " as source of root page"); + this.welcome = IOUtils.toString(full); + } + + @Required + public void setContextualizer(Contextualizer contextualizer) { + this.contextualizer = contextualizer; + } + + /** + * Serve up some HTML as the root of the service. + * + * @param ui + * A reference to how we were accessed by the service. + * @return The response, containing the HTML. + */ + @GET + @Path("{dummy:.*}") + @Produces("text/html") + public Response get(@Context UriInfo ui) { + return ok(contextualizer.contextualize(ui, welcome), TEXT_HTML_TYPE) + .build(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java new file mode 100644 index 0000000..73c884f --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/facade/package-info.java @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * Simple facade used at the top level of the Taverna Server in order to + * provide an entry splash page. + */ +package org.taverna.server.master.facade; http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java new file mode 100644 index 0000000..954b6f1 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ConfigurableRunFactory.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.factories; + +/** + * Interface to run factories for the purpose of configuration. + * + * @author Donal Fellows + */ +public interface ConfigurableRunFactory extends RunFactory { + /** Where is the registry? Getter */ + String getRegistryHost(); + + /** Where is the registry? Setter */ + void setRegistryHost(String host); + + /** Where is the registry? Getter */ + int getRegistryPort(); + + /** Where is the registry? Setter */ + void setRegistryPort(int port); + + /** How much can be done at once? Getter */ + int getMaxRuns(); + + /** How much can be done at once? Setter */ + void setMaxRuns(int maxRuns); + + /** How long will things live? Getter */ + int getDefaultLifetime(); + + /** How long will things live? Setter */ + void setDefaultLifetime(int defaultLifetime); + + /** How often do we probe for info? Getter */ + int getSleepTime(); + + /** How often do we probe for info? Setter */ + void setSleepTime(int sleepTime); + + /** How long do we allow for actions? Getter */ + int getWaitSeconds(); + + /** How long do we allow for actions? Setter */ + void setWaitSeconds(int seconds); + + /** How do we start the workflow engine? Getter */ + String getExecuteWorkflowScript(); + + /** How do we start the workflow engine? Setter */ + void setExecuteWorkflowScript(String executeWorkflowScript); + + /** How do we start the file system access process? Getter */ + String getServerWorkerJar(); + + /** How do we start the file system access process? Setter */ + void setServerWorkerJar(String serverWorkerJar); + + /** + * How do we start the file system access process? Extra arguments to pass. + * Getter + */ + String[] getExtraArguments(); + + /** + * How do we start the file system access process? Extra arguments to pass. + * Setter + */ + void setExtraArguments(String[] firstArguments); + + /** Where is Java? Getter */ + String getJavaBinary(); + + /** Where is Java? Setter */ + void setJavaBinary(String javaBinary); + + /** Where do we get passwords from? Getter */ + String getPasswordFile(); + + /** Where do we get passwords from? Setter */ + void setPasswordFile(String newValue); + + /** How do we switch users? Getter */ + String getServerForkerJar(); + + /** How do we switch users? Setter */ + void setServerForkerJar(String newValue); + + /** How many runs have there been? */ + int getTotalRuns(); + + /** How long did the last subprocess startup take? */ + int getLastStartupCheckCount(); + + /** What are the current runs? */ + String[] getCurrentRunNames(); + + /** What is the RMI ID of the factory process? */ + String getFactoryProcessName(); + + /** What was the last observed exit code? */ + Integer getLastExitCode(); + + /** What factory process to use for a particular user? */ + String[] getFactoryProcessMapping(); + + /** How many runs can be operating at once? Setter */ + void setOperatingLimit(int operatingLimit); + + /** How many runs can be operating at once? Getter */ + int getOperatingLimit(); + + /** + * How many runs are actually operating? + * + * @throws Exception + * if anything goes wrong + */ + int getOperatingCount() throws Exception; + + /** How do we start the RMI registry process? Getter */ + String getRmiRegistryJar(); + + /** How do we start the RMI registry process? Setter */ + void setRmiRegistryJar(String rmiRegistryJar); + + boolean getGenerateProvenance(); + + void setGenerateProvenance(boolean generateProvenance); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java new file mode 100644 index 0000000..ecc13cd --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/ListenerFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.factories; + +import java.util.List; + +import org.taverna.server.master.exceptions.NoListenerException; +import org.taverna.server.master.interfaces.Listener; +import org.taverna.server.master.interfaces.TavernaRun; + +/** + * How to make event listeners of various types that are attached to a workflow + * instance. + * + * @author Donal Fellows + */ +public interface ListenerFactory { + /** + * Make an event listener. + * + * @param run + * The workflow instance to attach the event listener to. + * @param listenerType + * The type of event listener to create. Must be one of the + * strings returned by {@link #getSupportedListenerTypes()}. + * @param configuration + * A configuration document to pass to the listener. + * @return The event listener that was created. + * @throws NoListenerException + * If the <b>listenerType</b> is unrecognized or the + * <b>configuration</b> is bad in some way. + */ + public Listener makeListener(TavernaRun run, String listenerType, + String configuration) throws NoListenerException; + + /** + * What types of listener are supported? Note that we assume that the list + * of types is the same for all users and all workflow instances. + * + * @return A list of supported listener types. + */ + public List<String> getSupportedListenerTypes(); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java new file mode 100644 index 0000000..eeacad7 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/RunFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010-2013 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.factories; + +import org.taverna.server.master.common.Workflow; +import org.taverna.server.master.exceptions.NoCreateException; +import org.taverna.server.master.interfaces.TavernaRun; +import org.taverna.server.master.utils.UsernamePrincipal; + +/** + * How to construct a Taverna Server Workflow Run. + * + * @author Donal Fellows + */ +public interface RunFactory { + /** + * Make a Taverna Server workflow run that is bound to a particular user + * (the "creator") and able to run a particular workflow. + * + * @param creator + * The user creating the workflow instance. + * @param workflow + * The workflow to instantiate + * @return An object representing the run. + * @throws NoCreateException + * On failure. + */ + TavernaRun create(UsernamePrincipal creator, Workflow workflow) + throws NoCreateException; + + /** + * Check whether the factory is permitting runs to actually start operating. + * + * @return Whether a run should start. + */ + boolean isAllowingRunsToStart(); +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java new file mode 100644 index 0000000..39b9ac6 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/factories/package-info.java @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * These interfaces define the principal way for the <i>factories</i> of + * worker classes to be invoked. + */ +package org.taverna.server.master.factories; http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java new file mode 100644 index 0000000..63402ef --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/AuthorityDerivedIDMapper.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.identity; + +import static org.taverna.server.master.defaults.Default.AUTHORITY_PREFIX; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.taverna.server.master.interfaces.LocalIdentityMapper; +import org.taverna.server.master.utils.UsernamePrincipal; + +/** + * Extracts the local user id from the set of Spring Security authorities + * granted to the current user. This is done by scanning the set of authorities + * to see if any of them start with the substring listed in the <tt>prefix</tt> + * property; the username is the rest of the authority string in that case. + * + * @author Donal Fellows + */ +public class AuthorityDerivedIDMapper implements LocalIdentityMapper { + private String prefix = AUTHORITY_PREFIX; + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + @Override + public String getUsernameForPrincipal(UsernamePrincipal user) { + Authentication auth = SecurityContextHolder.getContext() + .getAuthentication(); + if (auth == null || !auth.isAuthenticated()) + return null; + for (GrantedAuthority authority : auth.getAuthorities()) { + String token = authority.getAuthority(); + if (token == null) + continue; + if (token.startsWith(prefix)) + return token.substring(prefix.length()); + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java new file mode 100644 index 0000000..b5fcd5a --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/CompositeIDMapper.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.identity; + +import static org.apache.commons.logging.LogFactory.getLog; + +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.logging.Log; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.taverna.server.master.interfaces.LocalIdentityMapper; +import org.taverna.server.master.utils.UsernamePrincipal; + +/** + * An identity mapper that composes the results from other mappers, using the + * identity mappers in order until one can provide a non-<tt>null</tt> answer. + * + * @author Donal Fellows. + */ +public class CompositeIDMapper implements LocalIdentityMapper, + ApplicationContextAware { + private Log log = getLog("Taverna.Server.IdentityMapper"); + private List<LocalIdentityMapper> mappers; + private ApplicationContext context; + + /** + * @param mappers + * The list of mappers to delegate to. Order is significant. + */ + public void setIdentityMappers(List<LocalIdentityMapper> mappers) { + this.mappers = mappers; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + context = applicationContext; + } + + @Override + public String getUsernameForPrincipal(UsernamePrincipal user) { + if (mappers == null) + return null; + for (LocalIdentityMapper m : mappers) { + String u = m.getUsernameForPrincipal(user); + if (u == null) + continue; + for (Entry<String, ? extends LocalIdentityMapper> entry : context + .getBeansOfType(m.getClass()).entrySet()) + if (m == entry.getValue()) { + log.info("used " + entry.getKey() + " LIM to map " + user + + " to " + u); + break; + } + return u; + } + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java new file mode 100644 index 0000000..e81f926 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/ConstantIDMapper.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.identity; + +import org.taverna.server.master.interfaces.LocalIdentityMapper; +import org.taverna.server.master.utils.UsernamePrincipal; + +/** + * A trivial principal to user mapper that always uses the same ID. + * @author Donal Fellows + */ +public class ConstantIDMapper implements LocalIdentityMapper { + private String id; + + /** + * Sets what local user ID all users should be mapped to. + * + * @param id + * The local user ID. + */ + public void setConstantId(String id) { + this.id = id; + } + + @Override + public String getUsernameForPrincipal(UsernamePrincipal user) { + return id; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java new file mode 100644 index 0000000..42a3874 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/identity/NameIDMapper.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.identity; + +import static java.util.regex.Pattern.compile; + +import java.security.Principal; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import org.taverna.server.master.interfaces.LocalIdentityMapper; +import org.taverna.server.master.utils.UsernamePrincipal; + +/** + * A trivial identity mapper that just uses the name out of the + * {@link Principal}, or uses a regular expression to extract it from the string + * representation of the principal. + * + * @author Donal Fellows + */ +public class NameIDMapper implements LocalIdentityMapper { + private Pattern pat; + + /** + * @param regexp + * The regular expression to use. The first capturing group + * within the RE will be the result of the extraction. + * @throws PatternSyntaxException + * If the pattern is invalid. + */ + public void setRegexp(String regexp) throws PatternSyntaxException { + pat = compile(regexp); + } + + @Override + public String getUsernameForPrincipal(UsernamePrincipal user) { + if (pat != null) { + Matcher m = pat.matcher(user.toString()); + if (m.find() && m.groupCount() > 0) { + return m.group(1); + } + return null; + } + return user.getName(); + } +}
