/*
 *     Copyright (C) 2015 ASIP Santé
 */
package fr.asipsante.mss.clientcxfmss.spring;

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLSocketFactory;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Ce composant permet lors du paramétrage du client CXF de mettre en place la @SSLSocketFactory qui
 * fournira la stratégie d'authentification SSL lors des appels SOAP gérés par CXF.
 * @author ASIP Santé
 */
public class SSLSocketFactorySetter implements BeanPostProcessor{
    private static final Logger LOGGER = LoggerFactory.getLogger(SSLSocketFactorySetter.class);
    private SSLSocketFactory factory;

    public SSLSocketFactory getFactory() {
        return factory;
    }

    public void setFactory(SSLSocketFactory factory) {
        if(LOGGER.isDebugEnabled()){
            this.factory = new SSLSocketFactoryProxy(factory);
        }else{
            this.factory=factory;
        }
    }
    public Object postProcessBeforeInitialization(Object o, String string) throws BeansException {
        LOGGER.debug("pre processing "+o.getClass().getName());
        return o;
    }

    public Object postProcessAfterInitialization(Object o, String string) throws BeansException {
        LOGGER.debug("post processing "+o.getClass().getName());
        if(o instanceof TLSClientParameters){
            ((TLSClientParameters)o).setSSLSocketFactory(factory);
            if(LOGGER.isInfoEnabled()){
                LOGGER.info("SSL factory set on "+o.toString()+":"+string);
            }
        }
        return o;
    }
    
    /**
     * Cette classe permet de débugger la configuration, en particulier de confirmer 
     * que la SSLSocketFactory est bien en place.
     */
    private static class SSLSocketFactoryProxy extends SSLSocketFactory{
        private SSLSocketFactory impl;

        public SSLSocketFactoryProxy(SSLSocketFactory impl) {
            this.impl = impl;
        }
        
        @Override
        public String[] getDefaultCipherSuites() {
            LOGGER.debug("call getDefaultCipherSuites");
            return impl.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            LOGGER.debug("call getSupportedCipherSuites");
            return impl.getSupportedCipherSuites();
        }

        @Override
        public Socket createSocket(Socket socket, String string, int i, boolean bln) throws IOException {
            LOGGER.debug("call createSocket");
            return impl.createSocket(socket, string, i, bln);
        }

        @Override
        public Socket createSocket(String string, int i) throws IOException, UnknownHostException {
            LOGGER.debug("call createSocket");
            return impl.createSocket(string, i);
        }

        @Override
        public Socket createSocket(String string, int i, InetAddress ia, int i1) throws IOException, UnknownHostException {
            LOGGER.debug("call createSocket");
            return impl.createSocket(string, i, ia, i1);
        }

        @Override
        public Socket createSocket(InetAddress ia, int i) throws IOException {
            LOGGER.debug("call createSocket");
            return impl.createSocket(ia, i);
        }

        @Override
        public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throws IOException {
            LOGGER.debug("call createSocket");
            return impl.createSocket(ia, i,ia1,i1);
        }
        
    }
    
}
