Source code for /engineering/autohit-2003/src/autohit/vm/VMCore.javaOriginal file VMCore.java
   1 /**
   2  * AUTOHIT 2003
   3  * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
   4  * 
   5  * This program is free software; you can redistribute it and/or modify 
   6  * it under the terms of the GNU General Public License as published by 
   7  * the Free Software Foundation; either version 2 of the License, or (at
   8  * your option) any later version.
   9  * This program is distributed in the hope that it will be useful, but
  10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12  * more details.
  13  * 
  14  * You should have received a copy of the GNU General Public License along
  15  * with this program; if not, write to the Free Software Foundation, Inc.,
  16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17  *
  18  * Additional license information can be found in the documentation.
  19  * @author Erich P Gatejen
  20  */
  21 package autohit.vm;
  22 import java.io.Serializable;
  23 import java.util.HashMap;
  24 import java.util.Hashtable;
  25 import java.util.Set;
  26 import java.util.Stack;
  27 
  28 import autohit.vm.i.VMIScope;
  29 
  30 /**
  31  * There are four storage mechanisms.<p>
  32  * 1- A UNIVERSE: A persistent store accessible by everyone and 
  33  * addressable by name.
  34  * <p>
  35  * 2- ENVIRONMENT core:  A shared store accessible by everyone
  36  * containing name/value pairs.  There is only one per system, so
  37  * all references point to a single static instance.<br>
  38  * <pre>
  39  * set(String name, Object o)
  40  * read(String name)
  41  * test(String name)
  42  * lock(String name)
  43  * unlock(String name)
  44  * waitingLock(String name)
  45  * </pre>
  46  * <p>
  47  * 3- PERSISTANT core:  An owned store per VM that contains 
  48  * name/object pairs.  It is not subject to scope rules.  There can
  49  * only be one instance of any named object.  It is implemented as a
  50  * HashMap.  This primarily meant to move object data between services, 
  51  * executables, and calls.  This is NOT syncronized and threadsafe.<br>
  52  * <pre>
  53  * persist(String name, Object o)
  54  * free(String name)
  55  * has(String name)
  56  * get(String name)
  57  * </pre>
  58  * <p>
  59  * 4- STORAGE code: An owned store per VM that contains name/value
  60  * pairs.  It is subject to scope rules.  Within the reference of
  61  * a single scope, there is only one valid instance of a new
  62  * instance is created, it will supercede the previous.  The storage
  63  * system uses Stacks on Hashmaps to maintain scope rules.  When
  64  * the scope is discarded, it will take all instances 
  65  * with it.  Of course, any instances  created in the prior scope(s)
  66  * will still be there.  This is NOT syncronized and threadsafe.<br>
  67  * <pre>
  68  * store(String name, Object o) 
  69  * remove(String name)
  70  * exists(String name)
  71  * fetch(String name)
  72  * replace(String name, Object o)
  73  * getStorageNameSet()
  74  * </pre>
  75  * <p>
  76  * You should not access the scope stack directly.
  77  * <p>
  78  * @see #set(String name, Object o)
  79  * @see #read(String name)
  80  * @see #test(String name)
  81  * @see #lock(String name)
  82  * @see #unlock(String name)
  83  * @see #waitingLock(String name)
  84  * @see #persist(String name, Object o)
  85  * @see #free(String name)
  86  * @see #has(String name)
  87  * @see #get(String name)
  88  * @see #store(String name, Object o) 
  89  * @see #remove(String name)
  90  * @see #exists(String name)
  91  * @see #fetch(String name)
  92  * @see #replace(String name, Object o)
  93  * 
  94  * @author Erich P. Gatejen
  95  * @version 1.0
  96  * <i>Version History</i>
  97  * <code>EPG - Rewrite - 5Mayt03 
  98  * 
  99  */
 100 public class VMCore implements Serializable {
 101 
 102 	final static long serialVersionUID = 1;
 103 	
 104 	/**
 105 	 * Storage space.  It is subject to scope rules.  If more than one
 106 	 * item is stored in the same name, it is converted to a stack bucket
 107 	 * and items are stacked.<p>
 108 	 * @see #store(String name, Object o) 
 109 	 * @see #remove(String name)
 110 	 * @see #exists(String name)
 111 	 * @see #fetch(String name)
 112 	 * @see #replace(String name, Object o)
 113 	 */
 114 	protected HashMap storage;
 115 
 116 	/**
 117 	 * Persistant storage space.  It is NOT subject to scope rules.  There cannot
 118 	 * be more than one instance of an item.<p>
 119 	 * @see #persist(String name, Object o)
 120 	 * @see #free(String name)
 121 	 * @see #has(String name)
 122 	 * @see #get(String name)
 123 	 */
 124 	protected HashMap persists;
 125 
 126 	/**
 127 	 *  Scope stack.
 128 	 *
 129 	 *  Do NOT use scope.pop() or scope.push() yourself!  We must maintain the
 130 	 *  scope cache dirty flag.  However, you can use peek(), empty(), and
 131 	 *  search() at your leasure().
 132 	 */
 133 	protected Stack scope;
 134 
 135 	/**
 136 	 *  Scope stack cache dirty flag.  Will be automatically set when any
 137 	 *  scope stack methods are used.
 138 	 */
 139 	protected boolean scDirty;
 140 
 141 	/**
 142 	 * Environment.  System wide store.  Set by the factory.<p>
 143 	 * @see #set(String name, Object o)
 144 	 * @see #read(String name)
 145 	 * @see #test(String name)
 146 	 * @see #lock(String name)
 147 	 * @see #unlock(String name)
 148 	 * @see #waitingLock(String name)
 149 	 */
 150 	public Hashtable environment;
 151 
 152 	/**
 153 	 *  Call cache.
 154 	 */
 155 	public HashMap callcache;
 156 
 157 	/**
 158 	 *  Default constructor.  Use this if you want a private environment.
 159 	 *  Of course, that might be pointless.
 160 	 */
 161 	public VMCore() {
 162 		environment = new Hashtable();
 163 		init();
 164 	}
 165 
 166 	/**
 167 	 *  Constructor.  Gets a reference to the environment.
 168 	 */
 169 	public VMCore(Hashtable env) {
 170 		environment = env;
 171 		init();
 172 	}
 173 
 174 	/**
 175 	 *  Private initializer
 176 	 */
 177 	private void init() {
 178 		storage = new HashMap();
 179 		persists = new HashMap();
 180 		callcache = new HashMap();
 181 		scope = new Stack();
 182 		scDirty = false;
 183 	}
 184 
 185 	/**
 186 	 *  Push an object onto the scope stack.
 187 	 *
 188 	 *  @param o the object
 189 	 */
 190 	public void push(Object o) {
 191 		scDirty = true;
 192 		scope.push(o);
 193 	}
 194 
 195 	/**
 196 	 *  Check to see if the stack is dirty.  This is not thread safe.
 197 	 * @return true is the stack is dirty
 198 	 */
 199 	public boolean isDirty() {
 200 		return scDirty;
 201 	}
 202 
 203 	/**
 204 	 *  Pop an object off the stack.  USE THIS instead of scope.pop()!!!
 205 	 *  Have to dirty the cache flag...
 206 	 * <p>
 207 	 *  It'll throw any exception it encounters--most likely a EmptyStackException.
 208 	 * @return an object reference
 209 	 * @throws Exception
 210 	 */
 211 	public Object pop() throws Exception {
 212 		scDirty = true;
 213 		return scope.pop();
 214 	}
 215 
 216 	/**
 217 	 *  Peek into the scope stack.
 218 	 *
 219 	 *  @return a reference to the object or NULL if the stack is empty
 220 	 */
 221 	public Object peek() {
 222 		Object ob = null;
 223 		try {
 224 			ob = scope.peek();
 225 		} catch (Exception e) {
 226 			// don't care
 227 		}
 228 		return ob;
 229 	}
 230 
 231 	/**
 232 	 * Store an item.  It is subject to scope rules.  It will
 233 	 * overload a prior instance with the same name, but not overwrite it. 
 234 	 *
 235 	 * @param name object name as a string
 236 	 * @param o the object
 237 	 * @throws VMException
 238 	 * @see autohit.vm.VMException
 239 	 */
 240 	public void store(String name, Object o) throws VMException {
 241 		Object thang;
 242 		scope.push(name);
 243 		try {
 244 			// Is there something there already?
 245 			if (storage.containsKey(name)) {
 246 				// yes - is there more than one in a stack?
 247 				thang = storage.get(name);
 248 				if (thang instanceof Stack) {
 249 					// no.  Add it to the stack
 250 					 ((Stack) thang).push(o);
 251 
 252 				} else {
 253 					// Create a stack and add them both
 254 					Stack thangs = new Stack();
 255 					thangs.push(thang);
 256 					thangs.push(o);
 257 					storage.put(name, thangs);
 258 				}
 259 
 260 			} else {
 261 				// no.  just toss it on
 262 				storage.put(name, o);
 263 			}
 264 
 265 		} catch (Exception e) {
 266 			throw new VMException(
 267 				"Core failed to store " + name + ".  " + e.getMessage(),
 268 				VMException.CODE_VM_CORE_FAILED_STORE_FAULT,
 269 				e);
 270 		}
 271 	}
 272 
 273 	/**
 274 	 * Removes an object from a store.  No real reasion to use this.
 275 	 * It will throw an exception only if something realy bad happened.
 276 	 * This will not remove the item from the scope stack!
 277 	 *
 278 	 * @param name object name as a string
 279 	 * @throws VMException
 280 	 * @see autohit.vm.VMException
 281 	 */
 282 	public void remove(String name) throws VMException {
 283 
 284 		Object thang;
 285 
 286 		try {
 287 			// Is it even in the store?
 288 			if (storage.containsKey(name)) {
 289 
 290 				thang = storage.get(name);
 291 				// is it a stack or a solo item
 292 				if (thang instanceof Stack) {
 293 
 294 					// Is there one or two items in the stack?
 295 					if (((Stack) thang).size() > 2) {
 296 						// there is a bunch.  pop the one
 297 						 ((Stack) thang).pop();
 298 
 299 					} else {
 300 						// there are only two.  discard the stack and keep the 
 301 						// last item
 302 						 ((Stack) thang).pop();
 303 						thang = ((Stack) thang).pop();
 304 						storage.put(name, thang);
 305 					}
 306 
 307 				} else {
 308 					// Solo item - toss it
 309 					storage.remove(name);
 310 				}
 311 			}
 312 
 313 		} catch (Exception e) {
 314 			throw new VMException(
 315 				"VM: Core failed on remove for "
 316 					+ name
 317 					+ ".  "
 318 					+ e.getMessage(),
 319 				VMException.CODE_VM_CORE_GENERAL_FAULT,
 320 				e);
 321 		}
 322 	}
 323 
 324 	/**
 325 	 * Check for an object in storage. 
 326 	 *
 327 	 * @param name object name as a string
 328 	 * @throws VMException
 329 	 * @see autohit.vm.VMException
 330 	 */
 331 	public boolean exists(String name) throws VMException {
 332 
 333 		try {
 334 			if (storage.containsKey(name)) {
 335 				return true;
 336 			}
 337 
 338 		} catch (Exception e) {
 339 			throw new VMException(
 340 				"VM: Core failed storage check for "
 341 					+ name
 342 					+ ".  "
 343 					+ e.getMessage(),
 344 				VMException.CODE_VM_CORE_GENERAL_FAULT,
 345 				e);
 346 		}
 347 		return false;
 348 	}
 349 
 350 	/**
 351 	 * Fetch an object reference in storage. 
 352 	 *
 353 	 * @param name object name as a string
 354 	 * @return the object or null if it can't be found
 355 	 * @throws VMException
 356 	 * @see autohit.vm.VMException
 357 	 */
 358 	public Object fetch(String name) throws VMException {
 359 
 360 		Object thang;
 361 
 362 		try {
 363 			// is it even there?
 364 			if (storage.containsKey(name)) {
 365 
 366 				thang = storage.get(name);
 367 
 368 				// a stack or naked?
 369 				if (thang instanceof Stack) {
 370 					return ((Stack) thang).peek();
 371 				} else {
 372 					return thang;
 373 				}
 374 			}
 375 
 376 		} catch (Exception e) {
 377 			throw new VMException(
 378 				"VM: Core failed to fetch " + name + ".  " + e.getMessage(),
 379 				VMException.CODE_VM_CORE_FAILED_RETRIEVAL_FAULT,
 380 				e);
 381 		}
 382 		return null;
 383 	}
 384 
 385 	/**
 386 	 * Get a Set of variables in scope in storage. 
 387 	 *
 388 	 * @return A Set of Strings that are the variable names.
 389 	 * @throws VMException
 390 	 * @see autohit.vm.VMException
 391 	 */
 392 	public Set getStorageNameSet() throws VMException {
 393 
 394 		Set keySet;
 395 
 396 		try {
 397 			keySet = storage.keySet();
 398 
 399 		} catch (Exception e) {
 400 			throw new VMException(
 401 				"VM: Core failed to getStorageNameSet() the variables.  " + e.getMessage(),
 402 				VMException.CODE_VM_CORE_FAILED_RETRIEVAL_FAULT,
 403 				e);
 404 		}
 405 		return keySet;
 406 	}
 407 	
 408 	/**
 409 	 * Replace an object in storage.  Obviously it will replace the nearest
 410 	 * in scope.  If the object doesn't exist, it will throw an exception.
 411 	 *
 412 	 * @param name object name as a string
 413 	 * @param o object reference
 414 	 * @throws VMException
 415 	 * @see autohit.vm.VMException
 416 	 */
 417 	public void replace(String name, Object o) throws VMException {
 418 
 419 		Object thang;
 420 
 421 		// Is there something there already?
 422 		if (storage.containsKey(name)) {
 423 
 424 			try {
 425 				// yes - is there more than one in a stack?
 426 				thang = storage.get(name);
 427 				if (thang instanceof Stack) {
 428 					// yes.  pop the top and push the replacement
 429 					 ((Stack) thang).pop();
 430 					((Stack) thang).push(o);
 431 
 432 				} else {
 433 					// replace it
 434 					storage.put(name, o);
 435 				}
 436 			} catch (Exception e) {
 437 				throw new VMException(
 438 					"Core failed to replace " + name + ".  " + e.getMessage(),
 439 					VMException.CODE_VM_CORE_FAILED_STORE_FAULT);
 440 			}
 441 
 442 		} else {
 443 			// no.  just toss it on
 444 			throw new VMException(
 445 				"Object doesnt exist in core storage: " + name,
 446 				VMException.CODE_VM_CORE_DOESNT_EXIST_FAULT);
 447 		}
 448 
 449 	}
 450 
 451 	// -- PERSIST
 452 
 453 	/**
 454 	 * Persist an item.  It is NOT subject to scope rules.  It will
 455 	 * overwrite a prior instance of it. 
 456 	 *
 457 	 * @param name object name as a string
 458 	 * @param o the object
 459 	 * @throws VMException
 460 	 * @see autohit.vm.VMException
 461 	 */
 462 	public void persist(String name, Object o) throws VMException {
 463 
 464 		try {
 465 			persists.put(name, o);
 466 		} catch (Exception e) {
 467 			throw new VMException(
 468 				"VM: Core failed to persist " + name + ".  " + e.getMessage(),
 469 				VMException.CODE_VM_CORE_FAILED_STORE_FAULT,
 470 				e);
 471 		}
 472 	}
 473 
 474 	/**
 475 	 * Free an item from persistant storage.  
 476 	 * 
 477 	 * @param name object name as a string
 478 	 * @throws VMException
 479 	 * @see autohit.vm.VMException
 480 	 */
 481 	public void free(String name) throws VMException {
 482 
 483 		try {
 484 			if (persists.containsKey(name)) {
 485 				persists.remove(name);
 486 			}
 487 		} catch (Exception e) {
 488 			throw new VMException(
 489 				"VM: Core failed to free " + name + ".  " + e.getMessage(),
 490 				VMException.CODE_VM_CORE_GENERAL_FAULT,
 491 				e);
 492 		}
 493 	}
 494 
 495 	/**
 496 	 * Get an object in persistant storage. 
 497 	 *
 498 	 * @param name object name as a string
 499 	 * @return the object or null if it doesn't exist.
 500 	 * @throws VMException
 501 	 * @see autohit.vm.VMException
 502 	 */
 503 	public Object get(String name) throws VMException {
 504 		try {
 505 			if (persists.containsKey(name)) {
 506 				return persists.get(name);
 507 			}
 508 		} catch (Exception e) {
 509 			throw new VMException(
 510 				"VM: Core failed to get " + name + ".  " + e.getMessage(),
 511 				VMException.CODE_VM_CORE_FAILED_RETRIEVAL_FAULT,
 512 				e);
 513 		}
 514 		return null;
 515 	}
 516 
 517 	/**
 518 	 * Check persistant storage for an object. 
 519 	 *
 520 	 * @param name object name as a string
 521 	 * @throws VMException
 522 	 * @see autohit.vm.VMException
 523 	 * @return if the object exists
 524 	 */
 525 	public boolean has(String name) throws VMException {
 526 		try {
 527 			if (persists.containsKey(name)) {
 528 				return true;
 529 			}
 530 
 531 		} catch (Exception e) {
 532 			throw new VMException(
 533 				"VM: Core failed persistant storage check for "
 534 					+ name
 535 					+ ".  "
 536 					+ e.getMessage(),
 537 				VMException.CODE_VM_CORE_GENERAL_FAULT,
 538 				e);
 539 		}
 540 		return false;
 541 	}
 542 
 543 	/**
 544 	 *  Marks a scope on the scope stack
 545 	 */
 546 	public void markScope() {
 547 		VMIScope vs = new VMIScope();
 548 		scope.push(vs);
 549 	}
 550 
 551 	/**
 552 	 *  Discard scope frame.  This will remove all items on the scope to and 
 553 	 *  including the top-most recent VMIScope object.  It will pop the whole damned stack if it doesn't find one...
 554 	 * @throws any VMException
 555 	 */
 556 	public void discardScopeFrame() throws VMException {
 557 
 558 		scDirty = true;
 559 		Object item;
 560 
 561 		try {
 562 
 563 			// Just keep poping until we get to the scope.
 564 			item = scope.pop();
 565 			while (!(item instanceof VMIScope)) {
 566 
 567 				// If we are here, then it's going to be a string name
 568 				this.remove((String) item);
 569 				item = scope.pop();
 570 			}
 571 
 572 		} catch (VMException e) {
 573 			// This is bad.  Propagate it.
 574 			throw e;
 575 		} catch (Exception e) {
 576 			// looks like we emptied the whole stack.  BAD! 
 577 			throw new VMException(
 578 				"VM: SOFTWARE DETECTED FAULT.  Emptied the scope stack.  Bad thing(tm)!  "
 579 					+ e.getMessage(),
 580 				VMException.CODE_VM_SOFTWARE_DETECTED_FAULT,
 581 				e);
 582 		}
 583 	}
 584 
 585 	// -- ENVIRONMENT
 586 
 587 	/**
 588 	 * Lock an item in the environment.  It will get a reference to the
 589 	 * object.
 590 	 * @param name object name as a string
 591 	 * @return an vmobject reference or null if it is already locked
 592 	 * @throws VMException for en error or if the item doesn't exist.
 593 	 * @see autohit.vm.VMException
 594 	 */
 595 	public Object lock(String name) throws VMException {
 596 
 597 		VMObject to;
 598 
 599 		try {
 600 			if (environment.containsKey(name)) {
 601 
 602 				// lock it if we can
 603 				to = (VMObject) environment.get(name);
 604 				if (to.test()) {
 605 					to.lock();
 606 					return to.get();
 607 				}
 608 
 609 			} else {
 610 				throw new VMException(
 611 					"VM: Core failed to lock " + name + ".  It does not exist.",
 612 					VMException.CODE_VM_CORE_DOESNT_EXIST_FAULT);
 613 			}
 614 
 615 		} catch (VMException e) {
 616 			throw e;
 617 		} catch (Exception e) {
 618 			throw new VMException(
 619 				"VM: Core failed to lock due to system fault "
 620 					+ name
 621 					+ ".  "
 622 					+ e.getMessage(),
 623 				VMException.CODE_VM_CORE_FAILED_CONTROL_FAULT,
 624 				e);
 625 		}
 626 		return null;
 627 	}
 628 
 629 	/**
 630 	 * Unlock an environment item if we can.  Ignore errors except if the
 631 	 * item doesn't exist or it is owned by someone else.
 632 	 * @param name object name as a string
 633 	 * @throws VMException for en error or if the item doesn't exist.
 634 	 * @see autohit.vm.VMException
 635 	 */
 636 	public void unlock(String name) throws VMException {
 637 
 638 		VMObject to;
 639 
 640 		try {
 641 			if (environment.containsKey(name)) {
 642 
 643 				// lock it if we can
 644 				to = (VMObject) environment.get(name);
 645 				if (to.test()) {
 646 					to.unlock();
 647 				}
 648 
 649 			} else {
 650 				throw new VMException(
 651 					"VM: Core failed to lock " + name + ".  It does not exist.",
 652 					VMException.CODE_VM_CORE_DOESNT_EXIST_FAULT);
 653 			}
 654 
 655 		} catch (VMException e) {
 656 			throw e;
 657 		} catch (Exception e) {
 658 			throw new VMException(
 659 				"VM: Core failed to lock due to system fault "
 660 					+ name
 661 					+ ".  "
 662 					+ e.getMessage(),
 663 				VMException.CODE_VM_CORE_FAILED_CONTROL_FAULT,
 664 				e);
 665 		}
 666 	}
 667 
 668 	/**
 669 	 * Read an environment item if we can.  Ignore errors except if the
 670 	 * item doesn't exist or it is owned by someone else.
 671 	 * @param name object name as a string
 672 	 * @throws VMException for en error or if the item doesn't exist.
 673 	 * @return the item or null if it is empty
 674 	 * @see autohit.vm.VMException
 675 	 */
 676 	public Object read(String name) throws VMException {
 677 
 678 		VMObject to;
 679 
 680 		try {
 681 			if (environment.containsKey(name)) {
 682 
 683 				// lock it if we can
 684 				to = (VMObject) environment.get(name);
 685 				if (to.test()) {
 686 					return to.get();
 687 				}
 688 
 689 			} else {
 690 				throw new VMException(
 691 					"VM: Core failed to read() "
 692 						+ name
 693 						+ ".  It does not exist.",
 694 					VMException.CODE_VM_CORE_DOESNT_EXIST_FAULT);
 695 			}
 696 
 697 		} catch (VMException e) {
 698 			throw e;
 699 		} catch (Exception e) {
 700 			throw new VMException(
 701 				"VM: Core failed to read() due to system fault "
 702 					+ name
 703 					+ ".  "
 704 					+ e.getMessage(),
 705 				VMException.CODE_VM_CORE_FAILED_RETRIEVAL_FAULT,
 706 				e);
 707 		}
 708 		return null;
 709 	}
 710 
 711 	/**
 712 	 * Set an environment item if we can.  This will throw an exception if 
 713 	 * the item exists and is locked.  If it doesn't exist, this will create it.
 714 	 * @param name object name as a string
 715 	 * @throws VMException for en error or if the item doesn't exist.
 716 	 * @return the item or null if it is empty
 717 	 * @see autohit.vm.VMException
 718 	 */
 719 	public Object set(String name, Object o) throws VMException {
 720 
 721 		VMObject to;
 722 
 723 		try {
 724 			// does it already exist?
 725 			if (environment.containsKey(name)) {
 726 
 727 				// lock it if we can
 728 				to = (VMObject) environment.get(name);
 729 				if (to.test()) {
 730 					to.set(o);
 731 				} else {
 732 					throw new VMException(
 733 						"VM: Core failed to set() "
 734 							+ name
 735 							+ ".  It exists and is locked.",
 736 						VMException.CODE_VM_OBJECT_LOCKED_FAULT);
 737 				}
 738 
 739 			} else {
 740 
 741 				// no - create it
 742 				to = new VMObject(o);
 743 				environment.put(name, o);
 744 			}
 745 
 746 		} catch (VMException e) {
 747 			throw e;
 748 		} catch (Exception e) {
 749 			throw new VMException(
 750 				"VM: Core failed to set() due to system fault "
 751 					+ name
 752 					+ ".  "
 753 					+ e.getMessage(),
 754 				VMException.CODE_VM_CORE_FAILED_STORE_FAULT,
 755 				e);
 756 		}
 757 		return null;
 758 	}
 759 
 760 	/**
 761 	 * Wait for a lock on an environment.  It will get a reference to the
 762 	 * object.
 763 	 * @param name object name as a string
 764 	 * @return an vmobject reference or null if it is already locked
 765 	 * @throws VMException for en error or if the item doesn't exist.
 766 	 * @see autohit.vm.VMException
 767 	 */
 768 	public Object waitingLock(String name) throws VMException {
 769 
 770 		VMObject to;
 771 		Object thang;
 772 
 773 		try {
 774 			if (environment.containsKey(name)) {
 775 
 776 				// lock it if we can
 777 				to = (VMObject) environment.get(name);
 778 				to.waitingLock();
 779 				return to.get();
 780 
 781 			} else {
 782 				throw new VMException(
 783 					"VM: Core failed to waitlock "
 784 						+ name
 785 						+ ".  It does not exist.",
 786 					VMException.CODE_VM_CORE_DOESNT_EXIST_FAULT);
 787 			}
 788 
 789 		} catch (VMException e) {
 790 			throw e;
 791 		} catch (Exception e) {
 792 			throw new VMException(
 793 				"VM: Core failed to waitlock due to system fault "
 794 					+ name
 795 					+ ".  "
 796 					+ e.getMessage(),
 797 				VMException.CODE_VM_CORE_FAILED_CONTROL_FAULT,
 798 				e);
 799 		}
 800 		//return null;
 801 	}
 802 
 803 	/**
 804 	 * Test if environment item is accessable.  
 805 	 * @param name object name as a string
 806 	 * @return true if it is available, otherwise false.
 807 	 * @throws VMException for en error or if the item doesn't exist.
 808 	 * @see autohit.vm.VMException
 809 	 */
 810 	public boolean test(String name) throws VMException {
 811 
 812 		VMObject to;
 813 
 814 		try {
 815 			if (environment.containsKey(name)) {
 816 
 817 				// lock it if we can
 818 				to = (VMObject) environment.get(name);
 819 				return to.test();
 820 
 821 			} else {
 822 				throw new VMException(
 823 					"VM: Core failed to waitlock "
 824 						+ name
 825 						+ ".  It does not exist.",
 826 					VMException.CODE_VM_CORE_DOESNT_EXIST_FAULT);
 827 			}
 828 
 829 		} catch (VMException e) {
 830 			throw e;
 831 		} catch (Exception e) {
 832 			throw new VMException(
 833 				"VM: Core failed to waitlock due to system fault "
 834 					+ name
 835 					+ ".  "
 836 					+ e.getMessage(),
 837 				VMException.CODE_VM_CORE_FAILED_CONTROL_FAULT,
 838 				e);
 839 		}
 840 		//return null;
 841 	}
 842 
 843 	/**
 844 	 *  Dump the core to a string.
 845 	 *
 846 	 *  @return an empty string for now.  this will be dangerous.
 847 	 * TODO implement toString for VMCore
 848 	 */
 849 	public String toString() {
 850 		return "not implemented yet";
 851 	}
 852 
 853 }