http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java deleted file mode 100644 index c8d7ef6..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/RateLimitedDispatcher.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.notification; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.joda.time.DateTime; -import org.taverna.server.master.interfaces.MessageDispatcher; -import org.taverna.server.master.interfaces.TavernaRun; - -/** - * Rate-limiting support. Some message fabrics simply should not be used to send - * a lot of messages. - * - * @author Donal Fellows - */ -public abstract class RateLimitedDispatcher implements MessageDispatcher { - /** Pre-configured logger. */ - protected Log log = LogFactory.getLog("Taverna.Server.Notification"); - private int cooldownSeconds; - private Map<String, DateTime> lastSend = new HashMap<>(); - - String valid(String value, String def) { - if (value == null || value.trim().isEmpty() - || value.trim().startsWith("${")) - return def; - else - return value.trim(); - } - - /** - * Set how long must elapse between updates to the status of any particular - * user. Calls before that time are just silently dropped. - * - * @param cooldownSeconds - * Time to elapse, in seconds. - */ - public void setCooldownSeconds(int cooldownSeconds) { - this.cooldownSeconds = cooldownSeconds; - } - - /** - * Test whether the rate limiter allows the given user to send a message. - * - * @param who - * Who wants to send the message? - * @return <tt>true</tt> iff they are permitted. - */ - protected boolean isSendAllowed(String who) { - DateTime now = new DateTime(); - synchronized (lastSend) { - DateTime last = lastSend.get(who); - if (last != null) { - if (!now.isAfter(last.plusSeconds(cooldownSeconds))) - return false; - } - lastSend.put(who, now); - } - return true; - } - - @Override - public void dispatch(TavernaRun ignored, String messageSubject, - String messageContent, String target) throws Exception { - if (isSendAllowed(target)) - dispatch(messageSubject, messageContent, target); - } - - /** - * Dispatch a message to a recipient that doesn't care what produced it. - * - * @param messageSubject - * The subject of the message to send. - * @param messageContent - * The plain-text content of the message to send. - * @param target - * A description of where it is to go. - * @throws Exception - * If anything goes wrong. - */ - public abstract void dispatch(String messageSubject, String messageContent, - String target) throws Exception; -}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java deleted file mode 100644 index 5553141..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/SMSDispatcher.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.notification; - -import static org.taverna.server.master.defaults.Default.SMS_GATEWAY_URL; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.message.BasicNameValuePair; -import org.springframework.beans.factory.annotation.Required; - -/** - * Dispatch termination messages via SMS. - * - * @author Donal Fellows - */ -public class SMSDispatcher extends RateLimitedDispatcher { - @Override - public String getName() { - return "sms"; - } - - private CloseableHttpClient client; - private URI service; - private String user = "", pass = ""; - private String usernameField = "username", passwordField = "password", - destinationField = "to", messageField = "text"; - - /** - * @param usernameField - * The name of the field that conveys the sending username; this - * is the <i>server</i>'s identity. - */ - @Required - public void setUsernameField(String usernameField) { - this.usernameField = usernameField; - } - - /** - * @param passwordField - * The field holding the password to authenticate the server to - * the SMS gateway. - */ - @Required - public void setPasswordField(String passwordField) { - this.passwordField = passwordField; - } - - /** - * @param destinationField - * The field holding the number to send the SMS to. - */ - @Required - public void setDestinationField(String destinationField) { - this.destinationField = destinationField; - } - - /** - * @param messageField - * The field holding the plain-text message to send. - */ - @Required - public void setMessageField(String messageField) { - this.messageField = messageField; - } - - public void setService(String serviceURL) { - String s = valid(serviceURL, ""); - if (s.isEmpty()) { - log.warn("did not get sms.service from servlet config; using default (" - + SMS_GATEWAY_URL + ")"); - s = SMS_GATEWAY_URL; - } - try { - service = new URI(s); - } catch (URISyntaxException e) { - service = null; - } - } - - public void setUser(String user) { - this.user = valid(user, ""); - } - - public void setPassword(String pass) { - this.pass = valid(pass, ""); - } - - @PostConstruct - void init() { - client = HttpClientBuilder.create().build(); - } - - @PreDestroy - void close() throws IOException { - try { - if (client != null) - client.close(); - } finally { - client = null; - } - } - - @Override - public boolean isAvailable() { - return service != null && !user.isEmpty() && !pass.isEmpty(); - } - - @Override - public void dispatch(String messageSubject, String messageContent, - String targetParameter) throws Exception { - // Sanity check - if (!targetParameter.matches("[^0-9]+")) - throw new Exception("invalid phone number"); - - if (!isSendAllowed("anyone")) - return; - - // Build the message to send - List<NameValuePair> params = new ArrayList<>(); - params.add(new BasicNameValuePair(usernameField, user)); - params.add(new BasicNameValuePair(passwordField, pass)); - params.add(new BasicNameValuePair(destinationField, targetParameter)); - params.add(new BasicNameValuePair(messageField, messageContent)); - - // Send the message - HttpPost post = new HttpPost(service); - post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); - HttpResponse response = client.execute(post); - - // Log the response - HttpEntity entity = response.getEntity(); - if (entity != null) - try (BufferedReader e = new BufferedReader(new InputStreamReader( - entity.getContent()))) { - log.info(e.readLine()); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java b/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java deleted file mode 100644 index 8ee4815..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/TwitterDispatcher.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.notification; - -import java.util.Properties; - -import twitter4j.Twitter; -import twitter4j.TwitterFactory; -import twitter4j.conf.Configuration; -import twitter4j.conf.PropertyConfiguration; -import twitter4j.auth.AuthorizationFactory; - -/** - * Super simple-minded twitter dispatcher. You need to tell it your consumer key - * and secret as part of the connection parameters, for example via a dispatcher - * URN of "<tt>twitter:fred:bloggs</tt>" where <tt>fred</tt> is the key and - * <tt>bloggs</tt> is the secret. - * - * @author Donal Fellows - */ -public class TwitterDispatcher extends RateLimitedDispatcher { - @Override - public String getName() { - return "twitter"; - } - - public static final int MAX_MESSAGE_LENGTH = 140; - public static final char ELLIPSIS = '\u2026'; - - private String token = ""; - private String secret = ""; - - public void setAccessToken(String token) { - this.token = valid(token, ""); - } - - public void setAccessSecret(String secret) { - this.secret = valid(secret, ""); - } - - private Properties getConfig() throws NotConfiguredException { - if (token.isEmpty() || secret.isEmpty()) - throw new NotConfiguredException(); - Properties p = new Properties(); - p.setProperty(ACCESS_TOKEN_PROP, token); - p.setProperty(ACCESS_SECRET_PROP, secret); - return p; - } - - public static final String ACCESS_TOKEN_PROP = "oauth.accessToken"; - public static final String ACCESS_SECRET_PROP = "oauth.accessTokenSecret"; - - private Twitter getTwitter(String key, String secret) throws Exception { - if (key.isEmpty() || secret.isEmpty()) - throw new NoCredentialsException(); - - Properties p = getConfig(); - p.setProperty("oauth.consumerKey", key); - p.setProperty("oauth.consumerSecret", secret); - - Configuration config = new PropertyConfiguration(p); - TwitterFactory factory = new TwitterFactory(config); - Twitter t = factory.getInstance(AuthorizationFactory - .getInstance(config)); - // Verify that we can connect! - t.getOAuthAccessToken(); - return t; - } - - // TODO: Get secret from credential manager - @Override - public void dispatch(String messageSubject, String messageContent, - String targetParameter) throws Exception { - // messageSubject ignored - String[] target = targetParameter.split(":", 2); - if (target == null || target.length != 2) - throw new Exception("missing consumer key or secret"); - String who = target[0]; - if (!isSendAllowed(who)) - return; - Twitter twitter = getTwitter(who, target[1]); - - if (messageContent.length() > MAX_MESSAGE_LENGTH) - messageContent = messageContent - .substring(0, MAX_MESSAGE_LENGTH - 1) + ELLIPSIS; - twitter.updateStatus(messageContent); - } - - @Override - public boolean isAvailable() { - try { - // Try to create the configuration and push it through as far as - // confirming that we can build an access object (even if it isn't - // bound to a user) - new TwitterFactory(new PropertyConfiguration(getConfig())) - .getInstance(); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Indicates that the dispatcher has not been configured with service - * credentials. - * - * @author Donal Fellows - */ - @SuppressWarnings("serial") - public static class NotConfiguredException extends Exception { - NotConfiguredException() { - super("not configured with xAuth key and secret; " - + "dispatch not possible"); - } - } - - /** - * Indicates that the user did not supply their credentials. - * - * @author Donal Fellows - */ - @SuppressWarnings("serial") - public static class NoCredentialsException extends Exception { - NoCredentialsException() { - super("no consumer key and secret present; " - + "dispatch not possible"); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java deleted file mode 100644 index e5beaeb..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/AtomFeed.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.notification.atom; - -import static java.lang.String.format; -import static java.util.UUID.randomUUID; -import static javax.ws.rs.core.UriBuilder.fromUri; -import static org.taverna.server.master.common.Roles.USER; -import static org.taverna.server.master.common.Uri.secure; - -import java.net.URI; -import java.util.Date; - -import javax.annotation.security.RolesAllowed; -import javax.servlet.ServletContext; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - -import org.apache.abdera.Abdera; -import org.apache.abdera.model.Entry; -import org.apache.abdera.model.Feed; -import org.springframework.beans.factory.annotation.Required; -import org.springframework.web.context.ServletContextAware; -import org.taverna.server.master.TavernaServerSupport; -import org.taverna.server.master.interfaces.TavernaRun; -import org.taverna.server.master.interfaces.UriBuilderFactory; -import org.taverna.server.master.rest.TavernaServerREST.EventFeed; -import org.taverna.server.master.utils.InvocationCounter.CallCounted; - -/** - * Simple REST handler that allows an Atom feed to be served up of events - * generated by workflow runs. - * - * @author Donal Fellows - */ -public class AtomFeed implements EventFeed, UriBuilderFactory, - ServletContextAware { - /** - * The name of a parameter that states what address we should claim that the - * feed's internally-generated URIs are relative to. If not set, a default - * will be guessed. - */ - public static final String PREFERRED_URI_PARAM = "taverna.preferredUserUri"; - private EventDAO eventSource; - private TavernaServerSupport support; - private URI baseURI; - private Abdera abdera; - private String feedLanguage = "en"; - private String uuid = randomUUID().toString(); - - @Required - public void setEventSource(EventDAO eventSource) { - this.eventSource = eventSource; - } - - @Required - public void setSupport(TavernaServerSupport support) { - this.support = support; - } - - public void setFeedLanguage(String language) { - this.feedLanguage = language; - } - - public String getFeedLanguage() { - return feedLanguage; - } - - @Required - public void setAbdera(Abdera abdera) { - this.abdera = abdera; - } - - @Override - @CallCounted - @RolesAllowed(USER) - public Feed getFeed(UriInfo ui) { - Feed feed = abdera.getFactory().newFeed(); - feed.setTitle("events relating to workflow runs").setLanguage( - feedLanguage); - String user = support.getPrincipal().toString() - .replaceAll("[^A-Za-z0-9]+", ""); - feed.setId(format("urn:taverna-server:%s:%s", uuid, user)); - org.joda.time.DateTime modification = null; - for (Event e : eventSource.getEvents(support.getPrincipal())) { - if (modification == null || e.getPublished().isAfter(modification)) - modification = e.getPublished(); - feed.addEntry(e.getEntry(abdera, feedLanguage)); - } - if (modification == null) - feed.setUpdated(new Date()); - else - feed.setUpdated(modification.toDate()); - feed.addLink(ui.getAbsolutePath().toASCIIString(), "self"); - return feed; - } - - @Override - @CallCounted - @RolesAllowed(USER) - public Entry getEvent(String id) { - return eventSource.getEvent(support.getPrincipal(), id).getEntry( - abdera, feedLanguage); - } - - @Override - public UriBuilder getRunUriBuilder(TavernaRun run) { - return secure(fromUri(getBaseUriBuilder().path("runs/{uuid}").build( - run.getId()))); - } - - @Override - public UriBuilder getBaseUriBuilder() { - return secure(fromUri(baseURI)); - } - - @Override - public String resolve(String uri) { - if (uri == null) - return null; - return secure(baseURI, uri).toString(); - } - - @Override - public void setServletContext(ServletContext servletContext) { - String base = servletContext.getInitParameter(PREFERRED_URI_PARAM); - if (base == null) - base = servletContext.getContextPath() + "/rest"; - baseURI = URI.create(base); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java deleted file mode 100644 index 825029d..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/Event.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.notification.atom; - -import static java.util.UUID.randomUUID; - -import java.io.Serializable; -import java.net.URI; -import java.util.Date; - -import javax.jdo.annotations.Column; -import javax.jdo.annotations.Index; -import javax.jdo.annotations.PersistenceCapable; -import javax.jdo.annotations.Persistent; -import javax.jdo.annotations.Queries; -import javax.jdo.annotations.Query; - -import org.apache.abdera.Abdera; -import org.apache.abdera.model.Entry; -import org.joda.time.DateTime; -import org.taverna.server.master.utils.UsernamePrincipal; - -/** - * Parent class of all events that may appear on the feed for a workflow run. - * - * @author Donal Fellows - */ -@SuppressWarnings("serial") -@PersistenceCapable(schema = "ATOM", table = "EVENTS") -@Queries({ - @Query(name = "eventsForUser", language = "SQL", value = "SELECT id FROM ATOM.EVENTS WHERE owner = ? ORDER BY published DESC", resultClass = String.class), - @Query(name = "eventForUserAndId", language = "SQL", value = "SELECT id FROM ATOM.EVENTS WHERE owner = ? AND id = ?", resultClass = String.class), - @Query(name = "eventsFromBefore", language = "SQL", value = "SELECT id FROM ATOM.EVENTS where published < ?", resultClass = String.class) }) -public class Event implements Serializable { - @Persistent(primaryKey = "true") - @Column(length = 48) - private String id; - @Persistent - private String owner; - @Persistent - @Index - private Date published; - @Persistent - private String message; - @Persistent - private String title; - @Persistent - private String link; - - Event() { - } - - /** - * Initialise the identity of this event and the point at which it was - * published. - * - * @param idPrefix - * A prefix for the identity of this event. - * @param owner - * Who is the owner of this event. - */ - Event(String idPrefix, URI workflowLink, UsernamePrincipal owner, - String title, String message) { - id = idPrefix + "." + randomUUID().toString(); - published = new Date(); - this.owner = owner.getName(); - this.title = title; - this.message = message; - this.link = workflowLink.toASCIIString(); - } - - public final String getId() { - return id; - } - - public final String getOwner() { - return owner; - } - - public final DateTime getPublished() { - return new DateTime(published); - } - - public String getMessage() { - return message; - } - - public String getTitle() { - return title; - } - - public String getLink() { - return link; - } - - public Entry getEntry(Abdera abdera, String language) { - Entry entry = abdera.getFactory().newEntry(); - entry.setId(id); - entry.setPublished(published); - entry.addAuthor(owner).setLanguage(language); - entry.setUpdated(published); - entry.setTitle(title).setLanguage(language); - entry.addLink(link, "related").setTitle("workflow run"); - entry.setContent(message).setLanguage(language); - return entry; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java deleted file mode 100644 index 56f25ff..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/EventDAO.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.notification.atom; - -import static java.lang.Thread.interrupted; -import static java.lang.Thread.sleep; -import static java.util.Arrays.asList; - -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; - -import javax.annotation.Nonnull; -import javax.annotation.PreDestroy; -import javax.jdo.annotations.PersistenceAware; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.joda.time.DateTime; -import org.springframework.beans.factory.annotation.Required; -import org.taverna.server.master.interfaces.MessageDispatcher; -import org.taverna.server.master.interfaces.TavernaRun; -import org.taverna.server.master.interfaces.UriBuilderFactory; -import org.taverna.server.master.utils.JDOSupport; -import org.taverna.server.master.utils.UsernamePrincipal; - -/** - * The database interface that supports the event feed. - * - * @author Donal Fellows - */ -@PersistenceAware -public class EventDAO extends JDOSupport<Event> implements MessageDispatcher { - public EventDAO() { - super(Event.class); - } - - @Override - public String getName() { - return "atom"; - } - - private Log log = LogFactory.getLog("Taverna.Server.Atom"); - private UriBuilderFactory ubf; - private int expiryAgeDays; - - @Required - public void setExpiryAgeDays(int expiryAgeDays) { - this.expiryAgeDays = expiryAgeDays; - } - - @Required - public void setUriBuilderFactory(UriBuilderFactory ubf) { - this.ubf = ubf; - } - - /** - * Get the given user's list of events. - * - * @param user - * The identity of the user to get the events for. - * @return A copy of the list of events currently known about. - */ - @Nonnull - @WithinSingleTransaction - public List<Event> getEvents(@Nonnull UsernamePrincipal user) { - @SuppressWarnings("unchecked") - List<String> ids = (List<String>) namedQuery("eventsForUser").execute( - user.getName()); - if (log.isDebugEnabled()) - log.debug("found " + ids.size() + " events for user " + user); - - List<Event> result = new ArrayList<>(); - for (String id : ids) { - Event event = getById(id); - result.add(detach(event)); - } - return result; - } - - /** - * Get a particular event. - * - * @param user - * The identity of the user to get the event for. - * @param id - * The handle of the event to look up. - * @return A copy of the event. - */ - @Nonnull - @WithinSingleTransaction - public Event getEvent(@Nonnull UsernamePrincipal user, @Nonnull String id) { - @SuppressWarnings("unchecked") - List<String> ids = (List<String>) namedQuery("eventForUserAndId") - .execute(user.getName(), id); - if (log.isDebugEnabled()) - log.debug("found " + ids.size() + " events for user " + user - + " with id = " + id); - - if (ids.size() != 1) - throw new IllegalArgumentException("no such id"); - return detach(getById(ids.get(0))); - } - - /** - * Delete a particular event. - * - * @param id - * The identifier of the event to delete. - */ - @WithinSingleTransaction - public void deleteEventById(@Nonnull String id) { - delete(getById(id)); - } - - /** - * Delete all events that have expired. - */ - @WithinSingleTransaction - public void deleteExpiredEvents() { - Date death = new DateTime().plusDays(-expiryAgeDays).toDate(); - death = new Timestamp(death.getTime()); // UGLY SQL HACK - - @SuppressWarnings("unchecked") - List<String> ids = (List<String>) namedQuery("eventsFromBefore") - .execute(death); - if (log.isDebugEnabled() && !ids.isEmpty()) - log.debug("found " + ids.size() - + " events to be squelched (older than " + death + ")"); - - for (String id : ids) - delete(getById(id)); - } - - @Override - public boolean isAvailable() { - return true; - } - - private BlockingQueue<Event> insertQueue = new ArrayBlockingQueue<>(16); - - @Override - public void dispatch(TavernaRun originator, String messageSubject, - String messageContent, String targetParameter) throws Exception { - insertQueue.put(new Event("finish", ubf.getRunUriBuilder(originator) - .build(), originator.getSecurityContext().getOwner(), - messageSubject, messageContent)); - } - - public void started(TavernaRun originator, String messageSubject, - String messageContent) throws InterruptedException { - insertQueue.put(new Event("start", ubf.getRunUriBuilder(originator) - .build(), originator.getSecurityContext().getOwner(), - messageSubject, messageContent)); - } - - private Thread eventDaemon; - private boolean shuttingDown = false; - - @Required - public void setSelf(final EventDAO dao) { - eventDaemon = new Thread(new Runnable() { - @Override - public void run() { - try { - while (!shuttingDown && !interrupted()) { - transferEvents(dao, new ArrayList<Event>( - asList(insertQueue.take()))); - sleep(5000); - } - } catch (InterruptedException e) { - } finally { - transferEvents(dao, new ArrayList<Event>()); - } - } - }, "ATOM event daemon"); - eventDaemon.setContextClassLoader(null); - eventDaemon.setDaemon(true); - eventDaemon.start(); - } - - private void transferEvents(EventDAO dao, List<Event> e) { - insertQueue.drainTo(e); - dao.storeEvents(e); - } - - @PreDestroy - void stopDaemon() { - shuttingDown = true; - if (eventDaemon != null) - eventDaemon.interrupt(); - } - - @WithinSingleTransaction - protected void storeEvents(List<Event> events) { - for (Event e : events) - persist(e); - log.info("stored " + events.size() + " notification events"); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java deleted file mode 100644 index 9cc592d..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/atom/package-info.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -/** - * This package contains the Atom feed implementation within Taverna Server. - * @author Donal Fellows - */ -@XmlSchema(namespace = FEED, elementFormDefault = QUALIFIED, attributeFormDefault = QUALIFIED, xmlns = { - @XmlNs(prefix = "xlink", namespaceURI = XLINK), - @XmlNs(prefix = "ts", namespaceURI = SERVER), - @XmlNs(prefix = "ts-rest", namespaceURI = SERVER_REST), - @XmlNs(prefix = "ts-soap", namespaceURI = SERVER_SOAP), - @XmlNs(prefix = "feed", namespaceURI = FEED), - @XmlNs(prefix = "admin", namespaceURI = ADMIN) }) -package org.taverna.server.master.notification.atom; - -import static javax.xml.bind.annotation.XmlNsForm.QUALIFIED; -import static org.taverna.server.master.common.Namespaces.ADMIN; -import static org.taverna.server.master.common.Namespaces.FEED; -import static org.taverna.server.master.common.Namespaces.SERVER; -import static org.taverna.server.master.common.Namespaces.SERVER_REST; -import static org.taverna.server.master.common.Namespaces.SERVER_SOAP; -import static org.taverna.server.master.common.Namespaces.XLINK; - -import javax.xml.bind.annotation.XmlNs; -import javax.xml.bind.annotation.XmlSchema; - http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java deleted file mode 100644 index 979066a..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/notification/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -/** - * The notification fabric and implementations of notification dispatchers - * that support subscription. - */ -package org.taverna.server.master.notification; http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/package-info.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/package-info.java b/server-webapp/src/main/java/org/taverna/server/master/package-info.java deleted file mode 100644 index 17bfd03..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -/** - * The core of the implementation of Taverna Server, including the - * implementations of the SOAP and REST interfaces. - */ -package org.taverna.server.master; - http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java b/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java deleted file mode 100644 index b0819a5..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/ContentTypes.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2013 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static javax.ws.rs.core.MediaType.APPLICATION_ATOM_XML; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM; -import static javax.ws.rs.core.MediaType.APPLICATION_XML; -import static javax.ws.rs.core.MediaType.TEXT_PLAIN; - -/** - * Miscellaneous content type constants. - * - * @author Donal Fellows - */ -interface ContentTypes { - static final String URI_LIST = "text/uri-list"; - static final String ZIP = "application/zip"; - static final String TEXT = TEXT_PLAIN; - static final String XML = APPLICATION_XML; - static final String JSON = APPLICATION_JSON; - static final String BYTES = APPLICATION_OCTET_STREAM; - static final String ATOM = APPLICATION_ATOM_XML; - static final String ROBUNDLE = "application/vnd.wf4ever.robundle+zip"; -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java b/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java deleted file mode 100644 index e01d1c4..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/DirectoryContents.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static org.taverna.server.master.common.Uri.secure; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSeeAlso; -import javax.xml.bind.annotation.XmlType; - -import org.taverna.server.master.common.DirEntryReference; -import org.taverna.server.master.interfaces.DirectoryEntry; - -/** - * The result of a RESTful operation to list the contents of a directory. Done - * with JAXB. - * - * @author Donal Fellows - */ -@XmlRootElement -@XmlType(name = "DirectoryContents") -@XmlSeeAlso(MakeOrUpdateDirEntry.class) -public class DirectoryContents { - /** - * The contents of the directory. - */ - @XmlElementRef - public List<DirEntryReference> contents; - - /** - * Make an empty directory description. Required for JAXB. - */ - public DirectoryContents() { - contents = new ArrayList<>(); - } - - /** - * Make a directory description. - * - * @param ui - * The factory for URIs. - * @param collection - * The real directory contents that we are to describe. - */ - public DirectoryContents(UriInfo ui, Collection<DirectoryEntry> collection) { - contents = new ArrayList<>(); - UriBuilder ub = secure(ui).path("{filename}"); - for (DirectoryEntry e : collection) - contents.add(DirEntryReference.newInstance(ub, e)); - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java b/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java deleted file mode 100644 index 74269c1..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/FileSegment.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static javax.ws.rs.core.Response.ok; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.taverna.server.master.exceptions.FilesystemAccessException; -import org.taverna.server.master.interfaces.File; - -/** - * Representation of a segment of a file to be read by JAX-RS. - * - * @author Donal Fellows - */ -public class FileSegment { - /** The file to read a segment of. */ - public final File file; - /** The offset of the first byte of the segment to read. */ - public Integer from; - /** The offset of the first byte after the segment to read. */ - public Integer to; - - /** - * Parse the HTTP Range header and determine what exact range of the file to - * read. - * - * @param f - * The file this refers to - * @param range - * The content of the Range header. - * @throws FilesystemAccessException - * If we can't determine the length of the file (shouldn't - * happen). - */ - public FileSegment(File f, String range) throws FilesystemAccessException { - file = f; - Matcher m = Pattern.compile("^\\s*bytes=(\\d*)-(\\d*)\\s*$").matcher( - range); - if (m.matches()) { - if (!m.group(1).isEmpty()) - from = Integer.valueOf(m.group(1)); - if (!m.group(2).isEmpty()) - to = Integer.valueOf(m.group(2)) + 1; - int size = (int) f.getSize(); - if (from == null) { - from = size - to; - to = size; - } else if (to == null) - to = size; - else if (to > size) - to = size; - } - } - - /** - * Convert to a response, as per RFC 2616. - * - * @param type - * The expected type of the data. - * @return A JAX-RS response. - */ - public Response toResponse(MediaType type) { - if (from == null && to == null) - return ok(file).type(type).build(); - if (from >= to) - return ok("Requested range not satisfiable").status(416).build(); - return ok(this).status(206).type(type).build(); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java deleted file mode 100644 index b9b4718..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/InteractionFeedREST.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2013 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static org.taverna.server.master.rest.ContentTypes.ATOM; - -import java.net.MalformedURLException; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.OPTIONS; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Response; - -import org.apache.abdera.model.Entry; -import org.apache.abdera.model.Feed; -import org.apache.cxf.jaxrs.model.wadl.Description; -import org.taverna.server.master.exceptions.FilesystemAccessException; -import org.taverna.server.master.exceptions.NoDirectoryEntryException; -import org.taverna.server.master.exceptions.NoUpdateException; - -/** - * A very stripped down ATOM feed for the interaction service. - * - * @author Donal Fellows - */ -public interface InteractionFeedREST { - /** - * Get the feed document for this ATOM feed. - * - * @return The feed. - * @throws FilesystemAccessException - * If we can't read from the feed directory. - * @throws NoDirectoryEntryException - * If something changes things under our feet. - */ - @GET - @Path("/") - @Produces(ATOM) - @Description("Get the feed document for this ATOM feed.") - Feed getFeed() throws FilesystemAccessException, NoDirectoryEntryException; - - /** - * Adds an entry to this ATOM feed. - * - * @param entry - * The entry to create. - * @return A redirect to the created entry. - * @throws MalformedURLException - * If we have problems generating the URI of the entry. - * @throws FilesystemAccessException - * If we can't create the feed entry file. - * @throws NoDirectoryEntryException - * If things get changed under our feet. - * @throws NoUpdateException - * If we don't have permission to change things relating to this - * run. - */ - @POST - @Path("/") - @Consumes(ATOM) - @Produces(ATOM) - @Description("Adds an entry to this ATOM feed.") - Response addEntry(Entry entry) throws MalformedURLException, - FilesystemAccessException, NoDirectoryEntryException, - NoUpdateException; - - /** Handles the OPTIONS request. */ - @OPTIONS - @Path("/") - @Description("Describes what HTTP operations are supported on the feed.") - Response feedOptions(); - - /** - * Gets the content of an entry in this ATOM feed. - * - * @param id - * The ID of the entry to fetch. - * @return The entry contents. - * @throws FilesystemAccessException - * If we have problems reading the entry. - * @throws NoDirectoryEntryException - * If we can't find the entry to read. - */ - @GET - @Path("{id}") - @Produces(ATOM) - @Description("Get the entry with a particular ID within this ATOM feed.") - Entry getEntry(@PathParam("id") String id) - throws FilesystemAccessException, NoDirectoryEntryException; - - /** - * Delete an entry from this ATOM feed. - * - * @param id - * The ID of the entry to delete. - * @return A simple message. Not very important! - * @throws FilesystemAccessException - * If we have problems deleting the entry. - * @throws NoDirectoryEntryException - * If we can't find the entry to delete. - * @throws NoUpdateException - * If we don't have permission to alter things relating to this - * run. - */ - @DELETE - @Path("{id}") - @Produces("text/plain") - @Description("Deletes an entry from this ATOM feed.") - String deleteEntry(@PathParam("id") String id) - throws FilesystemAccessException, NoDirectoryEntryException, - NoUpdateException; - - /** Handles the OPTIONS request. */ - @OPTIONS - @Path("{id}") - @Description("Describes what HTTP operations are supported on an entry.") - Response entryOptions(@PathParam("{id}") String id); -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java b/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java deleted file mode 100644 index 7a072be..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/ListenerDefinition.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.XmlValue; - -/** - * Description of what sort of event listener to create and attach to a workflow - * run. Bound via JAXB. - * - * @author Donal Fellows - */ -@XmlRootElement(name = "listenerDefinition") -@XmlType(name="ListenerDefinition") -public class ListenerDefinition { - /** - * The type of event listener to create. - */ - @XmlAttribute - public String type; - /** - * How the event listener should be configured. - */ - @XmlValue - public String configuration; -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java b/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java deleted file mode 100644 index 0138f88..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/MakeOrUpdateDirEntry.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSeeAlso; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.XmlValue; - -/** - * The input to the REST interface for making directories and files, and - * uploading file contents. Done with JAXB. - * - * @author Donal Fellows - */ -@XmlRootElement(name = "filesystemOperation") -@XmlType(name = "FilesystemCreationOperation") -@XmlSeeAlso( { MakeOrUpdateDirEntry.MakeDirectory.class, - MakeOrUpdateDirEntry.SetFileContents.class }) -public abstract class MakeOrUpdateDirEntry { - /** - * The name of the file or directory that the operation applies to. - */ - @XmlAttribute - public String name; - /** - * The contents of the file to upload. - */ - @XmlValue - public byte[] contents; - - /** - * Create a directory, described with JAXB. Should leave the - * {@link MakeOrUpdateDirEntry#contents contents} field empty. - * - * @author Donal Fellows - */ - @XmlRootElement(name = "mkdir") - @XmlType(name = "MakeDirectory") - public static class MakeDirectory extends MakeOrUpdateDirEntry { - } - - /** - * Create a file or set its contents, described with JAXB. - * - * @author Donal Fellows - */ - @XmlRootElement(name = "upload") - @XmlType(name = "UploadFile") - public static class SetFileContents extends MakeOrUpdateDirEntry { - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java deleted file mode 100644 index ea2f776..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerDirectoryREST.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2010-2013 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static java.util.Collections.unmodifiableList; -import static javax.ws.rs.core.MediaType.WILDCARD; -import static org.taverna.server.master.common.Roles.USER; -import static org.taverna.server.master.rest.ContentTypes.BYTES; -import static org.taverna.server.master.rest.ContentTypes.JSON; -import static org.taverna.server.master.rest.ContentTypes.URI_LIST; -import static org.taverna.server.master.rest.ContentTypes.XML; -import static org.taverna.server.master.rest.ContentTypes.ZIP; - -import java.io.InputStream; -import java.net.URI; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.security.RolesAllowed; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.OPTIONS; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.PathSegment; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import javax.ws.rs.core.Variant; - -import org.apache.cxf.jaxrs.model.wadl.Description; -import org.taverna.server.master.exceptions.FilesystemAccessException; -import org.taverna.server.master.exceptions.NoDirectoryEntryException; -import org.taverna.server.master.exceptions.NoUpdateException; -import org.taverna.server.master.interfaces.Directory; -import org.taverna.server.master.interfaces.File; - -/** - * Representation of how a workflow run's working directory tree looks. - * - * @author Donal Fellows - */ -@RolesAllowed(USER) -@Produces({ XML, JSON }) -@Consumes({ XML, JSON }) -@Description("Representation of how a workflow run's working directory tree looks.") -public interface TavernaServerDirectoryREST { - /** - * Get the working directory of the workflow run. - * - * @param ui - * About how this method was called. - * @return A description of the working directory. - * @throws FilesystemAccessException - */ - @GET - @Path("/") - @Description("Describes the working directory of the workflow run.") - @Nonnull - DirectoryContents getDescription(@Nonnull @Context UriInfo ui) - throws FilesystemAccessException; - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("{path:.*}") - @Description("Produces the description of the files/directories' baclava operations.") - Response options(@PathParam("path") List<PathSegment> path); - - /** - * Gets a description of the named entity in or beneath the working - * directory of the workflow run, which may be either a {@link Directory} or - * a {@link File}. - * - * @param path - * The path to the thing to describe. - * @param ui - * About how this method was called. - * @param headers - * About what the caller was looking for. - * @return An HTTP response containing a description of the named thing. - * @throws NoDirectoryEntryException - * If the name of the file or directory can't be looked up. - * @throws FilesystemAccessException - * If something went wrong during the filesystem operation. - * @throws NegotiationFailedException - * If the content type being downloaded isn't one that this - * method can support. - */ - @GET - @Path("{path:.+}") - @Produces({ XML, JSON, BYTES, ZIP, WILDCARD }) - @Description("Gives a description of the named entity in or beneath the " - + "working directory of the workflow run (either a Directory or File).") - @Nonnull - Response getDirectoryOrFileContents( - @Nonnull @PathParam("path") List<PathSegment> path, - @Nonnull @Context UriInfo ui, @Nonnull @Context HttpHeaders headers) - throws NoDirectoryEntryException, FilesystemAccessException, - NegotiationFailedException; - - /** - * Creates a directory in the filesystem beneath the working directory of - * the workflow run, or creates or updates a file's contents, where that - * file is in or below the working directory of a workflow run. - * - * @param parent - * The directory to create the directory in. - * @param operation - * What to call the directory to create. - * @param ui - * About how this method was called. - * @return An HTTP response indicating where the directory was actually made - * or what file was created/updated. - * @throws NoDirectoryEntryException - * If the name of the containing directory can't be looked up. - * @throws NoUpdateException - * If the user is not permitted to update the run. - * @throws FilesystemAccessException - * If something went wrong during the filesystem operation. - */ - @POST - @Path("{path:.*}") - @Description("Creates a directory in the filesystem beneath the working " - + "directory of the workflow run, or creates or updates a file's " - + "contents, where that file is in or below the working directory " - + "of a workflow run.") - @Nonnull - Response makeDirectoryOrUpdateFile( - @Nonnull @PathParam("path") List<PathSegment> parent, - @Nonnull MakeOrUpdateDirEntry operation, - @Nonnull @Context UriInfo ui) throws NoUpdateException, - FilesystemAccessException, NoDirectoryEntryException; - - /** - * Creates or updates a file in a particular location beneath the working - * directory of the workflow run. - * - * @param file - * The path to the file to create or update. - * @param referenceList - * Location to get the file's contents from. Must be - * <i>publicly</i> readable. - * @param ui - * About how this method was called. - * @return An HTTP response indicating what file was created/updated. - * @throws NoDirectoryEntryException - * If the name of the containing directory can't be looked up. - * @throws NoUpdateException - * If the user is not permitted to update the run. - * @throws FilesystemAccessException - * If something went wrong during the filesystem operation. - */ - @POST - @Path("{path:(.*)}") - @Consumes(URI_LIST) - @Description("Creates or updates a file in a particular location beneath the " - + "working directory of the workflow run with the contents of a " - + "publicly readable URL.") - @Nonnull - Response setFileContentsFromURL(@PathParam("path") List<PathSegment> file, - List<URI> referenceList, @Context UriInfo ui) - throws NoDirectoryEntryException, NoUpdateException, - FilesystemAccessException; - - /** - * Creates or updates a file in a particular location beneath the working - * directory of the workflow run. - * - * @param file - * The path to the file to create or update. - * @param contents - * Stream of bytes to set the file's contents to. - * @param ui - * About how this method was called. - * @return An HTTP response indicating what file was created/updated. - * @throws NoDirectoryEntryException - * If the name of the containing directory can't be looked up. - * @throws NoUpdateException - * If the user is not permitted to update the run. - * @throws FilesystemAccessException - * If something went wrong during the filesystem operation. - */ - @PUT - @Path("{path:(.*)}") - @Consumes({ BYTES, WILDCARD }) - @Description("Creates or updates a file in a particular location beneath the " - + "working directory of the workflow run.") - @Nonnull - Response setFileContents(@PathParam("path") List<PathSegment> file, - InputStream contents, @Context UriInfo ui) - throws NoDirectoryEntryException, NoUpdateException, - FilesystemAccessException; - - /** - * Deletes a file or directory that is in or below the working directory of - * a workflow run. - * - * @param path - * The path to the file or directory. - * @return An HTTP response to the method. - * @throws NoUpdateException - * If the user is not permitted to update the run. - * @throws FilesystemAccessException - * If something went wrong during the filesystem operation. - * @throws NoDirectoryEntryException - * If the name of the file or directory can't be looked up. - */ - @DELETE - @Path("{path:.*}") - @Description("Deletes a file or directory that is in or below the working " - + "directory of a workflow run.") - @Nonnull - Response destroyDirectoryEntry(@PathParam("path") List<PathSegment> path) - throws NoUpdateException, FilesystemAccessException, - NoDirectoryEntryException; - - /** - * Exception thrown to indicate a failure by the client to provide an - * acceptable content type. - * - * @author Donal Fellows - */ - @SuppressWarnings("serial") - public static class NegotiationFailedException extends Exception { - public List<Variant> accepted; - - public NegotiationFailedException(String msg, List<Variant> accepted) { - super(msg); - this.accepted = unmodifiableList(accepted); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java deleted file mode 100644 index faed19d..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerInputREST.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static org.taverna.server.master.common.Roles.USER; -import static org.taverna.server.master.rest.ContentTypes.JSON; -import static org.taverna.server.master.rest.ContentTypes.TEXT; -import static org.taverna.server.master.rest.ContentTypes.XML; -import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.BACLAVA; -import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.EXPECTED; -import static org.taverna.server.master.rest.TavernaServerInputREST.PathNames.ONE_INPUT; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.security.RolesAllowed; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.OPTIONS; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.PathSegment; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElements; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.bind.annotation.XmlValue; - -import org.apache.cxf.jaxrs.model.wadl.Description; -import org.taverna.server.master.common.Uri; -import org.taverna.server.master.common.VersionedElement; -import org.taverna.server.master.exceptions.BadInputPortNameException; -import org.taverna.server.master.exceptions.BadPropertyValueException; -import org.taverna.server.master.exceptions.BadStateChangeException; -import org.taverna.server.master.exceptions.FilesystemAccessException; -import org.taverna.server.master.exceptions.NoUpdateException; -import org.taverna.server.master.interfaces.Input; -import org.taverna.server.master.interfaces.TavernaRun; -import org.taverna.server.port_description.InputDescription; - -/** - * This represents how a Taverna Server workflow run's inputs looks to a RESTful - * API. - * - * @author Donal Fellows. - */ -@RolesAllowed(USER) -@Description("This represents how a Taverna Server workflow run's inputs " - + "looks to a RESTful API.") -public interface TavernaServerInputREST { - /** - * @return A description of the various URIs to inputs associated with a - * workflow run. - */ - @GET - @Path("/") - @Produces({ XML, JSON }) - @Description("Describe the sub-URIs of this resource.") - @Nonnull - InputsDescriptor get(); - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("/") - @Description("Produces the description of one run's inputs' operations.") - Response options(); - - /** - * @return A description of the various URIs to inputs associated with a - * workflow run. - */ - @GET - @Path(EXPECTED) - @Produces({ XML, JSON }) - @Description("Describe the expected inputs of this workflow run.") - @Nonnull - InputDescription getExpected(); - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path(EXPECTED) - @Description("Produces the description of the expected inputs' operations.") - Response expectedOptions(); - - /** - * @return The Baclava file that will supply all the inputs to the workflow - * run, or empty to indicate that no such file is specified. - */ - @GET - @Path(BACLAVA) - @Produces(TEXT) - @Description("Gives the Baclava file describing the inputs, or empty if " - + "individual files are used.") - @Nonnull - String getBaclavaFile(); - - /** - * Set the Baclava file that will supply all the inputs to the workflow run. - * - * @param filename - * The filename to set. - * @return The name of the Baclava file that was actually set. - * @throws NoUpdateException - * If the user can't update the run. - * @throws BadStateChangeException - * If the run is not Initialized. - * @throws FilesystemAccessException - * If the filename starts with a <tt>/</tt> or if it contains a - * <tt>..</tt> segment. - */ - @PUT - @Path(BACLAVA) - @Consumes(TEXT) - @Produces(TEXT) - @Description("Sets the Baclava file describing the inputs.") - @Nonnull - String setBaclavaFile(@Nonnull String filename) throws NoUpdateException, - BadStateChangeException, FilesystemAccessException; - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path(BACLAVA) - @Description("Produces the description of the inputs' baclava operations.") - Response baclavaOptions(); - - /** - * Get what input is set for the specific input. - * - * @param name - * The input to set. - * @param uriInfo - * About the URI used to access this resource. - * @return A description of the input. - * @throws BadInputPortNameException - * If no input with that name exists. - */ - @GET - @Path(ONE_INPUT) - @Produces({ XML, JSON }) - @Description("Gives a description of what is used to supply a particular " - + "input.") - @Nonnull - InDesc getInput(@Nonnull @PathParam("name") String name, - @Context UriInfo uriInfo) throws BadInputPortNameException; - - /** - * Set what an input uses to provide data into the workflow run. - * - * @param name - * The name of the input. - * @param inputDescriptor - * A description of the input - * @param uriInfo - * About the URI used to access this resource. - * @return A description of the input. - * @throws NoUpdateException - * If the user can't update the run. - * @throws BadStateChangeException - * If the run is not Initialized. - * @throws FilesystemAccessException - * If a filename is being set and the filename starts with a - * <tt>/</tt> or if it contains a <tt>..</tt> segment. - * @throws BadInputPortNameException - * If no input with that name exists. - * @throws BadPropertyValueException - * If some bad misconfiguration has happened. - */ - @PUT - @Path(ONE_INPUT) - @Consumes({ XML, JSON }) - @Produces({ XML, JSON }) - @Description("Sets the source for a particular input port.") - @Nonnull - InDesc setInput(@Nonnull @PathParam("name") String name, - @Nonnull InDesc inputDescriptor, @Context UriInfo uriInfo) throws NoUpdateException, - BadStateChangeException, FilesystemAccessException, - BadPropertyValueException, BadInputPortNameException; - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path(ONE_INPUT) - @Description("Produces the description of the one input's operations.") - Response inputOptions(@PathParam("name") String name); - - interface PathNames { - final String EXPECTED = "expected"; - final String BACLAVA = "baclava"; - final String ONE_INPUT = "input/{name}"; - } - - /** - * A description of the structure of inputs to a Taverna workflow run, done - * with JAXB. - * - * @author Donal Fellows - */ - @XmlRootElement(name = "runInputs") - @XmlType(name = "TavernaRunInputs") - public static class InputsDescriptor extends VersionedElement { - /** - * Where to find a description of the expected inputs to this workflow - * run. - */ - public Uri expected; - /** - * Where to find the overall Baclava document filename (if set). - */ - public Uri baclava; - /** - * Where to find the details of inputs to particular ports (if set). - */ - public List<Uri> input; - - /** - * Make a blank description of the inputs. - */ - public InputsDescriptor() { - } - - /** - * Make the description of the inputs. - * - * @param ui - * Information about the URIs to generate. - * @param run - * The run whose inputs are to be described. - */ - public InputsDescriptor(UriInfo ui, TavernaRun run) { - super(true); - expected = new Uri(ui, EXPECTED); - baclava = new Uri(ui, BACLAVA); - input = new ArrayList<>(); - for (Input i : run.getInputs()) - input.add(new Uri(ui, ONE_INPUT, i.getName())); - } - } - - /** - * The Details of a particular input port's value assignment, done with - * JAXB. - * - * @author Donal Fellows - */ - @XmlRootElement(name = "runInput") - @XmlType(name = "InputDescription") - public static class InDesc extends VersionedElement { - /** Make a blank description of an input port. */ - public InDesc() { - } - - /** - * Make a description of the given input port. - * - * @param inputPort - */ - public InDesc(Input inputPort, UriInfo ui) { - super(true); - name = inputPort.getName(); - if (inputPort.getFile() != null) { - assignment = new InDesc.File(); - assignment.contents = inputPort.getFile(); - } else { - assignment = new InDesc.Value(); - assignment.contents = inputPort.getValue(); - } - // .../runs/{id}/input/input/{name} -> - // .../runs/{id}/input/expected#{name} - UriBuilder ub = ui.getBaseUriBuilder(); - List<PathSegment> segments = ui.getPathSegments(); - for (PathSegment s : segments.subList(0, segments.size() - 2)) - ub.segment(s.getPath()); - ub.fragment(name); - descriptorRef = new Uri(ub).ref; - } - - /** The name of the port. */ - @XmlAttribute(required = false) - public String name; - /** Where the port is described. Ignored in user input. */ - @XmlAttribute(required = false) - @XmlSchemaType(name = "anyURI") - public URI descriptorRef; - /** The character to use to split the input into a list. */ - @XmlAttribute(name = "listDelimiter", required = false) - public String delimiter; - - /** - * Either a filename or a literal string, used to provide input to a - * workflow port. - * - * @author Donal Fellows - */ - @XmlType(name = "InputContents") - public static abstract class AbstractContents { - /** - * The contents of the description of the input port. Meaning not - * defined. - */ - @XmlValue - public String contents; - }; - - /** - * The name of a file that provides input to the port. The - * {@link AbstractContents#contents contents} field is a filename. - * - * @author Donal Fellows - */ - @XmlType(name = "") - public static class File extends AbstractContents { - } - - /** - * The literal input to the port. The {@link AbstractContents#contents - * contents} field is a literal input value. - * - * @author Donal Fellows - */ - @XmlType(name = "") - public static class Value extends AbstractContents { - } - - /** - * A reference to a file elsewhere <i>on this server</i>. The - * {@link AbstractContents#contents contents} field is a URL to the file - * (using the RESTful notation). - * - * @author Donal Fellows - */ - @XmlType(name = "") - public static class Reference extends AbstractContents { - } - - /** - * The assignment of input values to the port. - */ - @XmlElements({ @XmlElement(name = "file", type = File.class), - @XmlElement(name = "reference", type = Reference.class), - @XmlElement(name = "value", type = Value.class) }) - public AbstractContents assignment; - } -} http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/2c71f9a9/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java ---------------------------------------------------------------------- diff --git a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java b/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java deleted file mode 100644 index e9b067e..0000000 --- a/server-webapp/src/main/java/org/taverna/server/master/rest/TavernaServerListenersREST.java +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright (C) 2010-2011 The University of Manchester - * - * See the file "LICENSE" for license terms. - */ -package org.taverna.server.master.rest; - -import static org.taverna.server.master.common.Namespaces.XLINK; -import static org.taverna.server.master.common.Roles.USER; -import static org.taverna.server.master.rest.ContentTypes.JSON; -import static org.taverna.server.master.rest.ContentTypes.TEXT; -import static org.taverna.server.master.rest.ContentTypes.XML; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; -import javax.annotation.security.RolesAllowed; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.OPTIONS; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; - -import org.apache.cxf.jaxrs.model.wadl.Description; -import org.taverna.server.master.common.Uri; -import org.taverna.server.master.common.VersionedElement; -import org.taverna.server.master.exceptions.NoListenerException; -import org.taverna.server.master.exceptions.NoUpdateException; -import org.taverna.server.master.interfaces.Listener; - -/** - * This represents <i>all</i> the event listeners attached to a workflow run. - * - * @author Donal Fellows - * @see TavernaServerListenerREST - */ -@RolesAllowed(USER) -@Description("This represents all the event listeners attached to a workflow " - + "run.") -public interface TavernaServerListenersREST { - /** - * Get the listeners installed in the workflow run. - * - * @param ui - * About how this method was called. - * @return A list of descriptions of listeners. - */ - @GET - @Path("/") - @Produces({ XML, JSON }) - @Description("Get the listeners installed in the workflow run.") - @Nonnull - Listeners getDescription(@Nonnull @Context UriInfo ui); - - /** - * Add a new event listener to the named workflow run. - * - * @param typeAndConfiguration - * What type of run should be created, and how should it be - * configured. - * @param ui - * About how this method was called. - * @return An HTTP response to the creation request. - * @throws NoUpdateException - * If the user is not permitted to update the run. - * @throws NoListenerException - * If no listener with the given type exists, or if the - * configuration is unacceptable in some way. - */ - @POST - @Path("/") - @Consumes({ XML, JSON }) - @Description("Add a new event listener to the named workflow run.") - @Nonnull - Response addListener(@Nonnull ListenerDefinition typeAndConfiguration, - @Nonnull @Context UriInfo ui) throws NoUpdateException, - NoListenerException; - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("/") - @Description("Produces the description of the run listeners' operations.") - Response listenersOptions(); - - /** - * Resolve a particular listener from its name. - * - * @param name - * The name of the listener to look up. - * @return The listener's delegate in the REST world. - * @throws NoListenerException - * If no listener with the given name exists. - */ - @Path("{name}") - @Description("Resolve a particular listener from its name.") - @Nonnull - TavernaServerListenerREST getListener( - @Nonnull @PathParam("name") String name) throws NoListenerException; - - /** - * This represents a single event listener attached to a workflow run. - * - * @author Donal Fellows - * @see TavernaServerListenersREST - * @see Property - */ - @RolesAllowed(USER) - @Description("This represents a single event listener attached to a " - + "workflow run.") - public interface TavernaServerListenerREST { - /** - * Get the description of this listener. - * - * @param ui - * Information about this request. - * @return A description document. - */ - @GET - @Path("/") - @Produces({ XML, JSON }) - @Description("Get the description of this listener.") - @Nonnull - ListenerDescription getDescription(@Nonnull @Context UriInfo ui); - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("/") - @Description("Produces the description of one run listener's operations.") - Response listenerOptions(); - - /** - * Get the configuration for the given event listener that is attached - * to a workflow run. - * - * @return The configuration of the listener. - */ - @GET - @Path("configuration") - @Produces(TEXT) - @Description("Get the configuration for the given event listener that " - + "is attached to a workflow run.") - @Nonnull - String getConfiguration(); - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("configuration") - @Description("Produces the description of one run listener's " - + "configuration's operations.") - Response configurationOptions(); - - /** - * Get the list of properties supported by a given event listener - * attached to a workflow run. - * - * @param ui - * Information about this request. - * @return The list of property names. - */ - @GET - @Path("properties") - @Produces({ XML, JSON }) - @Description("Get the list of properties supported by a given event " - + "listener attached to a workflow run.") - @Nonnull - Properties getProperties(@Nonnull @Context UriInfo ui); - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("properties") - @Description("Produces the description of one run listener's " - + "properties' operations.") - Response propertiesOptions(); - - /** - * Get an object representing a particular property. - * - * @param propertyName - * @return The property delegate. - * @throws NoListenerException - * If there is no such property. - */ - @Path("properties/{propertyName}") - @Description("Get an object representing a particular property.") - @Nonnull - Property getProperty( - @Nonnull @PathParam("propertyName") String propertyName) - throws NoListenerException; - } - - /** - * This represents a single property attached of an event listener. - * - * @author Donal Fellows - */ - @RolesAllowed(USER) - @Description("This represents a single property attached of an event " - + "listener.") - public interface Property { - /** - * Get the value of the particular property of an event listener - * attached to a workflow run. - * - * @return The value of the property. - */ - @GET - @Path("/") - @Produces(TEXT) - @Description("Get the value of the particular property of an event " - + "listener attached to a workflow run.") - @Nonnull - String getValue(); - - /** - * Set the value of the particular property of an event listener - * attached to a workflow run. Changing the value of the property may - * cause the listener to alter its behaviour significantly. - * - * @param value - * The value to set the property to. - * @return The value of the property after being set. - * @throws NoUpdateException - * If the user is not permitted to update the run. - * @throws NoListenerException - * If the property is in the wrong format. - */ - @PUT - @Path("/") - @Consumes(TEXT) - @Produces(TEXT) - @Description("Set the value of the particular property of an event " - + "listener attached to a workflow run.") - @Nonnull - String setValue(@Nonnull String value) throws NoUpdateException, - NoListenerException; - - /** Get an outline of the operations supported. */ - @OPTIONS - @Path("/") - @Description("Produces the description of one run listener's " - + "property's operations.") - Response options(); - } - - /** - * A description of an event listener that is attached to a workflow run. - * Done with JAXB. - * - * @author Donal Fellows - */ - @XmlRootElement - @XmlType(name = "ListenerDescription") - public class ListenerDescription extends VersionedElement { - /** Where this listener is located. */ - @XmlAttribute(name = "href", namespace = XLINK) - @XmlSchemaType(name = "anyURI") - public URI location; - /** The (arbitrary) name of the event listener. */ - @XmlAttribute - public String name; - /** The type of the event listener. */ - @XmlAttribute - public String type; - /** - * The location of the configuration document for the event listener. - */ - public Uri configuration; - /** - * The name and location of the properties supported by the event - * listener. - */ - @XmlElementWrapper(name = "properties", nillable = false) - @XmlElement(name = "property", nillable = false) - public List<PropertyDescription> properties; - - /** - * Make a blank listener description. - */ - public ListenerDescription() { - } - - /** - * Make a listener description that characterizes the given listener. - * - * @param listener - * The listener to describe. - * @param ub - * The factory for URIs. Must have already been secured. - */ - public ListenerDescription(Listener listener, UriBuilder ub) { - super(true); - name = listener.getName(); - type = listener.getType(); - configuration = new Uri(ub.clone().path("configuration")); - UriBuilder ub2 = ub.clone().path("properties/{prop}"); - String[] props = listener.listProperties(); - properties = new ArrayList<>(props.length); - for (String propName : props) - properties.add(new PropertyDescription(propName, ub2)); - } - } - - /** - * The description of a single property, done with JAXB. - * - * @author Donal Fellows - */ - @XmlType(name = "PropertyDescription") - public static class PropertyDescription extends Uri { - /** - * The name of the property. - */ - @XmlAttribute - String name; - - /** - * Make an empty description of a property. - */ - public PropertyDescription() { - } - - /** - * Make a description of a property. - * - * @param listenerName - * The name of the listener whose property this is. - * @param propName - * The name of the property. - * @param ub - * The factory for URIs. Must have already been secured. - */ - PropertyDescription(String propName, UriBuilder ub) { - super(ub, propName); - this.name = propName; - } - } - - /** - * The list of descriptions of listeners attached to a run. Done with JAXB. - * - * @author Donal Fellows - */ - @XmlRootElement - @XmlType(name = "") - public static class Listeners extends VersionedElement { - /** - * The listeners for a workflow run. - */ - @XmlElement(name = "listener") - public List<ListenerDescription> listener; - - /** - * Make a blank description of listeners. - */ - public Listeners() { - listener = new ArrayList<>(); - } - - /** - * Make a description of the whole group out of the given list of - * listener descriptions. - * - * @param listeners - * The collection of (partial) listener descriptions. - * @param ub - * How to build the location of the listeners. Must have - * already been secured. - */ - public Listeners(List<ListenerDescription> listeners, UriBuilder ub) { - super(true); - listener = listeners; - for (ListenerDescription ld : listeners) - ld.location = ub.build(ld.name); - } - } - - /** - * The list of properties of a listener. Done with JAXB. - * - * @author Donal Fellows - */ - @XmlRootElement - @XmlType(name = "") - public static class Properties extends VersionedElement { - /** - * The references to the properties of a listener. - */ - @XmlElement - public List<PropertyDescription> property; - - /** - * Make an empty description of the properties of a listener. - */ - public Properties() { - } - - /** - * Make the description of the properties of a listener. - * - * @param ub - * The factory for URIs, configured. Must have already been - * secured. - * @param properties - * The names of the properties. - */ - public Properties(UriBuilder ub, String[] properties) { - super(true); - property = new ArrayList<>(properties.length); - for (String propName : properties) - property.add(new PropertyDescription(propName, ub)); - } - } -}
