/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2007 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. * * 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: * *

* *

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: * *

* */ 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 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. */ 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; } }