package org.apache.taverna.biocatalogue.model;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JLabel;

import net.sf.taverna.raven.appconfig.ApplicationRuntime;
import org.apache.taverna.ui.perspectives.biocatalogue.BioCataloguePerspective;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;

/**
 * Class containing various reusable helper methods.
 * 
 * @author Sergejs Aleksejevs
 */
public class Util


{
	
	private static Logger logger = Logger.getLogger(Util.class);

  
  /**
   * Makes sure that one component (for example, a window) is centered horizontally and vertically
   * relatively to the other component. This is achieved by aligning centers of the two components.
   * 
   * This method can be used even if the 'dependentComponent' is larger than the 'mainComponent'. In
   * this case it is probably only useful for centering windows against each other rather than
   * components inside a container.
   * 
   * Method also makes sure that the dependent component will not be placed above the screen's upper
   * edge and to the left of the left edge.
   */
  public static void centerComponentWithinAnother(Component mainComponent, Component dependentComponent)
  {
    int iMainComponentCenterX = (int)Math.round(mainComponent.getLocationOnScreen().getX() + (mainComponent.getWidth() / 2));
    int iPosX = iMainComponentCenterX - (dependentComponent.getWidth() / 2);
    if (iPosX < 0) iPosX = 0;
    
    int iMainComponentCenterY = (int)Math.round(mainComponent.getLocationOnScreen().getY() + (mainComponent.getHeight() / 2));
    int iPosY = iMainComponentCenterY - (dependentComponent.getHeight() / 2);
    if (iPosY < 0) iPosY = 0;
    
    dependentComponent.setLocation(iPosX, iPosY);
  }
  
  
  /**
   * The parameter is the class name to be processed; class name is likely to be in
   * the form <class_name>$<integer_value>, where the trailing part starting with
   * the $ sign indicates the anonymous inner class within the base class. This will
   * strip out that part of the class name to get the base class name.
   */
  public static String getBaseClassName(String strClassName)
  {
    // strip out the class name part after the $ sign; return
    // the original value if the dollar sign wasn't found
    String strResult = strClassName;
    
    int iDollarIdx = strResult.indexOf("$");
    if (iDollarIdx != -1) strResult = strResult.substring(0, iDollarIdx);
    
    return (strResult);
  }
  
  
  /**
   * Makes sure that the supplied string is no longer than provided length.
   */
  public static String ensureStringLength(String str, int iLength) {
    if (str.length() > iLength) str = str.substring(0, iLength) + " (...)";
    return (str);
  }
  
  /**
   * Makes sure that the supplied string doesn't have any lines (separated by HTML line break tag) longer
   * than specified; assumes that there are no line breaks in the source line.
   * 
   * @param str The string to work with.
   * @param iLineLength Desired length of each line.
   * @param bIgnoreBrokenWords True if line breaks are to be inserted exactly each <code>iLineLength</code>
   *                           symbols (which will most likely cause broken words); false to insert line breaks
   *                           at the first space after <code>iLineLength</code> symbols since last line break.
   * @return New string with inserted HTML line breaks.
   */
  public static String ensureLineLengthWithinString(String str, int iLineLength, boolean bIgnoreBrokenWords)
  {
    StringBuilder out = new StringBuilder(str);
    
    // keep inserting line breaks from end of the line till the beginning until all done
    int iLineBreakPosition = 0;
    while (iLineBreakPosition >= 0 && iLineBreakPosition < out.length())
    {
      // insert line break either exactly at calculated position or 
      iLineBreakPosition += iLineLength;
      iLineBreakPosition = (bIgnoreBrokenWords ?
                            iLineBreakPosition :
                            out.indexOf(" ", iLineBreakPosition));
      
      if (iLineBreakPosition > 0 && iLineBreakPosition < out.length()) {
        out.insert(iLineBreakPosition, "<br>");
        iLineBreakPosition += 4;  // -- four is the length of "<br>"
      }
    }
    
    return (out.toString());
  }
  
  
  /**
   * This is a convenience method for calling
   * {@link Util#pluraliseNoun(String, long, boolean)}
   * with <code>false</code> as a value for third parameter.
   */
  public static String pluraliseNoun(String noun, long count) {
    return (pluraliseNoun(noun, count, false));
  }
  
