Updates for worklets transportation project.

aib7 [2002-12-13 02:43:20]
Updates for worklets transportation project.
Include separate class loaders for each worklet,
byte code 'pre-send', transportation of junctions as
byte arrays
Filename
WVM.java
WVM_Host.java
WVM_RMIClassLoaderSpi.java
WVM_RMI_Transporter.java
WVM_Transporter.java
diff --git a/WVM.java b/WVM.java
index f9f6fcf..fb5f9c6 100644
--- a/WVM.java
+++ b/WVM.java
@@ -31,12 +31,12 @@ import psl.worklets.WVMRSL.Registration;
 public final class WVM extends Thread {
   public static PrintStream out = System.out;
   public static PrintStream err = System.err;
-
+    public static String wvm_id = "";
   /**
    * The {@link WVM_Transporter} handles the sending and receiving of worklets and
    * messages (ping, rejoin registry requests, etc.)
    */
-  WVM_Transporter transporter;
+  public static WVM_Transporter transporter;

   /** The host adapter that acts as a reference to the target system */
   private final Object _system;
@@ -52,6 +52,9 @@ public final class WVM extends Thread {
   /** Collection of {@link WorkletJunction}(s) currently installed in this WVM */
   private final MultiMap _installedJunctions = new MultiMap();

+    /* collection of junctions of to send byte codes to*/
+    private final Hashtable _junctions = new Hashtable();
+
   /**
    * dp2041 The registration object that handles <code>WVMRSL</code> related issues
    * dp2041: email alex to see if this is correct.
@@ -61,6 +64,10 @@ public final class WVM extends Thread {
   /** Keeps track of whether this WVM is registered */
   private static boolean _registered;

+
+    public static WorkletByteCodeCache wkltRepository = new WorkletByteCodeCache();
+
+
   /**
    * The file that holds the properties of the <code>Registration</code> object
    * dp2041: not used
@@ -170,7 +177,7 @@ public final class WVM extends Thread {
       WVM.err.println("WVM security parameters incomplete.  see -help or Worklet documentation for details.");
       System.exit(0);
     }
-
+    // System.out.println("IN WVM CONSTRUCTOR");
     // then we initialize the WVM parameters
     _system = system;
     try {
@@ -181,6 +188,7 @@ public final class WVM extends Thread {
       }

       if (name == null) name =  _system.hashCode() + "_" +  System.currentTimeMillis();
+      wvm_id = name;

       transporter = new WVM_RMI_Transporter(this, host, name, port,
 					    keysfile, password, ctx, kmf, ks, rng,
@@ -272,6 +280,7 @@ public final class WVM extends Thread {
    * @param _worklet: newly arrived worklet
    */
   synchronized void installWorklet(Worklet _worklet) {
+      //   System.out.println("WVM: inastallWorklet");
     _worklet.init(_system, this);
     _installedWorklets.addElement(_worklet);
     if (_installedWorklets.size() == 1) {
@@ -288,6 +297,7 @@ public final class WVM extends Thread {
    * @param _hashCode: identifier for locating this worklet among all local worklets
    */
   private void executeWorklet(Worklet _worklet, String _hashCode) {
+      //   System.out.println("WVM: executeWorklet");
     Worklet _executingWorklet = _worklet;
     _executingWorklet._hashCode = _hashCode;
     // (new Thread(_executingWorklet, _hashCode)).start();
@@ -390,28 +400,35 @@ public final class WVM extends Thread {
    *
    * @return transporter's available plain port
    */
-  public int getWVMPort() { return (transporter._port); }
+  public int getWVMPort() {
+      // System.out.println("WVM: getWVMPort");
+      return (transporter._port); }

   /**
    * Gets the name associated with the RMI server
    *
    * @return name associated with the RMI server
    */
-  public String getWVMName() { return (transporter._name); }
+    public String getWVMName() { // System.out.println("WVM: getWVMName");
+  return (transporter._name); }

   /**
    * Gets the hostname or ip address
    *
    * @return hostname or ip address
    */
-  public String getWVMAddr() { return (transporter._host); }
+  public String getWVMAddr() {
+      // System.out.println("WVM: getWVMAddr");
+      return (transporter._host); }

   /**
    * Gets the port associated with the RMI server
    *
    * @return port associated with the RMI server
    */
-  public int getRMIPort() { return (((WVM_RMI_Transporter) transporter)._port); }
+  public int getRMIPort() {
+      // System.out.println("WVM: getRMIPort");
+      return (((WVM_RMI_Transporter) transporter)._port); }

   // Client-side ///////////////////////////////////////////////////////////////
   /**
@@ -423,6 +440,7 @@ public final class WVM extends Thread {
    * @return success of ping
    */
   public boolean ping(String wvmURL) {
+      //  System.out.println("WVM: ping");
     return (transporter.ping(wvmURL));
   }
   /**
@@ -437,6 +455,7 @@ public final class WVM extends Thread {
    * @return success of the send attempt
    */
   public boolean sendMessage(Object messageKey, Object message, String wvmURL) {
+      //  System.out.println("WVM: sendMessage");
     return (transporter.sendMessage(messageKey, message, wvmURL));
   }
   /**
@@ -450,6 +469,7 @@ public final class WVM extends Thread {
    * @return message that was received
    */
   public Object getMessage(Object messageKey, String wvmURL) {
+      //  System.out.println("WVM: getMessage");
     return (transporter.getMessage(messageKey, wvmURL));
   }
   // END: Client-side //////////////////////////////////////////////////////////
@@ -477,6 +497,7 @@ public final class WVM extends Thread {
    * @return true...always?(dp2041)
    */
   boolean receiveMessage(Object messageKey, Object message) {
+      //  System.out.println("WVM: receiveMessage");
     Thread t = new Thread(requestHandler);
     Integer i = new Integer(t.hashCode());
     String uniqueKey = i + "-" + messageKey;
@@ -501,6 +522,7 @@ public final class WVM extends Thread {
    * @return message that was received earlier of type <code>messageKey</code>
    */
   Object requestMessage(Object messageKey) {
+      //  System.out.println("WVM: requestMessage");
     Thread t = new Thread(requestHandler);
     Integer i = new Integer(t.hashCode());
     String uniqueKey = i + "-" + messageKey;
@@ -542,11 +564,17 @@ public final class WVM extends Thread {
    * @param wj: {@link WorkletJunction} to register
    */
   void registerJunction(WorkletJunction wj) {
+      //  System.out.println("WVM: registerJunction " + wj.id());
     _installedJunctions.put(wj.id(), wj);
     _myStats.log("Added Junction: ", wj);
     _myStats.accept();
   }
-
+    void regJunctions(String wid,Vector wjv) {
+	// System.out.println("WVM: registerJunction " + wid);
+    _junctions.put(wid, wjv);
+    //  _myStats.log("Added Junction: ", wj);
+    // _myStats.accept();
+  }
   /**
    * Gets a reference to a certain worklet junction
    *
@@ -554,10 +582,14 @@ public final class WVM extends Thread {
    * @return Vector of {@link WorkletJunction}(s) associated with
    * the {@link WorkletID}
    */
-  public Vector getJunctions(WorkletID id) {
+  public Vector getJunctions(String id) {
+      //  System.out.println("WVM: getJunctions " + id);
     return (Vector)_installedJunctions.get(id);
   }
-
+    public Vector getRegJunctions(String id) {
+	// System.out.println("WVM: getJunctions " + id);
+    return (Vector)_junctions.get(id);
+  }
   /**
    * Removes a {@link WorkletJunction} from the WVM stats
    *
@@ -565,6 +597,7 @@ public final class WVM extends Thread {
    * @return success of removal
    */
   boolean removeJunction(WorkletJunction wj) {
+      //  System.out.println("WVM: removeJunction");
     Object o = _installedJunctions.remove(wj.id(), wj);

     if (o != null) {
@@ -584,7 +617,8 @@ public final class WVM extends Thread {
    * {@link WorkletJunction}(s) to remove
    * @return success of removal
    */
-  boolean removeJunction(WorkletID wj_id) {
+  boolean removeJunction(String wj_id) {
+      //  System.out.println("WVM: removeJunction");
     Object o = _installedJunctions.remove(wj_id);

     if (o != null) {
diff --git a/WVM_Host.java b/WVM_Host.java
index 336e2c6..3f95b41 100644
--- a/WVM_Host.java
+++ b/WVM_Host.java
@@ -17,6 +17,7 @@ package psl.worklets;

 import java.rmi.*;
 import java.util.*;
+import java.net.URL;

 /** Interface of the {@link WVM}'s RMI server (the RTU) */
 public interface WVM_Host extends java.rmi.Remote {
@@ -27,9 +28,11 @@ public interface WVM_Host extends java.rmi.Remote {
    * Receives and installs a {@link Worklet}
    *
    * @param _worklet: {@link Worklet} to receive
-   * @throws RemoteException if {@link Worklet} could not be received
+   * @throws RemoteException if {@link Worklet} could no t be received
    */
   public void receiveWorklet(Worklet _worklet) throws RemoteException;
+    public void receiveWorkletId(String id,String codeBase) throws RemoteException;
+    public boolean receiveByteCode(String wid,String name, String u,byte []bc ) throws RemoteException;

   /**
    * Attemps to rejoin the {@link WVM_Registry}
diff --git a/WVM_RMIClassLoaderSpi.java b/WVM_RMIClassLoaderSpi.java
index 96bbdf9..6176595 100644
--- a/WVM_RMIClassLoaderSpi.java
+++ b/WVM_RMIClassLoaderSpi.java
@@ -51,6 +51,10 @@ public class WVM_RMIClassLoaderSpi extends RMIClassLoaderSpi {
     _default = dft;
     String wvmfile = System.getProperty("WVM_FILE");
     OptionsParser op = new OptionsParser("WVM_RMIClassLoaderSpi");
+    if(op == null)
+	System.out.println("op is null\n");
+    if(wvmfile == null)
+	System.out.println("wvmfile is null\n");
     op.loadWVMFile(wvmfile);
     _WVM_sf = new WVM_SSLSocketFactory(op.keysfile, op.password,
 				       System.getProperty("WVM_SSLCONTEXT"),
@@ -70,6 +74,7 @@ public class WVM_RMIClassLoaderSpi extends RMIClassLoaderSpi {
    * @throws ClassNotFoundException if the class could not be loaded
    */
   public Class loadClass(URL codebase, String name) throws MalformedURLException, ClassNotFoundException {
+      // System.out.println("RMIClassLoaderSpi: loadClass");
     return loadClass("" + codebase, name, _default);
   }

@@ -101,6 +106,8 @@ public class WVM_RMIClassLoaderSpi extends RMIClassLoaderSpi {
    */
   public Class loadClass(String codebase, String name, ClassLoader defaultLoader)
     throws MalformedURLException, ClassNotFoundException{
+
+      //System.out.println("RMICLassLoaderSpi: loadClass xxx");

     // we do not want to handle the loading of these classes...
     // dp2041: to debug, why is it that the loading of psl classes cause a class cast exception?
@@ -110,33 +117,86 @@ public class WVM_RMIClassLoaderSpi extends RMIClassLoaderSpi {
 	&& !name.matches("^sun[.].*") && !name.matches("^sunw[.].*")
 	&& !name.matches("^psl[.].*")
 	) {
-      // WVM.out.println("WVM_RMIClassLoaderSpi loading: " + codebase + ", " + name);
-      URL urls[] = new URL[1];
-      urls[0] = new URL(codebase);
-      WVM_ClassLoader _loader = new WVM_ClassLoader(urls, _WVM_sf);
-
-      try {
-	return _loader.findClass(name);
-      } catch (ClassNotFoundException e) {
-	// WVM.err.println("Couldn't find the class <"+name+"> through our methods, going to defaultLoader");
-      }
+	URL urls[] = new URL[1];
+	if(codebase == null){
+	    // sometimes it's null for some reason, don't want any exceptions here
+	    codebase = new String("http://localhost:"+WVM.transporter._webPort);
+	}
+	try{
+	    urls[0] = new URL(codebase);
+	} catch(Exception e){
+	    e.printStackTrace();
+	}
+	Integer index = new Integer(-1);
+		try{
+		    //  System.out.println("LOADER REMOTE CLIENT: " + java.rmi.server.RemoteServer.getClientHost());
+		    //	     System.out.println("LOADER REMOTE REF: " + ((WVM_RMI_Transporter)WVM.transporter).rtu.getRef().remoteHashCode());
+		    //	     System.out.println("CODEBASE : " + codebase);
+		     index = new Integer(((WVM_RMI_Transporter)WVM.transporter).rtu.getRef().remoteHashCode());
+		} catch (Exception e){
+		    // e.printStackTrace();
+		}
+	if(WVM_RMI_Transporter.wkltIds.containsKey(index)) {
+	    //  found worklet id for which classes are being loaded
+	    WorkletClassLoader _ldr,temp;
+	     WorkletIdEntry wie = (WorkletIdEntry)WVM_RMI_Transporter.wkltIds.get(index);
+	     String wid = new String(wie.wid);
+	     // let's use this codebase since it was supplied by the origin
+	     codebase = new String(wie.codebase);
+	     try{
+		 urls[0] = new URL(codebase);
+	     } catch(Exception e){
+		 e.printStackTrace();
+		 // System.exit(-1);
+	     }
+
+	     if(WVM.wkltRepository.containsKey(wid)){
+		 //found corresponding loader
+		 _ldr = (WorkletClassLoader)WVM.wkltRepository.get(wid);
+	     } else {
+		 //	System.out.println("CREATED LOADER FOR: " + wid);
+		 _ldr = new WorkletClassLoader(urls,_WVM_sf,wid);
+		 WVM.wkltRepository.put(wid,_ldr);
+	     }
+	     try {
+		 return _ldr.findClass(name);
+	     } catch (ClassNotFoundException e) {
+		 //	WVM.err.println("Couldn't find the class <"+name+"> through our methods, going to defaultLoader");
+	     }
+	     // WVM_RMI_Transporter.wkltIds.remove(index);
+	} else {
+	    //  WVM.err.println("Worklet id was not found! Using WVM_ClassLoader");
+	  	//  System.out.println("CODEBASE HERE IS : " + codebase);
+
+	    WVM_ClassLoader _loader = new WVM_ClassLoader(urls, _WVM_sf);
+	  	//  System.out.println(name + "  IN LOAD CLASS CODEBASE: " + codebase);
+	    //System.out.println("\nWVM ID IS : " + WVM.wvm_id + "\n");
+	    try {
+		//	System.out.println("RMISpi: calling WVM_ClassLoader:findClass");
+		return _loader.findClass(name);
+	    } catch (ClassNotFoundException e) {
+		//	WVM.err.println("Couldn't find the class <"+name+"> through our methods, going to defaultLoader");
+	    }
+	}
     }
-
-    // WVM.out.println("defaultLoader ClassLoader loading: " + codebase + ", " + name);
+    //  WVM.out.println("defaultLoader ClassLoader loading: " + codebase + ", " + name);
     return sun.rmi.server.LoaderHandler.loadClass(codebase, name, defaultLoader);
   }

   /** use the default Sun <code>LoaderHandler</code> implementation */
   public Class loadProxyClass(String codebase ,String[] interfaces, ClassLoader defaultLoader)
     throws MalformedURLException, ClassNotFoundException {
+      // System.out.println("RMISpi: loadProxyClass");
     return sun.rmi.server.LoaderHandler.loadProxyClass(codebase, interfaces, defaultLoader);
   }
   /** use the default Sun <code>LoaderHandler</code> implementation */
   public ClassLoader getClassLoader(String codebase) throws MalformedURLException {
-    return sun.rmi.server.LoaderHandler.getClassLoader(codebase);
+      // System.out.println("RMISpi: getClassLoader");
+      return sun.rmi.server.LoaderHandler.getClassLoader(codebase);
   }
   /** use the default Sun <code>LoaderHandler</code> implementation */
   public String getClassAnnotation(Class c){
+      // System.out.println("RMISpi: getClassAnnotation");
     return sun.rmi.server.LoaderHandler.getClassAnnotation(c);
   }
 }
diff --git a/WVM_RMI_Transporter.java b/WVM_RMI_Transporter.java
index 19fc3bd..7713001 100644
--- a/WVM_RMI_Transporter.java
+++ b/WVM_RMI_Transporter.java
@@ -9,12 +9,11 @@
  * CVS version control block - do not edit manually
  *  $RCSfile$
  *  $Revision$
- *  $Date$
+ *  $Date: 2002/10/26 00:38:21
  *  $Source$
  */

 package psl.worklets;
-
 import java.io.*;
 import java.net.*;
 import java.util.*;
@@ -22,6 +21,7 @@ import java.security.*;
 import java.rmi.*;
 import java.rmi.server.*;
 import java.rmi.registry.*;
+import java.awt.event.*;

 /**
  * Communication layer that handles the RMI (Remote Method Invocation)
@@ -30,7 +30,7 @@ import java.rmi.registry.*;
 class WVM_RMI_Transporter extends WVM_Transporter{

   /** RMI Transportation Unit: RMI server that registers with the {@link WVM_Registry} */
-  private RTU rtu;
+  public RTU rtu;
   /** object that mediates the binding/registration of the RMI server with the {@link WVM_Registry} */
   private RTU_RegistrarImpl rtuRegistrar;

@@ -54,6 +54,8 @@ class WVM_RMI_Transporter extends WVM_Transporter{
   /** reference to the host {@link WVM} */
   private WVM _wvm;

+    protected static Hashtable wkltIds = new Hashtable();
+
   /**
    * @deprecated never used
   */
@@ -206,7 +208,7 @@ class WVM_RMI_Transporter extends WVM_Transporter{
   * down
   */
   Date rejoinRegistry(String key) {
-    try {
+      try {
       return (key.equals(rtuRegistrar.getRegistrationKey()) ? rtu.rejoinRegistry() : null);
     } catch (RemoteException re) {
       // this will not really happen ;)
@@ -305,6 +307,9 @@ class WVM_RMI_Transporter extends WVM_Transporter{

       // TODO: set up the BAG-MULTISET in the ClassFileServer so that the
       // incoming BytecodeRetrieverWJ can get the data it needs
+
+      //send worklet id first, so we have a reference in the rmi class loader
+      wvmHost.receiveWorkletId(wkl.wid,RMIClassLoader.getClassAnnotation(wkl.getClass()));
       wvmHost.receiveWorklet(wkl);
       return true;
     } catch (NotBoundException e) {
@@ -317,6 +322,52 @@ class WVM_RMI_Transporter extends WVM_Transporter{
     return false;
   }

+    /*send out a byte code for class 'name' to be used
+      for this worklet with id wid
+      called from ClassServer
+    */
+    public boolean sendByteCode(String wid, String name,byte[] bytecode,String u){
+	Vector v = _wvm.getRegJunctions(wid);
+
+	for(int i = 0;i < v.size();i++){
+	    WorkletJunction wj = (WorkletJunction)v.elementAt(i);
+
+	    String rmiDestination = "//" + wj._host + ":" + wj._rmiport + "/" + wj._name;
+	    //WVM.out.println("      RMI Destination: " + rmiDestination);
+
+	    try {
+		WVM_Host wvmHost = null;
+		Registry reg = null;
+
+		if (_securityLevel > WVM.NO_SECURITY)
+		    reg = LocateRegistry.getRegistry(wj._host, wj._rmiport, _WVM_sf);
+		else
+		    reg = LocateRegistry.getRegistry(wj._host, wj._rmiport);
+
+		wvmHost = (WVM_Host)reg.lookup(wj._name);
+		try{
+		    if(wvmHost.receiveByteCode(wid,name,u,bytecode)){
+			//	WVM.out.println("TARGET SHOULD HAVE GOTTEN BYTE CODE");
+		    }
+		} catch (Exception e) {
+		    e.printStackTrace();
+		}
+
+	    } catch (NotBoundException e) {
+		WVM.out.println("      NotBoundException in SendWorklet: " + e);
+		continue;
+		//	e.printStackTrace();
+	    } catch (RemoteException e) {
+		WVM.out.println("      RemoteException in SendWorklet: " + e);
+		 e.printStackTrace();
+		continue;
+	    }
+	}
+	return true;
+    }
+
+
+
   /** @return local address */
   public String toString() {
     if (rmiService) return (_name + " @ " + _host + " : " + _port);
@@ -342,7 +393,7 @@ class WVM_RMI_Transporter extends WVM_Transporter{
    * Parses out the different addressing fields for representing
    * a {@link WVM}'s location
    *
-   * @param wvmURL: a <code>URL</code> that represents a
+   * @param wvmURL: a <code>URL</code> that represents
    * {@link WVM}'s location in the form of :
    * remote_hostname@RMI_name:remote_port where the RMI_name is
    * optional.
@@ -515,6 +566,7 @@ class WVM_RMI_Transporter extends WVM_Transporter{
         codebase += " http://" + _host + ":" + _webPort + "/";

       try {
+
         codebaseURL = new URL (codebase); // just to check whether it is malformed
         Properties props = System.getProperties();
         rmiCodebase = props.getProperty("java.rmi.server.codebase");
@@ -557,18 +609,57 @@ class WVM_RMI_Transporter extends WVM_Transporter{
       }
     }

-    /**
+
+      /*
+	get pre-sent byte code for worklet with wid
+	store it in the corresponding worklet class loader
+	create one if does not exist yet
+      */
+      public boolean receiveByteCode(String wid,String name,String u , byte []bc) throws RemoteException{
+	  try{
+	      URL [] us = new URL[1];
+	      us[0] = new URL(u);
+	      if(WVM.wkltRepository.containsKey(wid)){
+		  WVM.wkltRepository.putByteCode(wid, name, bc);
+	      }else{
+		  WorkletClassLoader _wldr = new WorkletClassLoader(us, _WVM_sf,wid);
+		  _wldr.putByteCode(name,bc);
+		  WVM.wkltRepository.put(wid,_wldr);
+	      }
+	  } catch (Exception e){
+	      e.printStackTrace();
+	  }
+	  return true;
+      }
+
+
+      /*
+	receives worklet id of the worklet to be received right after
+	stores it to use in rmi class loader
+      */
+      public void receiveWorkletId(String id,String cb) throws RemoteException {
+	  try{
+	      //get reference of the remote client to use as index into hashtable
+	      Integer index = new Integer(getRef().remoteHashCode());
+	      WorkletIdEntry wie = new WorkletIdEntry(id,cb,index);
+	      WVM_RMI_Transporter.wkltIds.put(index,wie);
+	  } catch (Exception e){
+	      e.printStackTrace();
+	  }
+      }
+
+      /**
      * Receives and installs a {@link Worklet}
      *
      * @param wkl: {@link Worklet} to receive
      * @throws RemoteException if {@link Worklet} could not be received
      */
-    public void receiveWorklet(Worklet wkl) throws RemoteException {
+      public void receiveWorklet(Worklet wkl) throws RemoteException {
+
       // TODO: Okay, now that the LEAST REQUIRED SET (LRS) of class bytecode
-      // has been downloaded from the source WVM, send out a BytecodeRetrieverWJ
+      // has been downloaded from the source WVM, seNS out a BytecodeRetrieverWJ
       // to get the relevant classes, viz. all those classes that the source
       // HTTP server served up to this WVM
-
       // adding to WVM's in-tray
       _wvm.installWorklet(wkl);
     }
@@ -774,13 +865,13 @@ class WVM_RMI_Transporter extends WVM_Transporter{
     /** Loaded classes are allowed to read a Collection of files */
     public void addReadableFiles (Collection c) {
       readableFiles.addAll(c);
-      // WVM.out.println ("**** ReadableFiles size " + readableFiles.size() + " ****");
+      WVM.out.println ("**** ReadableFiles size " + readableFiles.size() + " ****");
     }

     /** Loaded classes are allowed to read a filePath of files */
     public void addReadableFile (String filePath) {
       readableFiles.add(filePath);
-      // WVM.out.println ("**** ReadableFiles size " + readableFiles.size() + " ****");
+      WVM.out.println ("**** ReadableFiles size " + readableFiles.size() + " ****");
     }

     /** Removes Collection of files previously allowed for loaded classes to read */
diff --git a/WVM_Transporter.java b/WVM_Transporter.java
index 0d6250e..4e2566e 100644
--- a/WVM_Transporter.java
+++ b/WVM_Transporter.java
@@ -25,7 +25,7 @@ import psl.worklets.http.*;
  * The {@link WVM}'s network transport layer that handles
  * communication of {@link Worklet}s
  */
-class WVM_Transporter extends Thread {
+public class WVM_Transporter extends Thread {

   /** The {@link WVM} that this WVM_Transporter provides services for */
   WVM _wvm;
@@ -95,6 +95,12 @@ class WVM_Transporter extends Thread {
   /** identifier for reception of a worklet */
   protected static final String WORKLET_RECV = "Yo, I got your worklet";

+    protected static final String BYTECODE_XFER = "Yo, I am sending SOME BYTECODE";
+    /** identifier for reception of a bytecode */
+    protected static final String BYTECODE_RECV = "Yo, I got your BYTECODE";
+
+    //loader to use when receiving a worklet
+    WorkletClassLoader _ldr;
   /**
    * Creates the {@link WVM} related network layer composed of sockets
    *
@@ -183,8 +189,8 @@ class WVM_Transporter extends Thread {
         // WVM.err.println("Exception from loading urls in class loader: " + murle);
       }
     }
-    if (_securityLevel > WVM.NO_SECURITY) _loader = new WVM_ClassLoader(urls, _WVM_sf);
-    else _loader = new WVM_ClassLoader(urls);
+    // if (_securityLevel > WVM.NO_SECURITY) _loader = new WVM_ClassLoader(urls, _WVM_sf);
+    //else _loader = new WVM_ClassLoader(urls);
   }

   /**
@@ -218,6 +224,8 @@ class WVM_Transporter extends Thread {
    * @return port number of succesful server socket
    */
   private int createServerSocket(int startPort, String type){
+
+   	//   System.out.println("WVM_Transporter: CreateServerSocket " + startPort);
     int currentPort = startPort;
     while (currentPort >= startPort) {
       try {
@@ -283,6 +291,7 @@ class WVM_Transporter extends Thread {
    * @param socketType: type of server socket ("plain" or "secure")
    */
   private void listenSocket(final ServerSocket s, final String socketType) {
+   	//   System.out.println("WVM_Transporter: listenSocket");
     if (s == null) return;
     new Thread() {
       public void run() {
@@ -310,13 +319,15 @@ class WVM_Transporter extends Thread {
   private void processSocketStream(Socket s, String socketType){
     ObjectInputStream ois = null;
     ObjectOutputStream oos = null;
+    WorkletClassLoader temp;

     try {
       ois = new ObjectInputStream(s.getInputStream()) {
         protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException {
         String name = v.getName();
-        Class c = Class.forName(name, true, _loader);
-        // WVM.out.println("In custom ObjectInputStream, trying to resolve class: " + c);
+	//	System.out.println("processSocketStream: Class.forName");
+        Class c = Class.forName(name, true, _ldr);
+        WVM.out.println("In custom ObjectInputStream, trying to resolve class: " + c);
         return ( (c == null) ? super.resolveClass(v) : c );
         }
         };
@@ -363,6 +374,34 @@ class WVM_Transporter extends Thread {
         }
         oos.writeUTF(GETMSG_RESPONSE); oos.flush();
         return;
+      } else if (requestType.equals(BYTECODE_XFER)) {
+	  //receive pre-sent byte code
+	  String _rHost = ois.readUTF();
+	  String _rName = ois.readUTF();
+	  int _rPort = ois.readInt();
+	  URL u = new URL((String)ois.readObject());
+	  String _wid = (String)ois.readObject();
+	  String name = (String)ois.readObject();
+	//	  WVM.out.println("PROCESSING INCOMING BYTECODE FOR " + _wid + " " + name);
+	  int length = ois.readInt();
+	  byte []bc = new byte[length];
+	  ois.readFully(bc,0,length);
+	  URL [] us = new URL[1];
+	  us[0] = u;
+	  //store it in the corresponding class loader
+	  // if not present , create new one...
+	  if(WVM.wkltRepository.containsKey(_wid)){
+	      WVM.wkltRepository.putByteCode(_wid, name, bc);
+	  }else{
+	      WorkletClassLoader _wldr = new WorkletClassLoader(us, _WVM_sf,_wid);
+	      _wldr.putByteCode(name,bc);
+	      WVM.wkltRepository.put(_wid,_wldr);
+	  }
+	   // Now, send acknowledgement back to sender WVM
+	  oos.writeUTF(BYTECODE_RECV);
+	  oos.flush();
+	  return;
+
       } else if (! requestType.equals(WORKLET_XFER)) {
         // what kinda request is this anyway?
         WVM.out.println("  --  received a random request!");
@@ -372,9 +411,41 @@ class WVM_Transporter extends Thread {
       WVM.out.println("    received a worklet");
       classHashSet = new HashSet();

+
+      Vector urlsVec = null;
+      if (_securityLevel < WVM.HIGH_SECURITY)
+	  urlsVec = _webserver.getAliases();
+      if (_securityLevel > WVM.NO_SECURITY)
+	  urlsVec = _sslwebserver.getAliases();
+
+      URL urls[] = new URL[urlsVec.size()];
+      String protocol = "";
+      if (_securityLevel > WVM.NO_SECURITY)
+	  protocol = "https:";
+      else
+	  protocol = "file:";
+      for (int i=0; i<urls.length; i++) {
+	  try {
+	      urls[i] = new URL(protocol + urlsVec.elementAt(i));
+	  } catch (MalformedURLException murle) {
+	      // WVM.err.println("Exception from loading urls in class loader: " + murle);
+	  }
+      }
+
+
       String rHost = ois.readUTF();
       String rName = ois.readUTF();
       int rPort = ois.readInt();
+      String wid = (String)ois.readObject();
+      if(WVM.wkltRepository.containsKey(wid)){
+	  _ldr = (WorkletClassLoader)WVM.wkltRepository.get(wid);
+
+      } else {
+	//	  System.out.println("WORKLET ID IS " + wid);
+	  if (_securityLevel > WVM.NO_SECURITY) temp = _ldr = new WorkletClassLoader(urls, _WVM_sf,wid);
+	  else temp = _ldr = new WorkletClassLoader(urls,wid);
+	  WVM.wkltRepository.put(wid,temp);
+      }

       int numJunctions = ois.readInt();
       while (numJunctions-- > 0) {
@@ -382,7 +453,8 @@ class WVM_Transporter extends Thread {
         String codebase = ois.readUTF();
         try {
           addCodebase(codebase);
-          Class loadCl = _loader.loadClass(cName);
+		//  System.out.println("LOADING CLASS: " + cName);
+          Class loadCl = _ldr.loadClass(cName);
           // WVM.out.println("finally loaded class: " + loadCl);
         } catch (ClassNotFoundException e) {
           WVM.out.println ("WVM Transporter Exception: Class " + cName + " could not be loaded from codebase: " + codebase);
@@ -433,6 +505,7 @@ class WVM_Transporter extends Thread {
       } catch (IOException ioe) { }
     }
     WVM.out.println();
+    _ldr = null;
     return;
   }

@@ -458,10 +531,10 @@ class WVM_Transporter extends Thread {
     // urlsVec = new Vector(new HashSet(urlsVec));
     URL urls[] = new URL[urlsVec.size()];
     urlsVec.toArray(urls);
-    if (_loader == null) {
+    if (_ldr == null) {
       _loader = new WVM_ClassLoader(urls);
     } else {
-      _loader.addCodebase(urls);
+      _ldr.addCodebase(urls);
     }
   }

@@ -477,6 +550,7 @@ class WVM_Transporter extends Thread {
    * @return success of the send
    */
   boolean sendWorklet(Worklet wkl, WorkletJunction wj) {
+    	//  System.out.println("WVM_Transporter: sendWorklet");
     String[] methods = wj.getTransportMethods();

     boolean success = false;
@@ -514,6 +588,7 @@ class WVM_Transporter extends Thread {
    * @return success of the send
    */
   boolean sendSocket(Worklet wkl, WorkletJunction wj, boolean secure){
+    	//  System.out.println("WVM_Transporter: sendSocket");
     String targetHost = wj._host;
     int targetPort = wj._port;
     boolean transmissionComplete = false;
@@ -535,7 +610,8 @@ class WVM_Transporter extends Thread {
       oos.writeUTF(_host);
       oos.writeUTF(_name);
       oos.writeInt(_port);
-
+      oos.writeObject(wkl.wid);
+    	//  System.out.println("SENDING WORKLET ID IS " + wkl.wid);
       {
         ClassLoader sysCll = ClassLoader.getSystemClassLoader();
         Enumeration e = wkl.getClasses();
@@ -600,8 +676,8 @@ class WVM_Transporter extends Thread {
         WVM.out.println("      SecurityException in sendWorklet: " + e.getMessage());
         // e.printStackTrace();
     } catch (IOException e) {
-        WVM.out.println("      IOException in sendWorklet: " + e.getMessage());
-        // e.printStackTrace();
+	//  WVM.out.println("      IOException in sendWorklet: " + e.getMessage());
+        //e.printStackTrace();
     } finally {
       try {
         if (ois != null) ois.close();
@@ -613,6 +689,106 @@ class WVM_Transporter extends Thread {
     }
   }

+
+
+    // pre-send byte code for .class files
+    // used by ClassServer
+    public boolean sendByteCode(String wid, String name,byte[] bytecode,String u){
+	//	System.out.println("WVM_Transporter: sendBYTECODE");
+	Vector v = _wvm.getRegJunctions(wid);
+	if(v == null){
+	 	//   System.out.println("JUNCTIONS CVECTOR IS NULL");
+	}
+	boolean transmissionComplete = false;
+	for(int i = 0;i < v.size();i++){
+	    WorkletJunction wj = (WorkletJunction)v.elementAt(i);
+	    String targetHost = wj._host;
+	    int targetPort = wj._port;
+	  	//  System.out.println("Target: "+targetHost+" "+targetPort);
+	    Socket s = null;
+
+	    ObjectOutputStream oos = null;
+	    ObjectInputStream ois = null;
+
+	    try {
+		if (_securityLevel > WVM.NO_SECURITY && _WVM_sf != null)
+		    //	if (secure && _WVM_sf != null)
+		    s = _WVM_sf.createSocket(targetHost, targetPort);
+		else// if (!secure)
+		    s = new Socket(targetHost, targetPort);
+		//	else
+		//   return false;
+
+		oos = new ObjectOutputStream(s.getOutputStream());
+		oos.writeUTF(BYTECODE_XFER);
+		oos.writeUTF(_host);
+		oos.writeUTF(_name);
+		oos.writeInt(_port);
+		oos.writeObject(u);
+		oos.writeObject(wid);
+		oos.writeObject(name);
+		//	System.out.println("SENDING WORKLET ID IS " + wid);
+		oos.writeInt(java.lang.reflect.Array.getLength(bytecode));
+		oos.write(bytecode);
+
+		oos.flush();
+
+		// Receive ACK from the target WVM
+		ois = new ObjectInputStream(s.getInputStream());
+		transmissionComplete = ois.readUTF().equals(BYTECODE_RECV);
+	    } catch (InvalidClassException e) {
+		WVM.out.println("      InvalidClassException in sendByteCode: " + e.getMessage());
+	    // e.printStackTrace();
+	    } catch (NotSerializableException e) {
+		WVM.out.println("      NotSerializableException in sendByteCode: " + e.getMessage());
+		// e.printStackTrace();
+	    } catch (UnknownHostException e) {
+		WVM.out.println("      UnknownHostException in sendByteCode: " + e.getMessage());
+		// e.printStackTrace();
+	    } catch (SecurityException e) {
+		WVM.out.println("      SecurityException in sendByteCode: " + e.getMessage());
+		// e.printStackTrace();
+	    } catch (IOException e) {
+		WVM.out.println("      IOException in sendByteCode: " + e.getMessage());
+
+	    } finally {
+		try {
+		    if (ois != null) ois.close();
+		    if (oos != null) oos.close();
+		    if (s != null) s.close();
+		} catch (IOException ioe) { }
+	    }
+	}
+	return transmissionComplete;
+
+
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
   /** @return whether the transport layer is using secure sockets */
   boolean isSecure() {
     return (_securityLevel > WVM.NO_SECURITY);
@@ -628,6 +804,7 @@ class WVM_Transporter extends Thread {
    * @return success of ping
    */
   protected boolean ping(String wvmURL) {
+
     WVM.out.println("SHOULD-BE-OVERRIDDEN! WVM_Transporter.ping(String)");
     return false;
   }
@@ -643,6 +820,7 @@ class WVM_Transporter extends Thread {
    * @return success of the send attempt
    */
   protected boolean sendMessage(Object messageKey, Object message, String wvmURL) {
+    	//  System.out.println("WVM_Transporter: sendMessage");
     WVM.out.println("SHOULD-BE-OVERRIDDEN! WVM_Transporter.sendMessage(Object, Object, String)");
     return false;
   }
@@ -657,6 +835,7 @@ class WVM_Transporter extends Thread {
    * @return message that was received
    */
   protected Object getMessage(Object messageKey, String wvmURL) {
+    	//  System.out.println("WVM_Transporter: getMessage");
     WVM.out.println("SHOULD-BE-OVERRIDDEN! WVM_Transporter.getMessage(Object, String)");
     return null;
   }
@@ -717,6 +896,7 @@ class WVM_Transporter extends Thread {
    */
   final boolean sendMessage(Object messageKey, Object message, String host, int port) {
     // 2-do: really!
+    	//  System.out.println("WVM_Transporter: sendMessage2");
     boolean transmissionComplete = false;

     Socket s = null;
@@ -766,6 +946,7 @@ class WVM_Transporter extends Thread {
    */
   final Object getMessage(Object messageKey, String host, int port) {
     // 2-do: really!
+    	//	//  System.out.println("WVM_Transporter: getMessage");
     boolean transmissionComplete = false;
     Object message = null;