http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionRegistryImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionRegistryImpl.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionRegistryImpl.java
new file mode 100644
index 0000000..878cb19
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionRegistryImpl.java
@@ -0,0 +1,652 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.servicedescriptions.impl;
+
+import static java.lang.System.currentTimeMillis;
+import static java.lang.Thread.MIN_PRIORITY;
+import static java.lang.Thread.currentThread;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.taverna.lang.observer.MultiCaster;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.servicedescriptions.ConfigurableServiceProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescription;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionsConfiguration;
+import 
org.apache.taverna.servicedescriptions.ServiceDescriptionProvider.FindServiceDescriptionsCallBack;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+import org.apache.taverna.servicedescriptions.events.AddedProviderEvent;
+import 
org.apache.taverna.servicedescriptions.events.PartialServiceDescriptionsNotification;
+import org.apache.taverna.servicedescriptions.events.ProviderErrorNotification;
+import 
org.apache.taverna.servicedescriptions.events.ProviderStatusNotification;
+import 
org.apache.taverna.servicedescriptions.events.ProviderUpdatingNotification;
+import 
org.apache.taverna.servicedescriptions.events.ProviderWarningNotification;
+import org.apache.taverna.servicedescriptions.events.RemovedProviderEvent;
+import 
org.apache.taverna.servicedescriptions.events.ServiceDescriptionProvidedEvent;
+import 
org.apache.taverna.servicedescriptions.events.ServiceDescriptionRegistryEvent;
+import 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionDeserializer.DeserializationException;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+public class ServiceDescriptionRegistryImpl implements 
ServiceDescriptionRegistry {
+       /**
+        * If a writable property of this name on a provider exists (ie. the 
provider has a method
+        * setServiceDescriptionRegistry(ServiceDescriptionRegistry registry) - 
then this property will
+        * be set to the current registry.
+        */
+       public static final String SERVICE_DESCRIPTION_REGISTRY = 
"serviceDescriptionRegistry";
+       public static Logger logger = 
Logger.getLogger(ServiceDescriptionRegistryImpl.class);
+       public static final ThreadGroup threadGroup = new ThreadGroup("Service 
description providers");
+       /**
+        * Total maximum timeout while waiting for description threads to finish
+        */
+       private static final long DESCRIPTION_THREAD_TIMEOUT_MS = 3000;
+       protected static final String CONF_DIR = "conf";
+       protected static final String SERVICE_PROVIDERS_FILENAME = 
"service_providers.xml";
+       private static final String 
DEFAULT_CONFIGURABLE_SERVICE_PROVIDERS_FILENAME = 
"default_service_providers.xml";
+
+       private ServiceDescriptionsConfiguration serviceDescriptionsConfig;
+       private ApplicationConfiguration applicationConfiguration;
+       /**
+        * <code>false</code> until first call to {@link 
#loadServiceProviders()} - which is done by
+        * first call to {@link #getServiceDescriptionProviders()}.
+        */
+       private boolean hasLoadedProviders = false;
+       /**
+        * <code>true</code> while {@link #loadServiceProviders(File)},
+        * {@link #loadServiceProviders(URL)} or {@link 
#loadServiceProviders()} is in progress, avoids
+        * triggering {@link #saveServiceDescriptions()} on
+        * {@link #addServiceDescriptionProvider(ServiceDescriptionProvider)} 
calls.
+        */
+       private boolean loading = false;
+       private MultiCaster<ServiceDescriptionRegistryEvent> observers = new 
MultiCaster<>(this);
+       private List<ServiceDescriptionProvider> serviceDescriptionProviders;
+       private Set<ServiceDescriptionProvider> allServiceProviders;
+       private Map<ServiceDescriptionProvider, Set<ServiceDescription>> 
providerDescriptions = new HashMap<>();
+       private Map<ServiceDescriptionProvider, Thread> 
serviceDescriptionThreads = new HashMap<>();
+       /**
+        * Service providers added by the user, should be saved
+        */
+       private Set<ServiceDescriptionProvider> userAddedProviders = new 
HashSet<>();
+       private Set<ServiceDescriptionProvider> userRemovedProviders = new 
HashSet<>();
+       private Set<ServiceDescriptionProvider> 
defaultServiceDescriptionProviders;
+       /**
+        * File containing a list of configured ConfigurableServiceProviders 
which is used to get the
+        * default set of service descriptions together with those provided by 
AbstractTemplateServiceS.
+        * This file is located in the conf directory of the Taverna startup 
directory.
+        */
+       private File defaultConfigurableServiceProvidersFile;
+       private boolean defaultSystemConfigurableProvidersLoaded = false;
+
+       static {
+               threadGroup.setMaxPriority(MIN_PRIORITY);
+       }
+
+       public ServiceDescriptionRegistryImpl(
+                       ApplicationConfiguration applicationConfiguration) {
+               this.applicationConfiguration = applicationConfiguration;
+               defaultConfigurableServiceProvidersFile = new File(
+                               getTavernaStartupConfigurationDirectory(),
+                               
DEFAULT_CONFIGURABLE_SERVICE_PROVIDERS_FILENAME);
+       }
+
+       /**
+        * Get the Taverna distribution (startup) configuration directory.
+        */
+       private File getTavernaStartupConfigurationDirectory() {
+               File distroHome = null;
+               File configDirectory = null;
+               distroHome = applicationConfiguration.getStartupDir();
+               configDirectory = new File(distroHome, "conf");
+               if (!configDirectory.exists())
+                       configDirectory.mkdir();
+               return configDirectory;
+       }
+
+       private static void joinThreads(Collection<? extends Thread> threads,
+                       long descriptionThreadTimeoutMs) {
+               long finishJoinBy = currentTimeMillis() + 
descriptionThreadTimeoutMs;
+               for (Thread thread : threads) {
+                       // No shorter timeout than 1 ms (thread.join(0) waits 
forever!)
+                       long timeout = Math.max(1, finishJoinBy - 
currentTimeMillis());
+                       try {
+                               thread.join(timeout);
+                       } catch (InterruptedException e) {
+                               currentThread().interrupt();
+                               return;
+                       }
+                       if (thread.isAlive())
+                               logger.debug("Thread did not finish " + thread);
+               }
+       }
+
+
+       @Override
+       public void addObserver(Observer<ServiceDescriptionRegistryEvent> 
observer) {
+               observers.addObserver(observer);
+       }
+
+       @Override
+       public void addServiceDescriptionProvider(ServiceDescriptionProvider 
provider) {
+               synchronized (this) {
+                       userRemovedProviders.remove(provider);
+                       if 
(!getDefaultServiceDescriptionProviders().contains(provider))
+                               userAddedProviders.add(provider);
+                       allServiceProviders.add(provider);
+               }
+
+               // Spring-like auto-config
+               try {
+                       // BeanUtils should ignore this if provider does not 
have that property
+                       BeanUtils.setProperty(provider, 
SERVICE_DESCRIPTION_REGISTRY, this);
+               } catch (IllegalAccessException | InvocationTargetException e) {
+                       logger.warn("Could not set serviceDescriptionRegistry 
on "
+                                       + provider, e);
+               }
+
+               if (!loading)
+                       saveServiceDescriptions();
+               observers.notify(new AddedProviderEvent(provider));
+               updateServiceDescriptions(false, false);
+       }
+
+       private File findServiceDescriptionsFile() {
+               File confDir = new File(
+                               
applicationConfiguration.getApplicationHomeDir(), CONF_DIR);
+               confDir.mkdirs();
+               if (!confDir.isDirectory())
+                       throw new RuntimeException("Invalid directory: " + 
confDir);
+               File serviceDescriptionsFile = new File(confDir,
+                               SERVICE_PROVIDERS_FILENAME);
+               return serviceDescriptionsFile;
+       }
+
+       @Override
+       public List<Observer<ServiceDescriptionRegistryEvent>> getObservers() {
+               return observers.getObservers();
+       }
+
+       // Fallback to this method that uses hardcoded default services if you 
cannot read them from
+       // the file.
+//     @SuppressWarnings("unchecked")
+//     public synchronized Set<ServiceDescriptionProvider> 
getDefaultServiceDescriptionProvidersFallback() {
+//             /*if (defaultServiceDescriptionProviders != null) {
+//      return defaultServiceDescriptionProviders;
+//      }
+//      defaultServiceDescriptionProviders = new 
HashSet<ServiceDescriptionProvider>();
+//              */
+//             for (ServiceDescriptionProvider provider : 
serviceDescriptionProviders) {
+//
+//                     /* We do not need these - already loaded them from 
getDefaultServiceDescriptionProviders()
+//      if (!(provider instanceof ConfigurableServiceProvider)) {
+//      defaultServiceDescriptionProviders.add(provider);
+//      continue;
+//      }*/
+//
+//                     // Just load the hard coded default configurable 
service providers
+//                     if (provider instanceof ConfigurableServiceProvider){
+//                             ConfigurableServiceProvider<Object> template = 
((ConfigurableServiceProvider<Object>)
+//                                             provider);
+//                             // Get configurations
+//                             List<Object> configurables = 
template.getDefaultConfigurations();
+//                             for (Object config : configurables) {
+//                                     // Make a copy that we can configure
+//                                     ConfigurableServiceProvider<Object> 
configurableProvider = template.clone();
+//                                     try {
+//                                             
configurableProvider.configure(config);
+//                                     } catch (ConfigurationException e) {
+//                                             logger.warn("Can't configure 
provider "
+//                                                             + 
configurableProvider + " with " + config);
+//                                             continue;
+//                                     }
+//                                     
defaultServiceDescriptionProviders.add(configurableProvider);
+//                             }
+//                     }
+//             }
+//             return defaultServiceDescriptionProviders;
+//     }
+
+       // Get the default services.
+       @Override
+       public synchronized Set<ServiceDescriptionProvider> 
getDefaultServiceDescriptionProviders() {
+               if (defaultServiceDescriptionProviders != null)
+                       return defaultServiceDescriptionProviders;
+               defaultServiceDescriptionProviders = new HashSet<>();
+
+               /*
+                * Add default configurable service description providers from 
the
+                * default_service_providers.xml file
+                */
+               if (defaultConfigurableServiceProvidersFile.exists()) {
+                       try {
+                               ServiceDescriptionDeserializer deserializer = 
new ServiceDescriptionDeserializer(
+                                               serviceDescriptionProviders);
+                               
defaultServiceDescriptionProviders.addAll(deserializer
+                                               .deserializeDefaults(this,
+                                                               
defaultConfigurableServiceProvidersFile));
+                               /*
+                                * We have successfully loaded the defaults for 
system
+                                * configurable providers. Note that there are 
still defaults
+                                * for third party configurable providers, 
which will be loaded
+                                * below using getDefaultConfigurations().
+                                */
+                               defaultSystemConfigurableProvidersLoaded = true;
+                       } catch (Exception e) {
+                               logger.error("Could not load default service 
providers from "
+                                               + 
defaultConfigurableServiceProvidersFile.getAbsolutePath(), e);
+
+                               /*
+                                * Fallback on the old hardcoded method of 
loading default
+                                * system configurable service providers using
+                                * getDefaultConfigurations().
+                                */
+                               defaultSystemConfigurableProvidersLoaded = 
false;
+                       }
+               } else {
+                       logger.warn("Could not find the file "
+                                       + 
defaultConfigurableServiceProvidersFile.getAbsolutePath()
+                                       + " containing default system service 
providers. "
+                                       + "Using the hardcoded list of default 
system providers.");
+
+                       /*
+                        * Fallback on the old hardcoded method of loading 
default system
+                        * configurable service providers using 
getDefaultConfigurations().
+                        */
+                       defaultSystemConfigurableProvidersLoaded = false;
+               }
+
+               /*
+                * Load other default service description providers - template, 
local
+                * workers and third party configurable service providers
+                */
+               for (ServiceDescriptionProvider provider : 
serviceDescriptionProviders) {
+                       /*
+                        * Template service providers (beanshell, string 
constant, etc. )
+                        * and providers of local workers.
+                        */
+                       if (!(provider instanceof ConfigurableServiceProvider)) 
{
+                               
defaultServiceDescriptionProviders.add(provider);
+                               continue;
+                       }
+
+                       /*
+                        * Default system or third party configurable service 
description
+                        * provider. System ones are read from the
+                        * default_service_providers.xml file so 
getDefaultConfigurations()
+                        * on them will not have much effect here unless
+                        * defaultSystemConfigurableProvidersLoaded is set to 
false.
+                        */
+                       //FIXME needs to be designed to work using 
Configuration instances
+                       //FIXME needs to get configurations via OSGi discovery
+                       /*
+                       ConfigurableServiceProvider template = 
(ConfigurableServiceProvider) provider;
+                       // Get configurations
+                       for (ObjectNode config : 
template.getDefaultConfigurations()) {
+                               // Make a copy that we can configure
+                               ConfigurableServiceProvider 
configurableProvider = template.clone();
+                               try {
+                                       configurableProvider.configure(config);
+                               } catch (ConfigurationException e) {
+                                       logger.warn("Can't configure provider "
+                                                       + configurableProvider 
+ " with " + config);
+                                       continue;
+                               }
+                               
defaultServiceDescriptionProviders.add(configurableProvider);
+                       }
+                       */
+               }
+
+               return defaultServiceDescriptionProviders;
+       }
+
+       @Override
+       public synchronized Set<ServiceDescriptionProvider> 
getServiceDescriptionProviders() {
+               if (allServiceProviders != null)
+                       return new HashSet<>(allServiceProviders);
+               allServiceProviders = new HashSet<>(userAddedProviders);
+               synchronized (this) {
+                       if (!hasLoadedProviders)
+                               try {
+                                       loadServiceProviders();
+                               } catch (Exception e) {
+                                       logger.error("Could not load service 
providers", e);
+                               } finally {
+                                       hasLoadedProviders = true;
+                               }
+               }
+               for (ServiceDescriptionProvider provider : 
getDefaultServiceDescriptionProviders()) {
+                       if (userRemovedProviders.contains(provider))
+                               continue;
+                       if (provider instanceof ConfigurableServiceProvider
+                                       && 
!serviceDescriptionsConfig.isIncludeDefaults())
+                               // We'll skip the default configurable service 
provders
+                               continue;
+                       allServiceProviders.add(provider);
+               }
+               return new HashSet<>(allServiceProviders);
+       }
+
+       @Override
+       public Set<ServiceDescriptionProvider> getServiceDescriptionProviders(
+                       ServiceDescription sd) {
+               Set<ServiceDescriptionProvider> result = new HashSet<>();
+               for (ServiceDescriptionProvider sdp : 
providerDescriptions.keySet())
+                       if (providerDescriptions.get(sdp).contains(sd))
+                               result.add(sdp);
+               return result;
+       }
+
+       @Override
+       public Set<ServiceDescription> getServiceDescriptions() {
+               updateServiceDescriptions(false, true);
+               Set<ServiceDescription> serviceDescriptions = new HashSet<>();
+               synchronized (providerDescriptions) {
+                       for (Set<ServiceDescription> providerDesc : 
providerDescriptions
+                                       .values())
+                               serviceDescriptions.addAll(providerDesc);
+               }
+               return serviceDescriptions;
+       }
+
+       @Override
+       public ServiceDescription getServiceDescription(URI serviceType) {
+               for (ServiceDescription serviceDescription : 
getServiceDescriptions())
+                       if 
(serviceDescription.getActivityType().equals(serviceType))
+                               return serviceDescription;
+               return null;
+       }
+
+       @Override
+       public List<ConfigurableServiceProvider> 
getUnconfiguredServiceProviders() {
+               List<ConfigurableServiceProvider> providers = new ArrayList<>();
+               for (ServiceDescriptionProvider provider : 
serviceDescriptionProviders)
+                       if (provider instanceof ConfigurableServiceProvider)
+                               providers.add((ConfigurableServiceProvider) 
provider);
+               return providers;
+       }
+
+       @Override
+       public Set<ServiceDescriptionProvider> getUserAddedServiceProviders() {
+               return new HashSet<>(userAddedProviders);
+       }
+
+       @Override
+       public Set<ServiceDescriptionProvider> getUserRemovedServiceProviders() 
{
+               return new HashSet<>(userRemovedProviders);
+       }
+
+       @Override
+       public void loadServiceProviders() {
+               File serviceProviderFile = findServiceDescriptionsFile();
+               if (serviceProviderFile.isFile())
+                       loadServiceProviders(serviceProviderFile);
+               hasLoadedProviders = true;
+       }
+
+       @Override
+       public void loadServiceProviders(File serviceProvidersFile) {
+               ServiceDescriptionDeserializer deserializer = new 
ServiceDescriptionDeserializer(
+                               serviceDescriptionProviders);
+               loading = true;
+               try {
+                       deserializer.deserialize(this, serviceProvidersFile);
+               } catch (DeserializationException e) {
+                       logger.error("failed to deserialize configuration", e);
+               }
+               loading = false;
+       }
+
+       @Override
+       public void loadServiceProviders(URL serviceProvidersURL) {
+               ServiceDescriptionDeserializer deserializer = new 
ServiceDescriptionDeserializer(
+                               serviceDescriptionProviders);
+               loading = true;
+               try {
+                       deserializer.deserialize(this, serviceProvidersURL);
+               } catch (DeserializationException e) {
+                       logger.error("failed to deserialize configuration", e);
+               }
+               loading = false;
+       }
+
+       @Override
+       public void refresh() {
+               updateServiceDescriptions(true, false);
+       }
+
+       @Override
+       public void removeObserver(Observer<ServiceDescriptionRegistryEvent> 
observer) {
+               observers.removeObserver(observer);
+       }
+
+       @Override
+       public synchronized void removeServiceDescriptionProvider(
+                       ServiceDescriptionProvider provider) {
+               if (!userAddedProviders.remove(provider))
+                       // Not previously added - must be a default one.. but 
should we remove it?
+                       if (loading || 
serviceDescriptionsConfig.isRemovePermanently()
+                                       && 
serviceDescriptionsConfig.isIncludeDefaults())
+                               userRemovedProviders.add(provider);
+               if (allServiceProviders.remove(provider)) {
+                       synchronized (providerDescriptions) {
+                               Thread thread = 
serviceDescriptionThreads.remove(provider);
+                               if (thread != null)
+                                       thread.interrupt();
+                               providerDescriptions.remove(provider);
+                       }
+                       observers.notify(new RemovedProviderEvent(provider));
+               }
+               if (!loading)
+                       saveServiceDescriptions();
+       }
+
+       @Override
+       public void saveServiceDescriptions() {
+               File serviceDescriptionsFile = findServiceDescriptionsFile();
+               saveServiceDescriptions(serviceDescriptionsFile);
+       }
+
+       @Override
+       public void saveServiceDescriptions(File serviceDescriptionsFile) {
+               ServiceDescriptionSerializer serializer = new 
ServiceDescriptionSerializer();
+               try {
+                       serializer.serializeRegistry(this, 
serviceDescriptionsFile);
+               } catch (IOException e) {
+                       throw new RuntimeException("Can't save service 
descriptions to "
+                                       + serviceDescriptionsFile);
+               }
+       }
+
+       /**
+        * Exports all configurable service providers (that give service
+        * descriptions) currently found in the Service Registry (apart from 
service
+        * templates and local services) regardless of who added them (user or
+        * default system providers).
+        * <p>
+        * Unlike {@link #saveServiceDescriptions}, this export does not have 
the
+        * "ignored providers" section as this is just a plain export of 
everything
+        * in the Service Registry.
+        * 
+        * @param serviceDescriptionsFile
+        */
+       @Override
+       public void exportCurrentServiceDescriptions(File 
serviceDescriptionsFile) {
+               ServiceDescriptionSerializer serializer = new 
ServiceDescriptionSerializer();
+               try {
+                       serializer.serializeFullRegistry(this, 
serviceDescriptionsFile);
+               } catch (IOException e) {
+                       throw new RuntimeException("Could not save service 
descriptions to "
+                                       + serviceDescriptionsFile);
+               }
+       }
+
+       public void setServiceDescriptionProvidersList(
+                       List<ServiceDescriptionProvider> 
serviceDescriptionProviders) {
+               this.serviceDescriptionProviders = serviceDescriptionProviders;
+       }
+
+       private void updateServiceDescriptions(boolean refreshAll, boolean 
waitFor) {
+               List<Thread> threads = new ArrayList<>();
+               for (ServiceDescriptionProvider provider : 
getServiceDescriptionProviders()) {
+                       synchronized (providerDescriptions) {
+                               if (providerDescriptions.containsKey(provider) 
&& !refreshAll)
+                                       // We'll used the cached values
+                                       continue;
+                               Thread oldThread = 
serviceDescriptionThreads.get(provider);
+                               if (oldThread != null && oldThread.isAlive()) {
+                                       if (refreshAll)
+                                               // New thread will override the 
old thread
+                                               oldThread.interrupt();
+                                       else {
+                                               // observers.notify(new 
ProviderStatusNotification(provider, "Waiting for provider"));
+                                               continue;
+                                       }
+                               }
+                               // Not run yet - we'll start a new tread
+                               Thread thread = new 
FindServiceDescriptionsThread(provider);
+                               threads.add(thread);
+                               serviceDescriptionThreads.put(provider, thread);
+                               thread.start();
+                       }
+               }
+               if (waitFor)
+                       joinThreads(threads, DESCRIPTION_THREAD_TIMEOUT_MS);
+       }
+
+       @Override
+       public boolean isDefaultSystemConfigurableProvidersLoaded() {
+               return defaultSystemConfigurableProvidersLoaded;
+       }
+
+       /**
+        * Sets the serviceDescriptionsConfig.
+        * 
+        * @param serviceDescriptionsConfig
+        *            the new value of serviceDescriptionsConfig
+        */
+       public void setServiceDescriptionsConfig(
+                       ServiceDescriptionsConfiguration 
serviceDescriptionsConfig) {
+               this.serviceDescriptionsConfig = serviceDescriptionsConfig;
+       }
+
+       class FindServiceDescriptionsThread extends Thread implements
+                       UncaughtExceptionHandler, 
FindServiceDescriptionsCallBack {
+               private final ServiceDescriptionProvider provider;
+               private boolean aborting = false;
+               private final Set<ServiceDescription> providerDescs = new 
HashSet<>();
+
+               FindServiceDescriptionsThread(ServiceDescriptionProvider 
provider) {
+                       super(threadGroup, "Find service descriptions from " + 
provider);
+                       this.provider = provider;
+                       setUncaughtExceptionHandler(this);
+                       setDaemon(true);
+               }
+
+               @Override
+               public void fail(String message, Throwable ex) {
+                       logger.warn("Provider " + getProvider() + ": " + 
message, ex);
+                       if (aborting)
+                               return;
+                       observers.notify(new 
ProviderErrorNotification(getProvider(),
+                                       message, ex));
+               }
+
+               @Override
+               public void finished() {
+                       if (aborting)
+                               return;
+                       synchronized (providerDescriptions) {
+                               providerDescriptions.put(getProvider(), 
providerDescs);
+                       }
+                       observers.notify(new 
ServiceDescriptionProvidedEvent(getProvider(),
+                                       providerDescs));
+               }
+
+               @Override
+               public void partialResults(
+                               Collection<? extends ServiceDescription> 
serviceDescriptions) {
+                       if (aborting)
+                               return;
+                       providerDescs.addAll(serviceDescriptions);
+                       synchronized (providerDescriptions) {
+                               providerDescriptions.put(getProvider(), 
providerDescs);
+                       }
+                       observers.notify(new 
PartialServiceDescriptionsNotification(
+                                       getProvider(), serviceDescriptions));
+               }
+
+               @Override
+               public void status(String message) {
+                       logger.debug("Provider " + getProvider() + ": " + 
message);
+                       if (aborting)
+                               return;
+                       observers.notify(new 
ProviderStatusNotification(getProvider(),
+                                       message));
+               }
+
+               @Override
+               public void warning(String message) {
+                       logger.warn("Provider " + getProvider() + ": " + 
message);
+                       if (aborting)
+                               return;
+                       observers.notify(new 
ProviderWarningNotification(getProvider(),
+                                       message));
+               }
+
+               public ServiceDescriptionProvider getProvider() {
+                       return provider;
+               }
+
+               @Override
+               public void interrupt() {
+                       aborting = true;
+                       super.interrupt();
+               }
+
+               @Override
+               public void run() {
+                       observers.notify(new 
ProviderUpdatingNotification(provider));
+                       getProvider().findServiceDescriptionsAsync(this);
+               }
+
+               @Override
+               public void uncaughtException(Thread t, Throwable ex) {
+                       logger.error("Uncaught exception in " + t, ex);
+                       fail("Uncaught exception", ex);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionSerializer.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionSerializer.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionSerializer.java
new file mode 100644
index 0000000..f7465f7
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionSerializer.java
@@ -0,0 +1,102 @@
+package org.apache.taverna.servicedescriptions.impl;
+
+import static 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionConstants.CONFIGURATION;
+import static 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionConstants.IGNORED;
+import static 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionConstants.PROVIDERS;
+import static 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionConstants.PROVIDER_ID;
+import static 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionConstants.SERVICE_PANEL_CONFIGURATION;
+import static 
org.apache.taverna.servicedescriptions.impl.ServiceDescriptionConstants.TYPE;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.taverna.servicedescriptions.ConfigurableServiceProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionProvider;
+import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry;
+
+import org.apache.log4j.Logger;
+import org.jdom.JDOMException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+class ServiceDescriptionSerializer {
+       private static Logger logger = Logger
+                       .getLogger(ServiceDescriptionSerializer.class);
+
+       public void serializeRegistry(ServiceDescriptionRegistry registry, File 
file)
+                       throws IOException {
+               Set<ServiceDescriptionProvider> ignoreProviders = registry
+                               .getUserRemovedServiceProviders();
+               JsonNode registryElement = serializeRegistry(registry, 
ignoreProviders);
+               try (BufferedOutputStream bufferedOutStream = new 
BufferedOutputStream(
+                               new FileOutputStream(file))) {
+                       bufferedOutStream.write(registryElement.toString()
+                                       .getBytes("UTF-8"));
+               }
+       }
+
+       /**
+        * Export the whole service registry to an xml file, regardless of who 
added
+        * the service provider (user or system default). In this case there 
will be
+        * no "ignored providers" in the saved file.
+        */
+       public void serializeFullRegistry(ServiceDescriptionRegistry registry,
+                       File file) throws IOException {
+               JsonNode registryElement = serializeRegistry(registry, 
ALL_PROVIDERS);
+               try (BufferedOutputStream bufferedOutStream = new 
BufferedOutputStream(
+                               new FileOutputStream(file))) {
+                       bufferedOutStream.write(registryElement.toString()
+                                       .getBytes("UTF-8"));
+               }
+       }
+
+       private static final JsonNodeFactory factory = JsonNodeFactory.instance;
+       private static final Set<ServiceDescriptionProvider> ALL_PROVIDERS = 
null;
+
+       private JsonNode serializeRegistry(ServiceDescriptionRegistry registry,
+                       Set<ServiceDescriptionProvider> ignoreProviders) {
+               ObjectNode overallConfiguration = factory.objectNode();
+               overallConfiguration.put(SERVICE_PANEL_CONFIGURATION,
+                               ignoreProviders != ALL_PROVIDERS ? "full" : 
"defaults only");
+               ArrayNode providers = overallConfiguration.putArray(PROVIDERS);
+
+               for (ServiceDescriptionProvider provider : registry
+                               .getUserAddedServiceProviders())
+                       try {
+                               providers.add(serializeProvider(provider));
+                       } catch (JDOMException | IOException e) {
+                               logger.warn("Could not serialize " + provider, 
e);
+                       }
+
+               if (ignoreProviders != ALL_PROVIDERS) {
+                       ArrayNode ignored = 
overallConfiguration.putArray(IGNORED);
+                       for (ServiceDescriptionProvider provider : 
ignoreProviders)
+                               try {
+                                       
ignored.add(serializeProvider(provider));
+                               } catch (JDOMException | IOException e) {
+                                       logger.warn("Could not serialize " + 
provider, e);
+                               }
+               }
+
+               return overallConfiguration;
+       }
+
+       private JsonNode serializeProvider(ServiceDescriptionProvider provider)
+                       throws JDOMException, IOException {
+               ObjectNode node = factory.objectNode();
+               node.put(PROVIDER_ID, provider.getId());
+
+               if (provider instanceof ConfigurableServiceProvider) {
+                       ConfigurableServiceProvider configurable = 
(ConfigurableServiceProvider) provider;
+                       node.put(TYPE, 
configurable.getConfiguration().getType().toString());
+                       node.put(CONFIGURATION, 
configurable.getConfiguration().getJson());
+               }
+               return node;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionXMLConstants.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionXMLConstants.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionXMLConstants.java
new file mode 100644
index 0000000..be44022
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionXMLConstants.java
@@ -0,0 +1,15 @@
+package org.apache.taverna.servicedescriptions.impl;
+
+import org.jdom.Namespace;
+
+public interface ServiceDescriptionXMLConstants {
+
+       public static final Namespace SERVICE_DESCRIPTION_NS = Namespace
+                       
.getNamespace("http://taverna.sf.net/2009/xml/servicedescription";);
+       public static final String PROVIDER = "provider";
+       public static final String PROVIDERS = "providers";
+       public static final String SERVICE_DESCRIPTIONS = "serviceDescriptions";
+       public static final String IGNORED_PROVIDERS = "ignoredProviders";
+       public static final String PROVIDER_IDENTIFIER = "providerId";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionsConfigurationImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionsConfigurationImpl.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionsConfigurationImpl.java
new file mode 100644
index 0000000..2ed4b82
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/servicedescriptions/impl/ServiceDescriptionsConfigurationImpl.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.servicedescriptions.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.taverna.servicedescriptions.ServiceDescriptionsConfiguration;
+
+import uk.org.taverna.configuration.AbstractConfigurable;
+import uk.org.taverna.configuration.ConfigurationManager;
+
+public class ServiceDescriptionsConfigurationImpl extends AbstractConfigurable
+               implements ServiceDescriptionsConfiguration {
+       private static final String INCLUDE_DEFAULTS = "includeDefaults";
+       private static final String SERVICE_PALETTE = "Service providers";
+       private static final String SERVICE_PALETTE_PREFIX = "ServiceProviders";
+       private static final String CATEGORY = "Services";
+       private static final String UUID = 
"f0d1ef24-9337-412f-b2c3-220a01e2efd0";
+       private static final String REMOVE_PERMANENTLY = "removePermanently";
+
+       public ServiceDescriptionsConfigurationImpl(
+                       ConfigurationManager configurationManager) {
+               super(configurationManager);
+       }
+
+       @Override
+       public String getCategory() {
+               return CATEGORY;
+       }
+
+       @Override
+       public Map<String, String> getDefaultPropertyMap() {
+               Map<String, String> defaults = new HashMap<String, String>();
+               defaults.put(INCLUDE_DEFAULTS, "true");
+               defaults.put(REMOVE_PERMANENTLY, "true");
+               return defaults;
+       }
+
+       @Override
+       public String getDisplayName() {
+               return SERVICE_PALETTE;
+       }
+
+       @Override
+       public String getFilePrefix() {
+               return SERVICE_PALETTE_PREFIX;
+       }
+
+       @Override
+       public String getUUID() {
+               return UUID;
+       }
+
+       @Override
+       public boolean isIncludeDefaults() {
+               return Boolean.parseBoolean(getProperty(INCLUDE_DEFAULTS));
+       }
+
+       @Override
+       public void setIncludeDefaults(boolean includeDefaults) {
+               setProperty(INCLUDE_DEFAULTS, 
Boolean.toString(includeDefaults));
+       }
+
+       @Override
+       public boolean isRemovePermanently() {
+               return Boolean.parseBoolean(getProperty(REMOVE_PERMANENTLY));
+       }
+
+       @Override
+       public void setRemovePermanently(boolean removePermanently) {
+               setProperty(REMOVE_PERMANENTLY, 
Boolean.toString(removePermanently));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfiguration.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfiguration.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfiguration.java
new file mode 100644
index 0000000..7ea1a8c
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfiguration.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.ui.activitypalette;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import uk.org.taverna.configuration.AbstractConfigurable;
+import uk.org.taverna.configuration.ConfigurationManager;
+
+public class ActivityPaletteConfiguration extends AbstractConfigurable {
+       private Map<String,String> defaultPropertyMap;
+
+       public ActivityPaletteConfiguration(ConfigurationManager 
configurationManager) {
+               super(configurationManager);
+       }
+
+       @Override
+       public String getCategory() {
+               return "Services";
+       }
+
+       @Override
+       public Map<String, String> getDefaultPropertyMap() {
+               if (defaultPropertyMap == null) {
+                       defaultPropertyMap = new HashMap<>();
+
+                       // //wsdl
+                       //defaultPropertyMap.put("taverna.defaultwsdl", 
"http://www.ebi.ac.uk/xembl/XEMBL.wsdl,"+
+                       //                    
"http://soap.genome.jp/KEGG.wsdl,"+
+                       //                    
"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/soap/eutils.wsdl,"+
+                       //                    
"http://soap.bind.ca/wsdl/bind.wsdl,"+
+                       //                    
"http://www.ebi.ac.uk/ws/services/urn:Dbfetch?wsdl";);
+
+                       // //soaplab
+                       //defaultPropertyMap.put("taverna.defaultsoaplab", 
"http://www.ebi.ac.uk/soaplab/services/";);
+
+                       // //biomart
+                       
//defaultPropertyMap.put("taverna.defaultmartregistry","http://www.biomart.org/biomart";);
+
+                       //add property names
+                       //defaultPropertyMap.put("name.taverna.defaultwsdl", 
"WSDL");
+                       
//defaultPropertyMap.put("name.taverna.defaultsoaplab","Soaplab");
+                       
//defaultPropertyMap.put("name.taverna.defaultmartregistry", "Biomart");
+               }
+               return defaultPropertyMap;
+       }
+
+       @Override
+       public String getDisplayName() {
+               return "Activity Palette";
+       }
+
+       @Override
+       public String getFilePrefix() {
+               return "ActivityPalette";
+       }
+
+       @Override
+       public String getUUID() {
+               return "ad9f3a60-5967-11dd-ae16-0800200c9a66";
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationPanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationPanel.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationPanel.java
new file mode 100644
index 0000000..791e456
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationPanel.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.ui.activitypalette;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.EAST;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.FlowLayout.LEFT;
+import static java.awt.FlowLayout.RIGHT;
+import static javax.swing.BoxLayout.Y_AXIS;
+import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.YES_NO_OPTION;
+import static javax.swing.JOptionPane.YES_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static javax.swing.JOptionPane.showInputDialog;
+import static javax.swing.border.BevelBorder.LOWERED;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.BoxLayout;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.border.BevelBorder;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+public class ActivityPaletteConfigurationPanel extends JPanel {
+       private static Logger logger = Logger
+                       .getLogger(ActivityPaletteConfigurationPanel.class);
+
+       private Map<String,List<String>> values = new HashMap<>();
+       private Map<String,String> names = new HashMap<>();
+       private DefaultComboBoxModel<String> model;
+       private DefaultListModel<String> listModel;
+       private JList<String> propertyListItems;
+       private String selectedKey;
+       private JButton deleteTypeButton;
+       private final ActivityPaletteConfiguration config;
+
+       public ActivityPaletteConfigurationPanel(ActivityPaletteConfiguration 
config) {
+               super(new BorderLayout());
+               this.config = config;
+
+               model = new DefaultComboBoxModel<>();
+               for (String key : config.getInternalPropertyMap().keySet()) {
+                       if (key.startsWith("taverna.")
+                                       && config.getPropertyStringList(key) != 
null) {
+                               model.addElement(key);
+                               values.put(key,
+                                               new 
ArrayList<>(config.getPropertyStringList(key)));
+                       }
+                       if (key.startsWith("name.taverna."))
+                               names.put(key, 
config.getProperty(key).toString());
+               }
+               deleteTypeButton = new JButton("Delete");
+
+               final JButton addTypeButton = new JButton("Add");
+               final JComboBox<String> comboBox = new JComboBox<>(model);
+               comboBox.setRenderer(new DefaultListCellRenderer() {
+                       @Override
+                       public Component getListCellRendererComponent(JList<?> 
list,
+                                       Object value, int index, boolean 
isSelected,
+                                       boolean cellHasFocus) {
+                               if (value != null && value instanceof String) {
+                                       String name = names.get("name." + 
value);
+                                       if (name != null)
+                                               value = name;
+                               }
+                               return super.getListCellRendererComponent(list, 
value, index,
+                                               isSelected, cellHasFocus);
+                       }
+               });
+
+               deleteTypeButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               String displayText = names.get("name." + 
selectedKey);
+                               if (displayText == null)
+                                       displayText = selectedKey;
+                               if (confirm("Confirm removal",
+                                               "Are you sure you wish to 
remove the type "
+                                                               + displayText + 
"?")) {
+                                       names.remove("name." + selectedKey);
+                                       values.remove(selectedKey);
+                                       model.removeElement(selectedKey);
+                                       comboBox.setSelectedIndex(0);
+                               }
+                       }
+               });
+
+               addTypeButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               String key = input("New key", "Provide the new 
key.");
+                               if (key == null)
+                                       return;
+                               String name = input("Name for the key",
+                                               "Provide the name for the key: 
" + key);
+                               if (name == null)
+                                       return;
+
+                               values.put(key, new ArrayList<String>());
+                               names.put("name." + key, name);
+                               model.addElement(key);
+                               comboBox.setSelectedItem(key);
+                       }
+               });
+
+               comboBox.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (comboBox.getSelectedItem() != null
+                                               && comboBox.getSelectedItem() 
instanceof String) {
+                                       selectedKey = (String) 
comboBox.getSelectedItem();
+                                       List<String> selectedList = 
values.get(selectedKey);
+                                       populateList(selectedList);
+                                       
deleteTypeButton.setEnabled(selectedList.size() == 0);
+                               }
+                       }
+               });
+
+               JPanel propertySelectionPanel = new JPanel(new 
FlowLayout(LEFT));
+               propertySelectionPanel.add(new JLabel("Activity type:"));
+               propertySelectionPanel.add(comboBox);
+               propertySelectionPanel.add(addTypeButton);
+               propertySelectionPanel.add(deleteTypeButton);
+               add(propertySelectionPanel, NORTH);
+
+               JPanel listPanel = new JPanel(new BorderLayout());
+               listModel = new DefaultListModel<>();
+               propertyListItems = new JList<>(listModel);
+               propertyListItems.setBorder(new BevelBorder(LOWERED));
+
+               listPanel.add(propertyListItems, CENTER);
+               listPanel.add(listButtons(), EAST);
+
+               add(listPanel, CENTER);
+
+               add(applyButtonPanel(), SOUTH);
+
+               if (model.getSize() > 0)
+                       comboBox.setSelectedItem(model.getElementAt(0));
+       }
+
+       private void populateList(List<String> selectedList) {
+               listModel.removeAllElements();
+               for (String item : selectedList)
+                       listModel.addElement(item);
+       }
+
+       private JPanel applyButtonPanel() {
+               JPanel applyPanel = new JPanel(new FlowLayout(RIGHT));
+               JButton applyButton = new JButton("Apply");
+
+               applyButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               config.getInternalPropertyMap().clear();
+                               for (String key : values.keySet()) {
+                                       List<String> properties = 
values.get(key);
+                                       config.setPropertyStringList(key, new 
ArrayList<>(
+                                                       properties));
+                               }
+                               for (String key : names.keySet())
+                                       config.setProperty(key, names.get(key));
+                               store();
+                       }
+               });
+
+               applyPanel.add(applyButton);
+               return applyPanel;
+       }
+
+       private void store() {
+               try {
+                       //FIXME
+                       //ConfigurationManager.getInstance().store(config);
+               } catch (Exception e1) {
+                       logger.error("There was an error storing the 
configuration:"
+                                       + config.getFilePrefix() + " (UUID=" + 
config.getUUID()
+                                       + ")", e1);
+               }
+       }
+
+       private JPanel listButtons() {
+               JPanel panel = new JPanel();
+               panel.setLayout(new BoxLayout(panel, Y_AXIS));
+               JButton addButton = new JButton("+");
+               addButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               String value = input("New property", "Provide 
new value for: "
+                                               + selectedKey);
+                               if (value != null) {
+                                       listModel.addElement(value);
+                                       values.get(selectedKey).add(value);
+                                       deleteTypeButton.setEnabled(false);
+                               }
+                       }
+               });
+
+               JButton deleteButton = new JButton("-");
+               deleteButton.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               Object value = 
propertyListItems.getSelectedValue();
+                               if (confirm("Confirm removal",
+                                               "Are you sure you wish to 
remove " + value + "?")) {
+                                       listModel.removeElement(value);
+                                       values.get(selectedKey).remove(value);
+                                       if (values.get(selectedKey).size() == 0)
+                                               
deleteTypeButton.setEnabled(true);
+                               }
+                       }
+               });
+
+               panel.add(addButton);
+               panel.add(deleteButton);
+
+               return panel;
+       }
+
+       private boolean confirm(String title, String message) {
+               return showConfirmDialog(this, message, title, YES_NO_OPTION,
+                               WARNING_MESSAGE) == YES_OPTION;
+       }
+
+       private String input(String title, String message) {
+               return showInputDialog(this, message, title, 
INFORMATION_MESSAGE);
+       }
+
+/*     private JButton getAddTypeButton() {
+               JButton result = new JButton("Add");
+               result.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               String val = input("New property value","New 
property value");
+                               if (val!=null) {
+                                       if (values.get(val) == null) {
+                                               model.addElement(val);
+                                               values.put(val, new 
ArrayList<String>());
+                                       } else
+                                               
showMessageDialog(ActivityPaletteConfigurationPanel.this, "This property 
already exists");
+                               }
+                       }
+               });
+               return result;
+       }
+*/
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationUIFactory.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationUIFactory.java
 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationUIFactory.java
