/*
 * Created on 2005.7.14
 */

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.Hashtable;
import java.util.Vector;

import javax.net.ssl.*;

import org.apache.xmlrpc.*;
import org.apache.xmlrpc.secure.*;

/**
 * @author andrej
 */
public class SecureXmlRpcClientDemoAlt {
	private final static int PORT_NUM = 443;
	private final static String serverURL = "https://localhost:"+String.valueOf(PORT_NUM);
	private static final String SECURE_ALGORITHM = "SunX509";
	private static final String SECURE_PROTOCOL = "TLS";
	private static final String KEYSTORE_TYPE = "JKS";
	
	
	
	public static SSLSocketFactory getTrustedSSLSocketFactory(String trustStoreFilename,
            String trustStorePassword, String keyPassword)
            throws NoSuchAlgorithmException, KeyStoreException,
            CertificateException, UnrecoverableKeyException,
            KeyManagementException, IOException {
        KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);
        ks.load(new FileInputStream(trustStoreFilename), null);
        
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(SECURE_ALGORITHM);
        tmf.init(ks);

        SSLContext sslCtx = SSLContext.getInstance(SECURE_PROTOCOL);
        sslCtx.init(null, tmf.getTrustManagers(), null);

        return	(sslCtx.getSocketFactory());
    }


	public static void main(String[] args) {
	    String trustStoreFilename = "trustStoreClient";
	    String trustStorePassword = "blabla1";
	    String keyPassword = "blabla2";

        try {
        	SSLSocketFactory socketFactory = getTrustedSSLSocketFactory(trustStoreFilename, trustStorePassword, keyPassword);
        	
        	// HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);

            setHostNameVerifier();

            SecureXmlRpcClient client = new SecureXmlRpcClient(serverURL);
  
            // Fill in the appropriate method call that's available on your
            // server.
            String method = "sample.sumAndDifference";
            // Build our parameter list.
            Vector params = new Vector();
            params.addElement(new Integer(10));
            params.addElement(new Integer(7));

            System.out.println("Invoking remote method:");
            // Call the server, and get our result.
            
            Hashtable result = (Hashtable) client.execute(new XmlRpcRequest(method, params), new SecureXmlRpcTransport(serverURL, socketFactory));
 
            int sum = ((Integer) result.get("sum")).intValue();
            int difference = ((Integer) result.get("difference")).intValue();
            // Print out our result.
            System.out.println("Sum: " + Integer.toString(sum) + ", Difference: " + Integer.toString(difference));

        } 
        catch (XmlRpcException e) {
            e.printStackTrace();
        } 
        catch (MalformedURLException e) {
        	e.printStackTrace();
        } 
        catch (IOException e) {
        	e.printStackTrace();
        } 
        catch (Exception e) {
        	e.printStackTrace();
        }
		
		
		
	}
	
	
	private static void setHostNameVerifier() {
		HostnameVerifier hv = new HostnameVerifier() {
		    public boolean verify(String urlHostName, SSLSession session) {
		        System.out.println("Warning: URL Host: "+urlHostName+" vs. "+session.getPeerHost());
		        return true;
		    }
		};
		 
		HttpsURLConnection.setDefaultHostnameVerifier(hv);
	}
}


/**
 * Secure transport for Apache XML-RPC.
 * @author andrej
 */
class SecureXmlRpcTransport implements XmlRpcTransport {
    protected URL url;
    protected SSLSocketFactory factory;
    private HttpsURLConnection con;


    /**
     * Create a new SecureXmlRpcTransport with the specified URL.
     * @param url the url to POST XML-RPC requests to.
     * @param factory a SSL socket factory.
     */
    public SecureXmlRpcTransport(URL url, SSLSocketFactory factory) {
        this.url = url;
        this.factory = factory;
    }


    /**
     * Create a new SecureXmlRpcTransport with the specified URL and factory.
     * @param url the url to POST XML-RPC requests to.
     * @param factory a SSL socket factory.
     */
    public SecureXmlRpcTransport(String url, SSLSocketFactory factory) throws MalformedURLException {
        this(new URL(url), factory);
    }


	/* (non-Javadoc)
	 * @see org.apache.xmlrpc.XmlRpcTransport#endClientRequest()
	 */
    public void endClientRequest() throws XmlRpcClientException {
        try {
            con.getInputStream().close();
        }
        catch (Exception e) {
            throw new XmlRpcClientException("Exception closing URLConnection", e);
        }
    }
	
    /*
     *  (non-Javadoc)
     * @see org.apache.xmlrpc.XmlRpcTransport#sendXmlRpc(byte[])
     */
    public InputStream sendXmlRpc(byte [] request) throws IOException {
        con = (HttpsURLConnection)url.openConnection();
        con.setSSLSocketFactory(factory);
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setUseCaches(false);
        con.setAllowUserInteraction(false);
        con.setRequestProperty("Content-Length",
                Integer.toString(request.length));
        con.setRequestProperty("Content-Type", "text/xml");
        
        
        
        OutputStream out = con.getOutputStream();
        out.write(request);
        out.flush();
        out.close();
        return con.getInputStream();
    }
}

