http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
deleted file mode 100644
index 1bd2a95..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WSDLHeadOptionsInterceptor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.taverna.server.master.utils;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static org.apache.commons.logging.LogFactory.getLog;
-import static org.apache.cxf.common.util.UrlUtils.parseQueryString;
-import static org.apache.cxf.message.Message.HTTP_REQUEST_METHOD;
-import static org.apache.cxf.message.Message.QUERY_STRING;
-import static org.apache.cxf.message.Message.REQUEST_URL;
-import static org.apache.cxf.phase.Phase.READ;
-
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.cxf.binding.soap.interceptor.EndpointSelectionInterceptor;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.message.Message;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
-
-
-/**
- * Thunk for TAVSERV-293.
- * 
- * @author Donal Fellows (based on work by Daniel Hagen)
- */
-public class WSDLHeadOptionsInterceptor extends
-               AbstractPhaseInterceptor<Message> {
-       public static final Log log = getLog("Taverna.Server.Utils");
-
-       public WSDLHeadOptionsInterceptor() {
-               super(READ);
-               getAfter().add(EndpointSelectionInterceptor.class.getName());
-       }
-
-       @Override
-       public void handleMessage(Message message) throws Fault {
-               String method = (String) message.get(HTTP_REQUEST_METHOD);
-               String query = (String) message.get(QUERY_STRING);
-
-               if (("HEAD".equals(method) || "OPTIONS".equals(method))
-                               && query != null && !query.trim().isEmpty()
-                               && isRecognizedQuery(query)) {
-                       log.debug("adjusting message request method " + method 
+ " for "
-                                       + message.get(REQUEST_URL) + " to GET");
-                       message.put(HTTP_REQUEST_METHOD, "GET");
-               }
-       }
-
-       /*
-        * Stolen from 
http://permalink.gmane.org/gmane.comp.apache.cxf.user/20037
-        * which is itself in turn stolen from
-        * org.apache.cxf.frontend.WSDLGetInterceptor.isRecognizedQuery
-        */
-       /**
-        * Is this a query for WSDL or XSD relating to it?
-        * 
-        * @param query
-        *            The query string to check
-        * @return If the query is one to handle.
-        * @see 
org.apache.cxf.frontend.WSDLGetInterceptor#isRecognizedQuery(Map,String,String,org.apache.cxf.service.model.EndpointInfo)
-        *      WSDLGetInterceptor
-        */
-       private boolean isRecognizedQuery(String query) {
-               Map<String, String> map = parseQueryString(query);
-               return map.containsKey("wsdl") || map.containsKey("xsd");
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
deleted file mode 100644
index 24246b5..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/WebappAwareDataSource.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- */
-package org.taverna.server.master.utils;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static java.lang.Thread.currentThread;
-import static java.sql.DriverManager.deregisterDriver;
-import static java.sql.DriverManager.getDrivers;
-import static org.taverna.server.master.utils.Contextualizer.ROOT_PLACEHOLDER;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Enumeration;
-
-import javax.annotation.PreDestroy;
-
-import org.apache.commons.dbcp.BasicDataSource;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-
-/**
- * Add some awareness of the context so that we can locate databases internally
- * to the webapp.
- * 
- * @author Donal Fellows
- */
-public class WebappAwareDataSource extends BasicDataSource {
-       Log log = LogFactory.getLog("Taverna.Server.Utils");
-       private transient boolean init;
-       private Contextualizer ctxt;
-       private String shutdownUrl;
-
-       @Required
-       public void setContextualizer(Contextualizer ctxt) {
-               this.ctxt = ctxt;
-       }
-
-       /**
-        * A JDBC connection URL to use on shutting down the database. If not 
set,
-        * do nothing special.
-        * 
-        * @param url
-        */
-       public void setShutdownUrl(String url) {
-               shutdownUrl = url;
-       }
-
-       private void doInit() {
-               synchronized (this) {
-                       if (!init) {
-                               
setDriverClassLoader(currentThread().getContextClassLoader());
-                               String url = getUrl();
-                               if (url.contains(ROOT_PLACEHOLDER)) {
-                                       String newurl = ctxt.contextualize(url);
-                                       setUrl(newurl);
-                                       log.info("mapped " + url + " to " + 
newurl);
-                               } else {
-                                       log.info("did not find " + 
ROOT_PLACEHOLDER + " in " + url);
-                               }
-                               init = true;
-                       }
-               }
-       }
-
-       // -=-=-=-=-=-=-=-=-=-=- HOOKS -=-=-=-=-=-=-=-=-=-=-
-
-       @Override
-       public Connection getConnection() throws SQLException {
-               doInit();
-               return super.getConnection();
-       }
-
-       @Override
-       public void setLogWriter(PrintWriter pw) throws SQLException {
-               doInit();
-               super.setLogWriter(pw);
-       }
-
-       @Override
-       public void setLoginTimeout(int num) throws SQLException {
-               doInit();
-               super.setLoginTimeout(num);
-       }
-
-       @Override
-       public PrintWriter getLogWriter() throws SQLException {
-               doInit();
-               return super.getLogWriter();
-       }
-
-       @Override
-       public int getLoginTimeout() throws SQLException {
-               doInit();
-               return super.getLoginTimeout();
-       }
-
-       @PreDestroy
-       void realClose() {
-               try {
-                       close();
-               } catch (SQLException e) {
-                       log.warn("problem shutting down DB connection", e);
-               }
-               try {
-                       if (shutdownUrl != null)
-                               
DriverManager.getConnection(ctxt.contextualize(shutdownUrl));
-               } catch (SQLException e) {
-                       // Expected; ignore it
-               }
-               log = null;
-               dropDriver();
-       }
-
-       private void dropDriver() {
-               Enumeration<Driver> drivers = getDrivers();
-               while (drivers.hasMoreElements()) {
-                       Driver d = drivers.nextElement();
-                       if (d.getClass().getClassLoader() == 
getDriverClassLoader()
-                                       && 
d.getClass().getName().equals(getDriverClassName())) {
-                               try {
-                                       deregisterDriver(d);
-                               } catch (SQLException e) {
-                               }
-                               break;
-                       }
-               }
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
deleted file mode 100644
index d258079..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/X500Utils.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- */
-package org.taverna.server.master.utils;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static javax.security.auth.x500.X500Principal.RFC2253;
-
-import java.math.BigInteger;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.PreDestroy;
-import javax.security.auth.x500.X500Principal;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Support class that factors out some of the messier parts of working with
- * X.500 identities and X.509 certificates.
- * 
- * @author Donal Fellows
- */
-public class X500Utils {
-       private Log log = LogFactory.getLog("Taverna.Server.Utils");
-
-       @PreDestroy
-       void closeLog() {
-               log = null;
-       }
-
-       private static final char DN_SEPARATOR = ',';
-       private static final char DN_ESCAPE = '\\';
-       private static final char DN_QUOTE = '"';
-
-       /**
-        * Parse the DN from the Principal and extract the CN field.
-        * 
-        * @param id
-        *            The identity to extract the distinguished name from.
-        * @param fields
-        *            The names to look at when finding the field to return. 
Each
-        *            should be an upper-cased string.
-        * @return The common-name part of the distinguished name, or the 
literal
-        *         string "<tt>none</tt>" if there is no CN.
-        */
-       public String getName(X500Principal id, String... fields) {
-               String dn = id.getName(RFC2253);
-
-               int i = 0;
-               int startIndex = 0;
-               boolean ignoreThisChar = false;
-               boolean inQuotes = false;
-               Map<String, String> tokenized = new HashMap<>();
-
-               for (i = 0; i < dn.length(); i++)
-                       if (ignoreThisChar)
-                               ignoreThisChar = false;
-                       else if (dn.charAt(i) == DN_QUOTE)
-                               inQuotes = !inQuotes;
-                       else if (inQuotes)
-                               continue;
-                       else if (dn.charAt(i) == DN_ESCAPE)
-                               ignoreThisChar = true;
-                       else if ((dn.charAt(i) == DN_SEPARATOR) && 
!ignoreThisChar) {
-                               storeDNField(tokenized, 
dn.substring(startIndex, i).trim()
-                                               .split("=", 2));
-                               startIndex = i + 1;
-                       }
-               if (inQuotes || ignoreThisChar)
-                       log.warn("was parsing invalid DN format");
-               // Add last token - after the last delimiter
-               storeDNField(tokenized, 
dn.substring(startIndex).trim().split("=", 2));
-
-               for (String field : fields) {
-                       String value = tokenized.get(field);
-                       if (value != null)
-                               return value;
-               }
-               return "none";
-       }
-
-       private void storeDNField(Map<String, String> container, String[] 
split) {
-               if (split == null || split.length != 2)
-                       return;
-               String key = split[0].toUpperCase();
-               if (container.containsKey(key))
-                       log.warn("duplicate field in DN: " + key);
-               // LATER: Should the field be de-quoted?
-               container.put(key, split[1]);
-       }
-
-       /**
-        * Get the serial number from a certificate as a hex string.
-        * 
-        * @param cert
-        *            The certificate to extract from.
-        * @return A hex string, in upper-case.
-        */
-       public String getSerial(X509Certificate cert) {
-               return new BigInteger(1, cert.getSerialNumber().toByteArray())
-                               .toString(16).toUpperCase();
-       }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
deleted file mode 100644
index 64a9f68..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/utils/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- */
-/**
- * Miscellaneous utility classes. Includes aspects that might be attached
- * for purposes such as transaction management and invocation tracking.
- */
-package org.taverna.server.master.utils;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
deleted file mode 100644
index 1868f94..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/CompletionNotifier.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * How to convert a notification about the completion of a job into a message.
- * 
- * @author Donal Fellows
- */
-public interface CompletionNotifier {
-       /**
-        * @return The name of this notifier.
-        */
-       String getName();
-
-       /**
-        * Called to get the content of a message that a workflow run has 
finished.
-        * 
-        * @param name
-        *            The name of the run.
-        * @param run
-        *            What run are we talking about.
-        * @param code
-        *            What the exit code was.
-        * @return The plain-text content of the message.
-        */
-       String makeCompletionMessage(String name, RemoteRunDelegate run, int 
code);
-
-       /**
-        * Called to get the subject of the message to dispatch.
-        * 
-        * @param name
-        *            The name of the run.
-        * @param run
-        *            What run are we talking about.
-        * @param code
-        *            What the exit code was.
-        * @return The plain-text subject of the message.
-        */
-       String makeMessageSubject(String name, RemoteRunDelegate run, int code);
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
deleted file mode 100644
index d38f0cc..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/FactoryBean.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.taverna.server.master.notification.atom.EventDAO;
-
-/**
- * What the remote run really needs of its factory.
- * 
- * @author Donal Fellows
- */
-public interface FactoryBean {
-       /**
-        * @return Whether a run can actually be started at this time.
-        */
-       boolean isAllowingRunsToStart();
-
-       /**
-        * @return a handle to the master Atom event feed (<i>not</i> the 
per-run
-        *         feed)
-        */
-       EventDAO getMasterEventFeed();
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
deleted file mode 100644
index 649db64..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PasswordIssuer.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * A simple password issuing bean.
- * 
- * @author Donal Fellows
- */
-public class PasswordIssuer {
-       private static final char[] ALPHABET = { 'a', 'b', 'c', 'd', 'e', 'f', 
'g',
-                       'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 
's', 't',
-                       'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 
'F', 'G',
-                       'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 
'S', 'T',
-                       'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', 
'6', '7',
-                       '8', '9', '0', '!', '@', '#', '$', '%', '^', '&', '*', 
'(', ')',
-                       ',', '.', '<', '>', '/', '?', ':', ';', '-', '_', '+', 
'[', ']',
-                       '{', '}', '`', '~' };
-       private Log log = LogFactory.getLog("Taverna.Server.Worker");
-       private SecureRandom r;
-       private int length;
-
-       public PasswordIssuer() {
-               r = new SecureRandom();
-               log.info("constructing passwords with " + r.getAlgorithm());
-               setLength(8);
-       }
-
-       public PasswordIssuer(String algorithm) throws NoSuchAlgorithmException 
{
-               r = SecureRandom.getInstance(algorithm);
-               log.info("constructing passwords with " + r.getAlgorithm());
-               setLength(8);
-       }
-
-       public void setLength(int length) {
-               this.length = length;
-               log.info("issued password will be " + this.length
-                               + " symbols chosen from " + ALPHABET.length);
-       }
-
-       /**
-        * Issue a password.
-        * 
-        * @return The new password.
-        */
-       public String issue() {
-               StringBuilder sb = new StringBuilder();
-               for (int i = 0; i < length; i++)
-                       sb.append(ALPHABET[r.nextInt(ALPHABET.length)]);
-               log.info("issued new password of length " + sb.length());
-               return sb.toString();
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
deleted file mode 100644
index 37d5760..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyImpl.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static 
org.taverna.server.master.identity.WorkflowInternalAuthProvider.PREFIX;
-
-import java.net.URI;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Required;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.taverna.server.master.common.Roles;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.exceptions.NoCreateException;
-import org.taverna.server.master.exceptions.NoDestroyException;
-import org.taverna.server.master.exceptions.NoUpdateException;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Basic policy implementation that allows any workflow to be instantiated by
- * any user, but which does not permit users to access each others workflow
- * runs. It also imposes a global limit on the number of workflow runs at once.
- * 
- * @author Donal Fellows
- */
-class PolicyImpl implements Policy {
-       Log log = LogFactory.getLog("Taverna.Server.Worker.Policy");
-       private PolicyLimits limits;
-       private RunDBSupport runDB;
-
-       @Required
-       public void setLimits(PolicyLimits limits) {
-               this.limits = limits;
-       }
-
-       @Required
-       public void setRunDB(RunDBSupport runDB) {
-               this.runDB = runDB;
-       }
-
-       @Override
-       public int getMaxRuns() {
-               return limits.getMaxRuns();
-       }
-
-       @Override
-       public Integer getMaxRuns(UsernamePrincipal user) {
-               return null;
-       }
-
-       @Override
-       public int getOperatingLimit() {
-               return limits.getOperatingLimit();
-       }
-
-       @Override
-       public List<URI> listPermittedWorkflowURIs(UsernamePrincipal user) {
-               return limits.getPermittedWorkflowURIs();
-       }
-
-       private boolean isSelfAccess(String runId) {
-               Authentication auth = SecurityContextHolder.getContext()
-                               .getAuthentication();
-               boolean self = false;
-               String id = null;
-               for (GrantedAuthority a : auth.getAuthorities()) {
-                       String aa = a.getAuthority();
-                       if (aa.equals(Roles.SELF)) {
-                               self = true;
-                               continue;
-                       }
-                       if (!aa.startsWith(PREFIX))
-                               continue;
-                       id = aa.substring(PREFIX.length());
-               }
-               return self && runId.equals(id);
-       }
-
-       @Override
-       public boolean permitAccess(UsernamePrincipal user, TavernaRun run) {
-               String username = user.getName();
-               TavernaSecurityContext context = run.getSecurityContext();
-               if (context.getOwner().getName().equals(username)) {
-                       if (log.isDebugEnabled())
-                               log.debug("granted access by " + user.getName() 
+ " to "
-                                               + run.getId());
-                       return true;
-               }
-               if (isSelfAccess(run.getId())) {
-                       if (log.isDebugEnabled())
-                               log.debug("access by workflow to itself: " + 
run.getId());
-                       return true;
-               }
-               if (log.isDebugEnabled())
-                       log.debug("considering access by " + user.getName() + " 
to "
-                                       + run.getId());
-               return context.getPermittedReaders().contains(username);
-       }
-
-       @Override
-       public void permitCreate(UsernamePrincipal user, Workflow workflow)
-                       throws NoCreateException {
-               if (user == null)
-                       throw new NoCreateException(
-                                       "anonymous workflow creation not 
allowed");
-               if (runDB.countRuns() >= getMaxRuns())
-                       throw new NoCreateException("server load exceeded; 
please wait");
-       }
-
-       @Override
-       public synchronized void permitDestroy(UsernamePrincipal user, 
TavernaRun run)
-                       throws NoDestroyException {
-               if (user == null)
-                       throw new NoDestroyException();
-               String username = user.getName();
-               TavernaSecurityContext context = run.getSecurityContext();
-               if (context.getOwner() == null
-                               || 
context.getOwner().getName().equals(username))
-                       return;
-               if (!context.getPermittedDestroyers().contains(username))
-                       throw new NoDestroyException();
-       }
-
-       @Override
-       public void permitUpdate(UsernamePrincipal user, TavernaRun run)
-                       throws NoUpdateException {
-               if (user == null)
-                       throw new NoUpdateException(
-                                       "workflow run not owned by you and 
you're not granted access");
-               TavernaSecurityContext context = run.getSecurityContext();
-               if (context.getOwner().getName().equals(user.getName()))
-                       return;
-               if (isSelfAccess(run.getId())) {
-                       if (log.isDebugEnabled())
-                               log.debug("update access by workflow to itself: 
" + run.getId());
-                       return;
-               }
-               if (!context.getPermittedUpdaters().contains(user.getName()))
-                       throw new NoUpdateException(
-                                       "workflow run not owned by you and 
you're not granted access");
-       }
-
-       @Override
-       public void setPermittedWorkflowURIs(UsernamePrincipal user,
-                       List<URI> permitted) {
-               limits.setPermittedWorkflowURIs(permitted);
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
deleted file mode 100644
index 43c0aa4..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/PolicyLimits.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.net.URI;
-import java.util.List;
-
-import org.taverna.server.master.common.Status;
-
-/**
- * The worker policy delegates certain limits to the state model of the
- * particular worker.
- * 
- * @author Donal Fellows
- */
-public interface PolicyLimits {
-       /**
-        * @return the maximum number of extant workflow runs in any state
-        */
-       int getMaxRuns();
-
-       /**
-        * @return the maximum number of workflow runs in the
-        *         {@linkplain Status#Operating operating} state.
-        */
-       int getOperatingLimit();
-
-       /**
-        * @return the list of URIs to workflows that may be used to create 
workflow
-        *         runs. If empty or <tt>null</tt>, no restriction is present.
-        */
-       List<URI> getPermittedWorkflowURIs();
-
-       /**
-        * @param permitted
-        *            the list of URIs to workflows that may be used to create
-        *            workflow runs.
-        */
-       void setPermittedWorkflowURIs(List<URI> permitted);
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
deleted file mode 100644
index fb1ac47..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RemoteRunDelegate.java
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static java.lang.System.currentTimeMillis;
-import static java.util.Calendar.MINUTE;
-import static java.util.Collections.sort;
-import static java.util.Collections.unmodifiableSet;
-import static java.util.UUID.randomUUID;
-import static org.apache.commons.io.IOUtils.closeQuietly;
-import static org.apache.commons.logging.LogFactory.getLog;
-import static 
org.taverna.server.master.worker.RemoteRunDelegate.checkBadFilename;
-import static org.taverna.server.master.worker.RunConnection.NAME_LENGTH;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.PipedOutputStream;
-import java.rmi.MarshalledObject;
-import java.rmi.RemoteException;
-import java.security.GeneralSecurityException;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-import javax.annotation.Nonnull;
-
-import org.apache.commons.logging.Log;
-import org.taverna.server.localworker.remote.IllegalStateTransitionException;
-import org.taverna.server.localworker.remote.ImplementationException;
-import org.taverna.server.localworker.remote.RemoteDirectory;
-import org.taverna.server.localworker.remote.RemoteDirectoryEntry;
-import org.taverna.server.localworker.remote.RemoteFile;
-import org.taverna.server.localworker.remote.RemoteInput;
-import org.taverna.server.localworker.remote.RemoteListener;
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.localworker.remote.RemoteStatus;
-import org.taverna.server.localworker.remote.StillWorkingOnItException;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.common.Workflow;
-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.NoListenerException;
-import org.taverna.server.master.exceptions.OverloadedException;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.Directory;
-import org.taverna.server.master.interfaces.DirectoryEntry;
-import org.taverna.server.master.interfaces.File;
-import org.taverna.server.master.interfaces.Input;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.SecurityContextFactory;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.interfaces.TavernaSecurityContext;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * Bridging shim between the WebApp world and the RMI world.
- * 
- * @author Donal Fellows
- */
-@SuppressWarnings("serial")
-public class RemoteRunDelegate implements TavernaRun {
-       private transient Log log = getLog("Taverna.Server.Worker");
-       transient TavernaSecurityContext secContext;
-       Date creationInstant;
-       Workflow workflow;
-       Date expiry;
-       HashSet<String> readers;
-       HashSet<String> writers;
-       HashSet<String> destroyers;
-       transient String id;
-       transient RemoteSingleRun run;
-       transient RunDBSupport db;
-       transient FactoryBean factory;
-       boolean doneTransitionToFinished;
-       boolean generateProvenance;// FIXME expose
-       String name;
-       private static final String ELLIPSIS = "...";
-
-       public RemoteRunDelegate(Date creationInstant, Workflow workflow,
-                       RemoteSingleRun rsr, int defaultLifetime, RunDBSupport 
db, UUID id,
-                       boolean generateProvenance, FactoryBean factory) {
-               if (rsr == null)
-                       throw new IllegalArgumentException("remote run must not 
be null");
-               this.creationInstant = creationInstant;
-               this.workflow = workflow;
-               Calendar c = Calendar.getInstance();
-               c.add(MINUTE, defaultLifetime);
-               this.expiry = c.getTime();
-               this.run = rsr;
-               this.db = db;
-               this.generateProvenance = generateProvenance;
-               this.factory = factory;
-               try {
-                       this.name = "";
-                       String ci = " " + creationInstant;
-                       String n = workflow.getName();
-                       if (n.length() > NAME_LENGTH - ci.length())
-                               n = n.substring(0,
-                                               NAME_LENGTH - ci.length() - 
ELLIPSIS.length())
-                                               + ELLIPSIS;
-                       this.name = n + ci;
-               } catch (Exception e) {
-                       // Ignore; it's just a name, not something important.
-               }
-               if (id != null)
-                       this.id = id.toString();
-       }
-
-       RemoteRunDelegate() {
-       }
-
-       /**
-        * Get the types of listener supported by this run.
-        * 
-        * @return A list of listener type names.
-        * @throws RemoteException
-        *             If anything goes wrong.
-        */
-       public List<String> getListenerTypes() throws RemoteException {
-               return run.getListenerTypes();
-       }
-
-       @Override
-       public void addListener(Listener listener) {
-               if (listener instanceof ListenerDelegate)
-                       try {
-                               run.addListener(((ListenerDelegate) 
listener).getRemote());
-                       } catch (RemoteException e) {
-                               log.warn("communication problem adding 
listener", e);
-                       } catch (ImplementationException e) {
-                               log.warn("implementation problem adding 
listener", e);
-                       }
-               else
-                       log.fatal("bad listener " + listener.getClass()
-                                       + "; not applicable remotely!");
-       }
-
-       @Override
-       public String getId() {
-               if (id == null)
-                       id = randomUUID().toString();
-               return id;
-       }
-
-       /**
-        * Attach a listener to a workflow run and return its local delegate.
-        * 
-        * @param type
-        *            The type of listener to create.
-        * @param config
-        *            The configuration of the listener.
-        * @return The local delegate of the listener.
-        * @throws NoListenerException
-        *             If anything goes wrong.
-        */
-       public Listener makeListener(String type, String config)
-                       throws NoListenerException {
-               try {
-                       return new ListenerDelegate(run.makeListener(type, 
config));
-               } catch (RemoteException e) {
-                       throw new NoListenerException("failed to make 
listener", e);
-               }
-       }
-
-       @Override
-       public void destroy() {
-               try {
-                       run.destroy();
-               } catch (RemoteException | ImplementationException e) {
-                       log.warn("failed to destroy run", e);
-               }
-       }
-
-       @Override
-       public Date getExpiry() {
-               return new Date(expiry.getTime());
-       }
-
-       @Override
-       public List<Listener> getListeners() {
-               List<Listener> listeners = new ArrayList<>();
-               try {
-                       for (RemoteListener rl : run.getListeners())
-                               listeners.add(new ListenerDelegate(rl));
-               } catch (RemoteException e) {
-                       log.warn("failed to get listeners", e);
-               }
-               return listeners;
-       }
-
-       @Override
-       public TavernaSecurityContext getSecurityContext() {
-               return secContext;
-       }
-
-       @Override
-       public Status getStatus() {
-               try {
-                       switch (run.getStatus()) {
-                       case Initialized:
-                               return Status.Initialized;
-                       case Operating:
-                               return Status.Operating;
-                       case Stopped:
-                               return Status.Stopped;
-                       case Finished:
-                               return Status.Finished;
-                       }
-               } catch (RemoteException e) {
-                       log.warn("problem getting remote status", e);
-               }
-               return Status.Finished;
-       }
-
-       @Override
-       public Workflow getWorkflow() {
-               return workflow;
-       }
-
-       @Override
-       public Directory getWorkingDirectory() throws FilesystemAccessException 
{
-               try {
-                       return new DirectoryDelegate(run.getWorkingDirectory());
-               } catch (Throwable e) {
-                       if (e.getCause() != null)
-                               e = e.getCause();
-                       throw new FilesystemAccessException(
-                                       "problem getting main working directory 
handle", e);
-               }
-       }
-
-       @Override
-       public void setExpiry(Date d) {
-               if (d.after(new Date()))
-                       expiry = new Date(d.getTime());
-               db.flushToDisk(this);
-       }
-
-       @Override
-       public String setStatus(Status s) throws BadStateChangeException {
-               try {
-                       log.info("setting status of run " + id + " to " + s);
-                       switch (s) {
-                       case Initialized:
-                               run.setStatus(RemoteStatus.Initialized);
-                               break;
-                       case Operating:
-                               if (run.getStatus() == 
RemoteStatus.Initialized) {
-                                       if (!factory.isAllowingRunsToStart())
-                                               throw new OverloadedException();
-                                       secContext.conveySecurity();
-                               }
-                               run.setGenerateProvenance(generateProvenance);
-                               run.setStatus(RemoteStatus.Operating);
-                               factory.getMasterEventFeed()
-                                               .started(
-                                                               this,
-                                                               "started run 
execution",
-                                                               "The execution 
of run '" + getName()
-                                                                               
+ "' has started.");
-                               break;
-                       case Stopped:
-                               run.setStatus(RemoteStatus.Stopped);
-                               break;
-                       case Finished:
-                               run.setStatus(RemoteStatus.Finished);
-                               break;
-                       }
-                       return null;
-               } catch (IllegalStateTransitionException e) {
-                       throw new BadStateChangeException(e.getMessage());
-               } catch (RemoteException e) {
-                       throw new BadStateChangeException(e.getMessage(), 
e.getCause());
-               } catch (GeneralSecurityException | IOException e) {
-                       throw new BadStateChangeException(e.getMessage(), e);
-               } catch (ImplementationException e) {
-                       if (e.getCause() != null)
-                               throw new 
BadStateChangeException(e.getMessage(), e.getCause());
-                       throw new BadStateChangeException(e.getMessage(), e);
-               } catch (StillWorkingOnItException e) {
-                       log.info("still working on setting status of run " + id 
+ " to "
-                                       + s, e);
-                       return e.getMessage();
-               } catch (InterruptedException e) {
-                       throw new BadStateChangeException(
-                                       "interrupted while waiting to insert 
notification into database");
-               }
-       }
-
-       static void checkBadFilename(String filename)
-                       throws FilesystemAccessException {
-               if (filename.startsWith("/"))
-                       throw new FilesystemAccessException("filename may not 
be absolute");
-               if (Arrays.asList(filename.split("/")).contains(".."))
-                       throw new FilesystemAccessException(
-                                       "filename may not refer to parent");
-       }
-
-       @Override
-       public String getInputBaclavaFile() {
-               try {
-                       return run.getInputBaclavaFile();
-               } catch (RemoteException e) {
-                       log.warn("problem when fetching input baclava file", e);
-                       return null;
-               }
-       }
-
-       @Override
-       public List<Input> getInputs() {
-               ArrayList<Input> inputs = new ArrayList<>();
-               try {
-                       for (RemoteInput ri : run.getInputs())
-                               inputs.add(new RunInput(ri));
-               } catch (RemoteException e) {
-                       log.warn("problem when fetching list of workflow 
inputs", e);
-               }
-               return inputs;
-       }
-
-       @Override
-       public String getOutputBaclavaFile() {
-               try {
-                       return run.getOutputBaclavaFile();
-               } catch (RemoteException e) {
-                       log.warn("problem when fetching output baclava file", 
e);
-                       return null;
-               }
-       }
-
-       @Override
-       public Input makeInput(String name) throws BadStateChangeException {
-               try {
-                       return new RunInput(run.makeInput(name));
-               } catch (RemoteException e) {
-                       throw new BadStateChangeException("failed to make 
input", e);
-               }
-       }
-
-       @Override
-       public void setInputBaclavaFile(String filename)
-                       throws FilesystemAccessException, 
BadStateChangeException {
-               checkBadFilename(filename);
-               try {
-                       run.setInputBaclavaFile(filename);
-               } catch (RemoteException e) {
-                       throw new FilesystemAccessException(
-                                       "cannot set input baclava file name", 
e);
-               }
-       }
-
-       @Override
-       public void setOutputBaclavaFile(String filename)
-                       throws FilesystemAccessException, 
BadStateChangeException {
-               checkBadFilename(filename);
-               try {
-                       run.setOutputBaclavaFile(filename);
-               } catch (RemoteException e) {
-                       throw new FilesystemAccessException(
-                                       "cannot set output baclava file name", 
e);
-               }
-       }
-
-       @Override
-       public Date getCreationTimestamp() {
-               return creationInstant == null ? null : new Date(
-                               creationInstant.getTime());
-       }
-
-       @Override
-       public Date getFinishTimestamp() {
-               try {
-                       return run.getFinishTimestamp();
-               } catch (RemoteException e) {
-                       log.info("failed to get finish timestamp", e);
-                       return null;
-               }
-       }
-
-       @Override
-       public Date getStartTimestamp() {
-               try {
-                       return run.getStartTimestamp();
-               } catch (RemoteException e) {
-                       log.info("failed to get finish timestamp", e);
-                       return null;
-               }
-       }
-
-       /**
-        * @param readers
-        *            the readers to set
-        */
-       public void setReaders(Set<String> readers) {
-               this.readers = new HashSet<>(readers);
-               db.flushToDisk(this);
-       }
-
-       /**
-        * @return the readers
-        */
-       public Set<String> getReaders() {
-               return readers == null ? new HashSet<String>()
-                               : unmodifiableSet(readers);
-       }
-
-       /**
-        * @param writers
-        *            the writers to set
-        */
-       public void setWriters(Set<String> writers) {
-               this.writers = new HashSet<>(writers);
-               db.flushToDisk(this);
-       }
-
-       /**
-        * @return the writers
-        */
-       public Set<String> getWriters() {
-               return writers == null ? new HashSet<String>()
-                               : unmodifiableSet(writers);
-       }
-
-       /**
-        * @param destroyers
-        *            the destroyers to set
-        */
-       public void setDestroyers(Set<String> destroyers) {
-               this.destroyers = new HashSet<>(destroyers);
-               db.flushToDisk(this);
-       }
-
-       /**
-        * @return the destroyers
-        */
-       public Set<String> getDestroyers() {
-               return destroyers == null ? new HashSet<String>()
-                               : unmodifiableSet(destroyers);
-       }
-
-       private void writeObject(ObjectOutputStream out) throws IOException {
-               out.defaultWriteObject();
-               out.writeUTF(secContext.getOwner().getName());
-               out.writeObject(secContext.getFactory());
-               out.writeObject(new MarshalledObject<>(run));
-       }
-
-       @Override
-       public boolean getGenerateProvenance() {
-               return generateProvenance;
-       }
-
-       @Override
-       public void setGenerateProvenance(boolean generateProvenance) {
-               this.generateProvenance = generateProvenance;
-               db.flushToDisk(this);
-       }
-
-       @SuppressWarnings("unchecked")
-       private void readObject(ObjectInputStream in) throws IOException,
-                       ClassNotFoundException {
-               in.defaultReadObject();
-               if (log == null)
-                       log = getLog("Taverna.Server.LocalWorker");
-               final String creatorName = in.readUTF();
-               SecurityContextFactory factory = (SecurityContextFactory) in
-                               .readObject();
-               try {
-                       secContext = factory.create(this,
-                                       new UsernamePrincipal(creatorName));
-               } catch (RuntimeException | IOException e) {
-                       throw e;
-               } catch (Exception e) {
-                       throw new SecurityContextReconstructionException(e);
-               }
-               run = ((MarshalledObject<RemoteSingleRun>) 
in.readObject()).get();
-       }
-
-       public void setSecurityContext(TavernaSecurityContext 
tavernaSecurityContext) {
-               secContext = tavernaSecurityContext;
-       }
-
-       @Override
-       public String getName() {
-               return name;
-       }
-
-       @Override
-       public void setName(@Nonnull String name) {
-               if (name.length() > RunConnection.NAME_LENGTH)
-                       this.name = name.substring(0, 
RunConnection.NAME_LENGTH);
-               else
-                       this.name = name;
-               db.flushToDisk(this);
-       }
-
-       @Override
-       public void ping() throws UnknownRunException {
-               try {
-                       run.ping();
-               } catch (RemoteException e) {
-                       throw new UnknownRunException(e);
-               }
-       }
-}
-
-abstract class DEDelegate implements DirectoryEntry {
-       Log log = getLog("Taverna.Server.Worker");
-       private RemoteDirectoryEntry entry;
-       private String name;
-       private String full;
-       private Date cacheModTime;
-       private long cacheQueryTime = 0L;
-
-       DEDelegate(RemoteDirectoryEntry entry) {
-               this.entry = entry;
-       }
-
-       @Override
-       public void destroy() throws FilesystemAccessException {
-               try {
-                       entry.destroy();
-               } catch (IOException e) {
-                       throw new FilesystemAccessException(
-                                       "failed to delete directory entry", e);
-               }
-       }
-
-       @Override
-       public String getFullName() {
-               if (full != null)
-                       return full;
-               String n = getName();
-               RemoteDirectoryEntry re = entry;
-               try {
-                       while (true) {
-                               RemoteDirectory parent = 
re.getContainingDirectory();
-                               if (parent == null)
-                                       break;
-                               n = parent.getName() + "/" + n;
-                               re = parent;
-                       }
-               } catch (RemoteException e) {
-                       log.warn("failed to generate full name", e);
-               }
-               return (full = n);
-       }
-
-       @Override
-       public String getName() {
-               if (name == null)
-                       try {
-                               name = entry.getName();
-                       } catch (RemoteException e) {
-                               log.error("failed to get name", e);
-                       }
-               return name;
-       }
-
-       @Override
-       public Date getModificationDate() {
-               if (cacheModTime == null || currentTimeMillis() - 
cacheQueryTime < 5000)
-                       try {
-                               cacheModTime = entry.getModificationDate();
-                               cacheQueryTime = currentTimeMillis();
-                       } catch (RemoteException e) {
-                               log.error("failed to get modification time", e);
-                       }
-               return cacheModTime;
-       }
-
-       @Override
-       public int compareTo(DirectoryEntry de) {
-               return getFullName().compareTo(de.getFullName());
-       }
-
-       @Override
-       public boolean equals(Object o) {
-               return o != null && o instanceof DEDelegate
-                               && getFullName().equals(((DEDelegate) 
o).getFullName());
-       }
-
-       @Override
-       public int hashCode() {
-               return getFullName().hashCode();
-       }
-}
-
-class DirectoryDelegate extends DEDelegate implements Directory {
-       RemoteDirectory rd;
-
-       DirectoryDelegate(RemoteDirectory dir) {
-               super(dir);
-               rd = dir;
-       }
-
-       @Override
-       public Collection<DirectoryEntry> getContents()
-                       throws FilesystemAccessException {
-               ArrayList<DirectoryEntry> result = new ArrayList<>();
-               try {
-                       for (RemoteDirectoryEntry rde : rd.getContents()) {
-                               if (rde instanceof RemoteDirectory)
-                                       result.add(new 
DirectoryDelegate((RemoteDirectory) rde));
-                               else
-                                       result.add(new 
FileDelegate((RemoteFile) rde));
-                       }
-               } catch (IOException e) {
-                       throw new FilesystemAccessException(
-                                       "failed to get directory contents", e);
-               }
-               return result;
-       }
-
-       @Override
-       public Collection<DirectoryEntry> getContentsByDate()
-                       throws FilesystemAccessException {
-               ArrayList<DirectoryEntry> result = new 
ArrayList<>(getContents());
-               sort(result, new DateComparator());
-               return result;
-       }
-
-       static class DateComparator implements Comparator<DirectoryEntry> {
-               @Override
-               public int compare(DirectoryEntry a, DirectoryEntry b) {
-                       return 
a.getModificationDate().compareTo(b.getModificationDate());
-               }
-       }
-
-       @Override
-       public File makeEmptyFile(Principal actor, String name)
-                       throws FilesystemAccessException {
-               try {
-                       return new FileDelegate(rd.makeEmptyFile(name));
-               } catch (IOException e) {
-                       throw new FilesystemAccessException("failed to make 
empty file", e);
-               }
-       }
-
-       @Override
-       public Directory makeSubdirectory(Principal actor, String name)
-                       throws FilesystemAccessException {
-               try {
-                       return new DirectoryDelegate(rd.makeSubdirectory(name));
-               } catch (IOException e) {
-                       throw new FilesystemAccessException("failed to make 
subdirectory",
-                                       e);
-               }
-       }
-
-       @Override
-       public ZipStream getContentsAsZip() throws FilesystemAccessException {
-               ZipStream zs = new ZipStream();
-
-               final ZipOutputStream zos;
-               try {
-                       zos = new ZipOutputStream(new PipedOutputStream(zs));
-               } catch (IOException e) {
-                       throw new FilesystemAccessException("problem building 
zip stream",
-                                       e);
-               }
-               Thread t = new Thread(new Runnable() {
-                       @Override
-                       public void run() {
-                               try {
-                                       zipDirectory(rd, null, zos);
-                               } catch (IOException e) {
-                                       log.warn("problem when zipping 
directory", e);
-                               } finally {
-                                       closeQuietly(zos);
-                               }
-                       }
-               });
-               t.setDaemon(true);
-               t.start();
-               return zs;
-       }
-
-       /**
-        * Compresses a directory tree into a ZIP.
-        * 
-        * @param dir
-        *            The directory to compress.
-        * @param base
-        *            The base name of the directory (or <tt>null</tt> if this 
is
-        *            the root directory of the ZIP).
-        * @param zos
-        *            Where to write the compressed data.
-        * @throws RemoteException
-        *             If some kind of problem happens with the remote 
delegates.
-        * @throws IOException
-        *             If we run into problems with reading or writing data.
-        */
-       void zipDirectory(RemoteDirectory dir, String base, ZipOutputStream zos)
-                       throws RemoteException, IOException {
-               for (RemoteDirectoryEntry rde : dir.getContents()) {
-                       String name = rde.getName();
-                       if (base != null)
-                               name = base + "/" + name;
-                       if (rde instanceof RemoteDirectory) {
-                               RemoteDirectory rd = (RemoteDirectory) rde;
-                               zipDirectory(rd, name, zos);
-                       } else {
-                               RemoteFile rf = (RemoteFile) rde;
-                               zos.putNextEntry(new ZipEntry(name));
-                               try {
-                                       int off = 0;
-                                       while (true) {
-                                               byte[] c = rf.getContents(off, 
64 * 1024);
-                                               if (c == null || c.length == 0)
-                                                       break;
-                                               zos.write(c);
-                                               off += c.length;
-                                       }
-                               } finally {
-                                       zos.closeEntry();
-                               }
-                       }
-               }
-       }
-}
-
-class FileDelegate extends DEDelegate implements File {
-       RemoteFile rf;
-
-       FileDelegate(RemoteFile f) {
-               super(f);
-               this.rf = f;
-       }
-
-       @Override
-       public byte[] getContents(int offset, int length)
-                       throws FilesystemAccessException {
-               try {
-                       return rf.getContents(offset, length);
-               } catch (IOException e) {
-                       throw new FilesystemAccessException("failed to read 
file contents",
-                                       e);
-               }
-       }
-
-       @Override
-       public long getSize() throws FilesystemAccessException {
-               try {
-                       return rf.getSize();
-               } catch (IOException e) {
-                       throw new FilesystemAccessException("failed to get file 
length", e);
-               }
-       }
-
-       @Override
-       public void setContents(byte[] data) throws FilesystemAccessException {
-               try {
-                       rf.setContents(data);
-               } catch (IOException e) {
-                       throw new FilesystemAccessException(
-                                       "failed to write file contents", e);
-               }
-       }
-
-       @Override
-       public void appendContents(byte[] data) throws 
FilesystemAccessException {
-               try {
-                       rf.appendContents(data);
-               } catch (IOException e) {
-                       throw new FilesystemAccessException(
-                                       "failed to write file contents", e);
-               }
-       }
-
-       @Override
-       public void copy(File from) throws FilesystemAccessException {
-               FileDelegate fromFile;
-               try {
-                       fromFile = (FileDelegate) from;
-               } catch (ClassCastException e) {
-                       throw new FilesystemAccessException("different types of 
File?!");
-               }
-
-               try {
-                       rf.copy(fromFile.rf);
-               } catch (Exception e) {
-                       throw new FilesystemAccessException("failed to copy 
file contents",
-                                       e);
-               }
-               return;
-       }
-}
-
-class ListenerDelegate implements Listener {
-       private Log log = getLog("Taverna.Server.Worker");
-       private RemoteListener r;
-       String conf;
-
-       ListenerDelegate(RemoteListener l) {
-               r = l;
-       }
-
-       RemoteListener getRemote() {
-               return r;
-       }
-
-       @Override
-       public String getConfiguration() {
-               try {
-                       if (conf == null)
-                               conf = r.getConfiguration();
-               } catch (RemoteException e) {
-                       log.warn("failed to get configuration", e);
-               }
-               return conf;
-       }
-
-       @Override
-       public String getName() {
-               try {
-                       return r.getName();
-               } catch (RemoteException e) {
-                       log.warn("failed to get name", e);
-                       return "UNKNOWN NAME";
-               }
-       }
-
-       @Override
-       public String getProperty(String propName) throws NoListenerException {
-               try {
-                       return r.getProperty(propName);
-               } catch (RemoteException e) {
-                       throw new NoListenerException("no such property: " + 
propName, e);
-               }
-       }
-
-       @Override
-       public String getType() {
-               try {
-                       return r.getType();
-               } catch (RemoteException e) {
-                       log.warn("failed to get type", e);
-                       return "UNKNOWN TYPE";
-               }
-       }
-
-       @Override
-       public String[] listProperties() {
-               try {
-                       return r.listProperties();
-               } catch (RemoteException e) {
-                       log.warn("failed to list properties", e);
-                       return new String[0];
-               }
-       }
-
-       @Override
-       public void setProperty(String propName, String value)
-                       throws NoListenerException, BadPropertyValueException {
-               try {
-                       r.setProperty(propName, value);
-               } catch (RemoteException e) {
-                       log.warn("failed to set property", e);
-                       if (e.getCause() != null
-                                       && e.getCause() instanceof 
RuntimeException)
-                               throw new NoListenerException("failed to set 
property",
-                                               e.getCause());
-                       if (e.getCause() != null && e.getCause() instanceof 
Exception)
-                               throw new BadPropertyValueException("failed to 
set property",
-                                               e.getCause());
-                       throw new BadPropertyValueException("failed to set 
property", e);
-               }
-       }
-}
-
-class RunInput implements Input {
-       private final RemoteInput i;
-
-       RunInput(RemoteInput remote) {
-               this.i = remote;
-       }
-
-       @Override
-       public String getFile() {
-               try {
-                       return i.getFile();
-               } catch (RemoteException e) {
-                       return null;
-               }
-       }
-
-       @Override
-       public String getName() {
-               try {
-                       return i.getName();
-               } catch (RemoteException e) {
-                       return null;
-               }
-       }
-
-       @Override
-       public String getValue() {
-               try {
-                       return i.getValue();
-               } catch (RemoteException e) {
-                       return null;
-               }
-       }
-
-       @Override
-       public void setFile(String file) throws FilesystemAccessException,
-                       BadStateChangeException {
-               checkBadFilename(file);
-               try {
-                       i.setFile(file);
-               } catch (RemoteException e) {
-                       throw new FilesystemAccessException("cannot set file 
for input", e);
-               }
-       }
-
-       @Override
-       public void setValue(String value) throws BadStateChangeException {
-               try {
-                       i.setValue(value);
-               } catch (RemoteException e) {
-                       throw new BadStateChangeException(e);
-               }
-       }
-
-       @Override
-       public String getDelimiter() {
-               try {
-                       return i.getDelimiter();
-               } catch (RemoteException e) {
-                       return null;
-               }
-       }
-
-       @Override
-       public void setDelimiter(String delimiter) throws 
BadStateChangeException {
-               try {
-                       if (delimiter != null)
-                               delimiter = delimiter.substring(0, 1);
-                       i.setDelimiter(delimiter);
-               } catch (RemoteException e) {
-                       throw new BadStateChangeException(e);
-               }
-       }
-}
-
-@SuppressWarnings("serial")
-class SecurityContextReconstructionException extends RuntimeException {
-       public SecurityContextReconstructionException(Throwable t) {
-               super("failed to rebuild security context", t);
-       }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
deleted file mode 100644
index 0c2b1a9..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunConnection.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static org.taverna.server.master.worker.RunConnection.COUNT_QUERY;
-import static org.taverna.server.master.worker.RunConnection.NAMES_QUERY;
-import static org.taverna.server.master.worker.RunConnection.SCHEMA;
-import static org.taverna.server.master.worker.RunConnection.TABLE;
-import static org.taverna.server.master.worker.RunConnection.TIMEOUT_QUERY;
-import static 
org.taverna.server.master.worker.RunConnection.UNTERMINATED_QUERY;
-
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.jdo.annotations.Column;
-import javax.jdo.annotations.Join;
-import javax.jdo.annotations.PersistenceCapable;
-import javax.jdo.annotations.Persistent;
-import javax.jdo.annotations.PrimaryKey;
-import javax.jdo.annotations.Queries;
-import javax.jdo.annotations.Query;
-
-import org.taverna.server.localworker.remote.RemoteSingleRun;
-import org.taverna.server.master.common.Credential;
-import org.taverna.server.master.common.Trust;
-import org.taverna.server.master.common.Workflow;
-import org.taverna.server.master.interfaces.SecurityContextFactory;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * The representation of the connections to the runs that actually participates
- * in the persistence system.
- * 
- * @author Donal Fellows
- */
-@PersistenceCapable(table = TABLE, schema = SCHEMA)
-@Queries({
-               @Query(name = "count", language = "SQL", value = COUNT_QUERY, 
unique = "true", resultClass = Integer.class),
-               @Query(name = "names", language = "SQL", value = NAMES_QUERY, 
unique = "false", resultClass = String.class),
-               @Query(name = "unterminated", language = "SQL", value = 
UNTERMINATED_QUERY, unique = "false", resultClass = String.class),
-               @Query(name = "timedout", language = "SQL", value = 
TIMEOUT_QUERY, unique = "false", resultClass = String.class) })
-public class RunConnection {
-       static final String SCHEMA = "TAVERNA";
-       static final String TABLE = "RUN_CONNECTION";
-       private static final String FULL_NAME = SCHEMA + "." + TABLE;
-       static final String COUNT_QUERY = "SELECT count(*) FROM " + FULL_NAME;
-       static final String NAMES_QUERY = "SELECT ID FROM " + FULL_NAME;
-       static final String TIMEOUT_QUERY = "SELECT ID FROM " + FULL_NAME
-                       + "   WHERE expiry < CURRENT_TIMESTAMP";
-       static final String UNTERMINATED_QUERY = "SELECT ID FROM " + FULL_NAME
-                       + "   WHERE doneTransitionToFinished = 0";
-       static final int NAME_LENGTH = 48; 
-
-       @PrimaryKey
-       @Column(length = 40)
-       private String id;
-
-       @Persistent(defaultFetchGroup = "true")
-       @Column(length = NAME_LENGTH)
-       private String name;
-
-       @Persistent(defaultFetchGroup = "true")
-       private Date creationInstant;
-
-       @Persistent(defaultFetchGroup = "true", serialized = "true")
-       @Column(jdbcType = "BLOB", sqlType = "BLOB")
-       private Workflow workflow;
-
-       @Persistent(defaultFetchGroup = "true")
-       private Date expiry;
-
-       @Persistent(defaultFetchGroup = "true")
-       @Join(table = TABLE + "_READERS", column = "ID")
-       private String[] readers;
-
-       @Persistent(defaultFetchGroup = "true")
-       @Join(table = TABLE + "_WRITERS", column = "ID")
-       private String[] writers;
-
-       @Persistent(defaultFetchGroup = "true")
-       @Join(table = TABLE + "_DESTROYERS", column = "ID")
-       private String[] destroyers;
-
-       @Persistent(defaultFetchGroup = "true", serialized = "true")
-       @Column(jdbcType = "BLOB", sqlType = "BLOB")
-       private MarshalledObject<RemoteSingleRun> run;
-
-       @Persistent(defaultFetchGroup = "true")
-       private int doneTransitionToFinished;
-
-       @Persistent(defaultFetchGroup = "true")
-       private int generateProvenance;
-
-       @Persistent(defaultFetchGroup = "true")
-       @Column(length = 128)
-       String owner;
-
-       @Persistent(defaultFetchGroup = "true")
-       @Column(length = 36)
-       private String securityToken;
-
-       @Persistent(defaultFetchGroup = "true", serialized = "true")
-       @Column(jdbcType = "BLOB", sqlType = "BLOB")
-       private SecurityContextFactory securityContextFactory;
-       @Persistent(defaultFetchGroup = "true", serialized = "true")
-       @Column(jdbcType = "BLOB", sqlType = "BLOB")
-       private Credential[] credentials;
-       @Persistent(defaultFetchGroup = "true", serialized = "true")
-       @Column(jdbcType = "BLOB", sqlType = "BLOB")
-       private Trust[] trust;
-
-       private static final String[] STRING_ARY = new String[0];
-
-       public String getId() {
-               return id;
-       }
-
-       public boolean isFinished() {
-               return doneTransitionToFinished != 0;
-       }
-
-       public void setFinished(boolean finished) {
-               doneTransitionToFinished = (finished ? 1 : 0);
-       }
-
-       public boolean isProvenanceGenerated() {
-               return generateProvenance != 0;
-       }
-
-       public void setProvenanceGenerated(boolean generate) {
-               generateProvenance = (generate ? 1 : 0);
-       }
-
-       /**
-        * Manufacture a persistent representation of the given workflow run. 
Must
-        * be called within the context of a transaction.
-        * 
-        * @param rrd
-        *            The remote delegate of the workflow run.
-        * @return The persistent object.
-        * @throws IOException
-        *             If serialisation fails.
-        */
-       @Nonnull
-       public static RunConnection toDBform(@Nonnull RemoteRunDelegate rrd)
-                       throws IOException {
-               RunConnection rc = new RunConnection();
-               rc.id = rrd.id;
-               rc.makeChanges(rrd);
-               return rc;
-       }
-
-       private static List<String> list(String[] ary) {
-               if (ary == null)
-                       return emptyList();
-               return asList(ary);
-       }
-
-       /**
-        * Get the remote run delegate for a particular persistent connection. 
Must
-        * be called within the context of a transaction.
-        * 
-        * @param db
-        *            The database facade.
-        * @return The delegate object.
-        * @throws Exception
-        *             If anything goes wrong.
-        */
-       @Nonnull
-       public RemoteRunDelegate fromDBform(@Nonnull RunDBSupport db)
-                       throws Exception {
-               RemoteRunDelegate rrd = new RemoteRunDelegate();
-               rrd.id = getId();
-               rrd.creationInstant = creationInstant;
-               rrd.workflow = workflow;
-               rrd.expiry = expiry;
-               rrd.readers = new HashSet<>(list(readers));
-               rrd.writers = new HashSet<>(list(writers));
-               rrd.destroyers = new HashSet<>(list(destroyers));
-               rrd.run = run.get();
-               rrd.doneTransitionToFinished = isFinished();
-               rrd.generateProvenance = isProvenanceGenerated();
-               rrd.secContext = securityContextFactory.create(rrd,
-                               new UsernamePrincipal(owner));
-               
((SecurityContextDelegate)rrd.secContext).setCredentialsAndTrust(credentials,trust);
-               rrd.db = db;
-               rrd.factory = db.getFactory();
-               rrd.name = name;
-               return rrd;
-       }
-
-       /**
-        * Flush changes from a remote run delegate to the database. Must be 
called
-        * within the context of a transaction.
-        * 
-        * @param rrd
-        *            The remote run delegate object that has potential changes.
-        * @throws IOException
-        *             If anything goes wrong in serialization.
-        */
-       public void makeChanges(@Nonnull RemoteRunDelegate rrd) throws 
IOException {
-               // Properties that are set exactly once
-               if (creationInstant == null) {
-                       creationInstant = rrd.getCreationTimestamp();
-                       workflow = rrd.getWorkflow();
-                       run = new MarshalledObject<>(rrd.run);
-                       securityContextFactory = 
rrd.getSecurityContext().getFactory();
-                       owner = rrd.getSecurityContext().getOwner().getName();
-                       securityToken = 
((org.taverna.server.master.worker.SecurityContextFactory) 
securityContextFactory)
-                                       .issueNewPassword();
-               }
-               // Properties that are set multiple times
-               expiry = rrd.getExpiry();
-               readers = rrd.getReaders().toArray(STRING_ARY);
-               writers = rrd.getWriters().toArray(STRING_ARY);
-               destroyers = rrd.getDestroyers().toArray(STRING_ARY);
-               credentials = rrd.getSecurityContext().getCredentials();
-               trust = rrd.getSecurityContext().getTrusted();
-               if (rrd.name.length() > NAME_LENGTH)
-                       this.name = rrd.name.substring(0, NAME_LENGTH);
-               else
-                       this.name = rrd.name;
-               setFinished(rrd.doneTransitionToFinished);
-               setProvenanceGenerated(rrd.generateProvenance);
-       }
-
-       public String getSecurityToken() {
-               return securityToken;
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
deleted file mode 100644
index 5fa96b8..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDBSupport.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.util.List;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.taverna.server.master.notification.NotificationEngine;
-
-/**
- * The interface to the database of runs.
- * 
- * @author Donal Fellows
- */
-public interface RunDBSupport {
-       /**
-        * Scan each run to see if it has finished yet and issue registered
-        * notifications if it has.
-        */
-       void checkForFinishNow();
-
-       /**
-        * Remove currently-expired runs from this database.
-        */
-       void cleanNow();
-
-       /**
-        * How many runs are stored in the database.
-        * 
-        * @return The current size of the run table.
-        */
-       int countRuns();
-
-       /**
-        * Ensure that a run gets persisted in the database. It is assumed that 
the
-        * value is already in there.
-        * 
-        * @param run
-        *            The run to persist.
-        */
-       void flushToDisk(@Nonnull RemoteRunDelegate run);
-
-       /**
-        * Select an arbitrary representative run.
-        * 
-        * @return The selected run.
-        * @throws Exception
-        *             If anything goes wrong.
-        */
-       @Nullable
-       RemoteRunDelegate pickArbitraryRun() throws Exception;
-
-       /**
-        * Get a list of all the run names.
-        * 
-        * @return The names (i.e., UUIDs) of all the runs.
-        */
-       @Nonnull
-       List<String> listRunNames();
-
-       /**
-        * @param notificationEngine
-        *            A reference to the notification fabric bean.
-        */
-       void setNotificationEngine(NotificationEngine notificationEngine);
-
-       /**
-        * @param notifier
-        *            A reference to the bean that creates messages about 
workflow
-        *            run termination.
-        */
-       void setNotifier(CompletionNotifier notifier);
-
-       /**
-        * @return A reference to the actual factory for remote runs.
-        */
-       FactoryBean getFactory();
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-server/blob/00397eff/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
----------------------------------------------------------------------
diff --git 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
 
b/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
deleted file mode 100644
index 65aec70..0000000
--- 
a/taverna-server-webapp/src/main/java/org/taverna/server/master/worker/RunDatabase.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- */
-package org.taverna.server.master.worker;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import static java.lang.Integer.parseInt;
-import static java.util.UUID.randomUUID;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Required;
-import org.taverna.server.master.common.Status;
-import org.taverna.server.master.exceptions.UnknownRunException;
-import org.taverna.server.master.interfaces.Listener;
-import org.taverna.server.master.interfaces.Policy;
-import org.taverna.server.master.interfaces.RunStore;
-import org.taverna.server.master.interfaces.TavernaRun;
-import org.taverna.server.master.notification.NotificationEngine;
-import org.taverna.server.master.notification.NotificationEngine.Message;
-import org.taverna.server.master.utils.UsernamePrincipal;
-
-/**
- * The main facade bean that interfaces to the database of runs.
- * 
- * @author Donal Fellows
- */
-public class RunDatabase implements RunStore, RunDBSupport {
-       private Log log = LogFactory.getLog("Taverna.Server.Worker.RunDB");
-       RunDatabaseDAO dao;
-       CompletionNotifier backupNotifier;
-       Map<String, CompletionNotifier> typedNotifiers;
-       private NotificationEngine notificationEngine;
-       @Autowired
-       private FactoryBean factory;
-       private Map<String, TavernaRun> cache = new HashMap<>();
-
-       @Override
-       @Required
-       public void setNotifier(CompletionNotifier n) {
-               backupNotifier = n;
-       }
-
-       public void setTypeNotifiers(List<CompletionNotifier> notifiers) {
-               typedNotifiers = new HashMap<>();
-               for (CompletionNotifier n : notifiers)
-                       typedNotifiers.put(n.getName(), n);
-       }
-
-       @Required
-       @Override
-       public void setNotificationEngine(NotificationEngine 
notificationEngine) {
-               this.notificationEngine = notificationEngine;
-       }
-
-       @Required
-       public void setDao(RunDatabaseDAO dao) {
-               this.dao = dao;
-       }
-
-       @Override
-       public void checkForFinishNow() {
-               /*
-                * Get which runs are actually newly finished; this requires 
getting the
-                * candidates from the database and *then* doing the expensive 
requests
-                * to the back end to find out the status.
-                */
-               Map<String, RemoteRunDelegate> notifiable = new HashMap<>();
-               for (RemoteRunDelegate p : dao.getPotentiallyNotifiable())
-                       if (p.getStatus() == Status.Finished)
-                               notifiable.put(p.getId(), p);
-
-               // Check if there's nothing more to do
-               if (notifiable.isEmpty())
-                       return;
-
-               /*
-                * Tell the database about the ones we've got.
-                */
-               dao.markFinished(notifiable.keySet());
-
-               /*
-                * Send out the notifications. The notification addresses are 
stored in
-                * the back-end engine, so this is *another* thing that can 
take time.
-                */
-               for (RemoteRunDelegate rrd : notifiable.values())
-                       for (Listener l : rrd.getListeners())
-                               if (l.getName().equals("io")) {
-                                       try {
-                                               notifyFinished(rrd.id, l, rrd);
-                                       } catch (Exception e) {
-                                               log.warn("failed to do 
notification of completion", e);
-                                       }
-                                       break;
-                               }
-       }
-
-       @Override
-       public void cleanNow() {
-               List<String> cleaned;
-               try {
-                       cleaned = dao.doClean();
-               } catch (Exception e) {
-                       log.warn("failure during deletion of expired runs", e);
-                       return;
-               }
-               synchronized (cache) {
-                       for (String id : cleaned)
-                               cache.remove(id);
-               }
-       }
-
-       @Override
-       public int countRuns() {
-               return dao.countRuns();
-       }
-
-       @Override
-       public void flushToDisk(RemoteRunDelegate run) {
-               try {
-                       dao.flushToDisk(run);
-               } catch (IOException e) {
-                       throw new RuntimeException(
-                                       "unexpected problem when persisting run 
record in database",
-                                       e);
-               }
-       }
-
-       @Override
-       public RemoteRunDelegate pickArbitraryRun() throws Exception {
-               return dao.pickArbitraryRun();
-       }
-
-       @Override
-       public List<String> listRunNames() {
-               return dao.listRunNames();
-       }
-
-       @Nullable
-       private TavernaRun get(String uuid) {
-               TavernaRun run = null;
-               synchronized (cache) {
-                       run = cache.get(uuid);
-               }
-               try {
-                       if (run != null)
-                               run.ping();
-               } catch (UnknownRunException e) {
-                       if (log.isDebugEnabled())
-                               log.debug("stale mapping in cache?", e);
-                       // Don't need to flush the cache; this happens when 
cleaning anyway
-                       run = null;
-               }
-               if (run == null)
-                       run = dao.get(uuid);
-               return run;
-       }
-
-       @Override
-       public TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid)
-                       throws UnknownRunException {
-               // Check first to see if the 'uuid' actually looks like a UUID; 
if
-               // not, throw it out immediately without logging an exception.
-               try {
-                       UUID.fromString(uuid);
-               } catch (IllegalArgumentException e) {
-                       if (log.isDebugEnabled())
-                               log.debug("run ID does not look like UUID; 
rejecting...");
-                       throw new UnknownRunException();
-               }
-               TavernaRun run = get(uuid);
-               if (run != null && (user == null || p.permitAccess(user, run)))
-                       return run;
-               throw new UnknownRunException();
-       }
-
-       @Override
-       public TavernaRun getRun(String uuid) throws UnknownRunException {
-               TavernaRun run = get(uuid);
-               if (run != null)
-                       return run;
-               throw new UnknownRunException();
-       }
-
-       @Override
-       public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy 
p) {
-               synchronized (cache) {
-                       Map<String, TavernaRun> cached = new HashMap<>();
-                       for (Entry<String, TavernaRun> e : cache.entrySet()) {
-                               TavernaRun r = e.getValue();
-                               if (p.permitAccess(user, r))
-                                       cached.put(e.getKey(), r);
-                       }
-                       if (!cached.isEmpty())
-                               return cached;
-               }
-               return dao.listRuns(user, p);
-       }
-
-       private void logLength(String message, Object obj) {
-               if (!log.isDebugEnabled())
-                       return;
-               try {
-                       ByteArrayOutputStream baos = new 
ByteArrayOutputStream();
-                       try (ObjectOutputStream oos = new 
ObjectOutputStream(baos)) {
-                               oos.writeObject(obj);
-                       }
-                       log.debug(message + ": " + baos.size());
-               } catch (Exception e) {
-                       log.warn("oops", e);
-               }
-       }
-
-       @Override
-       public String registerRun(TavernaRun run) {
-               if (!(run instanceof RemoteRunDelegate))
-                       throw new IllegalArgumentException(
-                                       "run must be created by localworker 
package");
-               RemoteRunDelegate rrd = (RemoteRunDelegate) run;
-               if (rrd.id == null)
-                       rrd.id = randomUUID().toString();
-               logLength("RemoteRunDelegate serialized length", rrd);
-               try {
-                       dao.persistRun(rrd);
-               } catch (IOException e) {
-                       throw new RuntimeException(
-                                       "unexpected problem when persisting run 
record in database",
-                                       e);
-               }
-               synchronized (cache) {
-                       cache.put(rrd.getId(), run);
-               }
-               return rrd.getId();
-       }
-
-       @Override
-       public void unregisterRun(String uuid) {
-               try {
-                       if (dao.unpersistRun(uuid))
-                               synchronized (cache) {
-                                       cache.remove(uuid);
-                               }
-               } catch (RuntimeException e) {
-                       if (log.isDebugEnabled())
-                               log.debug("problem persisting the deletion of 
the run " + uuid,
-                                               e);
-               }
-       }
-
-       /**
-        * Process the event that a run has finished.
-        * 
-        * @param name
-        *            The name of the run.
-        * @param io
-        *            The io listener of the run (used to get information about 
the
-        *            run).
-        * @param run
-        *            The handle to the run.
-        * @throws Exception
-        *             If anything goes wrong.
-        */
-       private void notifyFinished(final String name, Listener io,
-                       final RemoteRunDelegate run) throws Exception {
-               String to = io.getProperty("notificationAddress");
-               final int code;
-               try {
-                       code = parseInt(io.getProperty("exitcode"));
-               } catch (NumberFormatException nfe) {
-                       // Ignore; not much we can do here...
-                       return;
-               }
-
-               notificationEngine.dispatchMessage(run, to, new Message() {
-                       private CompletionNotifier getNotifier(String type) {
-                               CompletionNotifier n = typedNotifiers.get(type);
-                               if (n == null)
-                                       n = backupNotifier;
-                               return n;
-                       }
-
-                       @Override
-                       public String getContent(String type) {
-                               return 
getNotifier(type).makeCompletionMessage(name, run, code);
-                       }
-
-                       @Override
-                       public String getTitle(String type) {
-                               return 
getNotifier(type).makeMessageSubject(name, run, code);
-                       }
-               });
-       }
-
-       @Override
-       public FactoryBean getFactory() {
-               return factory;
-       }
-}

Reply via email to