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