169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.tools.rmi; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.tools.web.*; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.ClassPool; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Method; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Hashtable; 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.util.Vector; 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * An AppletServer object is a web server that an ObjectImporter 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * communicates with. It makes the objects specified by 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>exportObject()</code> remotely accessible from applets. 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If the classes of the exported objects are requested by the client-side 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * JVM, this web server sends proxy classes for the requested classes. 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.rmi.ObjectImporter 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class AppletServer extends Webserver { 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private StubGenerator stubGen; 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Hashtable exportedNames; 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Vector exportedObjects; 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static final byte[] okHeader 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = "HTTP/1.0 200 OK\r\n\r\n".getBytes(); 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a web server. 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param port port number 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public AppletServer(String port) 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, NotFoundException, CannotCompileException 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this(Integer.parseInt(port)); 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a web server. 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param port port number 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public AppletServer(int port) 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, NotFoundException, CannotCompileException 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this(ClassPool.getDefault(), new StubGenerator(), port); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs a web server. 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param port port number 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param src the source of classs files. 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public AppletServer(int port, ClassPool src) 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, NotFoundException, CannotCompileException 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this(new ClassPool(src), new StubGenerator(), port); 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private AppletServer(ClassPool loader, StubGenerator gen, int port) 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, NotFoundException, CannotCompileException 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(port); 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exportedNames = new Hashtable(); 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exportedObjects = new Vector(); 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stubGen = gen; 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal addTranslator(loader, gen); 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Begins the HTTP service. 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void run() { 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.run(); 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Exports an object. 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method produces the bytecode of the proxy class used 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * to access the exported object. A remote applet can load 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the proxy class and call a method on the exported object. 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param name the name used for looking the object up. 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param obj the exported object. 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the object identifier 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.rmi.ObjectImporter#lookupObject(String) 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public synchronized int exportObject(String name, Object obj) 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class clazz = obj.getClass(); 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExportedObject eo = new ExportedObject(); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal eo.object = obj; 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal eo.methods = clazz.getMethods(); 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exportedObjects.addElement(eo); 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal eo.identifier = exportedObjects.size() - 1; 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (name != null) 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exportedNames.put(name, eo); 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal stubGen.makeProxyClass(clazz); 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e); 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return eo.identifier; 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Processes a request from a web browser (an ObjectImporter). 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void doReply(InputStream in, OutputStream out, String cmd) 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, BadHttpRequest 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cmd.startsWith("POST /rmi ")) 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal processRMI(in, out); 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (cmd.startsWith("POST /lookup ")) 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lookupName(cmd, in, out); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.doReply(in, out, cmd); 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void processRMI(InputStream ins, OutputStream outs) 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectInputStream in = new ObjectInputStream(ins); 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int objectId = in.readInt(); 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int methodId = in.readInt(); 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Exception err = null; 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object rvalue = null; 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExportedObject eo 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = (ExportedObject)exportedObjects.elementAt(objectId); 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object[] args = readParameters(in); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal rvalue = convertRvalue(eo.methods[methodId].invoke(eo.object, 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args)); 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch(Exception e) { 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal err = e; 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging2(e.toString()); 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal outs.write(okHeader); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectOutputStream out = new ObjectOutputStream(outs); 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (err != null) { 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeBoolean(false); 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeUTF(err.toString()); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeBoolean(true); 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeObject(rvalue); 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotSerializableException e) { 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging2(e.toString()); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (InvalidClassException e) { 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging2(e.toString()); 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.flush(); 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.close(); 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal in.close(); 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Object[] readParameters(ObjectInputStream in) 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException, ClassNotFoundException 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = in.readInt(); 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object[] args = new Object[n]; 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object a = in.readObject(); 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (a instanceof RemoteRef) { 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal RemoteRef ref = (RemoteRef)a; 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExportedObject eo 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = (ExportedObject)exportedObjects.elementAt(ref.oid); 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal a = eo.object; 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args[i] = a; 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return args; 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Object convertRvalue(Object rvalue) 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (rvalue == null) 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; // the return type is void. 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String classname = rvalue.getClass().getName(); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (stubGen.isProxyClass(classname)) 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new RemoteRef(exportObject(null, rvalue), classname); 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return rvalue; 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void lookupName(String cmd, InputStream ins, OutputStream outs) 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectInputStream in = new ObjectInputStream(ins); 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = DataInputStream.readUTF(in); 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ExportedObject found = (ExportedObject)exportedNames.get(name); 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal outs.write(okHeader); 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectOutputStream out = new ObjectOutputStream(outs); 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (found == null) { 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging2(name + "not found."); 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeInt(-1); // error code 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeUTF("error"); 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal logging2(name); 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeInt(found.identifier); 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.writeUTF(found.object.getClass().getName()); 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.flush(); 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.close(); 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal in.close(); 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalclass ExportedObject { 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int identifier; 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object object; 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Method[] methods; 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 251