http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java new file mode 100644 index 0000000..20d9f56 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/EntryHandler.java @@ -0,0 +1,131 @@ +package org.taverna.server.master.rest.handler; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonMap; +import static javax.ws.rs.core.Response.notAcceptable; + +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 java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; + +import javax.ws.rs.Consumes; +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.core.Variant; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import org.apache.abdera.Abdera; +import org.apache.abdera.model.Document; +import org.apache.abdera.model.Entry; +import org.apache.abdera.parser.Parser; +import org.apache.abdera.writer.Writer; +import org.springframework.beans.factory.annotation.Required; + +@Provider +@Produces({ "application/atom+xml", "application/atom+xml;type=entry" }) +@Consumes({ "application/atom+xml", "application/atom+xml;type=entry" }) +public class EntryHandler implements MessageBodyWriter<Entry>, + MessageBodyReader<Entry> { + private static final String ENC = "UTF-8"; + private static final MediaType ENTRY = new MediaType("application", + "atom+xml", singletonMap("type", "entry")); + private static final Variant VARIANT = new Variant(ENTRY, (String) null, + ENC); + private static final Charset UTF8 = Charset.forName(ENC); + + @Required + public void setAbdera(Abdera abdera) { + parser = abdera.getParser(); + writer = abdera.getWriterFactory().getWriter("prettyxml"); + } + + private Parser parser; + private Writer writer; + + @Override + public boolean isReadable(Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + if (!Entry.class.isAssignableFrom(type)) + return false; + if (!ENTRY.isCompatible(mediaType)) + return false; + if (mediaType.getParameters().containsKey("type")) + return "entry".equalsIgnoreCase(mediaType.getParameters().get( + "type")); + return true; + } + + @Override + public Entry readFrom(Class<Entry> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, String> httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + Charset cs = UTF8; + try { + String charset = mediaType.getParameters().get("charset"); + if (charset != null) + cs = Charset.forName(charset); + } catch (IllegalCharsetNameException e) { + throw new WebApplicationException(notAcceptable(asList(VARIANT)) + .entity("bad charset name").build()); + } catch (UnsupportedCharsetException e) { + throw new WebApplicationException(notAcceptable(asList(VARIANT)) + .entity("unsupportd charset name").build()); + } + try { + Document<Entry> doc = parser.parse(new InputStreamReader( + entityStream, cs)); + if (!Entry.class.isAssignableFrom(doc.getRoot().getClass())) { + throw new WebApplicationException( + notAcceptable(asList(VARIANT)).entity( + "not really a feed entry").build()); + } + return doc.getRoot(); + } catch (ClassCastException e) { + throw new WebApplicationException(notAcceptable(asList(VARIANT)) + .entity("not really a feed entry").build()); + + } + } + + @Override + public boolean isWriteable(Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + if (!Entry.class.isAssignableFrom(type)) + return false; + if (!ENTRY.isCompatible(mediaType)) + return false; + if (mediaType.getParameters().containsKey("type")) + return "entry".equalsIgnoreCase(mediaType.getParameters().get( + "type")); + return true; + } + + @Override + public long getSize(Entry t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return -1; + } + + @Override + public void writeTo(Entry t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException, + WebApplicationException { + httpHeaders.putSingle("Content-Type", ENTRY.toString() + ";charset=" + + ENC); + writer.writeTo(t, new OutputStreamWriter(entityStream, UTF8)); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java new file mode 100644 index 0000000..7c17f5c --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FeedHandler.java @@ -0,0 +1,66 @@ +package org.taverna.server.master.rest.handler; + +import static java.util.Collections.singletonMap; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +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.apache.abdera.Abdera; +import org.apache.abdera.model.Feed; +import org.apache.abdera.writer.Writer; +import org.springframework.beans.factory.annotation.Required; + +@Provider +@Produces({ "application/atom+xml", "application/atom+xml;type=feed" }) +public class FeedHandler implements MessageBodyWriter<Feed> { + private static final MediaType FEED = new MediaType("application", + "atom+xml", singletonMap("type", "feed")); + private static final String ENC = "UTF-8"; + + @Required + public void setAbdera(Abdera abdera) { + writer = abdera.getWriterFactory().getWriter("prettyxml"); + } + + private Writer writer; + + @Override + public boolean isWriteable(Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + if (!Feed.class.isAssignableFrom(type)) + return false; + if (!FEED.isCompatible(mediaType)) + return false; + if (mediaType.getParameters().containsKey("type")) + return "feed".equalsIgnoreCase(mediaType.getParameters() + .get("type")); + return true; + } + + @Override + public long getSize(Feed t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return -1; + } + + @Override + public void writeTo(Feed t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException, + WebApplicationException { + httpHeaders.putSingle("Content-Type", FEED.toString() + ";charset=" + + ENC); + writer.writeTo(t, new OutputStreamWriter(entityStream, ENC)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java new file mode 100644 index 0000000..ab18d73 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileConcatenationHandler.java @@ -0,0 +1,61 @@ +package org.taverna.server.master.rest.handler; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyWriter; + +import org.springframework.beans.factory.annotation.Required; +import org.taverna.server.master.FileConcatenation; +import org.taverna.server.master.exceptions.FilesystemAccessException; +import org.taverna.server.master.interfaces.File; + +public class FileConcatenationHandler implements + MessageBodyWriter<FileConcatenation> { + /** How much to pull from the worker in one read. */ + private int maxChunkSize; + + /** + * @param maxChunkSize + * How much to pull from the worker in one read. + */ + @Required + public void setMaxChunkSize(int maxChunkSize) { + this.maxChunkSize = maxChunkSize; + } + + @Override + public boolean isWriteable(Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return type.isAssignableFrom(FileConcatenation.class); + } + + @Override + public long getSize(FileConcatenation fc, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return fc.size(); + } + + @Override + public void writeTo(FileConcatenation fc, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException { + for (File f : fc) + try { + byte[] buffer; + for (int off = 0; true ; off += buffer.length) { + buffer = f.getContents(off, maxChunkSize); + if (buffer == null || buffer.length == 0) + break; + entityStream.write(buffer); + } + } catch (FilesystemAccessException e) { + // Ignore/skip to next file + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java new file mode 100644 index 0000000..0aeb816 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileMessageHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +import static org.apache.commons.logging.LogFactory.getLog; + +import java.io.IOException; +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.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import org.apache.commons.logging.Log; +import org.taverna.server.master.exceptions.FilesystemAccessException; +import org.taverna.server.master.interfaces.File; + +/** + * How to write out a File object with JAX-RS. + * + * @author Donal Fellows + */ +@Provider +public class FileMessageHandler implements MessageBodyWriter<File> { + private Log log = getLog("Taverna.Server.Webapp"); + /** How much to pull from the worker in one read. */ + private int maxChunkSize; + + /** + * @param maxChunkSize + * How much to pull from the worker in one read. + */ + public void setMaxChunkSize(int maxChunkSize) { + this.maxChunkSize = maxChunkSize; + } + + @Override + public boolean isWriteable(Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return File.class.isAssignableFrom(type); + } + + @Override + public long getSize(File t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + try { + return t.getSize(); // Is it really raw bytes? + } catch (FilesystemAccessException e) { + log.info("failed to get file length", e); + return -1; + } + } + + @Override + public void writeTo(File t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException, + WebApplicationException { + try { + int off = 0; + while (true) { + byte[] buffer = t.getContents(off, maxChunkSize); + if (buffer == null || buffer.length == 0) + break; + entityStream.write(buffer); + off += buffer.length; + } + } catch (FilesystemAccessException e) { + throw new IOException("problem when reading file", e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java new file mode 100644 index 0000000..f387cf6 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FileSegmentHandler.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +import static java.lang.Math.min; + +import java.io.IOException; +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.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import org.taverna.server.master.exceptions.FilesystemAccessException; +import org.taverna.server.master.rest.FileSegment; + +/** + * How to write out a segment of a file with JAX-RS. + * + * @author Donal Fellows + */ +@Provider +public class FileSegmentHandler implements MessageBodyWriter<FileSegment> { + /** How much to pull from the worker in one read. */ + private int maxChunkSize; + + /** + * @param maxChunkSize + * How much to pull from the worker in one read. + */ + public void setMaxChunkSize(int maxChunkSize) { + this.maxChunkSize = maxChunkSize; + } + + @Override + public boolean isWriteable(Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return FileSegment.class.isAssignableFrom(type); + } + + @Override + public long getSize(FileSegment t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return t.to - t.from; + } + + @Override + public void writeTo(FileSegment t, Class<?> type, Type genericType, + Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException, + WebApplicationException { + try { + int off = t.from; + while (off < t.to) { + byte[] buffer = t.file.getContents(off, + min(maxChunkSize, t.to - off)); + if (buffer == null || buffer.length == 0) + break; + entityStream.write(buffer); + off += buffer.length; + } + } catch (FilesystemAccessException e) { + throw new IOException("problem when reading file", e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java new file mode 100644 index 0000000..12c137e --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/FilesystemAccessHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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.FilesystemAccessException; + +@Provider +public class FilesystemAccessHandler extends HandlerCore implements + ExceptionMapper<FilesystemAccessException> { + @Override + public Response toResponse(FilesystemAccessException exn) { + return respond(FORBIDDEN, exn); + } +} \ 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/rest/handler/GeneralFailureHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java new file mode 100644 index 0000000..775805b --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/GeneralFailureHandler.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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.master.exceptions.GeneralFailureException; + +public class GeneralFailureHandler extends HandlerCore implements + ExceptionMapper<GeneralFailureException> { + @Override + public Response toResponse(GeneralFailureException exception) { + return respond(INTERNAL_SERVER_ERROR, exception); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java new file mode 100644 index 0000000..0e3fb51 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/HandlerCore.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +import static javax.ws.rs.core.MediaType.TEXT_PLAIN_TYPE; +import static javax.ws.rs.core.Response.status; +import static org.apache.commons.logging.LogFactory.getLog; + +import javax.ws.rs.core.Response; + +import org.apache.commons.logging.Log; +import org.taverna.server.master.api.ManagementModel; + +/** + * Base class for handlers that grants Spring-enabled access to the management + * model. + * + * @author Donal Fellows + */ +public class HandlerCore { + private Log log = getLog("Taverna.Server.Webapp"); + private ManagementModel managementModel; + + /** + * @param managementModel + * the managementModel to set + */ + public void setManagementModel(ManagementModel managementModel) { + this.managementModel = managementModel; + } + + /** + * Simplified interface for building responses. + * + * @param status + * What status code to use? + * @param exception + * What exception to report on? + * @return The build response. + */ + protected Response respond(Response.Status status, Exception exception) { + if (managementModel.getLogOutgoingExceptions() + || status.getStatusCode() >= 500) + log.info("converting exception to response", exception); + return status(status).type(TEXT_PLAIN_TYPE) + .entity(exception.getMessage()).build(); + } + + /** + * Simplified interface for building responses. + * + * @param status + * What status code to use? + * @param partialMessage + * The prefix to the message. + * @param exception + * What exception to report on? + * @return The build response. + */ + protected Response respond(Response.Status status, String partialMessage, + Exception exception) { + if (managementModel.getLogOutgoingExceptions() + || status.getStatusCode() >= 500) + log.info("converting exception to response", exception); + return status(status).type(TEXT_PLAIN_TYPE) + .entity(partialMessage + "\n" + exception.getMessage()).build(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java new file mode 100644 index 0000000..ac02015 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/IllegalArgumentHandler.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java new file mode 100644 index 0000000..1458667 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ImplementationProblemHandler.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java new file mode 100644 index 0000000..2c0c092 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InputStreamMessageHandler.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2010-2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java new file mode 100644 index 0000000..fe11de8 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/InvalidCredentialHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java new file mode 100644 index 0000000..33ac6a0 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/JAXBExceptionHandler.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java new file mode 100644 index 0000000..47153e7 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NegotiationFailedHandler.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java new file mode 100644 index 0000000..e4215a1 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCreateHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java new file mode 100644 index 0000000..d81f6ba --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoCredentialHandler.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java new file mode 100644 index 0000000..927af4b --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDestroyHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java new file mode 100644 index 0000000..ab2e54d --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoDirectoryEntryHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java new file mode 100644 index 0000000..36e3053 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoListenerHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java new file mode 100644 index 0000000..61a89d4 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NoUpdateHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java new file mode 100644 index 0000000..44de871 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/NotOwnerHandler.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java new file mode 100644 index 0000000..21e5e68 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/OverloadedHandler.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2013 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java new file mode 100644 index 0000000..03a4dd4 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/PermissionHandler.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java new file mode 100644 index 0000000..edeac63 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/Scufl2DocumentHandler.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE.txt" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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 uk.org.taverna.scufl2.api.io.ReaderException; +import uk.org.taverna.scufl2.api.io.WorkflowBundleIO; +import uk.org.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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java new file mode 100644 index 0000000..4227d80 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/T2FlowDocumentHandler.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java new file mode 100644 index 0000000..a90a229 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/URIListHandler.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java new file mode 100644 index 0000000..4542237 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/UnknownRunHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2010-2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java new file mode 100644 index 0000000..2241220 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/ZipStreamHandler.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.rest.handler; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java new file mode 100644 index 0000000..e72af22 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/handler/package-info.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * 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; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java new file mode 100644 index 0000000..0a0b069 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/rest/package-info.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +/** + * 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; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java new file mode 100644 index 0000000..bb8d73f --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/DirEntry.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2013 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.soap; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java new file mode 100644 index 0000000..7ebc991 --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/FileContents.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.soap; + +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/2c71f9a9/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java ---------------------------------------------------------------------- diff --git a/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java new file mode 100644 index 0000000..3ab6d0c --- /dev/null +++ b/taverna-server-webapp/src/main/java/org/taverna/server/master/soap/PermissionList.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 The University of Manchester + * + * See the file "LICENSE" for license terms. + */ +package org.taverna.server.master.soap; + +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
