scouter.javassist.tools.web.Viewer Maven / Gradle / Ivy
/*
* 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 scouter.javassist.tools.web;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
/**
* 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 scouter.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
* scouter.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 scouter.javassist.tools.web.Viewer class [args ...]");
}
/**
* Constructs a viewer.
*
* @param host server name
* @param p port number
*/
public Viewer(String host, int p) {
server = host;
port = p;
}
/**
* Returns the server name.
*/
public String getServer() { return server; }
/**
* Returns the port number.
*/
public int getPort() { return port; }
/**
* Invokes main() in the class specified by 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.
*/
@Override
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
.
*/
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
Class> c = null;
if (name.startsWith("java.") || name.startsWith("javax.")
|| name.equals("scouter.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;
}
}