1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999-2005 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.
*
* <p>This is a sort of applet viewer that can run any program even if
* the main class is not a subclass of <code>Applet</code>.
* This viewwer first calls <code>main()</code> in the main class.
*
* <p>To run, you should type:
*
* <ul><code>% java javassist.tools.web.Viewer <i>host port</i> Main arg1, ...</code></ul>
*
* <p>This command calls <code>Main.main()</code> with <code>arg1,...</code>
* All classes including <code>Main</code> are fetched from
* a server http://<i>host</i>:<i>port</i>.
* Only the class file for <code>Viewer</code> must exist
* on a local file system at the client side; even other
* <code>javassist.*</code> classes are not needed at the client side.
* <code>Viewer</code> uses only Java core API classes.
*
* <p>Note: since a <code>Viewer</code> object is a class loader,
* a program loaded by this object can call a method in <code>Viewer</code>.
* For example, you can write something like this:
*
* <ul><pre>
* Viewer v = (Viewer)this.getClass().getClassLoader();
* String port = v.getPort();
* </pre></ul>
*
*/
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 <host> <port> 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 <code>classname</code>.
*
* @param classname executed class
* @param args the arguments passed to <code>main()</code>.
*/
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 <code>java.*</code>, <code>javax.*</code>, or
* <code>Viewer</code>, then it is loaded by the parent class
* loader.
*
* <p>This method can be overridden by a subclass of
* <code>Viewer</code>.
*/
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;
}
}
|