http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/3ecb1291/taverna-credential-manager-impl/src/main/java/net/sf/taverna/t2/security/credentialmanager/impl/CredentialManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-credential-manager-impl/src/main/java/net/sf/taverna/t2/security/credentialmanager/impl/CredentialManagerImpl.java
 
b/taverna-credential-manager-impl/src/main/java/net/sf/taverna/t2/security/credentialmanager/impl/CredentialManagerImpl.java
deleted file mode 100644
index 3d66c1a..0000000
--- 
a/taverna-credential-manager-impl/src/main/java/net/sf/taverna/t2/security/credentialmanager/impl/CredentialManagerImpl.java
+++ /dev/null
@@ -1,2657 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2008-2014 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.security.credentialmanager.impl;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Method;
-import java.math.BigInteger;
-import java.net.Authenticator;
-import java.net.Socket;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.Key;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.Security;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import javax.crypto.spec.SecretKeySpec;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509ExtendedKeyManager;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-import static javax.security.auth.x500.X500Principal.RFC2253;
-import net.sf.taverna.t2.lang.observer.MultiCaster;
-import net.sf.taverna.t2.lang.observer.Observable;
-import net.sf.taverna.t2.lang.observer.Observer;
-import net.sf.taverna.t2.security.credentialmanager.CMException;
-import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
-import static 
net.sf.taverna.t2.security.credentialmanager.CredentialManager.KeystoreType.KEYSTORE;
-import static 
net.sf.taverna.t2.security.credentialmanager.CredentialManager.KeystoreType.TRUSTSTORE;
-import net.sf.taverna.t2.security.credentialmanager.DistinguishedNameParser;
-import 
net.sf.taverna.t2.security.credentialmanager.JavaTruststorePasswordProvider;
-import net.sf.taverna.t2.security.credentialmanager.KeystoreChangedEvent;
-import net.sf.taverna.t2.security.credentialmanager.MasterPasswordProvider;
-import net.sf.taverna.t2.security.credentialmanager.ParsedDistinguishedName;
-import 
net.sf.taverna.t2.security.credentialmanager.ServiceUsernameAndPasswordProvider;
-import net.sf.taverna.t2.security.credentialmanager.TrustConfirmationProvider;
-import net.sf.taverna.t2.security.credentialmanager.UsernamePassword;
-import org.apache.commons.io.FileUtils;
-import org.apache.log4j.Logger;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import uk.org.taverna.configuration.app.ApplicationConfiguration;
-
-/**
- * Provides an implementation of {@link #CredentialManagerService}.
- * 
- * @author Alex Nenadic
- * @author Stian Soiland-Reyes
- */
-
-public class CredentialManagerImpl implements CredentialManager,
-               Observable<KeystoreChangedEvent> {
-       /** Various passwords to try for the Java's default truststore. */
-       public static List<String> defaultTrustStorePasswords = Arrays.asList(
-                       System.getProperty(PROPERTY_TRUSTSTORE_PASSWORD, ""), 
"changeit",
-                       "changeme", "");
-
-       // For Taverna 2.2 and older - Keystore was BC-type with user-set 
password
-       // and Truststore was JKS-type with the default password
-       public static final String OLD_TRUSTSTORE_PASSWORD = 
"Tu/Ap%2_$dJt6*+Rca9v";
-       public static final String OLD_T2TRUSTSTORE_FILE = "t2truststore.jks";
-
-       private static Logger logger = Logger
-                       .getLogger(CredentialManagerImpl.class);
-
-       // Multicaster of KeystoreChangedEventS
-       private MultiCaster<KeystoreChangedEvent> multiCaster = new 
MultiCaster<>(
-                       this);
-
-       /**
-        * A directory containing Credential Manager's Keystore/Truststore/etc.
-        * files.
-        */
-       private File credentialManagerDirectory = null;
-
-       /**
-        * Master password for Credential Manager - used to create/access the
-        * Keystore and Truststore.
-        */
-       private String masterPassword;
-
-       // Keystore file
-       private File keystoreFile = null;
-
-       // Truststore file
-       private File truststoreFile = null;
-
-       /**
-        * Keystore containing user's passwords and private keys with 
corresponding
-        * public key certificate chains.
-        */
-       private KeyStore keystore;
-
-       /**
-        * Truststore containing trusted certificates of CA authorities and 
services
-        * (servers).
-        */
-       private KeyStore truststore;
-
-       /**
-        * Has the Credential Manager been initialized (i.e. the 
Keystore/Truststore
-        * loaded, etc.)
-        */
-       private boolean isInitialized = false;
-
-       /*
-        * Whether SSLSocketFactory has been initialised with Taverna's
-        * Keystore/Truststore. Actually tavernaSSLSocketFactory==null? check 
tells
-        * us if Taverna's SSLSocketFactory has been initialised
-        */
-       // private static boolean sslInitialized = false;
-
-       private static SSLSocketFactory tavernaSSLSocketFactory;
-
-       /**
-        * Observer of changes to the Keystore and Truststore that updates the
-        * default SSLContext and SSLSocketFactory at the single location rather
-        * than all over the code when changes to the keystores occur.
-        */
-       private KeystoreChangedObserver keystoresChangedObserver = new 
KeystoreChangedObserver();
-
-       /**
-        * Cached list of all services that have a username/password entry in 
the
-        * Keystore
-        */
-       private List<URI> cachedServiceURIsList = null;
-
-       /**
-        * Cached map of all URI fragments to their original URIs for services 
that
-        * have a username/password entry in the Keystore. This is normally 
used to
-        * recursively discover the realm of the service for HTTP 
authentication so
-        * we do not have to ask user for their username and password for every
-        * service in the same realm.
-        */
-       private HashMap<URI, URI> cachedServiceURIsMap = null;
-
-       // Observer that clears the above list and map on any change to the 
Keystore
-       private ClearCachedServiceURIsObserver clearCachedServiceURIsObserver = 
new ClearCachedServiceURIsObserver();
-
-       /** A list of master password providers */
-       private List<MasterPasswordProvider> masterPasswordProviders;
-
-       /**
-        * A list of Java truststore password (used to encrypt/decrypt the 
Java's
-        * default truststore) providers
-        */
-       private List<JavaTruststorePasswordProvider> 
javaTruststorePasswordProviders;
-
-       /** A list of providers of usernames and passwords for services */
-       private List<ServiceUsernameAndPasswordProvider> 
serviceUsernameAndPasswordProviders;
-
-       /** A list of providers of trust confirmation for services */
-       private List<TrustConfirmationProvider> trustConfirmationProviders;
-
-       private ApplicationConfiguration applicationConfiguration;
-
-       private File certificatesRevokedIndicatorFile;
-       
-        private DistinguishedNameParser dnParser = new 
DistinguishedNameParserImpl();
-
-       /**
-        * Return an array of URLs for 'special' trusted CAs' certificates 
contained in
-        * the resources folder that need to be loaded into Truststore, so that 
we can establish trust 
-        * into services such as BioCatalogue, BiodiversityCatalogue, heater, 
etc. by default.
-        * */
-       private static List<URL> getSpecialTrustedCertificates() {
-               List<URL> urls = new ArrayList<>();
-               Class<?> c = CredentialManager.class;
-               
urls.add(c.getResource("/trusted-certificates/TERENASSLCA.crt"));
-               
urls.add(c.getResource("/trusted-certificates/UTNAddTrustServer_CA.crt"));
-               
urls.add(c.getResource("/trusted-certificates/AddTrustExternalCARoot.crt"));
-               return urls;
-       }
-
-       /**
-        * Connects this credential manager to the Java {@linkplain 
Authenticator HTTP authenticator mechanism}.
-        */
-       public void installAuthenticator() {
-               Authenticator.setDefault(new 
CredentialManagerAuthenticator(this));
-       }
-
-       public void deleteRevokedCertificates(){
-               
-               if (truststore != null){
-                       // Delete the old revoked or unnecessary BioCatalogue,
-                       // BiodiversityCatalogue and heater's certificates, if 
present
-                       
-                       if (certificatesRevokedIndicatorFile == null){
-                               certificatesRevokedIndicatorFile = new 
File(credentialManagerDirectory, CERTIFICATES_REVOKED_INDICATOR_FILE_NAME);
-                       }
-                       
-                       if (!certificatesRevokedIndicatorFile.exists()) {
-                               
-                               List<URL> certURLsToDelete = new ArrayList<>();
-                               Class<?> c = CredentialManager.class;
-                               
certURLsToDelete.add(c.getResource("/trusted-certificates/www.biocatalogue.org-revoked.pem"));
-                               
certURLsToDelete.add(c.getResource("/trusted-certificates/www.biodiversitycatalogue.org-revoked.pem"));
-                               
certURLsToDelete.add(c.getResource("/trusted-certificates/heater.cs.man.ac.uk-not-needed.pem"));
-
-                               for (URL certURLToDelete : certURLsToDelete){
-                                       try (InputStream certStreamToDelete = 
certURLToDelete.openStream()) {                                   
-                                               // We know there will be only 
one cert in the chain
-                                               CertificateFactory cf = 
CertificateFactory
-                                                               
.getInstance("X.509");
-                                               Certificate certToDelete = 
cf.generateCertificates(certStreamToDelete).toArray(new Certificate[0])[0];
-                                               String aliasToDelete = 
truststore
-                                                               
.getCertificateAlias(certToDelete);                                             
-                                               if (aliasToDelete != null) {
-                                                       
truststore.deleteEntry(aliasToDelete);
-                                                       logger.warn("Deleting 
revoked/unnecessary certificate "
-                                                                       + 
aliasToDelete);
-                                               }
-                                       } catch (Exception ex) {
-                                               logger.info("Can't delete 
revoked certificate " + certURLToDelete, ex);
-                                       }
-                               }
-                               
-                               // Touch the file
-                               try {
-                                       FileUtils
-                                                       
.touch(certificatesRevokedIndicatorFile);
-                               } catch (IOException ioex) {
-                                       // Hmmm, ignore this?
-                                       logger.error("Failed to touch " + 
certificatesRevokedIndicatorFile.getAbsolutePath(), ioex);
-                               }
-                       }
-                       
-                       //Save changes
-                       try{
-                               FileOutputStream fos = new 
FileOutputStream(truststoreFile);
-                               truststore.store(fos, 
masterPassword.toCharArray());
-                       }
-                       catch(Exception ex){
-                               String exMessage = "Failed to save Truststore 
after deleting revoked certificates.";
-                               logger.error(exMessage, ex);
-                       }
-               }
-       }
-
-       public CredentialManagerImpl() throws CMException {
-               /*
-                * Make sure we have BouncyCastle provider installed, just in 
case
-                * (needed for some tests and reading PKCS#12 keystores)
-                */
-               Security.addProvider(new BouncyCastleProvider());
-
-               /*
-                * Open the files stored in the (DEFAULT!!!) Credential 
Manager's
-                * directory
-                */
-               // loadDefaultConfigurationFiles();
-               // FIXME
-               /*
-                * Get the location of the directory containing the Keystore and
-                * Truststore somehow - from OSGi's Configuration Service
-                */
-
-               // initialize();
-       }
-
-       /**
-        * Initialize Credential Manager - load the Keystore and Truststore.
-        */
-       private void initialize() throws CMException {
-               /*
-                * Only do this if the Credential Manager has not been 
initialized so
-                * far
-                */
-               if (!isInitialized) {
-                       masterPassword = getMasterPassword();
-
-                       this.addObserver(clearCachedServiceURIsObserver);
-                       this.addObserver(keystoresChangedObserver);
-
-                       // Load the Keystore
-                       try {
-                               loadKeystore();
-                               logger.info("loaded the Keystore");
-                       } catch (CMException cme) {
-                               isInitialized = false;
-                               masterPassword = null; // just in case we need 
to try again
-                               // logger.error(cme.getMessage(), cme);
-                               throw cme;
-                       }
-
-                       // Load the Truststore
-                       try {
-                               loadTruststore();
-                               logger.info("loaded the Truststore");
-                       } catch (CMException cme) {
-                               isInitialized = false;
-                               masterPassword = null; // just in case we need 
to try again
-                               // logger.error(cme.getMessage(), cme);
-                               throw cme;
-                       }
-
-                       isInitialized = true;
-               }
-       }
-
-       /**
-        * Get the master password from the available providers.
-        * 
-        * @return master password
-        * @throws CMException
-        *             if none of the providers can provide a non-null master
-        *             password
-        */
-       private String getMasterPassword() throws CMException {
-               if (masterPassword != null)
-                       return masterPassword;
-
-               if (keystoreFile == null)
-                       loadDefaultSecurityFiles();
-
-               boolean firstTime = !keystoreFile.exists();
-
-               /**
-                * Master password providers are already sorted by their 
priority by the
-                * OSGi framework
-                */
-               for (MasterPasswordProvider masterPasswordProvider : 
masterPasswordProviders) {
-                       // FIXME how to handle default password providers!?
-                       String password = masterPasswordProvider
-                                       .getMasterPassword(firstTime);
-                       if (password != null)
-                               return password;
-               }
-
-               /*
-                * We are in big trouble - we do not have a single master 
password
-                * provider.
-                */
-               String exMessage = "Failed to obtain master password from 
providers: "
-                               + masterPasswordProviders;
-               logger.error(exMessage);
-               throw new CMException(exMessage);
-       }
-
-       /**
-        * Load Taverna's Keystore from a file on the disk.
-        */
-       private void loadKeystore() throws CMException {
-               if (keystore == null) {
-                       try {
-                               // Try to create Taverna's Keystore as Bouncy 
Castle UBER-type
-                               // keystore.
-                               keystore = KeyStore.getInstance("UBER", "BC");
-                       } catch (Exception ex) {
-                               // The requested keystore type is not available 
from security
-                               // providers.
-                               throw new CMException("Failed to instantiate 
Taverna's Keystore.", ex);
-                       }
-
-                       if (keystoreFile.exists()) { // If the file exists, 
open it
-                               // Try to load the Keystore
-                               try (FileInputStream fis = new 
FileInputStream(keystoreFile)) {
-                                       // Load the Keystore from the file
-                                       keystore.load(fis, 
masterPassword.toCharArray());
-                               } catch (Exception ex) {
-                                       keystore = null; // make it null as it 
was just created but
-                                                                               
// failed to load so it is not null
-                                       masterPassword = null; // it is 
probably the wrong password
-                                                                               
        // so do not remember it just in
-                                                                               
        // case
-                                       String exMessage = "Failed to load 
Taverna's Keystore from "
-                                                       + 
keystoreFile.getAbsolutePath()
-                                                       + ". Possible reason: 
incorrect password or corrupted file.";
-                                       logger.error(exMessage, ex);
-                                       throw new CMException(exMessage, ex);
-                               }
-                       } else {
-                               // Otherwise create a new empty Keystore
-                               try (FileOutputStream fos = new 
FileOutputStream(keystoreFile)) {
-                                       keystore.load(null, null);
-                                       // Immediately save the new (empty) 
Keystore to the file
-                                       keystore.store(fos, 
masterPassword.toCharArray());
-                               } catch (Exception ex) {
-                                       String exMessage = "Failed to generate 
a new empty Keystore.";
-                                       // logger.error(exMessage, ex);
-                                       throw new CMException(exMessage, ex);
-                               }
-                       }
-
-                       /*
-                        * Taverna distro for MAC contains info.plist file with 
some Java
-                        * system properties set to use the Keychain which 
clashes with what
-                        * we are setting here so we need to clear them
-                        */
-                       System.clearProperty(PROPERTY_KEYSTORE_TYPE);
-                       System.clearProperty(PROPERTY_KEYSTORE_PROVIDER);
-
-                       /*
-                        * Not quite sure why we still need to set these two 
properties
-                        * since we are creating our own SSLSocketFactory with 
our own
-                        * KeyManager that uses Taverna's Keystore, but seem 
like after
-                        * Taverna starts up and the first time it needs 
SSLSocketFactory
-                        * for HTTPS connection it is still using the default 
Java's
-                        * keystore unless these properties are set. Set the 
system property
-                        * "javax.net.ssl.keystore" to use Taverna's keystore.
-                        *
-                        * Axis 1 likes reading from these properties but seems 
to work as
-                        * well with Taverna's SSLSocetFactory as well. We do 
not want to
-                        * expose these as they can be read from Beanshells.
-                        */
-                       // System.setProperty(PROPERTY_KEYSTORE, 
keystoreFile.getAbsolutePath());
-                       // System.setProperty(PROPERTY_KEYSTORE_PASSWORD, 
masterPassword);
-                       System.clearProperty(PROPERTY_KEYSTORE);
-                       System.clearProperty(PROPERTY_KEYSTORE_PASSWORD);
-               }
-       }
-
-       /**
-        * Load Taverna's Truststore from a file on a disk. If the Truststore 
does
-        * not already exist, a new empty one will be created and contents of 
Java's
-        * truststore located in <JAVA_HOME>/lib/security/cacerts will be copied
-        * over to the Truststore.
-        */
-       private void loadTruststore() throws CMException {
-               if (truststore == null) {
-                       try {
-                               // Try to create Taverna's Truststore as Bouncy 
Castle UBER-type
-                               // keystore.
-                               truststore = KeyStore.getInstance("UBER", "BC");
-                       } catch (Exception ex) {
-                               // The requested keystore type is not available 
from security
-                               // providers.
-                               throw new CMException("Failed to instantiate 
Taverna's Truststore", ex);
-                       }
-
-                       if (truststoreFile.exists()) {
-                               // If the Truststore file already exists, open 
it and load the
-                               // Truststore
-                               try (FileInputStream fis = new 
FileInputStream(truststoreFile)) {
-                                       // Load the Truststore from the file
-                                       truststore.load(fis, 
masterPassword.toCharArray());
-                                       
-                                       // Delete the old revoked or 
unnecessary BioCatalogue,
-                                       // BiodiversityCatalogue and heater's 
certificates, if present
-                                       deleteRevokedCertificates();
-                                       
-                               } catch (Exception ex) {
-                                       /* Clear out things that are 
useless/hindering now */
-                                       truststore = null;
-                                       masterPassword = null;
-                                       String exMessage = "Failed to load 
Taverna's Truststore from "
-                                                       + 
truststoreFile.getAbsolutePath()
-                                                       + ". Possible reason: 
incorrect password or corrupted file.";
-                                       logger.error(exMessage, ex);
-                                       throw new CMException(exMessage, ex);
-                               }
-                       } else {
-                               /*
-                                * Otherwise create a new empty Truststore and 
load it with
-                                * certs from Java's truststore.
-                                */
-                               File javaTruststoreFile = new File(
-                                               
System.getProperty("java.home"), "lib/security/cacerts");
-                               KeyStore javaTruststore = null;
-
-                               // Java's truststore is of type "JKS" - try to 
load it
-                               try {
-                                       javaTruststore = 
KeyStore.getInstance("JKS");
-                               } catch (Exception ex) {
-                                       // The requested keystore type is not 
available from the
-                                       // provider
-                                       throw new CMException("Failed to 
instantiate a 'JKS'-type keystore "
-                                                       + "for reading Java's 
truststore.", ex);
-                               }
-
-                               boolean loadedJavaTruststore = false;
-                               /*
-                                * Load Java's truststore from the file - try 
with the default
-                                * Java truststore passwords.
-                                */
-                               for (String password : 
defaultTrustStorePasswords) {
-                                       logger.info("Trying to load Java 
truststore using password: "
-                                                       + password);
-                                       try (FileInputStream fis = new 
FileInputStream(
-                                                       javaTruststoreFile)) {
-                                               javaTruststore.load(fis, 
password.toCharArray());
-                                               loadedJavaTruststore = true;
-                                               break;
-                                       } catch (IOException ioex) {
-                                               /*
-                                                * If there is an I/O or format 
problem with the
-                                                * keystore data, or if the 
given password was incorrect
-                                                * (Thank you Sun, now I can't 
know if it is the file or
-                                                * the password..)
-                                                */
-                                               logger.info(String
-                                                               .format("Failed 
to load the Java truststore to copy "
-                                                                               
+ "over certificates using default password: "
-                                                                               
+ "%s from %s", password,
-                                                                               
javaTruststoreFile));
-                                       } catch (NoSuchAlgorithmException e) {
-                                               logger.error("Unknown 
encryption algorithm "
-                                                               + "while 
loading Java truststore from "
-                                                               + 
javaTruststoreFile, e);
-                                               break;
-                                       } catch (CertificateException e) {
-                                               logger.error("Certificate error 
while "
-                                                               + "loading Java 
truststore from "
-                                                               + 
javaTruststoreFile, e);
-                                               break;
-                                       }
-                               }
-
-                               /*
-                                * Default Java truststore passwords failed - 
possibly the user
-                                * has changed it. Ask the Java truststore 
password providers if
-                                * they can help - this will typically pop up a 
dialog to ask
-                                * the user if we are in a graphical 
environment. If not, we
-                                * will simply not copy the default truststore 
certificates into
-                                * Credential Manager's Truststore.
-                                */
-                               if (!loadedJavaTruststore)
-                                       if 
(!(loadJavaTruststoreUsingPasswordProviders(
-                                                       javaTruststore, 
javaTruststoreFile))) {
-                                               String error = "Credential 
manager failed to load"
-                                                               + " 
certificates from Java's truststore.";
-                                               String help = "Try using the 
system property -D"
-                                                               + 
PROPERTY_TRUSTSTORE_PASSWORD
-                                                               + 
"=TheTrustStorePassword";
-                                               logger.error(error + " " + 
help);
-                                               // FIXME Writes to standard 
error!
-                                               System.err.println(error);
-                                               System.err.println(help);
-                                       }
-
-                               // Create a new empty Truststore for Taverna
-                               try (FileOutputStream fos = new 
FileOutputStream(truststoreFile)) {
-                                       truststore.load(null, null);
-                                       if (loadedJavaTruststore) {
-                                               // Copy certificates into 
Taverna's Truststore from
-                                               // Java's truststore.
-                                               Enumeration<String> aliases = 
javaTruststore.aliases();
-                                               while 
(aliases.hasMoreElements()) {
-                                                       Certificate certificate 
= javaTruststore
-                                                                       
.getCertificate(aliases.nextElement());
-                                                       if (certificate 
instanceof X509Certificate)
-                                                               truststore
-                                                                               
.setCertificateEntry(
-                                                                               
                createTrustedCertificateAlias((X509Certificate) certificate),
-                                                                               
                certificate);
-                                               }
-                                       }
-
-                                       // Insert special trusted CA 
certificates
-                                       logger.info("Loading certificates of 
trusted CAs so as to establish trust into our services such as BioCatalogue, 
BiodiversityCatalogue, heater, etc.");        
-                                       CertificateFactory cf = 
CertificateFactory
-                                                       .getInstance("X.509");
-                                       for (URL trustedCertURL : 
getSpecialTrustedCertificates())
-                                               // Load the certificate 
(possibly a chain) from the
-                                               // stream
-                                               try (InputStream stream = 
trustedCertURL.openStream()) {
-                                                       for (Certificate c : cf
-                                                                       
.generateCertificates(stream))
-                                                               truststore
-                                                                               
.setCertificateEntry(
-                                                                               
                createTrustedCertificateAlias((X509Certificate) c),
-                                                                               
                c);
-                                               } catch (Exception cex) {
-                                                       logger.error("Failed to 
insert trusted certificate entry in the Truststore", cex);
-                                               }
-
-                                       // Immediately save the new Truststore 
to the file
-                                       truststore.store(fos, 
masterPassword.toCharArray());
-                               } catch (Exception ex) {
-                                       /*
-                                        * make truststore null as it was just 
created but failed to
-                                        * save so we should retry next time
-                                        */
-                                       truststore = null;
-                                       throw new CMException("Failed to 
generate new empty Taverna's Truststore", ex);
-                               }
-                       }
-
-                       /*
-                        * Taverna distro for MAC contains info.plist file with 
some Java
-                        * system properties set to use the Keychain which 
clashes with what
-                        * we are setting here so we need to clear them.
-                        */
-                       System.clearProperty(PROPERTY_TRUSTSTORE_TYPE);
-                       System.clearProperty(PROPERTY_TRUSTSTORE_PROVIDER);
-
-                       /*
-                        * Not quite sure why we still need to set these two 
properties
-                        * since we are creating our own SSLSocketFactory with 
our own
-                        * TrustManager that uses Taverna's Truststore, but 
seem like after
-                        * Taverna starts up and the first time it needs 
SSLSocketFactory
-                        * for HTTPS connection it is still using the default 
Java's
-                        * truststore unless these properties are set. Set the 
system
-                        * property "javax.net.ssl.Truststore" to use Taverna's 
truststore.
-                        */
-
-                       /*
-                        * Axis 1 likes reading from these properties but seems 
to work as
-                        * well with Taverna's SSLSocetFactory as well. We do 
not want to
-                        * expose these as they can be read from Beanshells.
-                        */
-                       // System.setProperty(PROPERTY_TRUSTSTORE, 
truststoreFile.getAbsolutePath());
-                       // System.setProperty(PROPERTY_TRUSTSTORE_PASSWORD, 
masterPassword);
-                       System.clearProperty(PROPERTY_TRUSTSTORE);
-                       System.clearProperty(PROPERTY_TRUSTSTORE_PASSWORD);
-               }
-       }
-
-       /**
-        * Load the given keystore (which is Java's default truststore) from the
-        * given file (pointing to the Java's default truststore) using the
-        * {@link JavaTruststorePasswordProvider}s lookup to obtain the 
password for
-        * the keytore.
-        * 
-        * @param javaTruststore
-        *            Java's default truststore
-        * @param javaTruststoreFile
-        *            Java's default truststore file
-        * @return true if managed to load the keystore using the provided
-        *         passwords; false otherwise
-        */
-       private boolean loadJavaTruststoreUsingPasswordProviders(
-                       KeyStore javaTruststore, File javaTruststoreFile) {
-               String javaTruststorePassword = null;
-               for (JavaTruststorePasswordProvider provider : 
javaTruststorePasswordProviders) {
-                       javaTruststorePassword = 
provider.getJavaTruststorePassword();
-                       if (javaTruststorePassword == null)
-                               continue;
-                       try (FileInputStream fis = new 
FileInputStream(javaTruststoreFile)) {
-                               javaTruststore.load(fis, 
javaTruststorePassword.toCharArray());
-                               return true;
-                       } catch (Exception ex) {
-                               String exMessage = "Failed to load the Java 
truststore to copy over certificates"
-                                               + " using user-provided 
password from password provider "
-                                               + provider;
-                               logger.warn(exMessage, ex);
-                               return false;
-                       }
-               }
-               String exMessage = "No Java truststore password provider could 
unlock "
-                               + "Java's truststore. Creating a new empty "
-                               + "Truststore for Taverna.";
-               logger.error(exMessage);
-               return false;
-       }
-
-       /**
-        * Get a username and password pair for the given service, or null if it
-        * does not exit. The returned array contains username as the first 
element
-        * and password as the second.
-        * 
-        * @deprecated Use
-        *             {@link #getUsernameAndPasswordForService(URI, boolean, 
String)}
-        *             instead
-        */
-       @Deprecated
-       public String[] getUsernameAndPasswordForService(String serviceURL)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               UsernamePassword usernamePassword = 
getUsernameAndPasswordForService(
-                               URI.create(serviceURL), false, null);
-               if (usernamePassword == null)
-                       return null;
-
-               String[] pair = new String[2];
-               pair[0] = usernamePassword.getUsername();
-               pair[1] = String.valueOf(usernamePassword.getPassword());
-               usernamePassword.resetPassword();
-               return pair;
-       }
-
-       /**
-        * Get a username and password pair for the given service's URI, or 
null if
-        * it does not exit.
-        * <p>
-        * If the username and password are not available in the Keystore, it 
will
-        * invoke implementations of the {@link 
ServiceUsernameAndPasswordProvider}
-        * interface asking the user (typically through the UI) or resolving
-        * hard-coded credentials.
-        * <p>
-        * If the parameter <code>useURIPathRecursion</code> is true, then the
-        * Credential Manager will also attempt to look for stored credentials 
for
-        * each of the parent fragments of the URI.
-        * 
-        * @param serviceURI
-        *            The URI of the service for which we are providing the 
username
-        *            and password
-        * @param useURIPathRecursion
-        *            Whether to look for any username and passwords stored in 
the
-        *            Keystore for the parent fragments of the service URI (for
-        *            example, we are looking for the credentials for service
-        *            http://somehost/some-fragment but we already have 
credentials
-        *            stored for http://somehost which can be reused)
-        * @param requestingMessage
-        *            The message to be presented to the user when asking for 
the
-        *            username and password, normally useful for UI providers 
that
-        *            pop up dialogs, can be ignored otherwise
-        * @return username and password pair for the given service
-        * @throws CMException
-        *             if anything goes wrong during Keystore lookup, etc.
-        */
-       @Override
-       public UsernamePassword getUsernameAndPasswordForService(URI serviceURI,
-                       boolean usePathRecursion, String requestingMessage)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               synchronized (keystore) {
-                       SecretKeySpec passwordKey = null;
-                       LinkedHashSet<URI> possibleServiceURIsToLookup = 
getPossibleServiceURIsToLookup(
-                                       serviceURI, usePathRecursion);
-                       Map<URI, URI> allServiceURIs = 
getFragmentMappedURIsForAllUsernameAndPasswordPairs();
-
-                       try {
-                               for (URI lookupURI : 
possibleServiceURIsToLookup) {
-                                       URI mappedURI = 
allServiceURIs.get(lookupURI);
-                                       if (mappedURI == null)
-                                               continue;
-
-                                       // We found it - get the username and 
password in the
-                                       // Keystore associated with this 
service URI
-                                       String alias = null;
-                                       alias = "password#" + 
mappedURI.toASCIIString();
-                                       passwordKey = (((SecretKeySpec) 
keystore.getKey(alias,
-                                                       
masterPassword.toCharArray())));
-                                       if (passwordKey == null) {
-                                               // Unexpected, it was just 
there in the map!
-                                               logger.warn("Could not find 
alias " + alias
-                                                               + " for known 
uri " + lookupURI
-                                                               + ", just 
deleted?");
-                                               // Remember we went outside 
synchronized(keystore) while
-                                               // looping
-                                               continue;
-                                       }
-                                       String unpasspair = new 
String(passwordKey.getEncoded(),
-                                                       UTF_8);
-                                       /*
-                                        * decoded key contains string
-                                        * 
<USERNAME><SEPARATOR_CHARACTER><PASSWORD>
-                                        */
-
-                                       int separatorAt = unpasspair
-                                                       
.indexOf(USERNAME_AND_PASSWORD_SEPARATOR_CHARACTER);
-                                       if (separatorAt < 0)
-                                               throw new CMException("Invalid 
credentials stored for "
-                                                               + lookupURI);
-
-                                       String username = 
unpasspair.substring(0, separatorAt);
-                                       String password = 
unpasspair.substring(separatorAt + 1);
-
-                                       UsernamePassword usernamePassword = new 
UsernamePassword();
-                                       usernamePassword.setUsername(username);
-                                       
usernamePassword.setPassword(password.toCharArray());
-                                       return usernamePassword;
-                               }
-
-                               // Nothing found in the Keystore, let's lookup 
using the service
-                               // username and password providers
-                               for (ServiceUsernameAndPasswordProvider 
provider : serviceUsernameAndPasswordProviders) {
-                                       UsernamePassword usernamePassword = 
provider
-                                                       
.getServiceUsernameAndPassword(serviceURI,
-                                                                       
requestingMessage);
-                                       if (usernamePassword == null)
-                                               continue;
-                                       if (usernamePassword.isShouldSave()) {
-                                               URI uri = serviceURI;
-                                               if (usePathRecursion)
-                                                       uri = 
normalizeServiceURI(serviceURI);
-                                               
addUsernameAndPasswordForService(usernamePassword, uri);
-                                       }
-                                       return usernamePassword;
-                               }
-                               // Giving up
-                               return null;
-                       } catch (Exception ex) {
-                               String exMessage = "Failed to get the username 
and password pair for service "
-                                               + serviceURI + " from the 
Keystore";
-                               logger.error(exMessage, ex);
-                               throw new CMException(exMessage, ex);
-                       }
-               }
-       }
-
-       protected Map<URI, URI> 
getFragmentMappedURIsForAllUsernameAndPasswordPairs()
-                       throws CMException {
-               synchronized (Security.class) {// FIXME synchonization on 
strange thing!
-                       if (cachedServiceURIsMap == null) {
-                               HashMap<URI, URI> map = new HashMap<>();
-                               // Get all service URIs that have username and 
password in the
-                               // Keystore
-                               for (URI serviceURI : 
getServiceURIsForAllUsernameAndPasswordPairs()) {
-                                       // Always store 1-1, with or without 
fragment
-                                       map.put(serviceURI, serviceURI);
-                                       if (serviceURI.getFragment() == null)
-                                               continue;
-
-                                       // Look up the no-fragment uri as an 
additional mapping
-                                       URI noFragment;
-                                       try {
-                                               noFragment = dnParser
-                                                               
.setFragmentForURI(serviceURI, null);
-                                       } catch (URISyntaxException e) {
-                                               logger.warn("Could not reset 
fragment for service URI "
-                                                               + serviceURI);
-                                               continue;
-                                       }
-                                       if (map.containsKey(noFragment)) {
-                                               if 
(map.get(noFragment).getFragment() != null) {
-                                                       // No mapping for 
duplicates
-                                                       map.remove(noFragment);
-                                                       continue;
-                                               } // else it's noFragment -> 
noFragment, which is OK
-                                       } else {
-                                               // Brand new, put it in
-                                               map.put(noFragment, serviceURI);
-                                       }
-                               }
-                               cachedServiceURIsMap = map;
-                       }
-                       return cachedServiceURIsMap;
-               }
-       }
-
-       /*
-        * Creates a list of possible URIs to look up when searching for 
username
-        * and password for a service with a given URI. This is mainly useful 
for
-        * HTTP AuthN when we save the realm URI rather than the exact service 
URI
-        * as we want that username and password pair to be used for the whole 
realm
-        * and not bother user for credentials every time them access a URL from
-        * that realm.
-        */
-       protected LinkedHashSet<URI> getPossibleServiceURIsToLookup(URI 
serviceURI,
-                       boolean usePathRecursion) {
-               try {
-                       serviceURI = serviceURI.normalize();
-                       serviceURI = dnParser.setUserInfoForURI(serviceURI, 
null);
-               } catch (URISyntaxException ex) {
-                       logger.warn("Could not strip userinfo from " + 
serviceURI, ex);
-               }
-
-               /*
-                * We'll use a LinkedHashSet to avoid checking for duplicates, 
like if
-                * serviceURI.equals(withoutQuery) Only the first hit should be 
added to
-                * the set.
-                */
-               LinkedHashSet<URI> possibles = new LinkedHashSet<URI>();
-
-               possibles.add(serviceURI);
-               if (!usePathRecursion || !serviceURI.isAbsolute())
-                       return possibles;
-
-               /*
-                * We'll preserve the fragment, as it is used to indicate the 
realm
-                */
-               String rawFragment = serviceURI.getRawFragment();
-               if (rawFragment == null)
-                       rawFragment = "";
-
-               URI withoutQuery = serviceURI.resolve(serviceURI.getRawPath());
-               addFragmentedURI(possibles, withoutQuery, rawFragment);
-
-               // Immediate parent
-               URI parent = withoutQuery.resolve(".");
-               addFragmentedURI(possibles, parent, rawFragment);
-               URI oldParent = null;
-               // Top parent (to be added later)
-               URI root = parent.resolve("/");
-               while (!parent.equals(oldParent) && !parent.equals(root)
-                               && parent.getPath().length() > 0) {
-                       // Intermediate parents, but not for "http://bla.org"; 
as we would
-                       // find "http://bla.org..";
-                       oldParent = parent;
-                       parent = parent.resolve("..");
-                       addFragmentedURI(possibles, parent, rawFragment);
-               }
-               // In case while-loop did not do so, also include root
-               addFragmentedURI(possibles, root, rawFragment);
-               if (rawFragment.length() > 0)
-                       // Add the non-fragment versions in the bottom of the 
list
-                       for (URI withFragment : new ArrayList<>(possibles))
-                               try {
-                                       possibles
-                                                       
.add(dnParser.setFragmentForURI(withFragment, null));
-                               } catch (URISyntaxException e) {
-                                       logger.warn("Could not non-fragment URI 
" + withFragment);
-                               }
-               return possibles;
-       }
-
-       public void addFragmentedURI(LinkedHashSet<URI> possibles, URI uri,
-                       String rawFragment) {
-               if (rawFragment != null && rawFragment.length() > 0)
-                       uri = uri.resolve("#" + rawFragment);
-               possibles.add(uri);
-       }
-
-       /**
-        * Get service URLs associated with all username/password pairs 
currently in
-        * the Keystore.
-        * 
-        * @deprecated
-        * @see #getServiceURIsForAllUsernameAndPasswordPairs()
-        */
-       @Deprecated
-       public ArrayList<String> getServiceURLsforAllUsernameAndPasswordPairs()
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               List<URI> uris = getServiceURIsForAllUsernameAndPasswordPairs();
-               ArrayList<String> serviceURLs = new ArrayList<>();
-               for (URI uri : uris)
-                       serviceURLs.add(uri.toASCIIString());
-               return serviceURLs;
-       }
-
-       /**
-        * Insert a username and password pair for the given service URI in the
-        * Keystore.
-        * <p>
-        * Effectively, this method inserts a new secret key entry in the 
Keystore,
-        * where key contains <USERNAME>"\000"<PASSWORD> string, i.e. password 
is
-        * prepended with the username and separated by a \000 character (which
-        * hopefully will not appear in the username).
-        * <p>
-        * Username and password string is saved in the Keystore as byte array 
using
-        * SecretKeySpec (which constructs a secret key from the given byte 
array
-        * but does not check if the given bytes indeed specify a secret key of 
the
-        * specified algorithm).
-        * <p>
-        * An alias used to identify the username and password entry is 
constructed
-        * as "password#"<SERVICE_URL> using the service URL this 
username/password
-        * pair is to be used for.
-        * 
-        * @param usernamePassword
-        *            The {@link UsernamePassword} to store
-        * @param serviceURI
-        *            The (possibly normalized) URI to store the credentials 
under
-        * @throws CMException
-        *             If the credentials could not be stored
-        * @return the alias under which this username and password entry was 
saved
-        *         in the Keystore
-        */
-       @Override
-       public String addUsernameAndPasswordForService(
-                       UsernamePassword usernamePassword, URI serviceURI)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               String uriString = serviceURI.toASCIIString();
-               String alias = saveUsernameAndPasswordForService(
-                               usernamePassword.getUsername(),
-                               String.valueOf(usernamePassword.getPassword()), 
uriString);
-               return alias;
-       }
-
-       /**
-        * Insert a new username and password pair in the Keystore for the given
-        * service URL string.
-        * <p>
-        * Effectively, this method inserts a new secret key entry in the 
Keystore,
-        * where key contains <USERNAME>"\000"<PASSWORD> string, i.e. password 
is
-        * prepended with the username and separated by a \000 character.
-        * <p>
-        * Username and password string is saved in the Keystore as byte array 
using
-        * SecretKeySpec (which constructs a secret key from the given byte 
array
-        * but does not check if the given bytes indeed specify a secret key of 
the
-        * specified algorithm).
-        * <p>
-        * An alias used to identify the username and password entry is 
constructed
-        * as "password#"<SERVICE_URL> using the service URL this 
username/password
-        * pair is to be used for.
-        * <p>
-        * 
-        * @return the alias under which this username and password entry was 
saved
-        *         in the Keystore
-        * @deprecated Use
-        *             {@link 
#addUsernameAndPasswordForService(UsernamePassword, URI)}
-        *             instead
-        */
-       @Deprecated
-       public String saveUsernameAndPasswordForService(String username,
-                       String password, String serviceURL) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               String alias = null;
-
-               // Alias for the username and password entry
-               synchronized (keystore) {
-                       alias = "password#" + serviceURL;
-                       /*
-                        * Password (together with its related username) is 
wrapped as a
-                        * SecretKeySpec that implements SecretKey and 
constructs a secret
-                        * key from the given password as a byte array. The 
reason for this
-                        * is that we can only save instances of Key objects in 
the
-                        * Keystore, and SecretKeySpec class is useful for raw 
secret keys
-                        * (i.e. username and passwords concats) that can be 
represented as
-                        * a byte array and have no key or algorithm parameters 
associated
-                        * with them, e.g., DES or Triple DES. That is why we 
create it with
-                        * the name "DUMMY" for algorithm name, as this is not 
checked for
-                        * anyway.
-                        * 
-                        * Use a separator character that will not appear in 
the username or
-                        * password.
-                        */
-                       String keyToSave = username
-                                       + 
USERNAME_AND_PASSWORD_SEPARATOR_CHARACTER + password;
-
-                       SecretKeySpec passwordKey;
-                       try {
-                               passwordKey = new 
SecretKeySpec(keyToSave.getBytes(UTF_8),
-                                               "DUMMY");
-                       } catch (UnsupportedEncodingException e) {
-                               throw new RuntimeException("Could not find 
encoding " + UTF_8);
-                       }
-                       try {
-                               keystore.setKeyEntry(alias, passwordKey,
-                                               masterPassword.toCharArray(), 
null);
-                               saveKeystore(KEYSTORE);
-                               multiCaster.notify(new 
KeystoreChangedEvent(KEYSTORE));
-                       } catch (Exception ex) {
-                               String exMessage = "Failed to insert username 
and password pair for service "
-                                               + serviceURL + " in the 
Keystore";
-                               logger.error(exMessage, ex);
-                               throw new CMException(exMessage, ex);
-                       }
-               }
-
-               return alias;
-       }
-
-       /**
-        * Delete a username and password pair for the given service URI from 
the
-        * Keystore.
-        */
-       @Override
-       public void deleteUsernameAndPasswordForService(URI serviceURI)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               String uriString = serviceURI.toASCIIString();
-               deleteUsernameAndPasswordForService(uriString);
-       }
-
-       /**
-        * Delete a username and password pair for the given service URL string 
from
-        * the Keystore.
-        * 
-        * @deprecated Use
-        *             {@link #deleteUsernameAndPasswordForService(URI 
serviceURI)}
-        *             instead.
-        */
-       @Deprecated
-       public void deleteUsernameAndPasswordForService(String serviceURL)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               synchronized (keystore) {
-                       deleteEntry(KEYSTORE, "password#" + serviceURL);
-                       saveKeystore(KEYSTORE);
-                       multiCaster.notify(new KeystoreChangedEvent(KEYSTORE));
-               }
-       }
-
-       /**
-        * Insert a new key entry containing private key and the corresponding
-        * public key certificate chain in the Keystore.
-        * 
-        * An alias used to identify the keypair entry is constructed as:
-        * "keypair#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<
-        * CERT_SERIAL_NUMBER>
-        * 
-        * @return the alias under which this key entry was saved in the 
Keystore
-        */
-       @Override
-       public String addKeyPair(Key privateKey, Certificate[] certs)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               String alias = null;
-
-               synchronized (keystore) {
-                       // Create an alias for the new key pair entry in the 
Keystore as
-                       // 
"keypair#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<CERT_SERIAL_NUMBER>
-                       String ownerDN = ((X509Certificate) certs[0])
-                                       
.getSubjectX500Principal().getName(RFC2253);
-                       ParsedDistinguishedName parsedDN = 
dnParser.parseDN(ownerDN);
-                       String ownerCN = parsedDN.getCN(); // owner's common 
name
-
-                       // Get the hexadecimal representation of the 
certificate's serial
-                       // number
-                       String serialNumber = new BigInteger(1,
-                                       ((X509Certificate) 
certs[0]).getSerialNumber()
-                                                       
.toByteArray()).toString(16).toUpperCase();
-
-                       String issuerDN = ((X509Certificate) certs[0])
-                                       
.getIssuerX500Principal().getName(RFC2253);
-                       parsedDN = dnParser.parseDN(issuerDN);
-                       String issuerCN = parsedDN.getCN(); // issuer's common 
name
-
-                       alias = "keypair#" + ownerCN + "#" + issuerCN + "#" + 
serialNumber;
-
-                       try {
-                               keystore.setKeyEntry(alias, privateKey,
-                                               masterPassword.toCharArray(), 
certs);
-                               saveKeystore(KEYSTORE);
-                               multiCaster.notify(new 
KeystoreChangedEvent(KEYSTORE));
-
-                               /*
-                                * This is now done from the 
KeystoresChangedObserver's notify
-                                * method. Update the default SSLSocketFactory 
used by the
-                                * HttpsURLConnectionS
-                                */
-                               // 
HttpsURLConnection.setDefaultSSLSocketFactory(createTavernaSSLSocketFactory());
-                               logger.debug("updating SSLSocketFactory after 
inserting a key pair");
-                       } catch (Exception ex) {
-                               throw new CMException("failed to insert "
-                                               + "the key pair entry in the 
Keystore", ex);
-                       }
-               }
-               return alias;
-       }
-
-       /**
-        * Checks if the Keystore contains the given key pair entry (private 
key and
-        * its corresponding public key certificate chain).
-        */
-       @Override
-       public boolean hasKeyPair(Key privateKey, Certificate[] certs)
-                       throws CMException {
-               // Create an alias for the new key pair entry in the Keystore as
-               // 
"keypair#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<CERT_SERIAL_NUMBER>
-
-               String alias = createKeyPairAlias(privateKey, certs);
-               return hasEntryWithAlias(KEYSTORE, alias);
-       }
-
-       /**
-        * Delete a key pair entry from the Keystore given its alias.
-        */
-       @Override
-       public void deleteKeyPair(String alias) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               synchronized (keystore) {
-                       deleteEntry(KEYSTORE, alias);
-                       saveKeystore(KEYSTORE);
-                       multiCaster.notify(new KeystoreChangedEvent(KEYSTORE));
-
-                       /*
-                        * This is now done from the KeyManager's nad 
TrustManager's notify
-                        * methods. Update the default SSLSocketFactory used by 
the
-                        * HttpsURLConnectionS
-                        */
-                       // 
HttpsURLConnection.setDefaultSSLSocketFactory(createTavernaSSLSocketFactory());
-
-                       logger.info("updating SSLSocketFactory after deleting a 
keypair");
-               }
-       }
-
-       /**
-        * Delete a key pair entry from the Keystore given its private and 
public
-        * key parts.
-        */
-       @Override
-       public void deleteKeyPair(Key privateKey, Certificate[] certs)
-                       throws CMException {
-               deleteKeyPair(createKeyPairAlias(privateKey, certs));
-       }
-
-       /**
-        * Export a key entry containing private key and public key certificate
-        * chain from the Keystore to a PKCS #12 file.
-        */
-       @Override
-       public void exportKeyPair(String alias, File exportFile,
-                       String pkcs12Password) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               synchronized (keystore) {
-                       // Export the key pair
-                       try {
-                               // Get the private key for the alias
-                               PrivateKey privateKey = (PrivateKey) 
keystore.getKey(alias,
-                                               masterPassword.toCharArray());
-
-                               // Get the related public key's certificate 
chain
-                               Certificate[] certChain = 
getKeyPairsCertificateChain(alias);
-
-                               // Create a new PKCS #12 keystore
-                               KeyStore newPkcs12 = 
KeyStore.getInstance("PKCS12", "BC");
-                               newPkcs12.load(null, null);
-
-                               // Place the private key and certificate chain 
into the PKCS #12
-                               // keystore. Construct a new alias as
-                               // "<SUBJECT_COMMON_NAME>'s 
<ISSUER_ORGANISATION> ID"
-
-                               String sDN = ((X509Certificate) certChain[0])
-                                               
.getSubjectX500Principal().getName(RFC2253);
-                                
-                                ParsedDistinguishedName parsedDN = 
dnParser.parseDN(sDN);
-                               String sCN = parsedDN.getCN();
-
-                               String iDN = ((X509Certificate) certChain[0])
-                                               
.getIssuerX500Principal().getName(RFC2253);
-                                parsedDN = dnParser.parseDN(iDN);
-                               String iCN = parsedDN.getCN();
-
-                               String pkcs12Alias = sCN + "'s " + iCN + " ID";
-                               newPkcs12.setKeyEntry(pkcs12Alias, privateKey, 
new char[0],
-                                               certChain);
-
-                               // Store the new PKCS #12 keystore on the disk
-                               try (FileOutputStream fos = new 
FileOutputStream(exportFile)) {
-                                       newPkcs12.store(fos, 
pkcs12Password.toCharArray());
-                               }
-                       } catch (Exception ex) {
-                               String exMessage = "Failed to export the key 
pair from the Keystore";
-                               logger.error(exMessage, ex);
-                               throw new CMException(exMessage, ex);
-                       }
-               }
-       }
-
-       /**
-        * Get certificate entry from the Keystore or Truststore. If the given 
alias
-        * name identifies a trusted certificate entry, the certificate 
associated
-        * with that entry is returned from the Truststore. If the given alias 
name
-        * identifies a key pair entry, the first element of the certificate 
chain
-        * of that entry is returned from the Keystore.
-        */
-       @Override
-       public Certificate getCertificate(KeystoreType ksType, String alias)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       switch (ksType) {
-                       case KEYSTORE:
-                               synchronized (keystore) {
-                                       return keystore.getCertificate(alias);
-                               }
-                       case TRUSTSTORE:
-                               synchronized (truststore) {
-                                       return truststore.getCertificate(alias);
-                               }
-                       default:
-                               return null;
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "Failed to fetch certificate from 
the " + ksType;
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Get certificate chain for the key pair entry from the Keystore. This
-        * method works for the Keystore only as the Truststore does not 
contain key
-        * pair entries, but trusted certificate entries only.
-        */
-       @Override
-       public Certificate[] getKeyPairsCertificateChain(String alias)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       synchronized (keystore) {
-                               return keystore.getCertificateChain(alias);
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "Failed to fetch certificate chain 
for the keypair from the Keystore";
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Get the private key part of a key pair entry from the Keystore given 
its
-        * alias.
-        * <p>
-        * This method works for the Keystore only as the Truststore does not
-        * contain key pair entries, but trusted certificate entries only.
-        * 
-        * @throws CMException
-        */
-       @Override
-       public Key getKeyPairsPrivateKey(String alias) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       synchronized (keystore) {
-                               return keystore.getKey(alias, 
masterPassword.toCharArray());
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "Failed to fetch private key for the 
keypair from the Keystore";
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Insert a trusted certificate entry in the Truststore with an alias
-        * constructed as:
-        * 
-        * "trustedcert#<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#
-        * "<CERT_SERIAL_NUMBER>
-        * 
-        * @return the alias under which this trusted certificate entry was 
saved in
-        *         the Keystore
-        */
-       @Override
-       public String addTrustedCertificate(X509Certificate cert)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               String alias = null;
-
-               synchronized (truststore) {
-                       // Create an alias for the new trusted certificate 
entry in the
-                       // Truststore as
-                       // 
"trustedcert#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<CERT_SERIAL_NUMBER>
-                       alias = createTrustedCertificateAlias(cert);
-                       try {
-                               truststore.setCertificateEntry(alias, cert);
-                               saveKeystore(TRUSTSTORE);
-                               multiCaster.notify(new 
KeystoreChangedEvent(TRUSTSTORE));
-
-                               /*
-                                * This is now done from the 
KeystoresChangedObserver's notify
-                                * method. Update the default SSLSocketFactory 
used by the
-                                * HttpsURLConnectionS
-                                */
-                               // 
HttpsURLConnection.setDefaultSSLSocketFactory(createTavernaSSLSocketFactory());
-
-                               logger.debug("Updating SSLSocketFactory after 
inserting a trusted certificate");
-                       } catch (Exception ex) {
-                               throw new CMException(
-                                               "failed to insert trusted 
certificate entry in the Truststore",
-                                               ex);
-                       }
-               }
-
-               return alias;
-       }
-
-       /**
-        * Create a Keystore alias that would be used for adding the given key 
pair
-        * (private and public key) entry to the Keystore. The alias is cretaed 
as
-        * "keypair#"
-        * &lt;CERT_SUBJECT_COMMON_NAME&gt;"#"&lt;CERT_ISSUER_COMMON_NAME&gt
-        * ;"#"&lt;CERT_SERIAL_NUMBER&gt;
-        * 
-        * @param privateKey
-        *            private key
-        * @param certs
-        *            public key's certificate chain
-        * @return
-        */
-       @Override
-       public String createKeyPairAlias(Key privateKey, Certificate certs[]) {
-               String ownerDN = ((X509Certificate) 
certs[0]).getSubjectX500Principal()
-                               .getName(RFC2253);
-                ParsedDistinguishedName parsedDN = dnParser.parseDN(ownerDN);
-               String ownerCN = parsedDN.getCN(); // owner's common name
-
-               /*
-                * Get the hexadecimal representation of the certificate's 
serial number
-                */
-               String serialNumber = new BigInteger(1, ((X509Certificate) 
certs[0])
-                               
.getSerialNumber().toByteArray()).toString(16).toUpperCase();
-
-               String issuerDN = ((X509Certificate) 
certs[0]).getIssuerX500Principal()
-                               .getName(RFC2253);
-               parsedDN = dnParser.parseDN(issuerDN);
-               String issuerCN = parsedDN.getCN(); // issuer's common name
-
-               String alias = "keypair#" + ownerCN + "#" + issuerCN + "#"
-                               + serialNumber;
-               return alias;
-       }
-
-       /**
-        * Create a Truststore alias that would be used for adding the given 
trusted
-        * X509 certificate to the Truststore. The alias is cretaed as
-        * 
"trustedcert#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<
-        * CERT_SERIAL_NUMBER>
-        * 
-        * @param cert
-        *            certificate to generate the alias for
-        * @return the alias for the given certificate
-        */
-       @Override
-       public String createTrustedCertificateAlias(X509Certificate cert) {
-               String ownerDN = 
cert.getSubjectX500Principal().getName(RFC2253);
-               ParsedDistinguishedName parsedDN = dnParser.parseDN(ownerDN);
-               String owner;
-               String ownerCN = parsedDN.getCN(); // owner's common name
-               String ownerOU = parsedDN.getOU();
-               String ownerO = parsedDN.getO();
-               if (!ownerCN.equals("none")) { // try owner's CN first
-                       owner = ownerCN;
-               } // try owner's OU
-               else if (!ownerOU.equals("none")) {
-                       owner = ownerOU;
-               } else if (!ownerO.equals("none")) { // finally use owner's 
Organisation
-                       owner = ownerO;
-               } else {
-                       owner = "<Not Part of Certificate>";
-               }
-
-               /* Get the hexadecimal representation of the certificate's 
serial number */
-               String serialNumber = new BigInteger(1, cert.getSerialNumber()
-                               .toByteArray()).toString(16).toUpperCase();
-
-               String issuerDN = 
cert.getIssuerX500Principal().getName(RFC2253);
-               parsedDN = dnParser.parseDN(issuerDN);
-               String issuer;
-               String issuerCN = parsedDN.getCN(); // issuer's common name
-               String issuerOU = parsedDN.getOU();
-               String issuerO = parsedDN.getO();
-               if (!issuerCN.equals("none")) { // try issuer's CN first
-                       issuer = issuerCN;
-               } // try issuer's OU
-               else if (!issuerOU.equals("none")) {
-                       issuer = issuerOU;
-               } else if (!issuerO.equals("none")) { // finally use issuer's
-                       // Organisation
-                       issuer = issuerO;
-               } else {
-                       issuer = "<Not Part of Certificate>";
-               }
-
-               String alias = "trustedcert#" + owner + "#" + issuer + "#"
-                               + serialNumber;
-               return alias;
-       }
-
-       /**
-        * Checks if the Truststore contains the given public key certificate.
-        */
-       @Override
-       public boolean hasTrustedCertificate(Certificate cert) throws 
CMException {
-               // Create an alias for the new trusted certificate entry in the
-               // Truststore as
-               // 
"trustedcert#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<CERT_SERIAL_NUMBER>
-               String alias = createTrustedCertificateAlias((X509Certificate) 
cert);
-               return hasEntryWithAlias(TRUSTSTORE, alias);
-       }
-
-       /**
-        * Delete a trusted certificate entry from the Truststore given its 
alias.
-        */
-       @Override
-       public void deleteTrustedCertificate(String alias) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               synchronized (truststore) {
-                       deleteEntry(TRUSTSTORE, alias);
-                       saveKeystore(TRUSTSTORE);
-                       multiCaster.notify(new 
KeystoreChangedEvent(TRUSTSTORE));
-
-                       /*
-                        * This is now done from the KeyManager's nad 
TrustManager's notify
-                        * methods Update the default SSLSocketFactory used by 
the
-                        * HttpsURLConnectionS
-                        */
-                       // 
HttpsURLConnection.setDefaultSSLSocketFactory(createTavernaSSLSocketFactory());
-
-                       logger.info("Updating SSLSocketFactory "
-                                       + "after deleting a trusted 
certificate");
-               }
-       }
-
-       /**
-        * Delete a trusted certificate entry from the Truststore given the
-        * certificate.
-        */
-       @Override
-       public void deleteTrustedCertificate(X509Certificate cert)
-                       throws CMException {
-               String alias = createTrustedCertificateAlias(cert);
-               deleteTrustedCertificate(alias);
-       }
-
-       /**
-        * Check if the given alias identifies is a key entry in the Keystore.
-        */
-       @Override
-       public boolean isKeyEntry(String alias) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       synchronized (keystore) {
-                               return keystore.isKeyEntry(alias);
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "failed to access the key entry in 
the Keystore";
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Delete an entry from the Keystore or the Truststore.
-        */
-       private void deleteEntry(KeystoreType ksType, String alias)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       switch (ksType) {
-                       case KEYSTORE:
-                               synchronized (keystore) {
-                                       if (keystore.containsAlias(alias))
-                                               keystore.deleteEntry(alias);
-                                       return;
-                               }
-                       case TRUSTSTORE:
-                               synchronized (truststore) {
-                                       if (truststore.containsAlias(alias))
-                                               truststore.deleteEntry(alias);
-                                       return;
-                               }
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "failed to delete the entry with 
alias " + alias
-                                       + " from the " + ksType;
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Check if the Keystore/Truststore contains an entry with the given 
alias.
-        */
-       @Override
-       public boolean hasEntryWithAlias(KeystoreType ksType, String alias)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       switch (ksType) {
-                       case KEYSTORE:
-                               synchronized (keystore) {
-                                       return keystore.containsAlias(alias);
-                               }
-                       case TRUSTSTORE:
-                               synchronized (truststore) {
-                                       return truststore.containsAlias(alias);
-                               }
-                       default:
-                               return false;
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "failed to access the " + ksType
-                                       + " to check if an alias exists";
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Get all the aliases from the Keystore/Truststore or null if there was
-        * some error while accessing it.
-        */
-       @Override
-       public ArrayList<String> getAliases(KeystoreType ksType) throws 
CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       switch (ksType) {
-                       case KEYSTORE:
-                               synchronized (keystore) {
-                                       return 
Collections.list(keystore.aliases());
-                               }
-                       case TRUSTSTORE:
-                               synchronized (truststore) {
-                                       return 
Collections.list(truststore.aliases());
-                               }
-                       default:
-                               return null;
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "failed to access the " + ksType
-                                       + " to get the aliases";
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Get service URIs associated with all username/password pairs 
currently in
-        * the Keystore.
-        * 
-        * @see #hasUsernamePasswordForService(URI)
-        */
-       @Override
-       public List<URI> getServiceURIsForAllUsernameAndPasswordPairs()
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               synchronized (keystore) {
-                       if (cachedServiceURIsList == null) {
-                               List<URI> serviceURIs = new ArrayList<>();
-                               for (String alias : getAliases(KEYSTORE)) {
-                                       /*
-                                        * We are only interested in 
username/password entries here.
-                                        * Alias for such entries is 
constructed as
-                                        * "password#"<SERVICE_URI> where 
SERVICE_URI is the service
-                                        * this username/password pair is to be 
used for.
-                                        */
-                                       if (!alias.startsWith("password#"))
-                                               continue;
-                                       String[] split = alias.split("#", 2);
-                                       if (split.length != 2) {
-                                               logger.warn("Invalid alias " + 
alias);
-                                               continue;
-                                       }
-                                       String uriStr = split[1];
-                                       URI uri = URI.create(uriStr);
-                                       serviceURIs.add(uri);
-                               }
-                               cachedServiceURIsList = serviceURIs;
-                       }
-                       return cachedServiceURIsList;
-               }
-       }
-
-       /**
-        * Load a PKCS12-type keystore from a file using the supplied password.
-        */
-       @Override
-       public KeyStore loadPKCS12Keystore(File pkcs12File, String 
pkcs12Password)
-                       throws CMException {
-               // Load the PKCS #12 keystore from the file
-               try (InputStream input = new FileInputStream(pkcs12File)) {
-                       KeyStore pkcs12 = KeyStore.getInstance("PKCS12", "BC");
-                       pkcs12.load(input, pkcs12Password.toCharArray());
-                       return pkcs12;
-               } catch (Exception ex) {
-                       String exMessage = "failed to open a PKCS12-type 
keystore";
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Add an observer of the changes to the Keystore or Truststore.
-        */
-       @Override
-       public void addObserver(Observer<KeystoreChangedEvent> observer) {
-               multiCaster.addObserver(observer);
-       }
-
-       /**
-        * Get all current observers of changes to the Keystore or Truststore.
-        */
-       @Override
-       public List<Observer<KeystoreChangedEvent>> getObservers() {
-               return multiCaster.getObservers();
-       }
-
-       /**
-        * Remove an observer of the changes to the Keystore or Truststore.
-        */
-       @Override
-       public void removeObserver(Observer<KeystoreChangedEvent> observer) {
-               multiCaster.removeObserver(observer);
-       }
-
-       // /**
-       // * Checks if Credential Manager has been initialised.
-       // */
-       // public boolean isInitialized() {
-       // return isInitialized;
-       // }
-
-       // /**
-       // * Check if Keystore/Truststore file already exists on disk.
-       // */
-       // private boolean exists(KeystoreType ksType) {
-       //
-       // if (ksType.equals(KEYSTORE))
-       // return keystoreFile.exists();
-       // else if (ksType.equals(TRUSTSTORE)) {
-       // return truststoreFile.exists();
-       // } else
-       // return false;
-       // }
-
-       /**
-        * Save the Keystore back to the file it was originally loaded from.
-        */
-       private void saveKeystore(KeystoreType ksType) throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               try {
-                       switch (ksType) {
-                       case KEYSTORE:
-                               synchronized (keystore) {
-                                       try (FileOutputStream fos = new 
FileOutputStream(
-                                                       keystoreFile)) {
-                                               keystore.store(fos, 
masterPassword.toCharArray());
-                                               return;
-                                       }
-                               }
-                       case TRUSTSTORE:
-                               synchronized (truststore) {
-                                       try (FileOutputStream fos = new 
FileOutputStream(
-                                                       truststoreFile)) {
-                                               // Hard-coded trust store 
password
-                                               truststore.store(fos, 
masterPassword.toCharArray());
-                                               return;
-                                       }
-                               }
-                       }
-               } catch (Exception ex) {
-                       String exMessage = "failed to save the " + ksType;
-                       logger.error(exMessage, ex);
-                       throw new CMException(exMessage, ex);
-               }
-       }
-
-       /**
-        * Checks if Keystore's master password is the same as the one provided.
-        */
-       @Override
-       public boolean confirmMasterPassword(String password) throws 
CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               return (masterPassword != null) && 
masterPassword.equals(password);
-       }
-
-       private static final boolean REALLY_DISABLED = false;
-       /**
-        * Change the Keystore and the Truststore's master password to the one
-        * provided. The Keystore and Truststore both use the same password.
-        */
-       @Override
-       public void changeMasterPassword(String newMasterPassword)
-                       throws CMException {
-               // Need to make sure we are initialized before we do anything 
else
-               // as Credential Manager can be created but not initialized
-               initialize();
-
-               String oldMasterPassword = masterPassword;
-               KeyStore oldKeystore = keystore;
-               KeyStore oldTruststore = truststore;
-
-               try {
-                       synchronized (keystore) {
-                               // Create a new keystore and copy all items 
from the current
-                               // one, encrypting them with the new password
-                               KeyStore newKeystore = null;
-                               try {
-                                       // Try to create Taverna's Keystore as 
Bouncy Castle
-                                       // UBER-type keystore.
-                                       newKeystore = 
KeyStore.getInstance("UBER", "BC");
-                               } catch (Exception ex) {
-                                       // The requested keystore type is not 
available from
-                                       // security providers.
-                                       String exMessage = "Failed to 
instantiate a new Bouncy Castle Keystore when changing master password.";
-                                       throw new CMException(exMessage, ex);
-                               }
-                               try {
-                                       // Initialize a new empty keystore
-                                       newKeystore.load(null, null);
-                               } catch (Exception ex) {
-                                       String exMessage = "Failed to create a 
new empty Keystore to copy over the entries from the current one.";
-                                       throw new CMException(exMessage, ex);
-                               }
-
-                               Enumeration<String> aliases = 
keystore.aliases();
-                               while (aliases.hasMoreElements()) {
-                                       String alias = aliases.nextElement();
-                                       if (REALLY_DISABLED) {
-                                               if 
(alias.startsWith("password#")) { // a password entry
-                                                       SecretKeySpec 
passwordKey = (((SecretKeySpec) keystore
-                                                                       
.getKey(alias, masterPassword.toCharArray())));
-                                                       
newKeystore.setKeyEntry(alias, passwordKey,
-                                                                       
newMasterPassword.toCharArray(), null);
-                                               } else if 
(alias.startsWith("keypair#")) { // a private key entry
-                                                       // Get the private key 
for the alias
-                                                       PrivateKey privateKey = 
(PrivateKey) keystore
-                                                                       
.getKey(alias, masterPassword.toCharArray());
-                                                       // Get the related 
public key's certificate chain
-                                                       Certificate[] certChain 
= keystore
-                                                                       
.getCertificateChain(alias);
-                                                       
newKeystore.setKeyEntry(alias, privateKey,
-                                                                       
newMasterPassword.toCharArray(), certChain);
-                                               }
-                                       }
-                                       // Do all entries at once, not reason 
to separate password &
-                                       // key pair entries
-                                       newKeystore.setEntry(
-                                                       alias,
-                                                       keystore.getEntry(alias,
-                                                                       new 
KeyStore.PasswordProtection(
-                                                                               
        masterPassword.toCharArray())),
-                                                       new 
KeyStore.PasswordProtection(newMasterPassword
-                                                                       
.toCharArray()));
-                               }
-                               try (FileOutputStream fos = new 
FileOutputStream(keystoreFile)) {
-                                       newKeystore.store(fos, 
newMasterPassword.toCharArray());
-                               }
-                               keystore = newKeystore;
-                       }
-
-                       // Truststore does not need to be re-encrypeted item by 
item as
-                       // entries there are not encrypted, just the whole 
truststore
-                       synchronized (truststore) {
-                               try (FileOutputStream fos = new 
FileOutputStream(truststoreFile)) {
-                                       truststore.store(fos, 
newMasterPassword.toCharArray());
-                               }
-                       }
-
-                       // Set the new master password as well
-                       masterPassword = newMasterPassword;
-               } catch (Exception ex) {
-                       // rollback
-                       keystore = oldKeystore;
-                       truststore = oldTruststore;
-                       masterPassword = oldMasterPassword;
-                       saveKeystore(KEYSTORE);
-                       saveKeystore(TRUSTSTORE);
-
-                       String exMessage = "Failed to change maaster password - 
reverting to the old one";
-                       logger.error(exMessage, ex);
-                       throw (new CMException(exMessage));
-               }
-       }
-
-       @Override
-       public void initializeSSL() throws CMException {
-               /*
-                * We use the lazy initialization of Credential Manager from 
inside the
-                * Taverna's SSLSocketFactory (i.e. KeyManager's and 
TrustManager's
-                * init() methods) when it is actually needed so do not 
initialize it
-                * here. These init() methods will not be called unledd a SSL 
connection
-                * is attempted somewhere from Taverna and it is inside them 
that we
-                * actually call the initialize() method on Credential Manager 
(and not
-                * from the Credential Manager's constructor - hence lazy).
-                * 
-                * Create Taverna's SSLSocketFactory and set the SSL socket 
factory from
-                * HttpsURLConnectionS to use it
-                */
-               if (tavernaSSLSocketFactory == null)
-                       HttpsURLConnection
-                                       
.setDefaultSSLSocketFactory(createSSLSocketFactory());
-       }
-
-       /**
-        * Creates SSLSocketFactory based on Credential Manager's Keystore and
-        * Truststore but only initalizes Credential Manager when one of the 
methods
-        * needed for creating an HTTPS connection is invoked.
-        */
-       private SSLSocketFactory createSSLSocketFactory() throws CMException {
-               SSLContext sc = null;
-               try {
-                       sc = SSLContext.getInstance("SSLv3");
-               } catch (NoSuchAlgorithmException e1) {
-                       throw new CMException(
-                                       "Failed to create SSL socket factory: "
-                                                       + "the SSL algorithm 
was not available from any crypto provider",
-                                       e1);
-               }
-
-               KeyManager[] keyManagers = null;
-               try {
-                       // Create our own KeyManager with (possibly not yet 
initialised)
-                       // Taverna's Keystore
-                       keyManagers = new KeyManager[] { new 
TavernaKeyManager() };
-               } catch (Exception e) {
-                       throw new CMException("Failed to create SSL socket 
factory: "
-                                       + "could not initiate SSL Key Manager", 
e);
-               }
-
-               TrustManager[] trustManagers = null;
-               try {
-                       // Create our own TrustManager with (possibly not yet 
initialised)
-                       // Taverna's Truststore
-                       trustManagers = new TrustManager[] { new 
TavernaTrustManager() };
-               } catch (Exception e) {
-                       throw new CMException("Failed to create SSL socket 
factory: "
-                                       + "could not initiate SSL Trust 
Manager", e);
-               }
-
-               try {
-                       sc.init(keyManagers, trustManagers, new SecureRandom());
-               } catch (KeyManagementException kmex) {
-                       throw new CMException("Failed to initiate the SSL socet 
factory",
-                                       kmex);
-               }
-
-               /*
-                * Set the default SSLContext to be used for subsequent SSL 
sockets from
-                * Java
-                */
-               SSLContext.setDefault(sc);
-
-               /*
-                * Create SSL socket to be used for HTTPS connections from the 
JVM e.g.
-                * REST activity that uses Apache HTTP client library
-                */
-               tavernaSSLSocketFactory = sc.getSocketFactory();
-
-               return tavernaSSLSocketFactory;
-       }
-
-       @Override
-       public SSLSocketFactory getTavernaSSLSocketFactory() throws CMException 
{
-               if (tavernaSSLSocketFactory == null)
-                       return createSSLSocketFactory();
-               return tavernaSSLSocketFactory;
-       }
-
-        @Override
-        public Authenticator getAuthenticator() {
-            return new CredentialManagerAuthenticator(this);
-        }
-
-       /**
-        * Taverna's Key Manager is a customised X509KeyManager that initilises
-        * Credential Manager only if certain methods on it are invoked, i.e. if
-        * acces to Keystore is actually needed to authenticate the user.
-        */
-       private class TavernaKeyManager extends X509ExtendedKeyManager {
-               /**
-                * The X509KeyManager as returned by the SunX509 provider, 
initialised
-                * with the Keystore.
-                */
-               private X509KeyManager sunJSSEX509KeyManager = null;
-
-               /**
-                * Lazy initialisation - unless we are actually asked to do 
some SSL
-                * stuff - do not initialise Credential Manager as it will most 
probably
-                * result in popping the master password window, which we want 
to avoid
-                * early on while Taverna is starting, unless we need to 
contact a
-                * secure service early, e.g. to populate the Service Panel.
-                */
-               private void init() throws Exception {
-                       logger.debug("inside TavernaKeyManager.init()");
-
-                       // Create a "default" JSSE X509KeyManager.
-                       KeyManagerFactory kmf = 
KeyManagerFactory.getInstance("SunX509",
-                                       "SunJSSE");
-
-                       if (!isInitialized)
-                               // If we have not initialised the Credential 
Manager so far -
-                               // now is the time to do it
-                               try {
-                                       logger.debug("Credential Manager has 
not been instantiated yet");
-                                       initialize();
-                                       logger.debug("Credential Manager 
instantiated");
-                               } catch (CMException cme) {
-                                       throw new Exception(
-                                                       "Could not initialize 
Taverna's KeyManager for SSLSocketFactory:"
-                                                                       + " 
failed to initialise Credential Manager.");
-                               }
-
-                       // Keystore and master password should not be null as 
we have just
-                       // initalised Credential Manager
-                       synchronized (keystore) {
-                               logger.debug("Reinitialising the KeyManager.");
-
-                               kmf.init(keystore, 
masterPassword.toCharArray());
-
-                               /*
-                                * Iterate over the KeyManagers, look for an 
instance of
-                                * X509KeyManager. If found, use that as our 
"default" key
-                                * manager.
-                                */
-                               for (KeyManager km : kmf.getKeyManagers())
-                                       if (km instanceof X509KeyManager) {
-                                               sunJSSEX509KeyManager = 
(X509KeyManager) km;
-                                               return;
-                                       }
-
-                               // X509KeyManager not found - we have to fail 
the constructor.
-                               throw new Exception(
-                                               "Could not initialize Taverna's 
KeyManager for SSLSocketFactory:"
-                                                               + " could not 
find a SunJSSE X509 KeyManager.");
-                       }
-               }
-
-               @Override
-               public String chooseClientAlias(String[] keyType, Principal[] 
issuers,
-                               Socket socket) {
-                       logger.info("inside chooseClientAlias()");
-
-                       // We have postponed initialization until we are 
actually asked to
-                       // do something
-                       try {
-                               if (sunJSSEX509KeyManager == null)
-                                       init();
-                       } catch (Exception e) {
-                               logger.error(e);
-                               return null;
-                       }
-                       // Delegate the decision to the default key manager
-                       return sunJSSEX509KeyManager.chooseClientAlias(keyType, 
issuers,
-                                       socket);
-               }
-
-               @Override
-               public String chooseServerAlias(String keyType, Principal[] 
issuers,
-                               Socket socket) {
-                       // TODO Auto-generated method stub
-                       return null;
-               }
-
-               @Override
-               public X509Certificate[] getCertificateChain(String alias) {
-                       logger.debug("inside getCertificateChain()");
-                       // We have postponed initialisation until we are 
actually asked to
-                       // do something
-                       try {
-                               if (sunJSSEX509KeyManager == null)
-                                       init();
-                       } catch (Exception e) {
-                               logger.error(e);
-                               return null;
-                       }
-                       // Delegate the decision to the default key manager
-                       return sunJSSEX509KeyManager.getCertificateChain(alias);
-               }
-
-               @Override
-               public String[] getClientAliases(String keyType, Principal[] 
issuers) {
-                       logger.debug("inside getClientAliases()");
-                       // We have postponed initialisation until we are 
actually asked to
-                       // do something
-                       try {
-                               if (sunJSSEX509KeyManager == null)
-                                       init();
-                       } catch (Exception e) {
-                               logger.error(e);
-                               return null;
-                       }
-                       // Delegate the decision to the default key manager
-                       return sunJSSEX509KeyManager.getClientAliases(keyType, 
issuers);
-               }
-
-               @Override
-               public PrivateKey getPrivateKey(String alias) {
-                       logger.debug("inside getPrivateKey()");
-                       // We have postponed initialisation until we are 
actually asked to
-                       // do something
-                       try {
-                               if (sunJSSEX509KeyManager == null)
-                                       init();
-                       } catch (Exception e) {
-                               logger.error(e);
-                               return null;
-                       }
-                       // Delegate the decision to the default key manager
-                       return sunJSSEX509KeyManager.getPrivateKey(alias);
-               }
-
-               @Override
-               public String[] getServerAliases(String keyType, Principal[] 
issuers) {
-                       // TODO Auto-generated method stub
-                       return null;
-               }
-       }
-
-       /**
-        * Taverna's Trust Manager is a customised X509TrustManager that 
initilizes
-        * Credential Manager only if certain methods on it are invoked, i.e. if
-        * acces to Truststore is actually needed to authenticate the remote
-        * service.
-        */
-       private class TavernaTrustManager implements X509TrustManager {
-               /**
-                * The default X509TrustManager as returned by SunX509 provider,
-                * initialised with the Truststore. We delegate decisions to 
it, and
-                * fall back to ask the user if the default X509TrustManager 
does not
-                * trust the server's certificate.
-                */
-               private X509TrustManager sunJSSEX509TrustManager = null;
-
-               /**
-                * Lazy initialization - unless we are actually asked to do 
some SSL
-                * stuff - do not initialise Credential Manager as it will most 
probably
-                * result in popping the master password window, which we want 
to avoid
-                * early on while Taverna is starting, unless we need to 
contact a
-                * secure service early, e.g. to populate Service Panel.
-                */
-               private void init() throws Exception {
-                       logger.debug("inside TavernaTrustManager.init()");
-
-                       // Create a "default" JSSE X509TrustManager.
-                       TrustManagerFactory tmf = 
TrustManagerFactory.getInstance(
-                                       "SunX509", "SunJSSE");
-
-                       if (!isInitialized) {
-                               logger.debug("inside TavernaTrustManager.init() 
- "
-                                               + "Credential Manager has not 
been instantiated yet.");
-                               // If we have not initialised the Credential 
Manager so far -
-                               // now is the time to do it
-                               try {
-                                       initialize();
-                                       logger.debug("inside Taverna 
TrustManager.init() - "
-                                                       + "Credential Manager 
instantiated.");
-                               } catch (CMException cme) {
-                                       throw new Exception(
-                                                       "Could not initialize 
Taverna's TrustManager for SSLSocketFactory: "
-                                                                       + 
"failed to initialise Credential Manager.");
-                               }
-                       }
-
-                       // Truststore should not be null as we have just 
initalised
-                       // Credential Manager above
-                       synchronized (truststore) {
-                               logger.debug("inside TavernaTrustManager.init() 
- "
-                                               + "Reinitialising the 
TrustManager.");
-                               SSLSocketFactory.getDefault();
-                               tmf.init(truststore);
-
-                               /*
-                                * Iterate over the TrustManagers, look for an 
instance of
-                                * X509TrustManager. If found, use that as our 
"default" trust
-                                * manager.
-                                */
-                               for (TrustManager tm : tmf.getTrustManagers())
-                                       if (tm instanceof X509TrustManager) {
-                                               sunJSSEX509TrustManager = 
(X509TrustManager) tm;
-                                               return;
-                                       }
-
-                               // X509TrustManager not found - we have to fail 
the constructor.
-                               throw new Exception(
-                                               "Could not initialize Taverna's 
TrustManager for SSLSocketFactory.");
-                       }
-               }
-
-               /*
-                * This method is called on the server-side for establishing 
trust with
-                * a client.
-                */
-               @Override
-               public void checkClientTrusted(X509Certificate[] chain, String 
authType)
-                               throws CertificateException {
-               }
-
-               /*
-                * This method is called on the client-side for establishing 
trust with
-                * a server. We first try to delegate to the default trust 
manager that
-                * uses Taverna's Truststore. If that falls through we ask the 
user if
-                * they want to trust the certificate.
-                */
-               @Override
-               public void checkServerTrusted(X509Certificate[] chain, String 
authType)
-                               throws CertificateException {
-                       // We have postponed initialisation until we are 
actually asked to
-                       // do something
-                       try {
-                               if (sunJSSEX509TrustManager == null)
-                                       init();
-                       } catch (Exception e) {
-                               logger.error(e);
-                               throw new CertificateException(e);
-                       }
-                       // Delegate the decision to the default trust manager
-                       try {
-                               
sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
-                       } catch (CertificateException excep) {
-                               // Pop up a dialog box asking whether to trust 
the server's
-                               // certificate chain.
-                               if (!shouldTrust(chain))
-                                       throw excep;
-                       }
-               }
-
-               @Override
-               public X509Certificate[] getAcceptedIssuers() {
-                       // We have postponed initialisation until we are 
actually asked to
-                       // do something
-                       try {
-                               if (sunJSSEX509TrustManager == null)
-                                       init();
-                       } catch (Exception e) {
-                               logger.error(e);
-                               return null;
-                       }
-                       return sunJSSEX509TrustManager.getAcceptedIssuers();
-               }
-       }
-
-       /**
-        * Checks if a service is trusted and if not - asks user if they want to
-        * trust it.
-        */
-       private boolean shouldTrust(final X509Certificate[] chain)
-                       throws IllegalArgumentException {
-               if (chain == null || chain.length == 0)
-                       throw new IllegalArgumentException(
-                                       "At least one certificate needed in 
chain");
-
-               /*
-                * If the certificate already exists in the truststore, it is 
implicitly
-                * trusted. This will try to avoid prompting user twice as
-                * checkServerTrusted() method gets called twice.
-                * 
-                * Well, this is not working - checkServerTrusted() is still 
called
-                * twice.
-                */
-               String alias = createTrustedCertificateAlias(chain[0]);
-               try {
-                       if (truststore.containsAlias(alias))
-                               return true;
-               } catch (KeyStoreException e) {
-                       // Ignore
-               }
-
-               String name = chain[0].getSubjectX500Principal().getName();
-               for (TrustConfirmationProvider trustConfirmationProvider : 
trustConfirmationProviders) {
-                       Boolean trustConfirmation = trustConfirmationProvider
-                                       .shouldTrustCertificate(chain);
-                       if (trustConfirmation == null)
-                               // SPI can't say yes or no, try next one
-                               continue;
-
-                       try {
-                               if (trustConfirmation) {
-                                       // initialize(); // init the Credential 
Manager if needed
-                                       addTrustedCertificate((X509Certificate) 
chain[0]);
-                                       // this will initialize Cred. Manager
-                                       logger.info("Stored trusted certificate 
" + name);
-                               }
-                       } catch (CMException ex) {
-                               logger.error("Credential Manager failed to "
-                                               + "save trusted certificate " + 
name, ex);
-                       }
-                       if (logger.isDebugEnabled()) {
-                               if (trustConfirmation) {
-                                       logger.debug("Trusting " + name + " 
according to "
-                                                       + 
trustConfirmationProvider);
-                               } else {
-                                       logger.debug("Not trusting " + name + " 
according to "
-                                                       + 
trustConfirmationProvider);
-                               }
-                       }
-                       return trustConfirmation.booleanValue();
-               }
-               logger.warn("No TrustConfirmationProvider instances could 
confirm or deny the trust in "
-                               + name);
-               // None of the trust confirmation providers (if there were any 
at all)
-               // could confirm
-               return false;
-       }
-
-       /**
-        * Normalize an URI for insertion as the basis for path-recursive 
lookups,
-        * ie. strip query and filename. For example:
-        * 
-        * <pre>
-        * URI uri = 
URI.create("http://foo.org/dir1/dirX/../dir2/filename.html?q=x";)
-        * System.out.println(CredentialManager.normalizeServiceURI(uri));
-        * >>> http://foo.org/dir1/dir2/
-        * uri = URI.create("http://foo.org/dir1/dir2/";);
-        * System.out.println(CredentialManager.normalizeServiceURI(uri));
-        * >>> http://foo.org/dir1/dir2/
-        * </pre>
-        * <p>
-        * Note that #fragments are preserved, as these are used to indicate 
HTTP
-        * Basic Auth realms
-        * 
-        * @param serviceURI
-        *            URI for a service that is to be normalized
-        * @return A normalized URI without query, userinfo or filename, ie. 
where
-        *         uri.resolve(".").equals(uri).
-        */
-       public URI normalizeServiceURI(URI serviceURI) {
-               try {
-                       // Strip userinfo, keep fragment
-                       URI normalized = dnParser.setUserInfoForURI(serviceURI, 
null)
-                                       .normalize();
-                       return 
dnParser.setFragmentForURI(normalized.resolve("."),
-                                       serviceURI.getFragment());
-               } catch (URISyntaxException ex) {
-                       return serviceURI;
-               }
-       }
-
-       /**
-        * Reset the JVMs cache for authentication like HTTP Basic Auth.
-        * <p>
-        * Note that this method uses undocumented calls to
-        * <code>sun.net.www.protocol.http.AuthCacheValue</code> which might 
not be
-        * valid in virtual machines other than Sun Java 6. If these calls fail,
-        * this method will log the error and return <code>false</code>.
-        * 
-        * @return <code>true</code> if the JVMs cache could be reset, or
-        *         <code>false</code> otherwise.
-        */
-       @Override
-       public boolean resetAuthCache() {
-               // Sun should expose an official API to do this
-               try {
-                       Class<?> AuthCacheValue = Class
-                                       
.forName("sun.net.www.protocol.http.AuthCacheValue");
-                       Class<?> AuthCacheImpl = Class
-                                       
.forName("sun.net.www.protocol.http.AuthCacheImpl");
-                       Class<?> AuthCache = Class
-                                       
.forName("sun.net.www.protocol.http.AuthCache");
-                       Method setAuthCache = 
AuthCacheValue.getMethod("setAuthCache",
-                                       AuthCache);
-                       setAuthCache.invoke(null, AuthCacheImpl.newInstance());
-                       return true;
-               } catch (Exception ex) {
-                       logger.warn(
-                                       "Could not reset authcache, non-Sun JVM 
or internal Sun classes changed",
-                                       ex);
-                       return false;
-               }
-       }
-
-       /**
-        * Checks if the Keystore contains a username and password for the given
-        * service URI.
-        */
-       @Override
-       public boolean hasUsernamePasswordForService(URI serviceURI)
-                       throws CMException {
-               Map<URI, URI> mappedServiceURIs = 
getFragmentMappedURIsForAllUsernameAndPasswordPairs();
-               for (URI possible : getPossibleServiceURIsToLookup(serviceURI, 
true))
-                       if (mappedServiceURIs.containsKey(possible))
-                               return true;
-               return false;
-       }
-
-       private void loadDefaultSecurityFiles() {
-               if (credentialManagerDirectory == null)
-                       credentialManagerDirectory = dnParser
-                                       
.getCredentialManagerDefaultDirectory(applicationConfiguration);
-               if (keystoreFile == null)
-                       keystoreFile = new File(credentialManagerDirectory,
-                                       KEYSTORE_FILE_NAME);
-               if (truststoreFile == null)
-                       truststoreFile = new File(credentialManagerDirectory,
-                                       TRUSTSTORE_FILE_NAME);
-       }
-
-       /**
-        * Set the directory where Credential Manager's Keystore and Truststore
-        * files will be read from. If this method is not used, the directory 
will
-        * default to <TAVERNA_HOME>/security somewhere in user's home 
directory.
-        * 
-        * If you want to use this method to change the location of Credential
-        * Manager's configuration directory then make sure you call it before 
any
-        * other method on Credential Manager.
-        * 
-        * This was supposed to be done through OSGi services.
-        * 
-        * @param credentialManagerDirectory
-        * @throws CMException
-        */
-       @Override
-       public void setConfigurationDirectoryPath(File 
credentialManagerDirectory)
-                       throws CMException {
-               if (credentialManagerDirectory == null)
-                       throw new CMException(
-                                       "Credential Manager's configuration 
directory cannot be null.");
-
-               try {
-                       if (!credentialManagerDirectory.exists())
-                               credentialManagerDirectory.mkdir();
-               } catch (Exception e) {
-                       throw new CMException(
-                                       "Failed to open Credential Manager's 
directory "
-                                                       + 
credentialManagerDirectory
-                                                       + " to load the 
security files: " + e.getMessage(),
-                                       e);
-               }
-
-               keystoreFile = new File(credentialManagerDirectory, 
KEYSTORE_FILE_NAME);
-               truststoreFile = new File(credentialManagerDirectory,
-                               TRUSTSTORE_FILE_NAME);
-
-               // Are we resetting the directory? Has stuff been initialized 
yet?
-               // Then we need to reset everything else.
-               if (isInitialized) {
-                       masterPassword = null;
-                       keystore = null;
-                       truststore = null;
-                       isInitialized = false;
-               }
-       }
-
-       // private void loadSecurityFiles(String credentialManagerDirPath)
-       // throws CMException {
-       //
-       // // If credentialManagerDirPath is null (e.g. user did not specify 
-cmdir
-       // on the command line)
-       // // - try with Taverna's default one
-       // if (credentialManagerDirPath == null){
-       // credentialManagerDirectory =
-       // CMUtils.getCredentialManagerDefaultDirectory();
-       // }
-       //
-       // if (credentialManagerDirectory == null) {
-       // try {
-       // credentialManagerDirectory = new File(credentialManagerDirPath);
-       // } catch (Exception e) {
-       // throw new CMException(
-       // "Failed to open Credential Manager's directory to load the security 
files: "
-       // + e.getMessage(),
-       // e);
-       // }
-       // }
-       // if (keystoreFile == null){
-       // keystoreFile = new File(credentialManagerDirectory, 
KEYSTORE_FILE_NAME);
-       // }
-       // if (truststoreFile == null){
-       // truststoreFile = new File

<TRUNCATED>

Reply via email to