new file mode 100644
index 0000000..c522197
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationUIFactory.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.ui.activitypalette;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.configuration.Configurable;
+import uk.org.taverna.configuration.ConfigurationUIFactory;
+
+public class ActivityPaletteConfigurationUIFactory implements
+               ConfigurationUIFactory {
+       private ActivityPaletteConfiguration activityPaletteConfiguration;
+
+       @Override
+       public boolean canHandle(String uuid) {
+               return uuid != null && uuid.equals(getConfigurable().getUUID());
+       }
+
+       @Override
+       public Configurable getConfigurable() {
+               return activityPaletteConfiguration;
+       }
+
+       @Override
+       public JPanel getConfigurationPanel() {
+               return new ActivityPaletteConfigurationPanel(
+                               activityPaletteConfiguration);
+       }
+
+       public void setActivityPaletteConfiguration(
+                       ActivityPaletteConfiguration 
activityPaletteConfiguration) {
+               this.activityPaletteConfiguration = 
activityPaletteConfiguration;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
 
b/taverna-activity-palette-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
deleted file mode 100644
index 6c9fed9..0000000
--- 
a/taverna-activity-palette-impl/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
+++ /dev/null
@@ -1 +0,0 @@
-#net.sf.taverna.t2.workbench.ui.activitypalette.ActivityPaletteConfigurationUIFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/resources/META-INF/services/org.apache.taverna.workbench.configuration.ConfigurationUIFactory
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/resources/META-INF/services/org.apache.taverna.workbench.configuration.ConfigurationUIFactory
 
b/taverna-activity-palette-impl/src/main/resources/META-INF/services/org.apache.taverna.workbench.configuration.ConfigurationUIFactory
new file mode 100644
index 0000000..446b370
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/main/resources/META-INF/services/org.apache.taverna.workbench.configuration.ConfigurationUIFactory
@@ -0,0 +1 @@
+#org.apache.taverna.workbench.ui.activitypalette.ActivityPaletteConfigurationUIFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context-osgi.xml
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context-osgi.xml
 
b/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context-osgi.xml
index 34921f5..215562a 100644
--- 
a/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context-osgi.xml
+++ 
b/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context-osgi.xml
@@ -6,12 +6,12 @@
                       http://www.springframework.org/schema/osgi
                       
http://www.springframework.org/schema/osgi/spring-osgi.xsd";>
 
-       <service ref="ServiceDescriptionRegistryImpl" 
interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry"/>
-       <service ref="ServiceDescriptionsConfigurationImpl" 
interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionsConfiguration"/>
+       <service ref="ServiceDescriptionRegistryImpl" 
interface="org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry"/>
+       <service ref="ServiceDescriptionsConfigurationImpl" 
interface="org.apache.taverna.servicedescriptions.ServiceDescriptionsConfiguration"/>
 
        <reference id="configurationManager" 
interface="uk.org.taverna.configuration.ConfigurationManager" />
        <reference id="applicationConfiguration" 
interface="uk.org.taverna.configuration.app.ApplicationConfiguration" />
 
-       <list id="serviceDescriptionProviders" 
interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider" 
cardinality="0..N" greedy-proxying="true"/>
+       <list id="serviceDescriptionProviders" 
interface="org.apache.taverna.servicedescriptions.ServiceDescriptionProvider" 
cardinality="0..N" greedy-proxying="true"/>
 
 </beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context.xml
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context.xml
 
b/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context.xml
index 9f7110f..a91d0ce 100644
--- 
a/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context.xml
+++ 
b/taverna-activity-palette-impl/src/main/resources/META-INF/spring/activity-palette-impl-context.xml
@@ -3,7 +3,7 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                       
http://www.springframework.org/schema/beans/spring-beans.xsd";>
 
-       <bean name="ServiceDescriptionRegistryImpl" 
class="net.sf.taverna.t2.servicedescriptions.impl.ServiceDescriptionRegistryImpl">
+       <bean name="ServiceDescriptionRegistryImpl" 
class="org.apache.taverna.servicedescriptions.impl.ServiceDescriptionRegistryImpl">
                <constructor-arg name="applicationConfiguration" 
ref="applicationConfiguration" />
                <property name="serviceDescriptionProvidersList" 
ref="serviceDescriptionProviders" />
                <property name="serviceDescriptionsConfig">
@@ -11,12 +11,12 @@
                </property>
        </bean>
 
-       <bean id="ServiceDescriptionsConfigurationImpl" 
class="net.sf.taverna.t2.servicedescriptions.impl.ServiceDescriptionsConfigurationImpl">
+       <bean id="ServiceDescriptionsConfigurationImpl" 
class="org.apache.taverna.servicedescriptions.impl.ServiceDescriptionsConfigurationImpl">
                <constructor-arg ref="configurationManager"/>
        </bean>
 
        <!-- Don't think ActivityPalette is still used -->
-       <!-- <bean id="ActivityPaletteConfiguration" 
class="net.sf.taverna.t2.workbench.ui.activitypalette.ActivityPaletteConfiguration">
+       <!-- <bean id="ActivityPaletteConfiguration" 
class="org.apache.taverna.workbench.ui.activitypalette.ActivityPaletteConfiguration">
                <constructor-arg ref="configurationManager"/>
        </bean> -->
 

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/test/java/net/sf/taverna/t2/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/test/java/net/sf/taverna/t2/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
 
b/taverna-activity-palette-impl/src/test/java/net/sf/taverna/t2/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
deleted file mode 100644
index 081a9af..0000000
--- 
a/taverna-activity-palette-impl/src/test/java/net/sf/taverna/t2/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- *  Modifications to the initial code base are copyright of their
- *  respective authors, or their employers as appropriate.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1 of
- *  the License, or (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- 
******************************************************************************/
-package net.sf.taverna.t2.workbench.ui.activitypalette;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import uk.org.taverna.configuration.app.impl.ApplicationConfigurationImpl;
-import uk.org.taverna.configuration.impl.ConfigurationManagerImpl;
-
-public class ActivityPaletteConfigurationTest {
-
-       private ActivityPaletteConfiguration conf;
-       private ConfigurationManagerImpl manager;
-
-       @Before
-       public void setup() {
-               File f = new File(System.getProperty("java.io.tmpdir"));
-               final File d = new File(f,UUID.randomUUID().toString());
-               d.mkdir();
-               manager = new ConfigurationManagerImpl(new 
ApplicationConfigurationImpl() {
-                       @Override
-                       public File getApplicationHomeDir() {
-                               return d;
-                       }
-               });
-               conf=new ActivityPaletteConfiguration(manager);
-               conf.restoreDefaults();
-       }
-
-       @Test
-       public void testEmptyList() throws Exception {
-               conf.setPropertyStringList("list", new ArrayList<String>());
-               assertTrue("Result was not a list but 
was:"+conf.getProperty("list"),conf.getPropertyStringList("list") instanceof 
List);
-               assertTrue("Result was not a list but 
was:"+conf.getPropertyStringList("list"),conf.getPropertyStringList("list") 
instanceof List);
-               List<String> list = conf.getPropertyStringList("list");
-               assertEquals("There should be 0 elements",0,list.size());
-       }
-
-       @Test
-       public void testSingleItem() throws Exception {
-               List<String> list = new ArrayList<>();
-               list.add("fred");
-               conf.setPropertyStringList("single", list);
-
-               assertTrue("should be an 
ArrayList",conf.getPropertyStringList("single") instanceof List);
-               List<String> l = conf.getPropertyStringList("single");
-               assertEquals("There should be 1 element",1,l.size());
-               assertEquals("Its value should be fred","fred",l.get(0));
-       }
-
-       @Test
-       public void testList() throws Exception {
-               List<String> list = new ArrayList<>();
-               list.add("fred");
-               list.add("bloggs");
-               conf.setPropertyStringList("list", list);
-
-               assertTrue("should be an 
ArrayList",conf.getPropertyStringList("list") instanceof List);
-               List<String> l = conf.getPropertyStringList("list");
-               assertEquals("There should be 1 element",2,l.size());
-               assertEquals("Its value should be fred","fred",l.get(0));
-               assertEquals("Its value should be bloggs","bloggs",l.get(1));
-       }
-
-       @Test
-       public void testNull() throws Exception {
-               assertNull("Should return null",conf.getProperty("blah blah 
blah"));
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/test/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/test/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
 
b/taverna-activity-palette-impl/src/test/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
new file mode 100644
index 0000000..51dcacb
--- /dev/null
+++ 
b/taverna-activity-palette-impl/src/test/java/org/apache/taverna/workbench/ui/activitypalette/ActivityPaletteConfigurationTest.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package org.apache.taverna.workbench.ui.activitypalette;
+
+import 
org.apache.taverna.workbench.ui.activitypalette.ActivityPaletteConfiguration;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import uk.org.taverna.configuration.app.impl.ApplicationConfigurationImpl;
+import uk.org.taverna.configuration.impl.ConfigurationManagerImpl;
+
+public class ActivityPaletteConfigurationTest {
+
+       private ActivityPaletteConfiguration conf;
+       private ConfigurationManagerImpl manager;
+
+       @Before
+       public void setup() {
+               File f = new File(System.getProperty("java.io.tmpdir"));
+               final File d = new File(f,UUID.randomUUID().toString());
+               d.mkdir();
+               manager = new ConfigurationManagerImpl(new 
ApplicationConfigurationImpl() {
+                       @Override
+                       public File getApplicationHomeDir() {
+                               return d;
+                       }
+               });
+               conf=new ActivityPaletteConfiguration(manager);
+               conf.restoreDefaults();
+       }
+
+       @Test
+       public void testEmptyList() throws Exception {
+               conf.setPropertyStringList("list", new ArrayList<String>());
+               assertTrue("Result was not a list but 
was:"+conf.getProperty("list"),conf.getPropertyStringList("list") instanceof 
List);
+               assertTrue("Result was not a list but 
was:"+conf.getPropertyStringList("list"),conf.getPropertyStringList("list") 
instanceof List);
+               List<String> list = conf.getPropertyStringList("list");
+               assertEquals("There should be 0 elements",0,list.size());
+       }
+
+       @Test
+       public void testSingleItem() throws Exception {
+               List<String> list = new ArrayList<>();
+               list.add("fred");
+               conf.setPropertyStringList("single", list);
+
+               assertTrue("should be an 
ArrayList",conf.getPropertyStringList("single") instanceof List);
+               List<String> l = conf.getPropertyStringList("single");
+               assertEquals("There should be 1 element",1,l.size());
+               assertEquals("Its value should be fred","fred",l.get(0));
+       }
+
+       @Test
+       public void testList() throws Exception {
+               List<String> list = new ArrayList<>();
+               list.add("fred");
+               list.add("bloggs");
+               conf.setPropertyStringList("list", list);
+
+               assertTrue("should be an 
ArrayList",conf.getPropertyStringList("list") instanceof List);
+               List<String> l = conf.getPropertyStringList("list");
+               assertEquals("There should be 1 element",2,l.size());
+               assertEquals("Its value should be fred","fred",l.get(0));
+               assertEquals("Its value should be bloggs","bloggs",l.get(1));
+       }
+
+       @Test
+       public void testNull() throws Exception {
+               assertNull("Should return null",conf.getProperty("blah blah 
blah"));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PartitionAlgorithmSetSPI
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PartitionAlgorithmSetSPI
 
b/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PartitionAlgorithmSetSPI
index 9f3c02d..a9a162f 100644
--- 
a/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PartitionAlgorithmSetSPI
+++ 
b/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PartitionAlgorithmSetSPI
@@ -1 +1 @@
-net.sf.taverna.t2.partition.DummyPartitionAlgorithmSet
\ No newline at end of file
+org.apache.taverna.partition.DummyPartitionAlgorithmSet
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PropertyExtractorSPI
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PropertyExtractorSPI
 
b/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PropertyExtractorSPI
index f5e7226..ca99b00 100644
--- 
a/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PropertyExtractorSPI
+++ 
b/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.PropertyExtractorSPI
@@ -1,3 +1,3 @@
-net.sf.taverna.t2.partition.DummyExtractor1
-net.sf.taverna.t2.partition.DummyExtractor2
-net.sf.taverna.t2.partition.DummyExtractor3
\ No newline at end of file
+org.apache.taverna.partition.DummyExtractor1
+org.apache.taverna.partition.DummyExtractor2
+org.apache.taverna.partition.DummyExtractor3
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.QueryFactory
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.QueryFactory
 
b/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.QueryFactory
index 2d26d31a..d34c5a5 100644
--- 
a/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.QueryFactory
+++ 
b/taverna-activity-palette-impl/src/test/resources/META-INF/services/net.sf.taverna.t2.partition.QueryFactory
@@ -1,2 +1,2 @@
-net.sf.taverna.t2.partition.DummyActivityQueryFactory
-net.sf.taverna.t2.partition.DummyQueryFactory
\ No newline at end of file
+org.apache.taverna.partition.DummyActivityQueryFactory
+org.apache.taverna.partition.DummyQueryFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/PathElementFilterTreeNode.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/PathElementFilterTreeNode.java
 
b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/PathElementFilterTreeNode.java
deleted file mode 100644
index 5c65bc0..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/PathElementFilterTreeNode.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007-2009 The University of Manchester   
- * 
- *  Modifications to the initial code base are copyright of their
- *  respective authors, or their employers as appropriate.
- * 
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1 of
- *  the License, or (at your option) any later version.
- *    
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *    
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- 
******************************************************************************/
-package net.sf.taverna.t2.workbench.ui.servicepanel;
-
-import net.sf.taverna.t2.workbench.ui.servicepanel.tree.FilterTreeNode;
-
-/**
- * @author alanrw
- */
-public class PathElementFilterTreeNode extends FilterTreeNode {
-       private static final long serialVersionUID = 6491242031931630314L;
-
-       public PathElementFilterTreeNode(String userObject) {
-               super(userObject);
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/RootFilterTreeNode.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/RootFilterTreeNode.java
 
b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/RootFilterTreeNode.java
deleted file mode 100644
index 86fca05..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/RootFilterTreeNode.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007-2009 The University of Manchester   
- * 
- *  Modifications to the initial code base are copyright of their
- *  respective authors, or their employers as appropriate.
- * 
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1 of
- *  the License, or (at your option) any later version.
- *    
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *    
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- 
******************************************************************************/
-package net.sf.taverna.t2.workbench.ui.servicepanel;
-
-import net.sf.taverna.t2.workbench.ui.servicepanel.tree.FilterTreeNode;
-
-/**
- * @author alanrw
- */
-public class RootFilterTreeNode extends FilterTreeNode {
-       private static final long serialVersionUID = 1047743498806473971L;
-
-       public RootFilterTreeNode(String userObject) {
-               super(userObject);
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilter.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilter.java
 
b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilter.java
deleted file mode 100644
index a83ac2d..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilter.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007-2009 The University of Manchester   
- * 
- *  Modifications to the initial code base are copyright of their
- *  respective authors, or their employers as appropriate.
- * 
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1 of
- *  the License, or (at your option) any later version.
- *    
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *    
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- 
******************************************************************************/
-package net.sf.taverna.t2.workbench.ui.servicepanel;
-
-import static java.beans.Introspector.getBeanInfo;
-
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.swing.tree.DefaultMutableTreeNode;
-
-import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
-import net.sf.taverna.t2.workbench.ui.servicepanel.tree.Filter;
-
-import org.apache.log4j.Logger;
-
-public class ServiceFilter implements Filter {
-       private static Logger logger = Logger.getLogger(ServiceFilter.class);
-
-       private String filterString;
-       private boolean superseded;
-       private String[] filterLowerCaseSplit;
-       private final Object rootToIgnore;
-
-       public ServiceFilter(String filterString, Object rootToIgnore) {
-               this.filterString = filterString;
-               this.rootToIgnore = rootToIgnore;
-               this.filterLowerCaseSplit = filterString.toLowerCase().split(" 
");
-               this.superseded = false;
-       }
-
-       private boolean basicFilter(DefaultMutableTreeNode node) {
-               if (node == rootToIgnore)
-                       return false;
-               if (filterString.isEmpty())
-                       return true;
-
-               if (node.getUserObject() instanceof ServiceDescription) {
-                       ServiceDescription serviceDescription = 
(ServiceDescription) node
-                                       .getUserObject();
-                       for (String searchTerm : filterLowerCaseSplit) {
-                               if (superseded)
-                                       return false;
-                               String[] typeSplit = searchTerm.split(":", 2);
-                               String type;
-                               String keyword;
-                               if (typeSplit.length == 2) {
-                                       type = typeSplit[0];
-                                       keyword = typeSplit[1].toLowerCase();
-                               } else {
-                                       type = null;
-                                       keyword = searchTerm.toLowerCase();
-                               }
-                               try {
-                                       if 
(!doesPropertySatisfy(serviceDescription, type, keyword))
-                                               return false;
-                               } catch (IntrospectionException | 
IllegalArgumentException
-                                               | IllegalAccessException | 
InvocationTargetException e) {
-                                       logger.error(
-                                                       "failed to get 
properties of service description",
-                                                       e);
-                                       return false;
-                               }
-                       }
-                       return true;
-               }
-               for (String searchString : filterLowerCaseSplit)
-                       if 
(!node.getUserObject().toString().toLowerCase().contains(
-                                       searchString))
-                               return false;
-               return true;
-       }
-
-       /**
-        * Determine whether a service description satisfies a search term.
-        * 
-        * @param serviceDescription
-        *            The service description bean to look in.
-        * @param type
-        *            The name of the property to look in, or <tt>null</tt> to
-        *            search in all public non-expert properties.
-        * @param searchTerm
-        *            The string to search for.
-        * @return <tt>true</tt> if-and-only-if the description matches.
-        */
-       private boolean doesPropertySatisfy(ServiceDescription 
serviceDescription,
-                       String type, String searchTerm) throws 
IllegalAccessException,
-                       IllegalArgumentException, InvocationTargetException,
-                       IntrospectionException {
-               BeanInfo beanInfo = getBeanInfo(serviceDescription.getClass());
-               for (PropertyDescriptor property : 
beanInfo.getPropertyDescriptors()) {
-                       if (superseded)
-                               return false;
-                       if ((type == null && !property.isHidden() && 
!property.isExpert())
-                                       || 
property.getName().equalsIgnoreCase(type)) {
-                               Method readMethod = property.getReadMethod();
-                               if (readMethod == null)
-                                       continue;
-                               Object readProperty = 
readMethod.invoke(serviceDescription,
-                                               new Object[0]);
-                               if (readProperty == null)
-                                       continue;
-                               if 
(readProperty.toString().toLowerCase().contains(searchTerm))
-                                       return true;
-                               // Dig deeper?
-                       }
-               }
-               return false;
-       }
-
-       @Override
-       public boolean pass(DefaultMutableTreeNode node) {
-               return basicFilter(node);
-       }
-
-       @Override
-       public String filterRepresentation(String original) {
-               return original;
-       }
-
-       /**
-        * @return the superseded
-        */
-       @Override
-       public boolean isSuperseded() {
-               return superseded;
-       }
-
-       /**
-        * @param superseded
-        *            the superseded to set
-        */
-       @Override
-       public void setSuperseded(boolean superseded) {
-               this.superseded = superseded;
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilterTreeNode.java
----------------------------------------------------------------------
diff --git 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilterTreeNode.java
 
b/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilterTreeNode.java
deleted file mode 100644
index 0e559ce..0000000
--- 
a/taverna-activity-palette-ui/src/main/java/net/sf/taverna/t2/workbench/ui/servicepanel/ServiceFilterTreeNode.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007-2009 The University of Manchester   
- * 
- *  Modifications to the initial code base are copyright of their
- *  respective authors, or their employers as appropriate.
- * 
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public License
- *  as published by the Free Software Foundation; either version 2.1 of
- *  the License, or (at your option) any later version.
- *    
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *    
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- 
******************************************************************************/
-package net.sf.taverna.t2.workbench.ui.servicepanel;
-
-import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
-import net.sf.taverna.t2.workbench.ui.servicepanel.tree.FilterTreeNode;
-
-/**
- * @author alanrw
- */
-public class ServiceFilterTreeNode extends FilterTreeNode {
-       private static final long serialVersionUID = 6066698619971305454L;
-       
-       public ServiceFilterTreeNode(ServiceDescription userObject) {
-               super(userObject);
-       }
-
-       @Override
-       public ServiceDescription getUserObject() {
-               return (ServiceDescription) super.getUserObject();
-       }
-}

Reply via email to