You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2018/01/09 23:30:40 UTC

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

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/IllegalArgumentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/IllegalArgumentHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/IllegalArgumentHandler.java
new file mode 100644
index 0000000..d7ec8f4
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/IllegalArgumentHandler.java
@@ -0,0 +1,34 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.UNSUPPORTED_MEDIA_TYPE;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+@Provider
+public class IllegalArgumentHandler extends HandlerCore implements
+		ExceptionMapper<IllegalArgumentException> {
+	@Override
+	public Response toResponse(IllegalArgumentException exn) {
+		return respond(UNSUPPORTED_MEDIA_TYPE, exn);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ImplementationProblemHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ImplementationProblemHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ImplementationProblemHandler.java
new file mode 100644
index 0000000..806fc67
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ImplementationProblemHandler.java
@@ -0,0 +1,34 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.taverna.server.localworker.remote.ImplementationException;
+
+public class ImplementationProblemHandler extends HandlerCore implements
+		ExceptionMapper<ImplementationException> {
+	@Override
+	public Response toResponse(ImplementationException exception) {
+		return respond(INTERNAL_SERVER_ERROR, exception);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InputStreamMessageHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InputStreamMessageHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InputStreamMessageHandler.java
new file mode 100644
index 0000000..6b4470b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InputStreamMessageHandler.java
@@ -0,0 +1,120 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static java.lang.Long.parseLong;
+import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
+import static org.apache.commons.logging.LogFactory.getLog;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * Maps a stream from a client into a bounded ordinary input stream that the
+ * webapp can work with more easily.
+ * 
+ * @author Donal Fellows
+ */
+@Provider
+@Consumes(APPLICATION_OCTET_STREAM)
+public class InputStreamMessageHandler implements
+		MessageBodyReader<InputStream> {
+	@Override
+	public boolean isReadable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return InputStream.class.isAssignableFrom(type);
+	}
+
+	@Override
+	public InputStream readFrom(Class<InputStream> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+			throws IOException, WebApplicationException {
+		return new TransferStream(entityStream,
+				httpHeaders.get("Content-Length"));
+	}
+}
+
+/**
+ * The actual transfer thunk.
+ * 
+ * @author Donal Fellows
+ */
+class TransferStream extends InputStream {
+	private Log log = getLog("Taverna.Server.Handlers");
+
+	public TransferStream(InputStream entityStream, List<String> contentLength) {
+		this.entityStream = new BufferedInputStream(entityStream);
+		if (contentLength != null && contentLength.size() > 0) {
+			this.limit = parseLong(contentLength.get(0));
+			if (log.isDebugEnabled())
+				log.debug("will attempt to transfer " + this.limit + " bytes");
+		} else {
+			this.limit = -1;
+			if (log.isDebugEnabled())
+				log.debug("will attempt to transfer until EOF");
+		}
+	}
+
+	InputStream entityStream;
+	long limit;
+	long doneBytes = 0;
+
+	@Override
+	public int read() throws IOException {
+		if (limit >= 0 && doneBytes >= limit)
+			return -1;
+		int result = entityStream.read();
+		if (result >= 0)
+			doneBytes++;
+		return result;
+	}
+
+	@Override
+	public int read(byte[] ary, int off, int len) throws IOException {
+		if (limit >= 0) {
+			if (doneBytes >= limit)
+				return -1;
+			if (doneBytes + len > limit)
+				len = (int) (limit - doneBytes);
+		}
+		int readBytes = entityStream.read(ary, off, len);
+		if (readBytes >= 0)
+			doneBytes += readBytes;
+		return readBytes;
+	}
+
+	@Override
+	public void close() throws IOException {
+		entityStream.close();
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InvalidCredentialHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InvalidCredentialHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InvalidCredentialHandler.java
new file mode 100644
index 0000000..7208aa4
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/InvalidCredentialHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.InvalidCredentialException;
+
+@Provider
+public class InvalidCredentialHandler extends HandlerCore implements
+		ExceptionMapper<InvalidCredentialException> {
+	@Override
+	public Response toResponse(InvalidCredentialException exn) {
+		return respond(BAD_REQUEST, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/JAXBExceptionHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/JAXBExceptionHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/JAXBExceptionHandler.java
new file mode 100644
index 0000000..cf5952e
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/JAXBExceptionHandler.java
@@ -0,0 +1,35 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+import javax.xml.bind.JAXBException;
+
+@Provider
+public class JAXBExceptionHandler extends HandlerCore implements
+		ExceptionMapper<JAXBException> {
+	@Override
+	public Response toResponse(JAXBException exn) {
+		return respond(BAD_REQUEST, "APIEpicFail: " + exn.getErrorCode(), exn);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NegotiationFailedHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NegotiationFailedHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NegotiationFailedHandler.java
new file mode 100644
index 0000000..00457fe
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NegotiationFailedHandler.java
@@ -0,0 +1,38 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static javax.ws.rs.core.Response.notAcceptable;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.rest.TavernaServerDirectoryREST.NegotiationFailedException;
+
+@Provider
+public class NegotiationFailedHandler implements
+		ExceptionMapper<NegotiationFailedException> {
+	@Override
+	public Response toResponse(NegotiationFailedException exn) {
+		return notAcceptable(exn.accepted).type(TEXT_PLAIN)
+				.entity(exn.getMessage()).build();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCreateHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCreateHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCreateHandler.java
new file mode 100644
index 0000000..f20f876
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCreateHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoCreateException;
+
+@Provider
+public class NoCreateHandler extends HandlerCore implements
+		ExceptionMapper<NoCreateException> {
+	@Override
+	public Response toResponse(NoCreateException exn) {
+		return respond(SERVICE_UNAVAILABLE, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCredentialHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCredentialHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCredentialHandler.java
new file mode 100644
index 0000000..6644901
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoCredentialHandler.java
@@ -0,0 +1,34 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.taverna.server.master.exceptions.NoCredentialException;
+
+public class NoCredentialHandler extends HandlerCore implements
+		ExceptionMapper<NoCredentialException> {
+	@Override
+	public Response toResponse(NoCredentialException exn) {
+		return respond(NOT_FOUND, exn);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDestroyHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDestroyHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDestroyHandler.java
new file mode 100644
index 0000000..2c0f5a9
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDestroyHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoDestroyException;
+
+@Provider
+public class NoDestroyHandler extends HandlerCore implements
+		ExceptionMapper<NoDestroyException> {
+	@Override
+	public Response toResponse(NoDestroyException exn) {
+		return respond(FORBIDDEN, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
new file mode 100644
index 0000000..2f72487
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoDirectoryEntryException;
+
+@Provider
+public class NoDirectoryEntryHandler extends HandlerCore implements
+		ExceptionMapper<NoDirectoryEntryException> {
+	@Override
+	public Response toResponse(NoDirectoryEntryException exn) {
+		return respond(NOT_FOUND, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoListenerHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoListenerHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoListenerHandler.java
new file mode 100644
index 0000000..e119b60
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoListenerHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoListenerException;
+
+@Provider
+public class NoListenerHandler extends HandlerCore implements
+		ExceptionMapper<NoListenerException> {
+	@Override
+	public Response toResponse(NoListenerException exn) {
+		return respond(BAD_REQUEST, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoUpdateHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoUpdateHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoUpdateHandler.java
new file mode 100644
index 0000000..2d5dde3
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NoUpdateHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.NoUpdateException;
+
+@Provider
+public class NoUpdateHandler extends HandlerCore implements
+		ExceptionMapper<NoUpdateException> {
+	@Override
+	public Response toResponse(NoUpdateException exn) {
+		return respond(FORBIDDEN, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NotOwnerHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NotOwnerHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NotOwnerHandler.java
new file mode 100644
index 0000000..baeb6aa
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/NotOwnerHandler.java
@@ -0,0 +1,34 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.FORBIDDEN;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+import org.taverna.server.master.exceptions.NotOwnerException;
+
+public class NotOwnerHandler extends HandlerCore implements
+		ExceptionMapper<NotOwnerException> {
+	@Override
+	public Response toResponse(NotOwnerException exn) {
+		return respond(FORBIDDEN, exn);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/OverloadedHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/OverloadedHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/OverloadedHandler.java
new file mode 100644
index 0000000..9e142f3
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/OverloadedHandler.java
@@ -0,0 +1,35 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.OverloadedException;
+
+@Provider
+public class OverloadedHandler extends HandlerCore implements
+		ExceptionMapper<OverloadedException> {
+	@Override
+	public Response toResponse(OverloadedException exn) {
+		return respond(SERVICE_UNAVAILABLE, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/PermissionHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/PermissionHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/PermissionHandler.java
new file mode 100644
index 0000000..d7a4afc
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/PermissionHandler.java
@@ -0,0 +1,87 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN_TYPE;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.taverna.server.master.common.Permission;
+
+/**
+ * Handler that allows CXF to send and receive {@linkplain Permission
+ * permissions} as plain text directly.
+ * 
+ * @author Donal Fellows
+ */
+public class PermissionHandler implements MessageBodyReader<Permission>,
+		MessageBodyWriter<Permission> {
+	@Override
+	public boolean isWriteable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return type.isAssignableFrom(Permission.class)
+				&& mediaType.isCompatible(TEXT_PLAIN_TYPE);
+	}
+
+	@Override
+	public long getSize(Permission t, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return t.toString().length();
+	}
+
+	@Override
+	public void writeTo(Permission t, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, Object> httpHeaders,
+			OutputStream entityStream) throws IOException,
+			WebApplicationException {
+		new OutputStreamWriter(entityStream).write(t.toString());
+	}
+
+	@Override
+	public boolean isReadable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return type.isAssignableFrom(Permission.class)
+				&& mediaType.isCompatible(TEXT_PLAIN_TYPE);
+	}
+
+	@Override
+	public Permission readFrom(Class<Permission> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+			throws IOException, WebApplicationException {
+		char[] cbuf = new char[7];
+		int len = new InputStreamReader(entityStream).read(cbuf);
+		if (len < 0)
+			throw new IllegalArgumentException("no entity supplied");
+		return Permission.valueOf(new String(cbuf, 0, len));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/Scufl2DocumentHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
new file mode 100644
index 0000000..cf1ccdf
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/Scufl2DocumentHandler.java
@@ -0,0 +1,100 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.common.Workflow;
+
+import org.apache.taverna.scufl2.api.io.ReaderException;
+import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
+import org.apache.taverna.scufl2.api.io.WriterException;
+
+/**
+ * Handler that allows a .scufl2 document to be read from and written to a REST
+ * message directly.
+ * 
+ * @author Donal Fellows
+ */
+@Provider
+public class Scufl2DocumentHandler implements MessageBodyReader<Workflow>,
+		MessageBodyWriter<Workflow> {
+	private static final MediaType SCUFL2_TYPE = new MediaType("application",
+			"vnd.taverna.scufl2.workflow-bundle");
+	public static final String SCUFL2 = "application/vnd.taverna.scufl2.workflow-bundle";
+	private WorkflowBundleIO io = new WorkflowBundleIO();
+
+	@Override
+	public boolean isReadable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		if (type.isAssignableFrom(Workflow.class))
+			return mediaType.isCompatible(SCUFL2_TYPE);
+		return false;
+	}
+
+	@Override
+	public Workflow readFrom(Class<Workflow> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+			throws IOException, WebApplicationException {
+		try {
+			return new Workflow(io.readBundle(entityStream, SCUFL2));
+		} catch (ReaderException e) {
+			throw new WebApplicationException(e, 403);
+		}
+	}
+
+	@Override
+	public boolean isWriteable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		if (Workflow.class.isAssignableFrom(type))
+			return mediaType.isCompatible(SCUFL2_TYPE);
+		return false;
+	}
+
+	@Override
+	public long getSize(Workflow workflow, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return -1;
+	}
+
+	@Override
+	public void writeTo(Workflow workflow, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, Object> httpHeaders,
+			OutputStream entityStream) throws IOException,
+			WebApplicationException {
+		try {
+			io.writeBundle(workflow.getScufl2Workflow(), entityStream, SCUFL2);
+		} catch (WriterException e) {
+			throw new WebApplicationException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/T2FlowDocumentHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
new file mode 100644
index 0000000..1f6d328
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/T2FlowDocumentHandler.java
@@ -0,0 +1,131 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.taverna.server.master.common.Workflow;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * Handler that allows a .t2flow document to be read from and written to a REST
+ * message directly.
+ * 
+ * @author Donal Fellows
+ */
+@Provider
+public class T2FlowDocumentHandler implements MessageBodyReader<Workflow>,
+		MessageBodyWriter<Workflow> {
+	private static final MediaType T2FLOW_TYPE = new MediaType("application",
+			"vnd.taverna.t2flow+xml");
+	public static final String T2FLOW = "application/vnd.taverna.t2flow+xml";
+	public static final String T2FLOW_ROOTNAME = "workflow";
+	public static final String T2FLOW_NS = "http://taverna.sf.net/2008/xml/t2flow";
+	private DocumentBuilderFactory db;
+	private TransformerFactory transformer;
+
+	public T2FlowDocumentHandler() throws ParserConfigurationException,
+			TransformerConfigurationException {
+		db = DocumentBuilderFactory.newInstance();
+		db.setNamespaceAware(true);
+		transformer = TransformerFactory.newInstance();
+	}
+
+	@Override
+	public boolean isReadable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		if (type.isAssignableFrom(Workflow.class))
+			return mediaType.isCompatible(T2FLOW_TYPE);
+		return false;
+	}
+
+	@Override
+	public Workflow readFrom(Class<Workflow> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+			throws IOException, WebApplicationException {
+		Document doc;
+		try {
+			doc = db.newDocumentBuilder().parse(entityStream);
+		} catch (SAXException e) {
+			throw new WebApplicationException(e, 403);
+		} catch (ParserConfigurationException e) {
+			throw new WebApplicationException(e);
+		}
+		Workflow workflow = new Workflow(doc.getDocumentElement());
+		if (doc.getDocumentElement().getNamespaceURI().equals(T2FLOW_NS)
+				&& doc.getDocumentElement().getNodeName()
+						.equals(T2FLOW_ROOTNAME))
+			return workflow;
+		throw new WebApplicationException(Response.status(403)
+				.entity("invalid T2flow document; bad root element")
+				.type("text/plain").build());
+	}
+
+	@Override
+	public boolean isWriteable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		if (Workflow.class.isAssignableFrom(type))
+			return mediaType.isCompatible(T2FLOW_TYPE);
+		return false;
+	}
+
+	@Override
+	public long getSize(Workflow workflow, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return -1;
+	}
+
+	@Override
+	public void writeTo(Workflow workflow, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, Object> httpHeaders,
+			OutputStream entityStream) throws IOException,
+			WebApplicationException {
+		try {
+			transformer.newTransformer().transform(
+					new DOMSource(workflow.getT2flowWorkflow()),
+					new StreamResult(entityStream));
+		} catch (TransformerException e) {
+			if (e.getCause() != null && e.getCause() instanceof IOException)
+				throw (IOException) e.getCause();
+			throw new WebApplicationException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/URIListHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/URIListHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/URIListHandler.java
new file mode 100644
index 0000000..453ac73
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/URIListHandler.java
@@ -0,0 +1,134 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.status;
+import static org.taverna.server.master.rest.handler.URIListHandler.URI_LIST;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Deserialization and serialization engine for the <tt>{@value #URI_LIST}</tt>
+ * content type.
+ * 
+ * @author Donal Fellows
+ */
+@Provider
+@Consumes(URI_LIST)
+public class URIListHandler implements MessageBodyReader<List<URI>>,
+		MessageBodyWriter<List<URI>> {
+	/** The content type we handle. */
+	public static final String URI_LIST = "text/uri-list";
+	private static final MediaType URILIST = new MediaType("text", "uri-list");
+
+	@Override
+	public boolean isReadable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return type.isAssignableFrom(ArrayList.class)
+				&& genericType instanceof ParameterizedType
+				&& ((Class<?>) ((ParameterizedType) genericType)
+						.getActualTypeArguments()[0])
+						.isAssignableFrom(URI.class)
+				&& URILIST.isCompatible(mediaType);
+	}
+
+	@Override
+	public List<URI> readFrom(Class<List<URI>> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+			throws IOException, WebApplicationException {
+		String enc = mediaType.getParameters().get("encoding");
+		Charset c = (enc == null) ? Charset.defaultCharset() : Charset
+				.forName(enc);
+		BufferedReader br = new BufferedReader(new InputStreamReader(
+				entityStream, c));
+		ArrayList<URI> uris = new ArrayList<>();
+		String line;
+		while ((line = br.readLine()) != null) {
+			if (line.startsWith("#"))
+				continue;
+			try {
+				uris.add(new URI(line));
+			} catch (URISyntaxException e) {
+				throw new WebApplicationException(e, status(422).entity(
+						"ill-formed URI").build());
+			}
+		}
+		return uris;
+	}
+
+	@Override
+	public boolean isWriteable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return List.class.isAssignableFrom(type)
+				&& genericType instanceof ParameterizedType
+				&& ((ParameterizedType) genericType).getActualTypeArguments()[0] == URI.class
+				&& URILIST.isCompatible(mediaType);
+	}
+
+	@Override
+	public long getSize(List<URI> list, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return -1;
+	}
+
+	private static final String PREFERRED_ENCODING = "UTF-8";
+
+	@Override
+	public void writeTo(List<URI> list, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, Object> httpHeaders,
+			OutputStream entityStream) throws IOException {
+		String encoding = mediaType.getParameters().get("encoding");
+		if (encoding == null) {
+			encoding = PREFERRED_ENCODING;
+			httpHeaders.putSingle("Content-Type", URI_LIST + ";encoding="
+					+ encoding);
+		}
+		BufferedWriter w = new BufferedWriter(new OutputStreamWriter(
+				entityStream, encoding));
+		for (URI uri : list) {
+			w.write(uri.toString());
+			w.newLine();
+		}
+		w.flush();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/UnknownRunHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/UnknownRunHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/UnknownRunHandler.java
new file mode 100644
index 0000000..4d5c6e8
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/UnknownRunHandler.java
@@ -0,0 +1,36 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.exceptions.UnknownRunException;
+
+@Provider
+public class UnknownRunHandler extends HandlerCore implements
+		ExceptionMapper<UnknownRunException> {
+	@Override
+	public Response toResponse(UnknownRunException exn) {
+		return respond(NOT_FOUND, exn);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ZipStreamHandler.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ZipStreamHandler.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ZipStreamHandler.java
new file mode 100644
index 0000000..69e526d
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/ZipStreamHandler.java
@@ -0,0 +1,67 @@
+/*
+ */
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static org.apache.commons.io.IOUtils.copy;
+import static org.taverna.server.master.api.ContentTypes.APPLICATION_ZIP_TYPE;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.taverna.server.master.interfaces.Directory.ZipStream;
+
+/**
+ * How to write a ZIP file as the result entity of a request.
+ * 
+ * @author Donal Fellows
+ */
+@Provider
+@Produces("application/zip")
+public class ZipStreamHandler implements MessageBodyWriter<ZipStream> {
+	@Override
+	public boolean isWriteable(Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return ZipStream.class.isAssignableFrom(type)
+				&& mediaType.equals(APPLICATION_ZIP_TYPE);
+	}
+
+	@Override
+	public long getSize(ZipStream t, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType) {
+		return -1;
+	}
+
+	@Override
+	public void writeTo(ZipStream zipStream, Class<?> type, Type genericType,
+			Annotation[] annotations, MediaType mediaType,
+			MultivaluedMap<String, Object> httpHeaders,
+			OutputStream entityStream) throws IOException,
+			WebApplicationException {
+		copy(zipStream, entityStream);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/package-info.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/package-info.java
new file mode 100644
index 0000000..8404ead
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/handler/package-info.java
@@ -0,0 +1,44 @@
+/*
+ */
+/**
+ * This package contains type handlers for the RESTful interface to Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER_REST, 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 = "port", namespaceURI = DATA),
+		@XmlNs(prefix = "feed", namespaceURI = FEED),
+		@XmlNs(prefix = "admin", namespaceURI = ADMIN) })
+package org.taverna.server.master.rest.handler;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.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 static org.taverna.server.port_description.Namespaces.DATA;
+
+import javax.xml.bind.annotation.XmlNs;
+import javax.xml.bind.annotation.XmlSchema;
+

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/package-info.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/package-info.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/package-info.java
new file mode 100644
index 0000000..d35dc7b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/rest/package-info.java
@@ -0,0 +1,44 @@
+/*
+ */
+/**
+ * This package contains the RESTful interface to Taverna Server.
+ * @author Donal Fellows
+ */
+@XmlSchema(namespace = SERVER_REST, 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 = "port", namespaceURI = DATA),
+		@XmlNs(prefix = "feed", namespaceURI = FEED),
+		@XmlNs(prefix = "admin", namespaceURI = ADMIN) })
+package org.taverna.server.master.rest;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static javax.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 static org.taverna.server.port_description.Namespaces.DATA;
+
+import javax.xml.bind.annotation.XmlNs;
+import javax.xml.bind.annotation.XmlSchema;
+

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/DirEntry.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/DirEntry.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/DirEntry.java
new file mode 100644
index 0000000..752c6b1
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/DirEntry.java
@@ -0,0 +1,113 @@
+/*
+ */
+package org.taverna.server.master.soap;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static org.taverna.server.master.common.Namespaces.XLINK;
+
+import java.net.URI;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+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 org.taverna.server.master.common.DirEntryReference;
+
+/**
+ * A more Taverna-friendly version of the directory entry descriptor classes.
+ * 
+ * @author Donal Fellows
+ */
+@XmlType(name = "DirectoryEntry")
+@XmlRootElement(name = "entry")
+@XmlSeeAlso({ DirEntry.File.class, DirEntry.Directory.class })
+public class DirEntry {
+	/** A link to the entry. Ignored on input. */
+	@XmlAttribute(name = "href", namespace = XLINK)
+	@XmlSchemaType(name = "anyURI")
+	public URI link;
+	@XmlAttribute
+	public String name;
+	@XmlElement(required = true)
+	public String path;
+
+	/**
+	 * A file in a directory.
+	 * 
+	 * @author Donal Fellows
+	 */
+	@XmlType(name = "FileDirEntry")
+	@XmlRootElement(name = "file")
+	public static class File extends DirEntry {
+	}
+
+	/**
+	 * A directory in a directory. That is, a sub-directory.
+	 * 
+	 * @author Donal Fellows
+	 */
+	@XmlType(name = "DirectoryDirEntry")
+	@XmlRootElement(name = "dir")
+	public static class Directory extends DirEntry {
+	}
+
+	/**
+	 * Converts from the "common" format to the subclasses of this class.
+	 * 
+	 * @param deref
+	 *            The "common" format handle to convert.
+	 * @return The converted handle
+	 */
+	public static DirEntry convert(DirEntryReference deref) {
+		DirEntry result;
+		if (deref instanceof DirEntryReference.DirectoryReference)
+			result = new Directory();
+		else if (deref instanceof DirEntryReference.FileReference)
+			result = new File();
+		else
+			result = new DirEntry();
+		result.link = deref.link;
+		result.name = deref.name;
+		result.path = deref.path;
+		return result;
+	}
+
+	/**
+	 * Converts to the "common" format from the subclasses of this class.
+	 * 
+	 * @param deref
+	 *            The subclass of this class to convert.
+	 * @return The converted reference.
+	 */
+	public static DirEntryReference convert(DirEntry de) {
+		DirEntryReference result;
+		if (de instanceof Directory)
+			result = new DirEntryReference.DirectoryReference();
+		else if (de instanceof File)
+			result = new DirEntryReference.FileReference();
+		else
+			result = new DirEntryReference();
+		result.link = de.link;
+		result.name = de.name;
+		result.path = de.path;
+		return result;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/FileContents.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/FileContents.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/FileContents.java
new file mode 100644
index 0000000..fa9978b
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/FileContents.java
@@ -0,0 +1,184 @@
+/*
+ */
+package org.taverna.server.master.soap;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import static java.lang.Math.min;
+import static java.lang.System.arraycopy;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlMimeType;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.exceptions.FilesystemAccessException;
+import org.taverna.server.master.interfaces.File;
+
+/**
+ * An MTOM-capable description of how to transfer the contents of a file.
+ * 
+ * @author Donal Fellows
+ */
+@XmlType(name = "FileContents")
+public class FileContents {
+	@XmlElement
+	public String name;
+	@XmlMimeType("application/octet-stream") // JAXB bug: must be this
+	public DataHandler fileData;
+
+	/**
+	 * Initialize the contents of this descriptor from the given file and
+	 * content type.
+	 * 
+	 * @param file
+	 *            The file that is to be reported.
+	 * @param contentType
+	 *            The estimated content type of the file.
+	 */
+	public void setFile(File file, String contentType) {
+		name = file.getFullName();
+		fileData = new DataHandler(new TavernaFileSource(file, contentType));
+	}
+
+	/**
+	 * Write the content described by this class to the specified file.
+	 * @param file The file to write to; must already exist.
+	 * @throws IOException
+	 * @throws FilesystemAccessException
+	 */
+	public void writeToFile(File file) throws IOException,
+			FilesystemAccessException {
+		try (InputStream is = fileData.getInputStream()) {
+			byte[] buf = new byte[65536];
+			file.setContents(new byte[0]);
+			while (true) {
+				int len = is.read(buf);
+				if (len <= 0)
+					return;
+				if (len == buf.length)
+					file.appendContents(buf);
+				else {
+					byte[] shortbuf = new byte[len];
+					arraycopy(buf, 0, shortbuf, 0, len);
+					file.appendContents(shortbuf);
+				}
+			}
+		}
+	}
+}
+
+/**
+ * A data source that knows how to communicate with the Taverna Server back-end.
+ * 
+ * @author Donal Fellows
+ */
+class TavernaFileSource implements DataSource {
+	TavernaFileSource(File f, String type) {
+		this.f = f;
+		this.type = type;
+	}
+
+	private final File f;
+	private final String type;
+
+	@Override
+	public String getContentType() {
+		return type;
+	}
+
+	@Override
+	public String getName() {
+		return f.getName();
+	}
+
+	@Override
+	public InputStream getInputStream() throws IOException {
+		final File f = this.f;
+		return new InputStream() {
+			private int idx;
+
+			@Override
+			public int read(byte[] b, int off, int len) throws IOException {
+				byte[] r;
+				try {
+					r = f.getContents(idx, len);
+				} catch (FilesystemAccessException e) {
+					throw new IOException(e);
+				}
+				if (r == null)
+					return -1;
+				len = min(len, r.length);
+				arraycopy(r, 0, b, off, len);
+				idx += len;
+				return len;
+			}
+
+			@Override
+			public int read() throws IOException {
+				byte[] r;
+				try {
+					r = f.getContents(idx, 1);
+				} catch (FilesystemAccessException e) {
+					throw new IOException(e);
+				}
+				if (r == null)
+					return -1;
+				idx++;
+				return r[0];
+			}
+		};
+	}
+
+	@Override
+	public OutputStream getOutputStream() throws IOException {
+		final File f = this.f;
+		return new OutputStream() {
+			private boolean append = false;
+
+			@Override
+			public void write(int b) throws IOException {
+				write(new byte[] { (byte) b });
+			}
+
+			@Override
+			public void write(byte[] b) throws IOException {
+				try {
+					if (append)
+						f.appendContents(b);
+					else
+						f.setContents(b);
+					append = true;
+				} catch (FilesystemAccessException e) {
+					throw new IOException(e);
+				}
+			}
+
+			@Override
+			public void write(byte[] b, int off, int len) throws IOException {
+				byte[] ary = new byte[len];
+				arraycopy(b, off, ary, 0, len);
+				write(ary);
+			}
+		};
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/PermissionList.java
----------------------------------------------------------------------
diff --git a/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/PermissionList.java b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/PermissionList.java
new file mode 100644
index 0000000..6568ab2
--- /dev/null
+++ b/taverna-server-webapp/src/main/java/org/apache/taverna/server/master/soap/PermissionList.java
@@ -0,0 +1,63 @@
+/*
+ */
+package org.taverna.server.master.soap;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.taverna.server.master.common.Permission;
+
+/**
+ * The list of permissions to access a workflow run of users <i>other than the
+ * owner</i>. This class exists to support the JAXB mapping.
+ * 
+ * @author Donal Fellows
+ */
+@XmlType(name = "PermissionList")
+@XmlRootElement(name = "permissionList")
+public class PermissionList {
+	/**
+	 * The type of a single mapped permission. This class exists to support the
+	 * JAXB mapping.
+	 * 
+	 * @author Donal Fellows
+	 */
+	@XmlType(name = "")
+	public static class SinglePermissionMapping {
+		public SinglePermissionMapping() {
+		}
+
+		public SinglePermissionMapping(String user, Permission permission) {
+			this.userName = user;
+			this.permission = permission;
+		}
+
+		/** The name of the user that this talks about. */
+		public String userName;
+		/** The permission level that the user is granted. */
+		public Permission permission;
+	}
+
+	/** The list of (non-default) permissions granted. */
+	@XmlElement
+	public List<SinglePermissionMapping> permission;
+}
\ No newline at end of file