import java.lang.reflect.*;

/**
 * Retrieve a class containing an application 
 * (i.e., a class with a void main(String[] args))
 * from an HTTP server, save it locally, and execute it.
 * Example:
 *
 * java HTTPApplicationLauncher https://w3.cs.jmu.edu/bernstdh/web/common/lectures/javaexamples/classloader/ Example
 *
 * @version 1.0
 * @author  Prof. David Bernstein, James Madison University
 */
public class HTTPApplicationLauncher
{
    /**
     * The entry point of this application
     *
     * @param args   The command-line arguments (URL, class)
     */
    public static void main(String[] args) throws Exception
    {
	
	Class                   appClass;
	Class[]                 parameters;
	HTTPClassRetriever      retriever;
	int                     realArgsLength;
	Method                  mainMethod;
	Object[]                oargs;
	String[]                realArgs;


	// Construct an HTTPClassRetriever that retrieves from
	// the host and path in args[0]
	retriever = new HTTPClassRetriever(args[0]);


	// Retrieve and save the class in args[1]
	retriever.retrieveClass(args[1]);

	// Get the Class
	appClass = Class.forName(args[1]);

	// We need the signature of the main method which includes
	// the class of the argument.  The easiest way to do
	// this is to use reflection and get the class of args
	parameters = new Class[1];
	parameters[0] = args.getClass();


	// Get the main method
	mainMethod = appClass.getDeclaredMethod("main", parameters);


	// Copy the remaining command line arguments
	realArgsLength = Math.max(args.length - 2, 0);
	realArgs = new String[realArgsLength];
	if (realArgsLength > 0) 
	    System.arraycopy(args, 2, realArgs, 0, realArgsLength);
	oargs = new Object[]{realArgs}; // Initialize with realArgs


	// Invoke main
	//    Note: First argument is null because it's static
	mainMethod.invoke(null, oargs);
    }

}
