/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2004
//
// Copyright in this library belongs to the IT Innovation Centre of
// 2 Venture Road, Chilworth Science Park, Southampton, SO16 7NP, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//      Created by:             Darren Marvin
//      Created date:           2003/09/19
//      Created for project:    GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
//      Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//      Last commit info:       $Author: $
//                              $Date: $
//                              $Revision: $
//
/////////////////////////////////////////////////////////////////////////

package uk.ac.soton.itinnovation.gemss.transportmessaging.proxies.gemss;

import eu.gemss.*;
import eu.gemss.components.*;
import eu.gemss.components.transport.*;
import eu.gemss.components.transport.servicedescription.*;
import eu.gemss.signals.*;
import java.util.*;
import java.util.logging.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.configuration.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.connection.*;
import uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.context.*;

public class GEMSSTransportMessagingImpl implements eu.gemss.components.transport.GEMSSTransportAndMessaging {

    private static Logger mLogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.security.context.proxies.gemss");
    private static TransportMessaging mTransportMessaging;

    /**
     * Default constructor for the IT Innovation security context module implementation
     */
    public GEMSSTransportMessagingImpl() throws eu.gemss.components.transport.GEMSSTransportAndMessagingException {
        try{
            //get the configuration details

            Configuration config = null;
//[stuart DUMMYGEMSS removed nov03]
//            String isTest = System.getProperty("gemss.test");
//            if(isTest!=null && isTest.equals("true")) {
//                config = uk.ac.soton.itinnovation.gemss.DummyGEMSS.getConfiguration();
//		    mLogger.info("Using dummyGEMSS configuration component");
//            }
//            else {
                // get config object from the component manager
                config = (Configuration) GEMSS.getInstance().getInstance( "eu.gemss.components.Configuration" );
//            }

            if(config == null || config.getConfigDir()==null) {
                mLogger.warning("No configuration information was accessible, creating transport component without any configuration");
                mTransportMessaging = new TransportMessaging();
            }
            else {
                mLogger.log(Level.INFO,"Using '" + config.getConfigDir() + "' as configuration directory");
                TransportMessagingConfiguration ctxConfig = new TransportMessagingConfiguration(config.getConfigDir());
                mTransportMessaging = new TransportMessaging(ctxConfig,new GEMSSSignalPump());
            }
        }
        catch(Exception ex) {
            mLogger.log(Level.SEVERE,"Unexpected failure occured inside transport messaging component, please send a bug report including all log files",ex);
            throw new eu.gemss.components.transport.GEMSSTransportAndMessagingException("Unexpected failure occured inside transport messaging component, please send a bug report including all log files");
        }
    }

