summaryrefslogtreecommitdiffstats
path: root/src/main/javassist/tools/rmi/AppletServer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/tools/rmi/AppletServer.java')
-rw-r--r--src/main/javassist/tools/rmi/AppletServer.java250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/main/javassist/tools/rmi/AppletServer.java b/src/main/javassist/tools/rmi/AppletServer.java
new file mode 100644
index 00000000..5056e24c
--- /dev/null
+++ b/src/main/javassist/tools/rmi/AppletServer.java
@@ -0,0 +1,250 @@
+/*
+ * 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.rmi;
+
+import java.io.*;
+
+import javassist.tools.web.*;
+import javassist.CannotCompileException;
+import javassist.NotFoundException;
+import javassist.ClassPool;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * An AppletServer object is a web server that an ObjectImporter
+ * communicates with. It makes the objects specified by
+ * <code>exportObject()</code> remotely accessible from applets.
+ * If the classes of the exported objects are requested by the client-side
+ * JVM, this web server sends proxy classes for the requested classes.
+ *
+ * @see javassist.tools.rmi.ObjectImporter
+ */
+public class AppletServer extends Webserver {
+ private StubGenerator stubGen;
+ private Hashtable exportedNames;
+ private Vector exportedObjects;
+
+ private static final byte[] okHeader
+ = "HTTP/1.0 200 OK\r\n\r\n".getBytes();
+
+ /**
+ * Constructs a web server.
+ *
+ * @param port port number
+ */
+ public AppletServer(String port)
+ throws IOException, NotFoundException, CannotCompileException
+ {
+ this(Integer.parseInt(port));
+ }
+
+ /**
+ * Constructs a web server.
+ *
+ * @param port port number
+ */
+ public AppletServer(int port)
+ throws IOException, NotFoundException, CannotCompileException
+ {
+ this(ClassPool.getDefault(), new StubGenerator(), port);
+ }
+
+ /**
+ * Constructs a web server.
+ *
+ * @param port port number
+ * @param src the source of classs files.
+ */
+ public AppletServer(int port, ClassPool src)
+ throws IOException, NotFoundException, CannotCompileException
+ {
+ this(new ClassPool(src), new StubGenerator(), port);
+ }
+
+ private AppletServer(ClassPool loader, StubGenerator gen, int port)
+ throws IOException, NotFoundException, CannotCompileException
+ {
+ super(port);
+ exportedNames = new Hashtable();
+ exportedObjects = new Vector();
+ stubGen = gen;
+ addTranslator(loader, gen);
+ }
+
+ /**
+ * Begins the HTTP service.
+ */
+ public void run() {
+ super.run();
+ }
+
+ /**
+ * Exports an object.
+ * This method produces the bytecode of the proxy class used
+ * to access the exported object. A remote applet can load
+ * the proxy class and call a method on the exported object.
+ *
+ * @param name the name used for looking the object up.
+ * @param obj the exported object.
+ * @return the object identifier
+ *
+ * @see javassist.tools.rmi.ObjectImporter#lookupObject(String)
+ */
+ public synchronized int exportObject(String name, Object obj)
+ throws CannotCompileException
+ {
+ Class clazz = obj.getClass();
+ ExportedObject eo = new ExportedObject();
+ eo.object = obj;
+ eo.methods = clazz.getMethods();
+ exportedObjects.addElement(eo);
+ eo.identifier = exportedObjects.size() - 1;
+ if (name != null)
+ exportedNames.put(name, eo);
+
+ try {
+ stubGen.makeProxyClass(clazz);
+ }
+ catch (NotFoundException e) {
+ throw new CannotCompileException(e);
+ }
+
+ return eo.identifier;
+ }
+
+ /**
+ * Processes a request from a web browser (an ObjectImporter).
+ */
+ public void doReply(InputStream in, OutputStream out, String cmd)
+ throws IOException, BadHttpRequest
+ {
+ if (cmd.startsWith("POST /rmi "))
+ processRMI(in, out);
+ else if (cmd.startsWith("POST /lookup "))
+ lookupName(cmd, in, out);
+ else
+ super.doReply(in, out, cmd);
+ }
+
+ private void processRMI(InputStream ins, OutputStream outs)
+ throws IOException
+ {
+ ObjectInputStream in = new ObjectInputStream(ins);
+
+ int objectId = in.readInt();
+ int methodId = in.readInt();
+ Exception err = null;
+ Object rvalue = null;
+ try {
+ ExportedObject eo
+ = (ExportedObject)exportedObjects.elementAt(objectId);
+ Object[] args = readParameters(in);
+ rvalue = convertRvalue(eo.methods[methodId].invoke(eo.object,
+ args));
+ }
+ catch(Exception e) {
+ err = e;
+ logging2(e.toString());
+ }
+
+ outs.write(okHeader);
+ ObjectOutputStream out = new ObjectOutputStream(outs);
+ if (err != null) {
+ out.writeBoolean(false);
+ out.writeUTF(err.toString());
+ }
+ else
+ try {
+ out.writeBoolean(true);
+ out.writeObject(rvalue);
+ }
+ catch (NotSerializableException e) {
+ logging2(e.toString());
+ }
+ catch (InvalidClassException e) {
+ logging2(e.toString());
+ }
+
+ out.flush();
+ out.close();
+ in.close();
+ }
+
+ private Object[] readParameters(ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ int n = in.readInt();
+ Object[] args = new Object[n];
+ for (int i = 0; i < n; ++i) {
+ Object a = in.readObject();
+ if (a instanceof RemoteRef) {
+ RemoteRef ref = (RemoteRef)a;
+ ExportedObject eo
+ = (ExportedObject)exportedObjects.elementAt(ref.oid);
+ a = eo.object;
+ }
+
+ args[i] = a;
+ }
+
+ return args;
+ }
+
+ private Object convertRvalue(Object rvalue)
+ throws CannotCompileException
+ {
+ if (rvalue == null)
+ return null; // the return type is void.
+
+ String classname = rvalue.getClass().getName();
+ if (stubGen.isProxyClass(classname))
+ return new RemoteRef(exportObject(null, rvalue), classname);
+ else
+ return rvalue;
+ }
+
+ private void lookupName(String cmd, InputStream ins, OutputStream outs)
+ throws IOException
+ {
+ ObjectInputStream in = new ObjectInputStream(ins);
+ String name = DataInputStream.readUTF(in);
+ ExportedObject found = (ExportedObject)exportedNames.get(name);
+ outs.write(okHeader);
+ ObjectOutputStream out = new ObjectOutputStream(outs);
+ if (found == null) {
+ logging2(name + "not found.");
+ out.writeInt(-1); // error code
+ out.writeUTF("error");
+ }
+ else {
+ logging2(name);
+ out.writeInt(found.identifier);
+ out.writeUTF(found.object.getClass().getName());
+ }
+
+ out.flush();
+ out.close();
+ in.close();
+ }
+}
+
+class ExportedObject {
+ public int identifier;
+ public Object object;
+ public Method[] methods;
+}