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.

AppletServer.java 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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.rmi;
  17. import java.io.DataInputStream;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.io.InvalidClassException;
  21. import java.io.NotSerializableException;
  22. import java.io.ObjectInputStream;
  23. import java.io.ObjectOutputStream;
  24. import java.io.OutputStream;
  25. import java.lang.reflect.Method;
  26. import java.util.Hashtable;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.Vector;
  30. import javassist.CannotCompileException;
  31. import javassist.ClassPool;
  32. import javassist.NotFoundException;
  33. import javassist.tools.web.BadHttpRequest;
  34. import javassist.tools.web.Webserver;
  35. /**
  36. * An AppletServer object is a web server that an ObjectImporter
  37. * communicates with. It makes the objects specified by
  38. * <code>exportObject()</code> remotely accessible from applets.
  39. * If the classes of the exported objects are requested by the client-side
  40. * JVM, this web server sends proxy classes for the requested classes.
  41. *
  42. * @see javassist.tools.rmi.ObjectImporter
  43. */
  44. public class AppletServer extends Webserver {
  45. private StubGenerator stubGen;
  46. private Map<String,ExportedObject> exportedNames;
  47. private List<ExportedObject> exportedObjects;
  48. private static final byte[] okHeader
  49. = "HTTP/1.0 200 OK\r\n\r\n".getBytes();
  50. /**
  51. * Constructs a web server.
  52. *
  53. * @param port port number
  54. */
  55. public AppletServer(String port)
  56. throws IOException, NotFoundException, CannotCompileException
  57. {
  58. this(Integer.parseInt(port));
  59. }
  60. /**
  61. * Constructs a web server.
  62. *
  63. * @param port port number
  64. */
  65. public AppletServer(int port)
  66. throws IOException, NotFoundException, CannotCompileException
  67. {
  68. this(ClassPool.getDefault(), new StubGenerator(), port);
  69. }
  70. /**
  71. * Constructs a web server.
  72. *
  73. * @param port port number
  74. * @param src the source of classs files.
  75. */
  76. public AppletServer(int port, ClassPool src)
  77. throws IOException, NotFoundException, CannotCompileException
  78. {
  79. this(new ClassPool(src), new StubGenerator(), port);
  80. }
  81. private AppletServer(ClassPool loader, StubGenerator gen, int port)
  82. throws IOException, NotFoundException, CannotCompileException
  83. {
  84. super(port);
  85. exportedNames = new Hashtable<String,ExportedObject>();
  86. exportedObjects = new Vector<ExportedObject>();
  87. stubGen = gen;
  88. addTranslator(loader, gen);
  89. }
  90. /**
  91. * Begins the HTTP service.
  92. */
  93. @Override
  94. public void run() {
  95. super.run();
  96. }
  97. /**
  98. * Exports an object.
  99. * This method produces the bytecode of the proxy class used
  100. * to access the exported object. A remote applet can load
  101. * the proxy class and call a method on the exported object.
  102. *
  103. * @param name the name used for looking the object up.
  104. * @param obj the exported object.
  105. * @return the object identifier
  106. *
  107. * @see javassist.tools.rmi.ObjectImporter#lookupObject(String)
  108. */
  109. public synchronized int exportObject(String name, Object obj)
  110. throws CannotCompileException
  111. {
  112. Class<?> clazz = obj.getClass();
  113. ExportedObject eo = new ExportedObject();
  114. eo.object = obj;
  115. eo.methods = clazz.getMethods();
  116. exportedObjects.add(eo);
  117. eo.identifier = exportedObjects.size() - 1;
  118. if (name != null)
  119. exportedNames.put(name, eo);
  120. try {
  121. stubGen.makeProxyClass(clazz);
  122. }
  123. catch (NotFoundException e) {
  124. throw new CannotCompileException(e);
  125. }
  126. return eo.identifier;
  127. }
  128. /**
  129. * Processes a request from a web browser (an ObjectImporter).
  130. */
  131. @Override
  132. public void doReply(InputStream in, OutputStream out, String cmd)
  133. throws IOException, BadHttpRequest
  134. {
  135. if (cmd.startsWith("POST /rmi "))
  136. processRMI(in, out);
  137. else if (cmd.startsWith("POST /lookup "))
  138. lookupName(cmd, in, out);
  139. else
  140. super.doReply(in, out, cmd);
  141. }
  142. private void processRMI(InputStream ins, OutputStream outs)
  143. throws IOException {
  144. try (ObjectInputStream in = new ObjectInputStream(ins)) {
  145. int objectId = in.readInt();
  146. int methodId = in.readInt();
  147. Exception err = null;
  148. Object rvalue = null;
  149. try {
  150. ExportedObject eo = exportedObjects.get(objectId);
  151. Object[] args = readParameters(in);
  152. rvalue = convertRvalue(eo.methods[methodId].invoke(eo.object,
  153. args));
  154. } catch (Exception e) {
  155. err = e;
  156. logging2(e.toString());
  157. }
  158. outs.write(okHeader);
  159. try (ObjectOutputStream out = new ObjectOutputStream(outs)) {
  160. if (err != null) {
  161. out.writeBoolean(false);
  162. out.writeUTF(err.toString());
  163. } else {
  164. try {
  165. out.writeBoolean(true);
  166. out.writeObject(rvalue);
  167. } catch (NotSerializableException | InvalidClassException e) {
  168. logging2(e.toString());
  169. }
  170. }
  171. out.flush();
  172. }
  173. }
  174. }
  175. private Object[] readParameters(ObjectInputStream in)
  176. throws IOException, ClassNotFoundException
  177. {
  178. int n = in.readInt();
  179. Object[] args = new Object[n];
  180. for (int i = 0; i < n; ++i) {
  181. Object a = in.readObject();
  182. if (a instanceof RemoteRef) {
  183. RemoteRef ref = (RemoteRef)a;
  184. ExportedObject eo = exportedObjects.get(ref.oid);
  185. a = eo.object;
  186. }
  187. args[i] = a;
  188. }
  189. return args;
  190. }
  191. private Object convertRvalue(Object rvalue)
  192. throws CannotCompileException
  193. {
  194. if (rvalue == null)
  195. return null; // the return type is void.
  196. String classname = rvalue.getClass().getName();
  197. if (stubGen.isProxyClass(classname))
  198. return new RemoteRef(exportObject(null, rvalue), classname);
  199. return rvalue;
  200. }
  201. private void lookupName(String cmd, InputStream ins, OutputStream outs)
  202. throws IOException {
  203. try (ObjectInputStream in = new ObjectInputStream(ins)) {
  204. String name = DataInputStream.readUTF(in);
  205. ExportedObject found = exportedNames.get(name);
  206. outs.write(okHeader);
  207. try (ObjectOutputStream out = new ObjectOutputStream(outs)) {
  208. if (found == null) {
  209. logging2(name + "not found.");
  210. out.writeInt(-1); // error code
  211. out.writeUTF("error");
  212. } else {
  213. logging2(name);
  214. out.writeInt(found.identifier);
  215. out.writeUTF(found.object.getClass().getName());
  216. }
  217. out.flush();
  218. }
  219. }
  220. }
  221. }
  222. class ExportedObject {
  223. public int identifier;
  224. public Object object;
  225. public Method[] methods;
  226. }