169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.tools.web; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.net.*; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A sample applet viewer. 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This is a sort of applet viewer that can run any program even if 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the main class is not a subclass of <code>Applet</code>. 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This viewwer first calls <code>main()</code> in the main class. 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>To run, you should type: 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><code>% java javassist.tools.web.Viewer <i>host port</i> Main arg1, ...</code></ul> 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This command calls <code>Main.main()</code> with <code>arg1,...</code> 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * All classes including <code>Main</code> are fetched from 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a server http://<i>host</i>:<i>port</i>. 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Only the class file for <code>Viewer</code> must exist 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * on a local file system at the client side; even other 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>javassist.*</code> classes are not needed at the client side. 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Viewer</code> uses only Java core API classes. 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Note: since a <code>Viewer</code> object is a class loader, 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a program loaded by this object can call a method in <code>Viewer</code>. 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * For example, you can write something like this: 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre> 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Viewer v = (Viewer)this.getClass().getClassLoader(); 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * String port = v.getPort(); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Viewer extends ClassLoader { 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String server; 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int port; 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Starts a program. 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void main(String[] args) throws Throwable { 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (args.length >= 3) { 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Viewer cl = new Viewer(args[0], Integer.parseInt(args[1])); 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String[] args2 = new String[args.length - 3]; 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.arraycopy(args, 3, args2, 0, args.length - 3); 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cl.run(args[2], args2); 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.err.println( 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "Usage: java javassist.tools.web.Viewer <host> <port> class [args ...]"); 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a viewer. 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param host server name 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param p port number 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Viewer(String host, int p) { 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal server = host; 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal port = p; 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the server name. 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public String getServer() { return server; } 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns the port number. 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int getPort() { return port; } 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Invokes main() in the class specified by <code>classname</code>. 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param classname executed class 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param args the arguments passed to <code>main()</code>. 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void run(String classname, String[] args) 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws Throwable 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class c = loadClass(classname); 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c.getDeclaredMethod("main", new Class[] { String[].class }) 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal .invoke(null, new Object[] { args }); 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (java.lang.reflect.InvocationTargetException e) { 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e.getTargetException(); 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Requests the class loader to load a class. 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected synchronized Class loadClass(String name, boolean resolve) 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws ClassNotFoundException 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class c = findLoadedClass(name); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == null) 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = findClass(name); 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == null) 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new ClassNotFoundException(name); 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (resolve) 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal resolveClass(c); 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return c; 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Finds the specified class. The implementation in this class 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * fetches the class from the http server. If the class is 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * either <code>java.*</code>, <code>javax.*</code>, or 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Viewer</code>, then it is loaded by the parent class 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * loader. 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This method can be overridden by a subclass of 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Viewer</code>. 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected Class findClass(String name) throws ClassNotFoundException { 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class c = null; 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (name.startsWith("java.") || name.startsWith("javax.") 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal || name.equals("javassist.tools.web.Viewer")) 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = findSystemClass(name); 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (c == null) 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] b = fetchClass(name); 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (b != null) 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal c = defineClass(name, b, 0, b.length); 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return c; 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Fetches the class file of the specified class from the http 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * server. 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected byte[] fetchClass(String classname) throws Exception 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] b; 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal URL url = new URL("http", server, port, 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "/" + classname.replace('.', '/') + ".class"); 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal URLConnection con = url.openConnection(); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal con.connect(); 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int size = con.getContentLength(); 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InputStream s = con.getInputStream(); 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (size <= 0) 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal b = readStream(s); 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal b = new byte[size]; 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = 0; 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal do { 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = s.read(b, len, size - len); 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (n < 0) { 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s.close(); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new IOException("the stream was closed: " 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + classname); 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len += n; 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } while (len < size); 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal s.close(); 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return b; 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private byte[] readStream(InputStream fin) throws IOException { 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] buf = new byte[4096]; 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int size = 0; 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len = 0; 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal do { 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal size += len; 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (buf.length - size <= 0) { 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] newbuf = new byte[buf.length * 2]; 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.arraycopy(buf, 0, newbuf, 0, size); 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal buf = newbuf; 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = fin.read(buf, size, buf.length - size); 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } while (len >= 0); 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] result = new byte[size]; 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal System.arraycopy(buf, 0, result, 0, size); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return result; 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 209