    /**
     * Invokes the service described by the passed service description using input data
     * contained in the passed input container
     * @param serviceDesc service description
     * @param input input data container
     * @return
     */
    public InvocationOutput invokeService(ServiceDescription serviceDesc, InvocationInput input) throws GridException {
        try{
            return mTransportMessaging.invokeService(serviceDesc,input);
        }
        //catch the important ones for GEMSS
        catch(ConnectionException ex) {
            if(ex instanceof ConnectionInterruptedException) {
                ConnectionInterruptedException ex2 = (ConnectionInterruptedException) ex;
                throw new ConnectionBrokenException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else
                throw new ConnectionFailedException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.MessagingException ex) {
            if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) ex;
                throw new eu.gemss.components.transport.InvalidOperationException(ex2.getUserMessage(),ex2.getSystemMessage());
            }
            else if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) ex;
                throw new eu.gemss.components.transport.InputArgumentException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else if(ex instanceof MessageSecurityContextException) {
                MessageSecurityContextException ex2 = (MessageSecurityContextException) ex;
                Exception exception = ex2.getOriginalException();
                if(exception!=null) {
                    if(exception instanceof GridException)
                        throw (GridException) exception;
                    else
                        throw new GEMSSTransportAndMessagingException("Security context created exception '" + exception.getMessage() + "'","Security context created exception '" + exception.getMessage() + "'");
                }
                else throw new GEMSSTransportAndMessagingException("Failure associated with security context '" + ex2.getMessage() + "'","Failure associated with security context '" + ex2.getMessage() + "'");
            }
            else {
              mLogger.log(Level.SEVERE,"Could not complete invocation reason '" + ex.getSystemMessage(),ex);
              throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
            }
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.ServiceException ex) {
            //later there will be more specific service related exceptions but not yet
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.TransportMessagingException ex) {
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
    }

    /**
     * Invokes the service described by the passed service description using input data
     * contained in the passed input container
     * @param serviceDesc service description
     * @param input input data container
     * @param fileHandles map from return item names to file destination paths
     * @return
     */
    public InvocationOutput invokeService(ServiceDescription serviceDesc, InvocationInput input, Map fileHandles) throws GridException {
        try{
            return mTransportMessaging.invokeService(serviceDesc,input, fileHandles);
        }
        //catch the important ones for GEMSS
        catch(ConnectionException ex) {
            if(ex instanceof ConnectionInterruptedException) {
                ConnectionInterruptedException ex2 = (ConnectionInterruptedException) ex;
                throw new ConnectionBrokenException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else
                throw new ConnectionFailedException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.MessagingException ex) {
            if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) ex;
                throw new eu.gemss.components.transport.InvalidOperationException(ex2.getUserMessage(),ex2.getSystemMessage());
            }
            else if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) ex;
                throw new eu.gemss.components.transport.InputArgumentException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else if(ex instanceof MessageSecurityContextException) {
                MessageSecurityContextException ex2 = (MessageSecurityContextException) ex;
                Exception exception = ex2.getOriginalException();
                if(exception!=null) {
                    if(exception instanceof GridException)
                        throw (GridException) exception;
                    else
                        throw new GEMSSTransportAndMessagingException("Security context created exception '" + exception.getMessage() + "'","Security context created exception '" + exception.getMessage() + "'");
                }
                else throw new GEMSSTransportAndMessagingException("Failure associated with security context '" + ex2.getMessage() + "'","Failure associated with security context '" + ex2.getMessage() + "'");
            }
            else {
              mLogger.log(Level.SEVERE,"Could not complete invocation reason '" + ex.getSystemMessage(),ex);
              throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
            }
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.ServiceException ex) {
            //later there will be more specific service related exceptions but not yet
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.TransportMessagingException ex) {
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
    }

    /**
     * Invokes the service described by the passed service description using input data
     * contained in the passed input container
     * @param serviceDesc service description
     * @param input input data container
     * @param usePolicyFile true if you static policy file, false otherwise
     * @return
     */
    public InvocationOutput invokeService(ServiceDescription serviceDesc, InvocationInput input, boolean usePolicyFile) throws GridException {
        try{
            return mTransportMessaging.invokeService(serviceDesc,input,usePolicyFile);
        }
        //catch the important ones for GEMSS
        catch(ConnectionException ex) {
            if(ex instanceof ConnectionInterruptedException) {
                ConnectionInterruptedException ex2 = (ConnectionInterruptedException) ex;
                throw new ConnectionBrokenException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else
                throw new ConnectionFailedException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.MessagingException ex) {
            if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) ex;
                throw new eu.gemss.components.transport.InvalidOperationException(ex2.getUserMessage(),ex2.getSystemMessage());
            }
            else if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) ex;
                throw new eu.gemss.components.transport.InputArgumentException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else if(ex instanceof MessageSecurityContextException) {
                MessageSecurityContextException ex2 = (MessageSecurityContextException) ex;
                Exception exception = ex2.getOriginalException();
                if(exception!=null) {
                    if(exception instanceof GridException)
                        throw (GridException) exception;
                    else
                        throw new GEMSSTransportAndMessagingException("Security context created exception '" + exception.getMessage() + "'","Security context created exception '" + exception.getMessage() + "'");
                }
                else throw new GEMSSTransportAndMessagingException("Failure associated with security context '" + ex2.getMessage() + "'","Failure associated with security context '" + ex2.getMessage() + "'");
            }
            else {
              mLogger.log(Level.SEVERE,"Could not complete invocation reason '" + ex.getSystemMessage(),ex);
              throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
            }

        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.ServiceException ex) {
            //later there will be more specific service related exceptions but not yet
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.TransportMessagingException ex) {
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
    }

    /**
     * Invokes the service described by the passed service description using input data
     * contained in the passed input container
     * @param serviceDesc service description
     * @param input input data container
     * @param usePolicyFile true if use static policy file, false otherwise
     * @param fileHandles map from return item names to file destination paths
     * @return
     */
    public InvocationOutput invokeService(ServiceDescription serviceDesc, InvocationInput input, Map fileHandles, boolean usePolicyFile) throws GridException {
        try{
            return mTransportMessaging.invokeService(serviceDesc,input, fileHandles,usePolicyFile);
        }
        //catch the important ones for GEMSS
        catch(ConnectionException ex) {
            if(ex instanceof ConnectionInterruptedException) {
                ConnectionInterruptedException ex2 = (ConnectionInterruptedException) ex;
                throw new ConnectionBrokenException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else
                throw new ConnectionFailedException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.MessagingException ex) {
            if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InvalidOperationException) ex;
                throw new eu.gemss.components.transport.InvalidOperationException(ex2.getUserMessage(),ex2.getSystemMessage());
            }
            else if(ex instanceof uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) {
                uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException ex2 =
                        (uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.InputArgumentException) ex;
                throw new eu.gemss.components.transport.InputArgumentException(ex.getUserMessage(),ex.getSystemMessage());
            }
            else if(ex instanceof MessageSecurityContextException) {
                MessageSecurityContextException ex2 = (MessageSecurityContextException) ex;
                Exception exception = ex2.getOriginalException();
                if(exception!=null) {
                    if(exception instanceof GridException)
                        throw (GridException) exception;
                    else
                        throw new GEMSSTransportAndMessagingException("Security context created exception '" + exception.getMessage() + "'","Security context created exception '" + exception.getMessage() + "'");
                }
                else throw new GEMSSTransportAndMessagingException("Failure associated with security context '" + ex2.getMessage() + "'","Failure associated with security context '" + ex2.getMessage() + "'");
            }
            else {
              mLogger.log(Level.SEVERE,"Could not complete invocation reason '" + ex.getSystemMessage(),ex);
              throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
            }
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.messaging.ServiceException ex) {
            //later there will be more specific service related exceptions but not yet
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
        catch(uk.ac.soton.itinnovation.gemss.transportmessaging.TransportMessagingException ex) {
            throw new GEMSSTransportAndMessagingException(ex.getUserMessage(),ex.getSystemMessage());
        }
    }


    private class GEMSSSignalPump implements SignalHandler {

        public GEMSSSignalPump() {}

        public void process(Signal signal) {
            ComponentManager cManager = null;
 //[stuart DUMMYGEMSS removed nov03]
//		String isTest = System.getProperty("gemss.test");
//            if(isTest!=null && isTest.equals("true")) {
//                cManager = uk.ac.soton.itinnovation.gemss.DummyGEMSS.getInstance();
//            }
//            else {
                cManager = GEMSS.getInstance();
//            }

        }
    }

}