/************************************************************************** * Copyright (c) 2001 by Punch Telematix. All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Punch Telematix nor the names of * * other contributors may be used to endorse or promote products * * derived from this software without specific prior written permission.* * * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL PUNCH TELEMATIX OR OTHER CONTRIBUTORS BE LIABLE * * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ package wonka.rmi; import java.io.*; import java.net.*; import java.rmi.server.*; import java.rmi.dgc.*; import java.rmi.RemoteException; import java.rmi.NoSuchObjectException; import java.lang.reflect.Method; import java.util.WeakHashMap; class RMIRequestHandler extends Thread { //We use a WeakHashMap to make sure no entries stay around forever ... static final WeakHashMap clientHostNames = new WeakHashMap(13); private Socket s; RMIRequestHandler(Socket s){ super("RMIRequestHandler Thread "+s); if(RMIConnection.DEBUG < 6) {System.out.println("Constructing RMIRequestHandler "+this+" for "+s);} this.s = s; try { s.setSoLinger(true, 30000); } catch(java.net.SocketException se){} this.start(); } public void run(){ if(RMIConnection.DEBUG < 6) {System.out.println("RMIRequestHandler started "+this);} synchronized(clientHostNames){ clientHostNames.put(this,s.getInetAddress().getHostName()); } try { RMIConnection.serverSideHandShake(s); InputStream in = s.getInputStream(); DataOutputStream out = new DataOutputStream(s.getOutputStream()); DataInputStream din = new DataInputStream(in); String address = din.readUTF(); if(RMIConnection.DEBUG < 6) {System.out.println("Address :"+address); } int port = din.readInt(); if(RMIConnection.DEBUG < 6) {System.out.println("Port :"+port); } while(true){ int type = din.read(); if(RMIConnection.DEBUG < 6) {System.out.println("Reading resonse "+Integer.toHexString(0xff & type));} if(type == RMIConstants.CALL){ ObjectInputStream oin = new RMIObjectInputStream(new PushbackInputStream(in)); ObjID id = ObjID.read(oin); if(RMIConnection.DEBUG < 6) {System.out.println("ObjID: "+id);} int operation = oin.readInt(); if(RMIConnection.DEBUG < 6) {System.out.println("Operation: "+operation);} long hash = oin.readLong(); if(RMIConnection.DEBUG < 6) {System.out.println("Hash: "+hash);} if(hash == RMIConstants.HASH_DIRTY){ dirty(oin, operation, out); } else{ if(RMIConnection.DEBUG < 6) {System.out.println("Request to invoke a method");} ObjIDData data = (ObjIDData) RMIConnection.idData.get(id); if(RMIConnection.DEBUG < 6) {System.out.println("Request to invoke a method "+data+", id = "+id);} if(data == null){ RMIConnection.wrapException(out, new NoSuchObjectException("object not found")); } else { Method method = (Method)data.methods.get(new Long(hash)); if(method == null){ RMIConnection.wrapException(out, new NoSuchObjectException("method with hash '"+hash+"' not found in object")); } else { dispatch(oin, operation, out, data, method); } } } } else if(type == RMIConstants.PING){ out.write(RMIConstants.PING_ACK); } else { if(RMIConnection.DEBUG < 6) {System.out.println("Request to do "+Integer.toHexString(type)+" =?= DgcAck");} if(type == -1){ break; } } } } catch(Throwable e){ e.printStackTrace(); } finally { try { s.close(); } catch(Exception _){} } synchronized(clientHostNames){ clientHostNames.remove(this); } if(RMIConnection.DEBUG < 6) {System.out.println("RMIRequestHandler finished execution "+this);} } /** ** still TODO DGC ... */ private void dirty(ObjectInputStream oin, int operation, OutputStream out) throws IOException, ClassNotFoundException { out.write(RMIConstants.RETURN_DATA); ObjectOutputStream oout = new RMIObjectOutputStream(out); if(operation == RMIConstants.OPERATION_DIRTY){ ObjID[] id = (ObjID[]) oin.readObject(); if(RMIConnection.DEBUG < 8) {System.out.println("\ndirty is called");} if(RMIConnection.DEBUG < 6) {System.out.println("Argument ObjID[]: "+id+" of length "+id.length);} if(RMIConnection.DEBUG < 6){ for(int i = 0 ; i < id.length ; i++){ System.out.println("Argument ObjID["+i+"]: "+id[i]); } } long sequenceNumber = oin.readLong(); if(RMIConnection.DEBUG < 6) {System.out.println("sequenceNumber ??? "+sequenceNumber);} Lease lease = (Lease)oin.readObject(); if(RMIConnection.DEBUG < 6) {System.out.println("Argument Lease: "+lease+"\n");} oout.write(RMIConstants.RETURN_VALUE); new UID().write(oout); VMID vmID = lease.getVMID(); oout.writeObject(new Lease(vmID, lease.getValue())); } else if(operation == RMIConstants.OPERATION_CLEAN){ ObjID[] id = (ObjID[]) oin.readObject(); if(RMIConnection.DEBUG < 8) {System.out.println("\nclean is called");} if(RMIConnection.DEBUG < 6) {System.out.println("\nArgument ObjID[]: "+id);} long sequenceNumber = oin.readLong(); if(RMIConnection.DEBUG < 6) {System.out.println("sequenceNumber ??? "+sequenceNumber);} VMID vmid = (VMID)oin.readObject(); if(RMIConnection.DEBUG < 6) {System.out.println("Argument VMID: "+vmid);} boolean strong = oin.readBoolean(); if(RMIConnection.DEBUG < 6) {System.out.println("Argument boolean: "+strong+"\n");} oout.write(RMIConstants.RETURN_VALUE); new UID().write(oout); } else { oout.write(RMIConstants.EXCEPTION); new UID().write(oout); oout.writeObject(new RemoteException("invalid operation")); } oout.flush(); } private void dispatch(ObjectInputStream oin, int operation, OutputStream out, ObjIDData data, Method method) throws IOException, ClassNotFoundException { if(RMIConnection.DEBUG < 6) {System.out.println("Invoking method: "+method+"\n\tObjIDData data = "+data );} Class[] classes = method.getParameterTypes(); Object[] params = new Object[classes.length]; for(int i = 0 ; i < classes.length ; i++){ if(classes[i].isPrimitive()){ params[i] = ParameterSet.readPrimitive(classes[i], oin); } else { params[i] = oin.readObject(); if(RMIConnection.DEBUG < 6) { System.out.println("Marshalling "+params[i]+" class = "+(null == params[i] ? null : params[i].getClass()) +" <--> "+classes[i]); } } } try { if(RMIConnection.DEBUG < 6) {System.out.println("invoking method on "+data.impl);} Object o = method.invoke(data.impl, params); if(RMIConnection.DEBUG < 6) { System.out.println("done invoking method on "+data.impl+" got '"+o+"' of "+(o == null ? o : o.getClass())); } out.write(RMIConstants.RETURN_DATA); if(RMIConnection.DEBUG < 6) {System.out.println("SETTING UP STREAM");} ObjectOutputStream oout = new RMIObjectOutputStream(out); oout.write(RMIConstants.RETURN_VALUE); new UID().write(oout); if(RMIConnection.DEBUG < 6) {System.out.println("SERIALIZING RESPONSE");} Class returntype = method.getReturnType(); if(returntype == Void.TYPE){ if(RMIConnection.DEBUG < 6) {System.out.println("Called a void method "+o);} } else if(returntype.isPrimitive()){ ParameterSet.writePrimitive(returntype, o, oout); } else { oout.writeObject(o); } oout.flush(); if(RMIConnection.DEBUG < 6) {System.out.println("REQUEST IS DONE");} } catch(IllegalAccessException iae){ RMIConnection.wrapException(out,iae); } catch(java.lang.reflect.InvocationTargetException ite){ RMIConnection.wrapException(out,ite); } } }