|
Loading Java Classes from a Remote Machine
An Introduction |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
/**
* An object that is responsible for retrieving classes from an
* HTTP server and writing them to a local file
*
* @version 1.0
* @author Prof. David Bernstein, James Madison University
*/
public class HTTPClassRetriever
{
private String uri;
public static final String EXT = ".class";
/**
* Explicit Value Constructor
*
* @param uri The host and path to load from
*/
public HTTPClassRetriever(String uri)
{
this.uri = uri;
}
/**
* Retrieve the class using HTTP
*
* @param name The name of the class (without the extension)
* @param The bytes that comprise the class
*/
public void retrieveClass(String name) throws IOException
{
byte[] bytes;
FileOutputStream out;
bytes = requestBytes(name);
out = new FileOutputStream(name+EXT);
out.write(bytes);
}
/**
* Request the bytes in the class using an HTTP GET request
*
* @param name The name of the class (without the extension)
* @param The bytes that comprise the class
*/
private byte[] requestBytes(String name) throws IOException
{
byte[] bytes;
InputStream in;
URL u;
u = new URL(uri + name + EXT);
in = u.openStream();
bytes = new byte[in.available()];
in.read(bytes);
return bytes;
}
}
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);
}
}
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
/**
* An object that is responsible for loading classes from an
* HTTP server.
*
* @version 1.0
* @author Prof. David Bernstein, James Madison University
*/
public class HTTPClassLoader extends ClassLoader
{
private String uri;
public static final String EXT = ".class";
/**
* Explicit Value Constructor
*
* @param uri The host and path to load from
*/
public HTTPClassLoader(String uri)
{
this.uri = uri;
}
/**
* Finds the class with the specified name
*
* @param name The name of the class (without extension)
* @return The resulting Class object
*/
protected Class findClass(String name) throws ClassNotFoundException
{
byte[] bytes;
Class c;
bytes = null;
try
{
bytes = requestBytes(name);
c = defineClass(name, bytes, 0, bytes.length);
if (c == null) throw new ClassNotFoundException(name);
}
catch (IOException ioe)
{
throw new ClassNotFoundException(name);
}
return c;
}
/**
* Request the bytes in the class using an HTTP GET request
*
* @param name The name of the class (without the extension)
* @param The bytes that comprise the class
*/
private byte[] requestBytes(String name) throws IOException
{
byte[] bytes;
InputStream in;
URL u;
u = new URL(uri + name + EXT);
in = u.openStream();
bytes = new byte[in.available()];
in.read(bytes);
return bytes;
}
}
import java.lang.reflect.*;
/**
* Load an application (i.e., a class with a void main(String[] args))
* from an HTTP server and execute it.
*
* Example:
*
* java HTTPApplicationLoader https://w3.cs.jmu.edu/bernstdh/web/common/lectures/javaexamples/classloader/ OtherExample Fred
*
* @version 1.0
* @author Computer Science Department, James Madison University
*/
public class HTTPApplicationLoader
{
/**
* 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;
HTTPClassLoader classLoader;
int realArgsLength;
Method mainMethod;
Object[] oargs;
String[] realArgs;
// Construct an HTTPClassLoader that retrieves from
// the host and path in args[0]
classLoader = new HTTPClassLoader(args[0]);
//setContextClassLoader(classLoader);
// Load the class in args[1]
// Note: To get an instance use appClass.newInstance()
appClass = classLoader.loadClass(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);
}
}