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 Sigalimport java.net.*; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.applet.Applet; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.*; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The object importer enables applets to call a method on a remote 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * object running on the <code>Webserver</code> (the <b>main</b> class of this 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * package). 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>To access the remote 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * object, the applet first calls <code>lookupObject()</code> and 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * obtains a proxy object, which is a reference to that object. 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The class name of the proxy object is identical to that of 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the remote object. 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The proxy object provides the same set of methods as the remote object. 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If one of the methods is invoked on the proxy object, 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the invocation is delegated to the remote object. 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * From the viewpoint of the applet, therefore, the two objects are 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * identical. The applet can access the object on the server 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * with the regular Java syntax without concern about the actual 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * location. 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>The methods remotely called by the applet must be <code>public</code>. 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This is true even if the applet's class and the remote object's classs 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * belong to the same package. 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If class X is a class of remote objects, a subclass of X must be 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * also a class of remote objects. On the other hand, this restriction 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is not applied to the superclass of X. The class X does not have to 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * contain a constructor taking no arguments. 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>The parameters to a remote method is passed in the <i>call-by-value</i> 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * manner. Thus all the parameter classes must implement 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>java.io.Serializable</code>. However, if the parameter is the 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * proxy object, the reference to the remote object instead of a copy of 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the object is passed to the method. 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Because of the limitations of the current implementation, 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul> 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <li>The parameter objects cannot contain the proxy 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * object as a field value. 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <li>If class <code>C</code> is of the remote object, then 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the applet cannot instantiate <code>C</code> locally or remotely. 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </ul> 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>All the exceptions thrown by the remote object are converted 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * into <code>RemoteException</code>. Since this exception is a subclass 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * of <code>RuntimeException</code>, the caller method does not need 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * to catch the exception. However, good programs should catch 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the <code>RuntimeException</code>. 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.rmi.AppletServer 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.rmi.RemoteException 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.web.Viewer 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class ObjectImporter implements java.io.Serializable { 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private final byte[] endofline = { 0x0d, 0x0a }; 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String servername, orgServername; 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int port, orgPort; 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected byte[] lookupCommand = "POST /lookup HTTP/1.0".getBytes(); 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected byte[] rmiCommand = "POST /rmi HTTP/1.0".getBytes(); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs an object importer. 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>Remote objects are imported from the web server that the given 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * applet has been loaded from. 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param applet the applet loaded from the <code>Webserver</code>. 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ObjectImporter(Applet applet) { 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal URL codebase = applet.getCodeBase(); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal orgServername = servername = codebase.getHost(); 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal orgPort = port = codebase.getPort(); 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Constructs an object importer. 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If you run a program with <code>javassist.tools.web.Viewer</code>, 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * you can construct an object importer as follows: 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre> 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Viewer v = (Viewer)this.getClass().getClassLoader(); 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * ObjectImporter oi = new ObjectImporter(v.getServer(), v.getPort()); 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul> 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see javassist.tools.web.Viewer 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public ObjectImporter(String servername, int port) { 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.orgServername = this.servername = servername; 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.orgPort = this.port = port; 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Finds the object exported by a server with the specified name. 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If the object is not found, this method returns null. 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param name the name of the exported object. 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the proxy object or null. 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object getObject(String name) { 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return lookupObject(name); 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (ObjectNotFoundException e) { 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return null; 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Sets an http proxy server. After this method is called, the object 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * importer connects a server through the http proxy server. 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void setHttpProxy(String host, int port) { 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String proxyHeader = "POST http://" + orgServername + ":" + orgPort; 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cmd = proxyHeader + "/lookup HTTP/1.0"; 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal lookupCommand = cmd.getBytes(); 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cmd = proxyHeader + "/rmi HTTP/1.0"; 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal rmiCommand = cmd.getBytes(); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.servername = host; 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal this.port = port; 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Finds the object exported by the server with the specified name. 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It sends a POST request to the server (via an http proxy server 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if needed). 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param name the name of the exported object. 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return the proxy object. 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object lookupObject(String name) throws ObjectNotFoundException 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Socket sock = new Socket(servername, port); 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal OutputStream out = sock.getOutputStream(); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(lookupCommand); 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectOutputStream dout = new ObjectOutputStream(out); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.writeUTF(name); 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.flush(); 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InputStream in = new BufferedInputStream(sock.getInputStream()); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal skipHeader(in); 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectInputStream din = new ObjectInputStream(in); 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = din.readInt(); 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String classname = din.readUTF(); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal din.close(); 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.close(); 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sock.close(); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (n >= 0) 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return createProxy(n, classname); 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal e.printStackTrace(); 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new ObjectNotFoundException(name, e); 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new ObjectNotFoundException(name); 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static final Class[] proxyConstructorParamTypes 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new Class[] { ObjectImporter.class, int.class }; 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private Object createProxy(int oid, String classname) throws Exception { 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class c = Class.forName(classname); 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Constructor cons = c.getConstructor(proxyConstructorParamTypes); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return cons.newInstance(new Object[] { this, new Integer(oid) }); 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Calls a method on a remote object. 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It sends a POST request to the server (via an http proxy server 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if needed). 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>This method is called by only proxy objects. 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public Object call(int objectid, int methodid, Object[] args) 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws RemoteException 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal boolean result; 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object rvalue; 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String errmsg; 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* This method establishes a raw tcp connection for sending 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * a POST message. Thus the object cannot communicate a 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * remote object beyond a fire wall. To avoid this problem, 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the connection should be established with a mechanism 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * collaborating a proxy server. Unfortunately, java.lang.URL 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * does not seem to provide such a mechanism. 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * You might think that using HttpURLConnection is a better 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * way than constructing a raw tcp connection. Unfortunately, 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * URL.openConnection() does not return an HttpURLConnection 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * object in Netscape's JVM. It returns a 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * netscape.net.URLConnection object. 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * lookupObject() has the same problem. 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Socket sock = new Socket(servername, port); 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal OutputStream out = new BufferedOutputStream( 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sock.getOutputStream()); 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(rmiCommand); 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.write(endofline); 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectOutputStream dout = new ObjectOutputStream(out); 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.writeInt(objectid); 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.writeInt(methodid); 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeParameters(dout, args); 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.flush(); 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InputStream ins = new BufferedInputStream(sock.getInputStream()); 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal skipHeader(ins); 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ObjectInputStream din = new ObjectInputStream(ins); 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal result = din.readBoolean(); 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal rvalue = null; 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal errmsg = null; 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (result) 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal rvalue = din.readObject(); 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal errmsg = din.readUTF(); 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal din.close(); 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.close(); 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sock.close(); 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (rvalue instanceof RemoteRef) { 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal RemoteRef ref = (RemoteRef)rvalue; 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal rvalue = createProxy(ref.oid, ref.classname); 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (ClassNotFoundException e) { 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RemoteException(e); 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IOException e) { 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RemoteException(e); 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RemoteException(e); 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (result) 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return rvalue; 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RemoteException(errmsg); 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void skipHeader(InputStream in) throws IOException { 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int len; 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal do { 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int c; 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal len = 0; 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while ((c = in.read()) >= 0 && c != 0x0d) 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++len; 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal in.read(); /* skip 0x0a (LF) */ 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } while (len > 0); 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void writeParameters(ObjectOutputStream dout, Object[] params) 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws IOException 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = params.length; 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.writeInt(n); 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (params[i] instanceof Proxy) { 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Proxy p = (Proxy)params[i]; 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.writeObject(new RemoteRef(p._getObjectId())); 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dout.writeObject(params[i]); 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 299