You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Viewer.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- 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. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.tools.web;
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.net.URL;
  20. import java.net.URLConnection;
  21. /**
  22. * A sample 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. * <pre>% java javassist.tools.web.Viewer <i>host port</i> Main arg1, ...</pre>
  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. * <pre>
  45. * Viewer v = (Viewer)this.getClass().getClassLoader();
  46. * String port = v.getPort();
  47. * </pre>
  48. *
  49. */
  50. public class Viewer extends ClassLoader {
  51. private String server;
  52. private int port;
  53. /**
  54. * Starts a program.
  55. */
  56. public static void main(String[] args) throws Throwable {
  57. if (args.length >= 3) {
  58. Viewer cl = new Viewer(args[0], Integer.parseInt(args[1]));
  59. String[] args2 = new String[args.length - 3];
  60. System.arraycopy(args, 3, args2, 0, args.length - 3);
  61. cl.run(args[2], args2);
  62. }
  63. else
  64. System.err.println(
  65. "Usage: java javassist.tools.web.Viewer <host> <port> class [args ...]");
  66. }
  67. /**
  68. * Constructs a viewer.
  69. *
  70. * @param host server name
  71. * @param p port number
  72. */
  73. public Viewer(String host, int p) {
  74. server = host;
  75. port = p;
  76. }
  77. /**
  78. * Returns the server name.
  79. */
  80. public String getServer() { return server; }
  81. /**
  82. * Returns the port number.
  83. */
  84. public int getPort() { return port; }
  85. /**
  86. * Invokes main() in the class specified by <code>classname</code>.
  87. *
  88. * @param classname executed class
  89. * @param args the arguments passed to <code>main()</code>.
  90. */
  91. public void run(String classname, String[] args)
  92. throws Throwable
  93. {
  94. Class<?> c = loadClass(classname);
  95. try {
  96. c.getDeclaredMethod("main", new Class[] { String[].class })
  97. .invoke(null, new Object[] { args });
  98. }
  99. catch (java.lang.reflect.InvocationTargetException e) {
  100. throw e.getTargetException();
  101. }
  102. }
  103. /**
  104. * Requests the class loader to load a class.
  105. */
  106. @Override
  107. protected synchronized Class<?> loadClass(String name, boolean resolve)
  108. throws ClassNotFoundException
  109. {
  110. Class<?> c = findLoadedClass(name);
  111. if (c == null)
  112. c = findClass(name);
  113. if (c == null)
  114. throw new ClassNotFoundException(name);
  115. if (resolve)
  116. resolveClass(c);
  117. return c;
  118. }
  119. /**
  120. * Finds the specified class. The implementation in this class
  121. * fetches the class from the http server. If the class is
  122. * either <code>java.*</code>, <code>javax.*</code>, or
  123. * <code>Viewer</code>, then it is loaded by the parent class
  124. * loader.
  125. *
  126. * <p>This method can be overridden by a subclass of
  127. * <code>Viewer</code>.
  128. */
  129. @Override
  130. protected Class<?> findClass(String name) throws ClassNotFoundException {
  131. Class<?> c = null;
  132. if (name.startsWith("java.") || name.startsWith("javax.")
  133. || name.equals("javassist.tools.web.Viewer"))
  134. c = findSystemClass(name);
  135. if (c == null)
  136. try {
  137. byte[] b = fetchClass(name);
  138. if (b != null)
  139. c = defineClass(name, b, 0, b.length);
  140. }
  141. catch (Exception e) {
  142. }
  143. return c;
  144. }
  145. /**
  146. * Fetches the class file of the specified class from the http
  147. * server.
  148. */
  149. protected byte[] fetchClass(String classname) throws Exception
  150. {
  151. byte[] b;
  152. URL url = new URL("http", server, port,
  153. "/" + classname.replace('.', '/') + ".class");
  154. URLConnection con = url.openConnection();
  155. con.connect();
  156. int size = con.getContentLength();
  157. try (InputStream s = con.getInputStream()) {
  158. if (size <= 0) {
  159. b = readStream(s);
  160. } else {
  161. b = new byte[size];
  162. int len = 0;
  163. do {
  164. int n = s.read(b, len, size - len);
  165. if (n < 0) {
  166. throw new IOException("the stream was closed: "
  167. + classname);
  168. }
  169. len += n;
  170. } while (len < size);
  171. }
  172. }
  173. return b;
  174. }
  175. private byte[] readStream(InputStream fin) throws IOException {
  176. byte[] buf = new byte[4096];
  177. int size = 0;
  178. int len = 0;
  179. do {
  180. size += len;
  181. if (buf.length - size <= 0) {
  182. byte[] newbuf = new byte[buf.length * 2];
  183. System.arraycopy(buf, 0, newbuf, 0, size);
  184. buf = newbuf;
  185. }
  186. len = fin.read(buf, size, buf.length - size);
  187. } while (len >= 0);
  188. byte[] result = new byte[size];
  189. System.arraycopy(buf, 0, result, 0, size);
  190. return result;
  191. }
  192. }