/Users/lyon/j4p/src/javassist/web/Viewer.java
|
1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16 package javassist.web;
17
18 import java.io.*;
19 import java.net.*;
20
21 /**
22 * An applet viewer.
23 *
24 * <p>This is a sort of applet viewer that can run any program even if
25 * the main class is not a subclass of <code>Applet</code>.
26 * This viewwer first calls <code>main()</code> in the main class.
27 *
28 * <p>To run, you should type:
29 *
30 * <ul><code>% java javassist.web.Viewer <i>host port</i> Main arg1, ...</code></ul>
31 *
32 * <p>This command calls <code>Main.main()</code> with <code>arg1,...</code>
33 * All classes including <code>Main</code> are fetched from
34 * a server http://<i>host</i>:<i>port</i>.
35 * Only the class file for <code>Viewer</code> must exist
36 * on a local file system at the client side; even other
37 * <code>javassist.*</code> classes are not needed at the client side.
38 * <code>Viewer</code> uses only Java core API classes.
39 *
40 * <p>Note: since a <code>Viewer</code> object is a class loader,
41 * a program loaded by this object can call a method in <code>Viewer</code>.
42 * For example, you can write something like this:
43 *
44 * <ul><pre>
45 * Viewer v = (Viewer)this.getClass().getClassLoader();
46 * String port = v.getPort();
47 * </pre></ul>
48 *
49 */
50 public class Viewer extends ClassLoader {
51 private String server;
52 private int port;
53
54 /**
55 * Starts a program.
56 */
57 public static void main(String[] args) throws Throwable {
58 if (args.length >= 3) {
59 Viewer cl = new Viewer(args[0], Integer.parseInt(args[1]));
60 String[] args2 = new String[args.length - 3];
61 System.arraycopy(args, 3, args2, 0, args.length - 3);
62 cl.run(args[2], args2);
63 } else
64 System.err.println(
65 "Usage: java javassist.web.Viewer <host> <port> class [args ...]");
66 }
67
68 /**
69 * Constructs a viewer.
70 *
71 * @param host server name
72 * @param p port number
73 */
74 public Viewer(String host, int p) {
75 server = host;
76 port = p;
77 }
78
79 /**
80 * Returns the server name.
81 */
82 public String getServer() {
83 return server;
84 }
85
86 /**
87 * Returns the port number.
88 */
89 public int getPort() {
90 return port;
91 }
92
93 /**
94 * Invokes main() in the class specified by <code>classname</code>.
95 *
96 * @param classname executed class
97 * @param args the arguments passed to <code>main()</code>.
98 */
99 public void run(String classname, String[] args)
100 throws Throwable {
101 Class c = loadClass(classname);
102 try {
103 c.getDeclaredMethod("main", new Class[]{String[].class})
104 .invoke(null, new Object[]{args});
105 } catch (java.lang.reflect.InvocationTargetException e) {
106 throw e.getTargetException();
107 }
108 }
109
110 /**
111 * Requests the class loader to load a class.
112 */
113 public synchronized Class loadClass(String name, boolean resolve)
114 throws ClassNotFoundException {
115 Class c = findLoadedClass(name);
116 if (c == null)
117 c = findClass(name);
118
119 if (c == null)
120 throw new ClassNotFoundException(name);
121
122 if (resolve)
123 resolveClass(c);
124
125 return c;
126 }
127
128 /**
129 * Finds the specified class. The implementation in this class
130 * fetches the class from the http server. If the class is
131 * either <code>java.*</code>, <code>javax.*</code>, or
132 * <code>Viewer</code>, then it is loaded by the parent class
133 * loader.
134 *
135 * <p>This method can be overridden by a subclass of
136 * <code>Viewer</code>.
137 */
138 public Class findClass(String name) throws ClassNotFoundException {
139 Class c = null;
140 if (name.startsWith("java.") || name.startsWith("javax.")
141 || name.equals("javassist.web.Viewer"))
142 c = findSystemClass(name);
143
144 if (c == null)
145 try {
146 byte[] b = fetchClass(name);
147 if (b != null)
148 c = defineClass(name, b, 0, b.length);
149 } catch (Exception e) {
150 }
151
152 return c;
153 }
154
155 /**
156 * Fetches the class file of the specified class from the http
157 * server.
158 */
159 public byte[] fetchClass(String classname) throws Exception {
160 byte[] b;
161 URL url = new URL("http", server, port,
162 "/" + classname.replace('.', '/') + ".class");
163 URLConnection con = url.openConnection();
164 con.connect();
165 int size = con.getContentLength();
166 InputStream s = con.getInputStream();
167 if (size <= 0)
168 b = readStream(s);
169 else {
170 b = new byte[size];
171 int len = 0;
172 do {
173 int n = s.read(b, len, size - len);
174 if (n < 0) {
175 s.close();
176 throw new IOException("the stream was closed: "
177 + classname);
178 }
179 len += n;
180 } while (len < size);
181 }
182
183 s.close();
184 return b;
185 }
186
187 public byte[] readStream(InputStream fin) throws IOException {
188 byte[] buf = new byte[4096];
189 int size = 0;
190 int len = 0;
191 do {
192 size += len;
193 if (buf.length - size <= 0) {
194 byte[] newbuf = new byte[buf.length * 2];
195 System.arraycopy(buf, 0, newbuf, 0, size);
196 buf = newbuf;
197 }
198
199 len = fin.read(buf, size, buf.length - size);
200 } while (len >= 0);
201
202 byte[] result = new byte[size];
203 System.arraycopy(buf, 0, result, 0, size);
204 return result;
205 }
206 }
207