package bluej.extensions;

import bluej.BlueJEvent;
import bluej.debugger.DebuggerObject;
import bluej.debugger.ExceptionDescription;
import bluej.debugmgr.ExecutionEvent;
import bluej.debugmgr.Invoker;
import bluej.debugmgr.ResultWatcher;
import bluej.debugmgr.objectbench.ObjectWrapper;
import bluej.pkgmgr.PkgMgrFrame;
import bluej.testmgr.record.InvokerRecord;
import bluej.utility.Utility;
import bluej.views.CallableView;
import bluej.views.ConstructorView;
import bluej.views.MethodView;


| Provides a gateway to invoke methods on objects using a specified set of parameters. | | @author Damiano Bolla, University of Kent at Canterbury, 2003,2004 | @author Clive Miller, University of Kent at Canterbury, 2002 | class DirectInvoker { private final PkgMgrFrame pkgFrame; private String resultName;
| For use by the bluej.extensions | | @param i_pkgFrame Description of the Parameter | @param i_callable Description of the Parameter | DirectInvoker(PkgMgrFrame i_pkgFrame) { pkgFrame = i_pkgFrame; }
| Call this if you want to call a constructor | | <p>The arguments passed in the args array may have any type, | but the type will determine exactly what is passed to the | constructor: | | <ul> | <li>String - the String will be passed directly to the constructor | <li>BObject - the object will be passed directly to the constructor, | though it must be on the object bench for this to work | <li>Anything else - toString() is called on the object and the | result is treated as a Java expression, which is | evaluated and passed to the constructor. | </ul> | | <p>An attempt is made to ensure that the argument types are suitable | for the constructor. InvocationArgumentException will be thrown if | the arguments are clearly unsuitable, however some cases will | generate an InvocationErrorException instead. In such cases no | expression arguments will be evaluated. | | @param callable The constructor to call | @param args Arguments to the constructor | @return The newly created object | @throws InvocationArgumentException if the argument list is not consistent with the signature | @throws InvocationErrorException if there is a system error | p.public DebuggerObject invokeConstructor(ConstructorView callable, Object[] args) throws InvocationArgumentException, InvocationErrorException { if (!paramsAlmostMatch(args, callable.getParameters())) { throw new InvocationArgumentException("invokeConstructor: bad arglist"); } DirectResultWatcher watcher = new DirectResultWatcher(); Invoker invoker = new Invoker(pkgFrame, callable, watcher); String [] argStrings = convObjToString(args); invoker.invokeDirect(argStrings); DebuggerObject result = watcher.getResult(); String resultType = watcher.getResultType(); if (resultType != null) { ExecutionEvent ee = new ExecutionEvent(pkgFrame.getPackage(), callable.getClassName(), null); raiseEvent(ee, callable, argStrings, watcher); } if (watcher.isFailed()) { throw new InvocationErrorException("invokeConstructor: Error=" + watcher.getError()); } if (result == null) { throw new InvocationErrorException("invokeConstructor: ERROR: result==null"); } resultName = watcher.getResultName(); return result; }
| Call a method on an object. | You need to pass the object where you want it applied. | | <p>The arguments passed in the args array may have any type, | but the type will determine exactly what is passed to the | method: | | <ul> | <li>String - the String will be passed directly to the method | <li>BObject - the object will be passed directly to the method, | though it must be on the object bench for this to work | <li>Anything else - toString() is called on the object and the | result is treated as a Java expression, which is | evaluated and passed to the method. | </ul> | | <p>An attempt is made to ensure that the argument types are suitable | for the method. InvocationArgumentException will be thrown if | the arguments are clearly unsuitable, however some cases will | generate an InvocationErrorException instead. In such cases no | expression arguments will be evaluated. | | @param onThisObjectInstance the method is called on this object | @param args The arguments for the method | @return The result object; for a constructor call this is the | constructed object; for any other invocation this will be | an object with a 'result' field containing the actual result, | or the null object (i.e. isNullObject() == true) if the result | type is void. | @exception InvocationArgumentException Thrown if the arglist is not consistent with the signature | @exception InvocationErrorException Thrown if there is a system error | p.public DebuggerObject invokeMethod(ObjectWrapper onThisObjectInstance, MethodView callable, Object[] args) throws InvocationArgumentException, InvocationErrorException { if (!paramsAlmostMatch(args, callable.getParameters())) { throw new InvocationArgumentException("invokeMethod: bad arglist"); } DirectResultWatcher watcher = new DirectResultWatcher(); Invoker invoker; if (callable.isStatic()) { invoker = new Invoker(pkgFrame, callable, watcher); } else { invoker = new Invoker(pkgFrame, (MethodView) callable, onThisObjectInstance.getName(), onThisObjectInstance.getObject(), watcher); } String [] argStrings = convObjToString(args); invoker.invokeDirect(convObjToString(args)); DebuggerObject result = watcher.getResult(); String resultType = watcher.getResultType(); if (resultType != null) { ExecutionEvent ee = new ExecutionEvent(pkgFrame.getPackage(), callable.getClassName(), (onThisObjectInstance==null)?null:onThisObjectInstance.getName()); ee.setMethodName(callable.getName()); raiseEvent(ee, callable, argStrings, watcher); } if (watcher.isFailed()) { throw new InvocationErrorException("invokeMethod: Error=" + watcher.getError()); } resultName = watcher.getResultName(); return result; }
| Raise an appropriate execution event, after a result has been received. | private static void raiseEvent(ExecutionEvent event, CallableView callable, String [] argStrings, DirectResultWatcher watcher) { DebuggerObject result = watcher.getResult(); String resultType = watcher.getResultType(); event.setParameters(callable.getParamTypes(false), argStrings); event.setResult(resultType); if (resultType == ExecutionEvent.NORMAL_EXIT) { event.setResultObject(result); event.setObjectName(watcher.getResultName()); } else if (resultType == ExecutionEvent.EXCEPTION_EXIT) { event.setException(watcher.getException()); } BlueJEvent.raiseEvent(BlueJEvent.EXECUTION_RESULT, event); }
| Returns the result object name of an invocation | | @return The resultName value | String getResultName() { return resultName; }
| Converts an array of Object into an array of String with java | expressions representing the objects, as per the convOneObj method. | | @param i_array Input object values | @return Objects transformed into an array of strings | private String[] convObjToString(Object[] i_array) { if (i_array == null) { return null; } if (i_array.length <= 0) { return new String[0]; } String[] o_array = new String[i_array.length]; for (int index = 0; index < i_array.length; index++) { o_array[index] = convOneObj(i_array[index]); } return o_array; }
| Does one conversion of a supplied object to a java expression | representing that object, according to the following rules: | | <ul> | <li>String - the String will be quoted according to Java quoting | rules, and enclosed in quotes | <li>BObject - the name of the BObject on the object bench will be | returned | <li>Anything else - toString() is called on the object and the | result is treated as a Java expression, which is | returned. | </ul> | | @param i_obj Input object to convert | @return The resulting string representation | private String convOneObj(Object i_obj) { if (i_obj == null) { return null; } if (i_obj instanceof String) { return "\"" + Utility.quoteString(i_obj.toString()) + "\""; } if (i_obj instanceof BObject) { return ((BObject) i_obj).getInstanceName(); } return i_obj.toString(); }
| Simple utility to decide when two params list do not match. | The test is done on params length but not on the type. | | @param params The params given | @param paramClass The reference params array | @return true if they match, false othervise | private boolean paramsAlmostMatch(Object[] params, Class<?>[] paramClass) { if (params != null && params.length < 1) { params = null; } if (paramClass != null && paramClass.length < 1) { paramClass = null; } if (params == null && paramClass == null) { return true; } if (params == null || paramClass == null) { return false; } if (params.length != paramClass.length) { return false; } return true; }
| This is used to interface with the core BlueJ | This new version does return when there is an INTERRUPT | class DirectResultWatcher implements ResultWatcher { private boolean resultReady; private boolean isFailed; private String resultType; private DebuggerObject result; private ExceptionDescription exception; private String errorMsg; private String resultName;
| Constructor for the DirectResultWatcher object | public DirectResultWatcher() { resultReady = false; isFailed = false; result = null; errorMsg = null; }
| This will try to get the result of an invocation. | null can be returned if the thread is interrupted !!! | | @return The result value | public synchronized DebuggerObject getResult() { while (!resultReady){ try { wait(); } catch (InterruptedException exc) { isFailed = true; errorMsg = "getResult: Interrupt: Exception=" + exc.getMessage(); return null; } } return result; }
| I need a way to reliably detect if there is an error or not. | Careful... should I look for resultReady too ? | | @return The failed value | public synchronized boolean isFailed() { return isFailed; }
| | @see bluej.debugmgr.ResultWatcher#beginExecution() | public void beginCompile() { }
| | @see bluej.debugmgr.ResultWatcher#beginExecution() | public void beginExecution(InvokerRecord ir) { }
| Used to return a result. We know that it is a good one. | | @param aResult The actual result object | @param anObjectName The object name in the object bench | @param ir Further parameter, see ResultWatcher | public synchronized void putResult(DebuggerObject aResult, String anObjectName, InvokerRecord ir) { result = aResult; resultType = ExecutionEvent.NORMAL_EXIT; resultName = anObjectName; resultReady = true; notifyAll(); }
| This is used to return an error. | @param error The error message | public synchronized void putError(String error, InvokerRecord ir) { errorMsg = "Invocation: Error=" + error; isFailed = true; resultReady = true; notifyAll(); }
| Treat run-time error the same as compile-time error. | @param msg The exception message | public synchronized void putException(ExceptionDescription exception, InvokerRecord ir) { this.exception = exception; resultType = ExecutionEvent.EXCEPTION_EXIT; putError(exception.getText(), ir); }
| Treat termination as an error | public void putVMTerminated(InvokerRecord ir) { resultType = ExecutionEvent.TERMINATED_EXIT; putError("Terminated", ir); }
| Gets the error attribute of the DirectResultWatcher object | | @return The error value | public String getError() { return errorMsg; }
| Gets the resultName attribute of the DirectResultWatcher object | | @return The resultName value | public String getResultName() { return resultName; }
| Returns the result type: | ExecutionEvent.NORMAL_EXIT if execution completed normally; | ExecutionEvent.EXCEPTION_EXIT if an exception occurred in user code; | ExecutionEvent.TERMINATED_EXIT if the user VM exited for any reason; | null if compilation failure occurred. | public String getResultType() { return resultType; }
| Get the exception which occurred (if result type == EXCEPTION_EXIT). | public ExceptionDescription getException() { return exception; } } }

.   - DirectInvoker
.   invokeConstructor
.   invokeMethod
.   raiseEvent
.   convObjToString
.   convOneObj
.   paramsAlmostMatch
.   - DirectResultWatcher
.   DirectResultWatcher
.   getResult
.   isFailed
.   beginCompile
.   beginExecution
.   putResult
.   putError
.   putException
.   putVMTerminated
.   getError
.   getResultName
.   getResultType
.   getException




401 neLoCode + 112 LoComm