
package net.i2p.aum;

import java.lang.*;
import java.io.*;
import java.util.*;
import java.net.*;

import org.apache.xmlrpc.*;

import net.i2p.*;
import net.i2p.client.*;
import net.i2p.client.streaming.*;
import net.i2p.data.Base64;
import net.i2p.util.*;
import net.i2p.data.*;


/**
 * Creates I2P XML-RPC client objects, which you can use
 * to issue XML-RPC function calls over I2P.
 * Instantiating this class causes the vm-wide http proxy system
 * properties to be set to the address of the I2P eepProxy host/port.
 * I2PXmlRpcClient objects need to communicate with the I2P
 * eepProxy. If your eepProxy is at the standard localhost:4444 address,
 * you can use the default constructor. Otherwise, you can set this
 * eepProxy address by either (1) passing eepProxy hostname/port to the
 * constructor, or (2) running the jvm with 'eepproxy.tcp.host' and
 * 'eepproxy.tcp.port' system properties set. Note that (1) takes precedence.
 * Failure to set up EepProxy host/port correctly will result in an IOException
 * when you invoke .execute() on your client objects.
 * Invoke this class from your shell to see a demo
 */

public class I2PXmlRpcClientFactory
{
    public static boolean debug = false;
    
    public static String _defaultEepHost = "127.0.0.1";
    public static int    _defaultEepPort = 4444;

    protected static Log _log;
    
    /**
     * Create an I2P XML-RPC client factory, and set it to create
     * clients of a given class.
     * @param clientClass a class to use when creating new clients
     */
    public I2PXmlRpcClientFactory()
    {
        this(null, 0);
    }

    /**
     * Create an I2P XML-RPC client factory, and set it to create
     * clients of a given class, and dispatch calls through a non-standard
     * eepProxy.
     * @param eepHost the eepProxy TCP hostname
     * @param eepPort the eepProxy TCP port number
     */
    public I2PXmlRpcClientFactory(String eepHost, int eepPort)
    {
        String eepPortStr;

        _log = new Log("I2PXmlRpcClientFactory");
        _log.shouldLog(Log.DEBUG);
    
        Properties p = System.getProperties();

        // determine what actual eepproxy host/port we're using
        if (eepHost == null) {
            eepHost = p.getProperty("eepproxy.tcp.host", _defaultEepHost);
        }
        if (eepPort > 0) {
            eepPortStr = String.valueOf(eepPort);
        }
        else {
            eepPortStr = p.getProperty("eepproxy.tcp.port");
            if (eepPortStr == null) {
                eepPortStr = String.valueOf(_defaultEepPort);
            }
        }
        
        p.put("proxySet", "true");
        p.put("http.proxyHost", eepHost);
        p.put("http.proxyPort", eepPortStr);
    }

    /**
     * Create an I2P XML-RPC client object, which is subsequently used for
     * dispatching XML-RPC requests.
     * @param dest - an I2P destination object, comprising the
     * destination of the remote
     * I2P XML-RPC server.
     * @return a new XmlRpcClient object (refer org.apache.xmlrpc.XmlRpcClient).
     */
    public I2PXmlRpcClient newClient(Destination dest) throws MalformedURLException {

        return newClient(new URL("http", "i2p/"+dest.toBase64(), "/"));
    }
    
    /**
     * Create an I2P XML-RPC client object, which is subsequently used for
     * dispatching XML-RPC requests.
     * @param hostOrDest - an I2P hostname (listed in hosts.txt) or a
     * destination base64 string, for the remote I2P XML-RPC server
     * @return a new XmlRpcClient object (refer org.apache.xmlrpc.XmlRpcClient).
     */
    public I2PXmlRpcClient newClient(String hostOrDest)
        throws DataFormatException, MalformedURLException
    {
        String hostname;
        URL u;
    
        try {
            // try to make a dest out of the string
            Destination dest = new Destination();
            dest.fromBase64(hostOrDest);
    
            // converted ok, treat as valid dest, form i2p/blahblah url from it
            I2PXmlRpcClient client = newClient(new URL("http", "i2p/"+hostOrDest, "/"));
            client.debug = debug;
            return client;
    
        } catch (DataFormatException e) {
    
            if (debug) {
                e.printStackTrace();
                print("hostOrDest length="+hostOrDest.length());
            }
    
            // failed to load up a dest, test length
            if (hostOrDest.length() < 255) {
                // short-ish, assume a hostname
                u = new URL("http", hostOrDest, "/");
                I2PXmlRpcClient client = newClient(u);
                client.debug = debug;
                return client;
            }
            else {
                // too long for a host, barf
                throw new DataFormatException("Bad I2P hostname/dest:\n"+hostOrDest);
            }
        }
    }

    /**
     * Create an I2P XML-RPC client object, which is subsequently used for
     * dispatching XML-RPC requests. This method is not recommended.
     * @param u - a URL object, containing the URL of the remote
     * I2P XML-RPC server, for example, "http://xmlrpc.aum.i2p" (assuming
     * there's a hosts.txt entry for 'xmlrpc.aum.i2p'), or
     * "http://i2p/base64destblahblah...". Note that if you use this method
     * directly, the created XML-RPC client object will ONLY work if you
     * instantiate the URL object as 'new URL("http", "i2p/"+host-or-dest, "/")'.
     */
    protected I2PXmlRpcClient newClient(URL u)
    {
        Object [] args = { u };
        //return new I2PXmlRpcClient(u);
        
        // construct and return a client object of required class
        return new I2PXmlRpcClient(u);
    }
    
    /**
     * Runs a demo of an I2P XML-RPC client. Assumes you have already
     * launched an I2PXmlRpcServerFactory demo, because it gets its
     * dest from the file 'demo.dest64' created by I2PXmlRpcServerFactory demo.
     *
     * Ensure you have first launched net.i2p.aum.I2PXmlRpcServerFactory
     * from your command line.
     */
    public static void main(String [] args) {
    
        String destStr;
    
        debug = true;
    
        try {
            print("Creating client factory...");
            
            I2PXmlRpcClientFactory f = new I2PXmlRpcClientFactory();
        
            print("Creating new client...");
    
            if (args.length == 0) {
                print("Reading dest from demo.dest64");
                destStr = new SimpleFile("demo.dest64", "r").read();
            }
            else {
                destStr = args[0];
            }
                
            XmlRpcClient c = f.newClient(destStr);
        
            print("Invoking foo...");
            
            Vector v = new Vector();
            v.add("one");
            v.add("two");
        
            Object res = c.execute("foo.bar", v);
            
            print("Got back object: " + res);
    
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    /**
     * Used for internal debugging
     */
    protected static void print(String msg)
    {
        if (debug) {
            System.out.println("I2PXmlRpcClient: " + msg);
    
            if (_log != null) {
                System.out.println("LOGGING SOME SHIT");
                _log.debug(msg);
            }
        }
    }
}