  /**
   * Performs naive pluralisation of the supplied noun.
   * 
   * @param noun Noun in a singular form.
   * @param count Number of occurrences of the item, for which the noun is provided.
   * @param forceAppendingSByDefault <code>true</code> to make sure that "y" -> "ies"
   *                                 substitution is <b>not made</b>, but instead "s" is appended
   *                                 to unmodified root of the noun.
   * @return Pluralised <code>noun</code>: with appended -s or -y replaced with -ies.
   */
  public static String pluraliseNoun(String noun, long count, boolean forceAppendingSByDefault)
  {
    if (count % 10 != 1 || count == 11) {
      if (!forceAppendingSByDefault && noun.endsWith("y")) {
        return (noun.substring(0, noun.length() - 1) + "ies");  // e.g. ENTRY -> ENTRIES
      }
      else {
        return (noun + "s");  // e.g. SHIP -> SHIPS
      }
    }
    else {
      // no need to pluralise - count is of the type 21, 31, etc.. 
      return noun;
    }
  }
  
  
  /**
   * Calculates time difference between two {@link Calendar} instances.
   * 
   * @param earlier The "earlier" date.
   * @param later The "later" date.
   * @param maxDifferenceMillis The maximum allowed time difference between the two
   *                            {@link Calendar} instances, in milliseconds. If the calculated
   *                            difference will exceed <code>maxDifferenceMillis</code>,
   *                            <code>null</code> will be returned. If this parameter has
   *                            a value <code>less or equal to zero</code>, any time difference
   *                            between the {@link Calendar} instances will be permitted.
   * @return String in the form "XX seconds|minutes|hours|days ago". Proper pluralisation will
   *         be performed on the name of the time unit. <code>null</code> will be returned in
   *         cases where one of the {@link Calendar} instances is <code>null</code>, time
   *         difference between the provided instances is greater than <code>maxDifferenceMillis</code>
   *         or <code>earlier</code> date is not really earlier than <code>later</code> one.
   */
  public static String getAgoString(Calendar earlier, Calendar later, long maxDifferenceMillis)
  {
    // one of the dates is missing
    if (earlier == null || later == null) {
      return null;
    }
    
    if (earlier.before(later)) {
      long differenceMillis = later.getTimeInMillis() - earlier.getTimeInMillis();
      
      if (maxDifferenceMillis <= 0 || (maxDifferenceMillis > 0 && differenceMillis <= maxDifferenceMillis)) 
      {
        long result = 0;
        String unitName = "";
        
        if (differenceMillis < 60 * 1000) {
          result = differenceMillis / 1000;
          unitName = "second";
        }
        else if (differenceMillis < 60 * 60 * 1000) {
          result = differenceMillis / (60 * 1000);
          unitName = "minute";
        }
        else if (differenceMillis < 24 * 60 * 60 * 1000) {
          result = differenceMillis / (60 * 60 * 1000);
          unitName = "hour"; 
        }
        else {
          result = differenceMillis / (24 * 60 * 60 * 1000);
          unitName = "day";
        }
        
        return (result + " " + Util.pluraliseNoun(unitName, result, true) + " ago");
      }
      else {
        // the difference is too large - larger than the supplied threshold
        return null;
      }
    }
    else {
      // the "later" date is not really later than the "earlier" one
      return null;
    }
  }
  
  
  /**
   * Joins the set of tokens in the provided list into a single string.
   * This method is a shorthand for {@link Util#join(List, String, String, String)}.
   * 
   * @param tokens List of strings to join.
   * @param separator Separator to insert between individual strings.
   * @return String of the form <code>[token1][separator][token2][separator]...[tokenN]</code>
   */
  public static String join(List<String> tokens, String separator) {
    return (join(tokens, null, null, separator));
  }
  
