Last commit for Worklet.java: e648691acebb1ed23bc2912ad66eee036b3bed6a

alex's newer changes. bytecode serialisation now happens within the

gskc [2002-12-17 22:14:42]
alex's newer changes. bytecode serialisation now happens within the
Worklet code, ie transparent to whoever codes the WJ
  1. /*
  2.  * @(#)Worklet.java
  3.  *
  4.  * Copyright (c) 2001: The Trustees of Columbia University in the City of New York. All Rights Reserved
  5.  *
  6.  * Copyright (c) 2001: @author Gaurav S. Kc
  7.  * Last modified by: Dan Phung (dp2041@cs.columbia.edu)
  8.  *
  9.  * CVS version control block - do not edit manually
  10.  * $RCSfile$
  11.  * $Revision$
  12.  * $Date$
  13.  * $Source$
  14.  */
  15.  
  16. package psl.worklets;
  17.  
  18. import java.io.*;
  19. import java.util.*;
  20. import java.net.URL;
  21.  
  22. /**
  23.  * The mobile agent that is transported to and from {@link WVM}'s
  24.  * in order to carry out certain tasks, as designated through the
  25.  * {@link WorkletJunction} execution points.
  26.  */
  27. public final class Worklet implements Serializable {
  28.  
  29. /** local {@link WVM} that the Worklet is currently at */
  30. private transient WVM _wvm;
  31. /** The host adapter that acts as a reference to the target system */
  32. private transient Object _system;
  33. /** local hostname */
  34. private String _lHost;
  35. /** local name of the RMI service */
  36. private String _lName;
  37. /** local port of the RMI service */
  38. private int _lPort;
  39.  
  40. /** local hash of the class set */
  41. transient HashSet classHashSet;
  42.  
  43. /** true if the Worklet is at its the origin point */
  44. private boolean _atOrigin;
  45.  
  46. /** reference to the {@link WorkletJunction} at the origin point */
  47. private WorkletJunction _originJunction;
  48.  
  49. /** reference to the current {@link WorkletJunction} */
  50. private WorkletJunction _currentJunction;
  51.  
  52. /** _hashCode used by ClassLoader to index within WVM's _activeWorklets */
  53. String _hashCode = null;
  54.  
  55. /** Collected "data" of WorkletJunction */
  56. protected Hashtable _payload;
  57. public String wid = "";
  58.  
  59. /** route that the Worket is to take */
  60. private final Vector _route = new Vector();
  61. /** {@link WorkletJunction}s of the Worklet */
  62. private final Vector _junctions = new Vector();
  63. /** set of classes associated with the {@link WorkletJunction}s of the Worklet */
  64. private final Vector _wjClasses = new Vector();
  65.  
  66. /** default to transporter security */
  67. private boolean _defaultSecurity = true;
  68. /** default security */
  69. private boolean _isSecure = false;
  70. private transient WorkletClassLoader _ldr = null;
  71. public Hashtable byteArrays = new Hashtable();
  72. //just a reference for serialization stuff...
  73. private WorkletJunction lastAdded = null;
  74.  
  75. /**
  76.   * Creates a Worklet with the given {@link WorkletJunction} as the
  77.   * originJunction
  78.   *
  79.   * @param _oj: execution point to set as original junction.
  80.   */
  81. public Worklet(WorkletJunction _oj) {
  82. _originJunction = _oj;
  83. if (_oj != null) {
  84. _wjClasses.add(_oj.getClass());
  85. _oj._worklet = this;
  86. }
  87. wid = new String((new Long(new Date().getTime())).toString()+WVM.wvm_id);
  88. // System.out.println("WORKLET ID IS " + wid);
  89. }
  90.  
  91. /**
  92.   * Adds the {@link WorkletJunction} to this Worklet
  93.   *
  94.   * @param _wj: {@link WorkletJunction} to add
  95.   */
  96. public void addJunction(WorkletJunction _wj) {
  97. // System.out.println("Worklet: addJunction");
  98. if (_wj == null) return;
  99. synchronized(_junctions) {
  100. lastAdded = _wj;
  101. _junctions.addElement(_wj);
  102. _wjClasses.add(_wj.getClass());
  103. // System.out.println("_wj.getClass, name: " + _wj.getClass().getName());
  104. _wj.setOriginWorkletJunction(_originJunction);
  105. _wj._worklet = this;
  106. }
  107. }
  108.  
  109.  
  110.  
  111. // Old add Junction for serialization
  112. // does not work because worklet pulls in all the classes
  113. // for junction even before any junction is being loaded....
  114. /* public void addJunction(WorkletJunction _wj,boolean ba){
  115. Class []cls = _wj.getClass().getClasses();
  116.   for(int i=0;i<java.lang.reflect.Array.getLength(cls);i++){
  117. System.out.println("NESTED CLASS: " + cls[i].getName());
  118.   }
  119. if(ba == false){
  120. addJunction(_wj);
  121. } else {
  122. try{
  123. addJunction(new WorkletJunction(_wj._host, _wj._name, _wj._port,_wj.appName,wid,_wj.getIndex()) {
  124. public void init(Object system, WVM wvm) { }
  125. public void execute() { }
  126. });
  127.  
  128. ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
  129. ObjectOutputStream ooStream = new ObjectOutputStream(baoStream);
  130. ooStream.writeObject(_wj);
  131. byte []wjbytes = baoStream.toByteArray();
  132. baoStream.close();
  133. System.out.println("PUTTING WJ WITH INDEX: "+_wj.getIndex());
  134. // byte []wjbytes = ...;
  135. byteArrays.put(_wj.getIndex(),wjbytes);
  136. } catch (Exception e){
  137. e.printStackTrace();
  138. }
  139. }
  140. }*/
  141.  
  142.  
  143. /*Add a dummy junction, with actual junction being supplied as byte code*/
  144. /*code base for actual junction must be supplied also*/
  145. public void addJunction(WorkletJunction _wj,URL url){
  146. byte [] bc = _wj.getBytes();
  147. // _wj._originClassServer = url;
  148. addJunction(new WorkletJunction(_wj._host,_wj._name,_wj._port,url){
  149. public void init(Object system, WVM wvm) {}
  150. public void execute() {}
  151. });
  152. byteArrays.put(lastAdded.getIndex(),bc);
  153. }
  154.  
  155.  
  156. /**
  157.   * Gets the {@link WorkletJunction} at the origin
  158.   *
  159.   * @return {@link WorkletJunction} at the origin
  160.   */
  161. public WorkletJunction getOriginJunction() {
  162. // System.out.println("Worklet: getOriginJunction");
  163. return (_originJunction);
  164. }
  165.  
  166. /**
  167.   * Initializes the Worklet with the local system and {@link WVM}
  168.   *
  169.   * @param system: reference to local system (host adapter)
  170.   * @param wvm: reference to local {@link WVM}
  171.   */
  172. void init(Object system, WVM wvm) {
  173. // System.out.println("Worklet: init");
  174. _wvm = wvm;
  175. _system = system;
  176. if (_atOrigin) {
  177. _originJunction.sysInit(system, wvm);
  178.  
  179. } else {
  180. classHashSet = new HashSet();
  181. _wjClasses.removeElement(_currentJunction.getClass());
  182. _currentJunction.sysInit(system, wvm);
  183.  
  184. }
  185. }
  186.  
  187. /**
  188.   * Start the executes thread for the Worklet. Used by the
  189.   * {@link WVM} after Worklet has been received.
  190.   */
  191. void execute() {
  192. // System.out.println("Worklet: execute");
  193. (new Thread() {
  194. // create a new thread regardless
  195. public void run() {
  196. // get the worklet class loader for this worklet
  197.  
  198. if(WVM.wkltRepository.containsKey(wid)){
  199. _ldr = (WorkletClassLoader)WVM.wkltRepository.get(wid);
  200.  
  201. } else {
  202. WVM.err.println("LOADER FOR WORKLET HAS NOT BEEN FOUND!");
  203. WVM.err.println("MOVING ON TO THE NEXT JUNCTION");
  204. if (!_atOrigin) {
  205. if (_junctions.isEmpty()) returnToOrigin();
  206. else {
  207. moveToNextJunction();
  208. return;
  209. }
  210. }
  211. }
  212. // do not send worklet id for classes loaded during execution
  213. _ldr.dontSendWorkletId();
  214. // 2-do: create _priority variable in WJ:
  215. // 2-do: existing super-priority thread to inherit higher priorities from ...
  216. WorkletJunction _wj = _atOrigin ? _originJunction : _currentJunction;
  217. if(byteArrays.containsKey(_wj.getIndex())){
  218. try{
  219. _junctions.removeElement(_wj);
  220. byte []bytecode = (byte[])byteArrays.get(_wj.getIndex());
  221. ByteArrayInputStream baiStream = new ByteArrayInputStream(bytecode);
  222. // ObjectInputStream oiStream = new ObjectInputStream(baiStream);
  223. // workletJunction = (WorkletJunction) oiStream.readObject();
  224. //baiStream.close();
  225.  
  226. //this must be present
  227. _ldr.addTopCodebase(_wj._originClassServer);
  228.  
  229. ObjectInputStream ois = new ObjectInputStream(baiStream) {
  230. protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException {
  231. String name = v.getName();
  232. // System.out.println("processSocketStream: Class.forName");
  233. Class c = Class.forName(name, true, _ldr);
  234. WVM.out.println("In custom ObjectInputStream, trying to resolve class: " + c);
  235. return ( (c == null) ? super.resolveClass(v) : c );
  236. }
  237. };
  238. _wj = (WorkletJunction) ois.readObject();
  239. _wj.sysInit(_system, _wvm);
  240. // _currentJunction.sysInit(system, wvm);
  241. WVM.out.println("RECREATED THE JUNCTION FROM THE BYTES ARRAY");
  242. baiStream.close();
  243. } catch(Exception e){
  244. WVM.err.println("FAILED TO LOAD WJ from BYTES ARRAY:");
  245. e.printStackTrace();
  246. WVM.err.println("MOVING ON TO THE NEXT JUNCTION");
  247. if (!_atOrigin) {
  248. if (_junctions.isEmpty()) returnToOrigin();
  249. else{
  250. moveToNextJunction();
  251. return;
  252. }
  253. }
  254. }
  255. // _ldr.sendWorkletId();
  256.  
  257. }
  258. Thread t = new Thread(_wj, _hashCode);
  259. t.setPriority(_wj.getPriority());
  260. t.start();
  261.  
  262. if (_atOrigin || !_currentJunction.dropOff()) {
  263. try {
  264. t.join();
  265. } catch (InterruptedException ie) { }
  266. }
  267.  
  268. if (!_atOrigin) {
  269. if (_junctions.isEmpty()) returnToOrigin();
  270. else{
  271. moveToNextJunction();
  272. return;
  273. }
  274. }
  275. }
  276. }).start();
  277. // immediately return control to the WVM
  278. }
  279.  
  280. /**
  281.   * After all the {@link WorkletJunction}s have been added, deploy the
  282.   * Worklet to the given {@link WVM}
  283.   *
  284.   * @param wvm: {@link WVM} to send the Worklet to
  285.   */
  286. public void deployWorklet(WVM wvm) {
  287. // System.out.println("Worklet: deployWorklet");
  288. synchronized (_junctions) {
  289. _currentJunction = (WorkletJunction) _junctions.firstElement();
  290. _junctions.removeElement(_currentJunction);
  291. _junctions.trimToSize();
  292. }
  293. // System.out.println(wid + " " + _junctions.size());
  294. try{
  295. wvm.regJunctions(wid,_junctions);
  296. }catch(Exception e){
  297. e.printStackTrace();
  298. }
  299. _wvm = wvm;
  300. _lHost = wvm.transporter._host;
  301. _lName = wvm.transporter._name;
  302. _lPort = wvm.transporter._port;
  303.  
  304. wvm.transporter.sendWorklet(this, _currentJunction);
  305. }
  306.  
  307. /** Moves the Worklet from one {@link WorkletJunction} to the next */
  308. void moveToNextJunction() {
  309. // System.out.println("Worklet: moveToNextJunction");
  310. WVM _tmpWVM = _wvm;
  311. _ldr = null;
  312. synchronized (_junctions) {
  313. _currentJunction = (WorkletJunction) _junctions.firstElement();
  314. _junctions.removeElement(_currentJunction);
  315. _junctions.trimToSize();
  316. }
  317.  
  318. _lHost = _wvm.transporter._host;
  319. _lName = _wvm.transporter._name;
  320. _lPort = _wvm.transporter._port;
  321.  
  322. // todo: locate and use predefined WVM URL comparison function.
  323. // note: hopefully that predefined WVM function resolves the difference
  324. // between 'localhost' and 127.0.0.1, and the computer's actual ip!!!
  325. if (_lHost == _currentJunction._host &&
  326. (_lName == _currentJunction._name || _lPort == _currentJunction._port)) {
  327.  
  328. _wvm.installWorklet(this);
  329.  
  330. } else {
  331. // Use local WVM to catapult to next junction
  332. _tmpWVM.transporter.sendWorklet(this, _currentJunction);
  333. }
  334. }
  335.  
  336. /** Moves the Worklet to the {@link WorkletJunction} at the origin */
  337. void returnToOrigin() {
  338. // System.out.println("Worklet: returnToOrigin");
  339. WVM _tmpWVM = _wvm;
  340. _atOrigin = true;
  341. _currentJunction = null;
  342.  
  343. _lHost = _wvm.transporter._host;
  344. _lName = _wvm.transporter._name;
  345. _lPort = _wvm.transporter._port;
  346.  
  347. if (_originJunction != null) {
  348. // todo: locate and use predefined WVM URL comparison function.
  349. if (_lHost == _originJunction._host &&
  350. (_lName == _originJunction._name || _lPort == _originJunction._port)) {
  351.  
  352. _wvm.installWorklet(this);
  353.  
  354. } else {
  355. // Use local system to catapult self back to home
  356. _tmpWVM.transporter.sendWorklet(this, _originJunction);
  357. }
  358. }
  359. }
  360.  
  361. /** Gets the number of classes associated with the {@link WorkletJunction}s */
  362. int getNumClasses() {
  363. return (_wjClasses.size());
  364. }
  365.  
  366. /** Gets an enumeration of the classes associated with the {@link WorkletJunction}s */
  367. Enumeration getClasses() {
  368. return (_wjClasses.elements());
  369. }
  370.  
  371. /**
  372.   * Sets the security of the Worklet
  373.   *
  374.   * @param isSecure: true if the Worklet is to be secure
  375.   */
  376. public final void isSecure(boolean isSecure){
  377. _defaultSecurity = false;
  378. _isSecure = isSecure;
  379. }
  380.  
  381. /**
  382.   * Checks whether this Worklet is secure, which could default to
  383.   * security level of the {@link WVM}
  384.   *
  385.   * @return whether the Worklet is to be secure
  386.   */
  387. public final boolean isSecure(){
  388. if (_defaultSecurity && _wvm != null)
  389. return _wvm.isSecure();
  390. else
  391. return _isSecure;
  392. }
  393. }