/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later, * or the Apache License Version 2.0. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */ package javassist.tools.web; import java.io.*; import java.net.*; /** * A sample applet viewer. * *
This is a sort of applet viewer that can run any program even if
* the main class is not a subclass of Applet
.
* This viewwer first calls main()
in the main class.
*
*
To run, you should type: * *
% java javassist.tools.web.Viewer host port Main arg1, ...
This command calls Main.main()
with arg1,...
* All classes including Main
are fetched from
* a server http://host:port.
* Only the class file for Viewer
must exist
* on a local file system at the client side; even other
* javassist.*
classes are not needed at the client side.
* Viewer
uses only Java core API classes.
*
*
Note: since a Viewer
object is a class loader,
* a program loaded by this object can call a method in Viewer
.
* For example, you can write something like this:
*
*
* Viewer v = (Viewer)this.getClass().getClassLoader(); * String port = v.getPort(); ** */ public class Viewer extends ClassLoader { private String server; private int port; /** * Starts a program. */ public static void main(String[] args) throws Throwable { if (args.length >= 3) { Viewer cl = new Viewer(args[0], Integer.parseInt(args[1])); String[] args2 = new String[args.length - 3]; System.arraycopy(args, 3, args2, 0, args.length - 3); cl.run(args[2], args2); } else System.err.println( "Usage: java javassist.tools.web.Viewer
classname
.
*
* @param classname executed class
* @param args the arguments passed to main()
.
*/
public void run(String classname, String[] args)
throws Throwable
{
Class c = loadClass(classname);
try {
c.getDeclaredMethod("main", new Class[] { String[].class })
.invoke(null, new Object[] { args });
}
catch (java.lang.reflect.InvocationTargetException e) {
throw e.getTargetException();
}
}
/**
* Requests the class loader to load a class.
*/
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
if (c == null)
c = findClass(name);
if (c == null)
throw new ClassNotFoundException(name);
if (resolve)
resolveClass(c);
return c;
}
/**
* Finds the specified class. The implementation in this class
* fetches the class from the http server. If the class is
* either java.*
, javax.*
, or
* Viewer
, then it is loaded by the parent class
* loader.
*
* This method can be overridden by a subclass of
* Viewer
.
*/
protected Class findClass(String name) throws ClassNotFoundException {
Class c = null;
if (name.startsWith("java.") || name.startsWith("javax.")
|| name.equals("javassist.tools.web.Viewer"))
c = findSystemClass(name);
if (c == null)
try {
byte[] b = fetchClass(name);
if (b != null)
c = defineClass(name, b, 0, b.length);
}
catch (Exception e) {
}
return c;
}
/**
* Fetches the class file of the specified class from the http
* server.
*/
protected byte[] fetchClass(String classname) throws Exception
{
byte[] b;
URL url = new URL("http", server, port,
"/" + classname.replace('.', '/') + ".class");
URLConnection con = url.openConnection();
con.connect();
int size = con.getContentLength();
InputStream s = con.getInputStream();
if (size <= 0)
b = readStream(s);
else {
b = new byte[size];
int len = 0;
do {
int n = s.read(b, len, size - len);
if (n < 0) {
s.close();
throw new IOException("the stream was closed: "
+ classname);
}
len += n;
} while (len < size);
}
s.close();
return b;
}
private byte[] readStream(InputStream fin) throws IOException {
byte[] buf = new byte[4096];
int size = 0;
int len = 0;
do {
size += len;
if (buf.length - size <= 0) {
byte[] newbuf = new byte[buf.length * 2];
System.arraycopy(buf, 0, newbuf, 0, size);
buf = newbuf;
}
len = fin.read(buf, size, buf.length - size);
} while (len >= 0);
byte[] result = new byte[size];
System.arraycopy(buf, 0, result, 0, size);
return result;
}
}