  /**
   * Joins the set of tokens in the provided list into a single string.
   * 
   * Any empty strings or <code>null</code> entries in the <code>tokens</code> list 
   * will be removed to achieve a better resulting joined string.
   * 
   * @param tokens List of strings to join.
   * @param prefix String to prepend to each token.
   * @param suffix String to append to each token.
   * @param separator Separator to insert between individual strings.
   * @return String of the form <code>[prefix][token1][suffix][separator][prefix][token2][suffix][separator]...[prefix][tokenN][suffix]</code>
   *         <br/><br/>
   *         Example: call <code>join(["cat","sat","on","the","mat"], "[", "]", ", ")</code> results in the following output:
   *                  <code>"[cat], [sat], [on], [the], [mat]"</code>
   */
  public static String join(List<String> tokens, String prefix, String suffix, String separator)
  {
    if (tokens == null) {
      // nothing to join
      return (null);
    }
    
    // list of strings is not empty, but some pre-processing is necessary
    // to remove any empty strings that may be there
    for (int i = tokens.size() - 1; i >= 0; i--) {
      if (tokens.get(i) == null || tokens.get(i).length() == 0) {
        tokens.remove(i);
      }
    }
    
    // now start the actual processing, but it may be the case that all strings
    // were empty and we now have an empty list
    if (tokens.isEmpty()) {
      // nothing to join - just return an empty string
      return ("");
    }
    else {
      // there are some tokens -- perform the joining
      String effectivePrefix = (prefix == null ? "" : prefix);
      String effectiveSuffix = (suffix == null ? "" : suffix);
      String effectiveSeparator = (separator == null ? "" : separator);
      
      StringBuilder result = new StringBuilder();
      for (int i = 0; i < tokens.size(); i++) {
        result.append(effectivePrefix + tokens.get(i) + effectiveSuffix);
        result.append(i == tokens.size() - 1 ? "" : effectiveSeparator);
      }
      
      return (result.toString());
    }
  }
  
  /**
   * Determines whether the plugin is running as a standalone JFrame or inside Taverna Workbench.
   * This is a naive test, based only on the fact that Taverna uses Raven ApplicationRuntime.
   */
  public static boolean isRunningInTaverna()
  {
    try {
      // ApplicationRuntime class is defined within Taverna API. If this is available,
      // it should mean that the plugin runs within Taverna.
      ApplicationRuntime.getInstance();
      return true;
    }
    catch (NoClassDefFoundError e) {
      return false;
    }
  }
  
  
  // === STRIPPING OUT HTML FROM STRINGS ===
  
  public static String prepareStringForComponent(String source) {
	  return "<html>" + StringEscapeUtils.escapeHtml(source) + "</html>";
  }


  /*
   * === The following section is providing URL handling methods. ===
   */
  
  /**
   * See: {@link Util#appendStringBeforeParametersOfURL(String, String, boolean)}
   * 
   * Assumes the last parameter as false, so that the URL encoding will be done.
   */
  public static String appendStringBeforeParametersOfURL(String url, String strToAppend) {
    return (appendStringBeforeParametersOfURL(url, strToAppend, false));
  }
  
  /**
   * Tiny helper to strip out all HTML tags. This will not leave any HTML tags
   * at all (so that the content can be displayed in DialogTextArea - and the
   * like - components. This helps to present HTML content inside JAVA easier.
   */
  public static String stripAllHTML(String source) {
        // don't do anything if not string is provided
        if (source == null)
          return ("");
   
        // need to preserve at least all line breaks
        // (ending and starting paragraph also make a line break)
        source = source.replaceAll("</p>[\r\n]*<p>", "<br/>");
        source = source.replaceAll("[\\s]+", " ");
        source = source.replaceAll("\\<br/?\\>", "\n");
        source = source.replaceAll("\n ", "\n");

       // strip all HTML
        source = source.replaceAll("\\<.*?\\>", ""); // any HTML tags
        source = source.replaceAll("&\\w{1,4};", ""); // this is for things like "&nbsp;", "&gt;", etc

        return (source);
  }

  
  /**
   * Appends given string at the end of the provided URL just before the list of parameters in the url.
   * 
   * For example, appending ".xml" to URL "http://www.sandbox.biocatalogue.org/services?tag=blast" will
   * yield "http://www.sandbox.biocatalogue.org/services.xml?tag=blast".
   * 
   * No duplication checking is made - if the URL is already ending (before parameters) with the value of
   * the string to append, that string will still be appended.
   * 
   * @param url URL to append the string to.
   * @param strToAppend The string to append. The value will be url-encode before appending.
   * @return New string containing modified <code>url</code> with the <code>strToAppend</code> appended
   *         before the "query string" of the URL.
   */
  public static String appendStringBeforeParametersOfURL(String url, String strToAppend, boolean ignoreURLEncoding)
  {
    StringBuilder modifiedURL = new StringBuilder(url);
    
    int iPositionToInsertProvidedString = modifiedURL.indexOf("?");
    if (iPositionToInsertProvidedString == -1) iPositionToInsertProvidedString = modifiedURL.length();
    
    String stringToInsert = (ignoreURLEncoding ? strToAppend : Util.urlEncodeQuery(strToAppend));
    modifiedURL.insert(iPositionToInsertProvidedString, stringToInsert);
    
    return (modifiedURL.toString());
  }
  
  
  /**
   * This method takes a collection of name-value pairs in the form of a map.
   * It then adds all parameters from this map to the provided URL. 
   * 
   * If any parameter has the same name as was already present in the URL, the new value
   * will replace the existing one.
   * 
   * The implementation of this method is not particularly efficient - it makes a
   * lot of overhead, but it's fine for non-intensive usage.
   * 
   * @param url The URL to add a new parameter to.
   * @param Map of parameters to add to the URL. Keys and values of the map are the names and values for URL parameters.
   * @return New string which is the original <code>url</code> with all provided
   *         parameters (in the form <code>name</code>=<code>value</code> pair) added to it.
   */
  public static String appendAllURLParameters(String url, Map<String,String> parameterMap)
  {
    if (parameterMap == null || parameterMap.size() == 0) {
      // nothing to add, return the same URL
      return (url);
    }
    else {
      // just call an overloaded method which has the main logic
      // to do this action for each name-value pair in the map
      String out = url;
      for (Map.Entry<String,String> anotherParameter : parameterMap.entrySet()) {
        out = appendURLParameter(out, anotherParameter);
      }
      return (out);
    }
  }
  
  
  
  /**
   * This method takes a string representation of a URL and a name-value pair
   * of strings - in the form of Map.Entry instance to add to the URL as a new parameter.
   * 
   * If parameter with the same name was already present in the URL, the new value
   * will replace the existing one.
   * 
   * @param url The URL to add a new parameter to.
   * @param Map.Entry instance containing the name & the value for the parameter to add.
   * @return New string which is the original <code>url</code> with the desired
   *         parameter (<code>name</code>=<code>value</code> pair) added to it.
   */
  public static String appendURLParameter(String url, Map.Entry<String,String> parameter)
  {
    if (parameter == null) {
      // nothing to add, return the same URL
      return (url);
    }
    else {
      // just call an overloaded method which has the main logic to do this action
      return (appendURLParameter(url, parameter.getKey(), parameter.getValue()));
    }
  }
  
  
  /**
   * This method takes a string representation of a URL and a name-value pair
   * of strings to add to the URL as a new parameter.
   * 
   * If parameter with the same name was already present in the URL, the new value
   * will replace the existing one.
   * 
   * @param url The URL to add a new parameter to.
   * @param parameter String array with 2 elements - first element is the name
   *        of the parameter to add, second - the value of the parameter.
   * @return New string which is the original <code>url</code> with the desired
   *         parameter (<code>name</code>=<code>value</code> pair) added to it.
   */
  public static String appendURLParameter(String url, String[] parameter)
  {
    if (parameter == null || parameter.length != 2) {
      // nothing to add, return the same URL
      return (url);
    }
    else {
      // just call an overloaded method which has the main logic to do this action
      return (appendURLParameter(url, parameter[0], parameter[1]));
    }
  }
  
  
  /**
   * This method takes a string representation of a URL and a name-value pair
   * of strings to add to the URL as a new parameter.
   * 
   * If parameter with the same name was already present in the URL, the new value
   * will replace the existing one.
   * 
   * @param url The URL to add a new parameter to.
   * @param name Name of the parameter to add.
   * @param value Value of the parameter to add.
   * @return New string which is the original <code>url</code> with the desired
   *         parameter (<code>name</code>=<code>value</code> pair) added to it.
   */
  public static String appendURLParameter(String url, String name, String value)
  {
    // if name of the parameter is not given, ignore this request
    // (makes sense to return the same URL as the input in this case -
    //  as appending "nothing" wouldn't make it any different)
    if (name == null || name.length() == 0) {
      return (url);
    }
    
    // do everything in the protected block
    try
    {
      // parse the parameters of the given URL
      Map<String,String> urlParameters = extractURLParameters(url);
      if (urlParameters == null) {
        // there were no parameters in the original URL, create new map
        urlParameters = new HashMap<String,String>();
      }
      
      // add the new parameter (this will replace a parameter with identical
      // name if it was already present in the map)
      urlParameters.put(name, value);
      
      // parse the URL string into the URL object to extract original query string
      URL theURL = new URL(url);
      String originalQueryString = theURL.getQuery();
      
      // prepare the basis for the new URL to return
      String newUrl = null;
      if (originalQueryString != null) {
        // replace the original query string with empty space to
        // give way for appending the new query string
        newUrl = url.replace(originalQueryString, "");
      }
      else {
        // there were no parameters in the original URL
        newUrl = url + "?";  
      }
      
      // append the new query string
      newUrl += constructURLQueryString(urlParameters);
      
      return (newUrl);
    }
    catch (Exception e)
    {
      logger.error("\nCouldn't append parameter ('" + name + "', '" + value + "') to the URL: " + url, e); 
      return (null);
    }
  }
  
  
  /**
   * Extracts a value of a specific parameter from the supplied URL.
   *  
   * @param url The URL to extract the parameter from.
   * @param parameterName Name of the URL parameter to extract the value for.
   * @return Value of the parameter with <code>parameterName</code> in the given <code>url</code>.
   *         If the parameter with specified name is not found in the given <code>url</code>,
   *         <code>null</code> is returned instead. 
   */
  public static String extractURLParameter(String url, String parameterName)
  {
    // both URL and the name of the required parameter must be supplied
    if (url == null || url.length() == 0 || parameterName == null || parameterName.length() == 0) return null;
    
    Map<String,String> urlParameters = extractURLParameters(url);
    if (urlParameters != null) {
      // the URL has some parameters; check what's the value of the desired parameter
      return (urlParameters.get(parameterName));
    }
    else {
      // the URL doesn't contain any parameters
      return (null);
    }
  }
  
  
  /**
   * Extracts the query string from the provided URL. Parses this query string into
   * a map of parameters.
   * 
   * All parameters (both names and values) will have special characters unescaped
   * (i.e. decoded from the standard url-encoding) and can be used directly.
   * 
   * @param url The string representation of the URL to parse.
   */
  public static Map<String,String> extractURLParameters(String url)
  {
    try {
      // extract the query part of the supplied URL
      URL theURL = new URL(url);
      String queryString = theURL.getQuery();
      
      // prepare storage for output
      Map<String,String> parameterMap = null;
      
      // extract each name-value pair from query string (if any are specified in the URL)
      if (queryString != null && queryString.length() > 0)
      {
        // only initialise if there are some parameters
        parameterMap = new HashMap<String,String>();
        
        for (String parameter : queryString.split("&")) {
          String[] nameValueArr = parameter.split("=");
          
          String name = nameValueArr[0]; // parameter name must always be present
          String value = (nameValueArr.length == 2 ? nameValueArr[1] : null); // could be that parameter value is not set (e.g. "q=") - insert null then
          
          // decode possible special characters
          name = urlDecodeQuery(name);
          if (value != null) value = urlDecodeQuery(value);
          
          parameterMap.put(name, value);
        }
      }
      
      return (parameterMap);
    }
    catch (MalformedURLException e)
    {
      // some problem occurred - report it; can't return any data in this case
      logger.error("Couldn't parse parameters of a URL: " + url + "; details below:", e);
      return null;
    }
  }
  
  
  /**
   * This method is the opposite for <code>extractURLParameters(String url)</code>.
   * It takes a map of parameters, performs URL-encoding of each and assembles them
   * into a query string.
   * 
   * The query string then can be added to the <code>URL</code> object by using standard
   * Java API. 
   * 
   * @param urlParameters Map of parameters to use in query string construction.
   * @return URL-encoded query string.
   */
  public static String constructURLQueryString(Map<String,String> urlParameters)
  {
    if (urlParameters != null) {
      StringBuilder queryString = new StringBuilder();
      
      // iterate through all parameters and reconstruct the query string
      for (Map.Entry<String,String> parameter : urlParameters.entrySet())
      {
        if (queryString.length() > 0) queryString.append("&"); // parameter separator
        queryString.append(urlEncodeQuery(parameter.getKey()) + "=" + urlEncodeQuery(parameter.getValue()));
      }
      
      return (queryString.toString());
    }
    else {
      return (null);
    }
  }
  
  
  /**
   * Prepares the string to serve as a part of url query to the server.
   * @param query The string that needs URL encoding.
   * @return URL encoded string that can be inserted into the request URL.
   */
  public static String urlEncodeQuery(String query)
  {
    // "fast exit" - if null supplied, just return an empty string;
    // this is because in the URLs we have "q=", rather than "q=null" - this will cater for such cases
    if (query == null) return ("");
    
    // encode the query
    String strRes = "";
    try {
      strRes = URLEncoder.encode(query, "UTF-8");
    }
    catch (UnsupportedEncodingException e) {
      // do nothing
    }
    
    return (strRes);
  }
  
  
  /**
   * Decodes a string which came as a part of of URL (e.g. a URL parameter). This converts
   * codes of escaped special characters back into those special characters.
   * 
   * @param query The string that needs URL decoded.
   * @return Decoded string that will contain all the special characters.
   */
  public static String urlDecodeQuery(String query)
  {
    String strRes = "";
    
    try {
      strRes = URLDecoder.decode(query, "UTF-8");
    }
    catch (UnsupportedEncodingException e) {
      // do nothing
    }
    
    return (strRes);
  }
  
  
  /**
   * This method is "clones" an object supplied as an argument. It uses
   * serialisation to achieve this (as opposed to manually implementing deep
   * copying of all referenced objects in the graph of the provided object).
   * This technique is used to make sure that the new object will be exact
   * replica, but totally independent of the original one.
   * 
   * Note that this code works ~100 times slower than it would do if deep copying
   * was implemented. However, this will not be used in tight loops (and in loops
   * at all), so for one-off tasks it is fine.
   * 
   * @author Dave Miller<br/>
   * Original version of the code in this method is taken from
   * <a href="http://www.javaworld.com/javaworld/javatips/jw-javatip76.html?page=2">
   *    http://www.javaworld.com/javaworld/javatips/jw-javatip76.html?page=2
   * </a> [accessed on 25/Feb/2010].
   * <br/><br/>
   * 
   * @author Subhajit Dasgupta<br/>
   * Example of using an alternative class loader during object de-serialisation
   * was taken from
   * <a href="http://blogs.sun.com/adventures/entry/desrializing_objects_custom_class_loaders">
   *    http://blogs.sun.com/adventures/entry/desrializing_objects_custom_class_loaders
   * </a> [accessed on 29/Mar/2010].
   * 
   * @return Deep copy of the provided object. If deep copying doesn't succeed,
   *         <code>null</code> is returned.
   */
  public static Object deepCopy(Object objectToCopy)
  {
    // a "safety net" - a class loader of BioCatalogue perspective may be used in
    // de-serialisation process to make sure that all classes are recognised
    // (system class loader may not be able to "see" all BioCatalogue plugin's files,
    //  but just those in Taverna's /lib folder)
    final ClassLoader[] customClassLoaders = new ClassLoader[] { BioCataloguePerspective.class.getClassLoader() };
    
    try
    {
      ObjectOutputStream oos = null;
      ObjectInputStream ois = null;
      try
      {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         oos = new ObjectOutputStream(bos);
         
         // serialise and pass the object
         oos.writeObject(objectToCopy);
         oos.flush();
         
         // read and return the new object
         ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
         ois = new ObjectInputStream(bin) {
                     /**
                      * <code>resolveClass()</code> method is overridden to make use of
                      * custom ClassLoader in the de-serialisation process.
                      * <br/>
                      * This is needed to make sure that the ClassLoader of the BioCatalogue
                      * perspective is used as opposed to the system ClassLoader which will
                      * only be able to see classes from Taverna's /lib folder.
                      */
                     protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException
                     {
                       String className = desc.getName();
                       try {
                         // attempt to use default class loader
                         return Class.forName(className);
                       }
                       catch (ClassNotFoundException exc)
                       {
                         // default class loader was unable to locate a required class -
                         // attempt to use one of the provided class loaders
                         for (ClassLoader cl : customClassLoaders) {
                           try {
                             return cl.loadClass(className);
                           } 
                           catch (ClassNotFoundException e) {
                             /* do nothing here - there may be other class loaders to try */
                           }
                         }
                         // none of the class loaders was able to recognise the currently
                         // de-serialised class, so it's indeed an exception
                         throw new ClassNotFoundException(className + 
                             " -- neither system, nor alternative class loaders were able to load this class");
                       }
                     }
                   };
         return ois.readObject();
      }
      catch(Exception e)
      {
         logger.error("Could not perform deep copy of " + objectToCopy.getClass() + " instance", e);
      }
      finally
      {
         oos.close();
         ois.close();
      }
    }
    catch (Exception e) {
      logger.error("Could not close object streams during deep copy of " + objectToCopy.getClass() + " instance");
    }
    
    // Error occurred - couldn't produce the deep copy...
    return null;
  }
}
