/** * The main processing loop for this actor. All we do here is call * <em>ourSession.shellMainLoop</em>. This allows the shell session to begin processing commands * with the proper permissions for invoking the local "impl" commands. */ @pausable public void execute() { try { // Log.println("<ShellActorImpl.run>: Requesting session reference from service..."); Object[] invokeArgs = new Object[1]; invokeArgs[0] = create.constructorArgs[0]; ourSession = (ShellSession) mgrActorInvokeService(manager, Shell.name, "shellProxyInit", invokeArgs); } catch (Exception e) { // If we get an error here then we have no reliable way of // reporting it because the creator of this actor is set to // null. So, just log the error and kill ourselves by calling // actorFatalError. // Log.println("Error in run loop of shell actor: " + e); // Have to do some handstands to log the stack trace. CharArrayWriter temp1 = new CharArrayWriter(); PrintWriter temp2 = new PrintWriter(temp1, true); e.printStackTrace(temp2); temp2.close(); temp1.close(); // Log.println(temp1.toString()); // kill ourselves mgrActorFatalError(manager, e); } // Now initialize our session actor before running it // Log.println("<ShellActorImpl.run>: Received references, initializing session..."); ourSession.ourActor = self; ourSession.ourActorRef = this; active = true; // Log.println("<ShellActorImpl.run>: Creating stream aliases..."); stdinName = ((BasicActorManager) manager).actorCreateAlias(this); stdoutName = ((BasicActorManager) manager).actorCreateAlias(this); stderrName = ((BasicActorManager) manager).actorCreateAlias(this); // When the shell loop exits we are considered in active. We also // close the standard streams at this point. ourSession.shellMainLoop(); try { if (stdinStream != null) stdinStream.close(); if (stdoutStream != null) stdoutStream.close(); if (stderrStream != null) stderrStream.close(); } catch (IOException e) { // We ignore these since it probably indicates that the // connection has already been closed. } active = false; // Even though our shell session has died at this point. We still // need to keep this actor around as our address may have been // propagated over the network. So we just suspend the actor here // and rely on garbage collection to eventually clean up old shell // actors. // suspend(); }
/** * Receive a new message from our manager. Depending on who the message is targeted to, we may * either deliver the message to the shell session by calling <em>ShellSession.newShellMsg</em>, * or we may perform a stream operation. In either case, we dump the message if this shell session * is no longer active. * * <p> * * @param <b>msg</b> The <em>ActorMsgRequest</em> structure to be delivered. This structure must * be maintained by the actor as it is required if an exception is returned to the manager. */ protected void actorDeliver(ActorMsgRequest msg) { Object rVal = null; String mName = null; Object[] mArgs = null; try { // PRAGMA [debug,osl.service.shell.ShellActorImpl] Log.println("<ShellActorImpl> Handling // request: " + msg); // We only deliver the message if we are still active (that is, // the shell session we are associated with is still running). // Otherwise we just dump the message. if (active) { // What we do depends on who the message is targetted to if (msg.receiver.equals(self)) { // give the message to our shell session ourSession.newShellMsg(msg); return; } // This message should be to one of our stream aliases so // handle it. try { // Decode the name and args mName = msg.method; mArgs = msg.methodArgs; rVal = null; if ((mName.equals("asynchException")) && (mArgs.length == 2) && (mArgs[0] instanceof ActorRequest) && (mArgs[1] instanceof Exception)) { // We just log these messages. // Log.println(this, "Received exception for request: " + mArgs[0]); // Log.println(this, "Exception stack trace follows:"); // Log.logExceptionTrace(this, (Exception)mArgs[1]); return; } else if (msg.receiver.equals(stdinName)) { // this should be a request to the stdin stream we encapsulate // If the stream connection was never answered then just dump the message if (stdinStream == null) return; if ((mName.equals("read")) && (mArgs.length == 0)) { rVal = read(); } else if ((mName.equals("read")) && (mArgs.length == 2) && (mArgs[0] instanceof ActorName) && (mArgs[1] instanceof String)) { read((ActorName) mArgs[0], (String) mArgs[1]); } else if ((mName.equals("read")) && (mArgs.length == 1) && (mArgs[0] instanceof Integer)) { rVal = read((Integer) mArgs[0]); } else if ((mName.equals("read")) && (mArgs.length == 3) && (mArgs[0] instanceof ActorName) && (mArgs[1] instanceof String) && (mArgs[2] instanceof Integer)) { read((ActorName) mArgs[0], (String) mArgs[1], (Integer) mArgs[2]); } else if ((mName.equals("skip")) && (mArgs.length == 1) && (mArgs[0] instanceof Long)) { rVal = skip((Long) mArgs[0]); } else if ((mName.equals("skip")) && (mArgs.length == 3) && (mArgs[0] instanceof ActorName) && (mArgs[1] instanceof String) && (mArgs[2] instanceof Long)) { skip((ActorName) mArgs[0], (String) mArgs[1], (Long) mArgs[2]); } else if ((mName.equals("available")) && (mArgs.length == 0)) { rVal = available(); } else if ((mName.equals("available")) && (mArgs.length == 2) && (mArgs[0] instanceof ActorName) && (mArgs[1] instanceof String)) { available((ActorName) mArgs[0], (String) mArgs[1]); } else if ((mName.equals("close")) && (mArgs.length == 0)) { close(); } else if ((mName.equals("mark")) && (mArgs.length == 1) && (mArgs[0] instanceof Integer)) { mark((Integer) mArgs[0]); } else if ((mName.equals("reset")) && (mArgs.length == 0)) { reset(); } else if ((mName.equals("markSupported")) && (mArgs.length == 0)) { rVal = markSupported(); } else if ((mName.equals("markSupported")) && (mArgs.length == 2) && (mArgs[0] instanceof ActorName) && (mArgs[1] instanceof String)) { markSupported((ActorName) mArgs[0], (String) mArgs[1]); } else if ((mName.equals("readln")) && (mArgs.length == 0)) { rVal = readln(); } else if ((mName.equals("readln")) && (mArgs.length == 2) && (mArgs[0] instanceof ActorName) && (mArgs[1] instanceof String)) { readln((ActorName) mArgs[0], (String) mArgs[1]); } else { // Throw a NoSuchMethodException. String argVals = "("; for (int i = 0; i < mArgs.length; i++) argVals = argVals + mArgs[0].getClass().toString() + ", "; argVals = argVals + ")"; throw new NoSuchMethodException(mName + argVals); } } else { // this is either a request for the stdout or stderr stream we // encapsulate OutputStream out = (msg.receiver.equals(stdoutName) ? stdoutStream : stderrStream); // If the stream connection was never answered then just dump the message if (out == null) return; if ((mName.equals("write")) && (mArgs.length == 1) && (mArgs[0] instanceof Integer)) { write(out, (Integer) mArgs[0]); } else if ((mName.equals("write")) && (mArgs.length == 1) && (mArgs[0] instanceof Byte[])) { write(out, (Byte[]) mArgs[0]); } else if ((mName.equals("write")) && (mArgs.length == 3) && (mArgs[0] instanceof Byte[]) && (mArgs[1] instanceof Integer) && (mArgs[2] instanceof Integer)) { write(out, (Byte[]) mArgs[0], (Integer) mArgs[1], (Integer) mArgs[2]); } else if ((mName.equals("print")) && // (mArgs.length == 1) && // (mArgs[0] instanceof String) ) { (mArgs.length == 1)) { print(out, mArgs[0].toString()); } else if ((mName.equals("println")) && // (mArgs.length == 1) && // (mArgs[0] instanceof String) ) { (mArgs.length == 1)) { println(out, mArgs[0].toString()); } else if ((mName.equals("flush")) && (mArgs.length == 0)) { flush(out); } else if ((mName.equals("close")) && (mArgs.length == 0)) { close(out); } else { // Throw a NoSuchMethodException. This will be ignored // if the original message is asynchException, in which // case we just log it. String argVals = "("; for (int i = 0; i < mArgs.length; i++) argVals = argVals + mArgs[0].getClass().toString() + ", "; argVals = argVals + ")"; throw new NoSuchMethodException(mName + argVals); } } // If this message is an RPC request, then send out the // reply message if (msg.RPCRequest) { Object[] returnIt = new Object[1]; ActorMsgRequest theReply = new ActorMsgRequest(msg.receiver, msg.sender, "__RPCReply", returnIt, false); returnIt[0] = rVal; theReply.originator = self; stampRequest(theReply); // PRAGMA [debug,osl.service.shell.ShellActorImpl] Log.println("<ShellActorImpl> Sending // reply message: " + theReply); mgrActorSend(manager, theReply); } } catch (Exception e) { // Any exception caught here is sent back to the original // caller as an asynchException message. Object[] args = new Object[2]; ActorMsgRequest errMsg = new ActorMsgRequest(msg.receiver, msg.sender, "asynchException", args, false); args[0] = msg; args[1] = e; errMsg.originator = self; stampRequest(errMsg); mgrActorSend(manager, errMsg); } } } catch (Throwable e) { // Any errors which we fail to trap above are bonafied bugs so // we kill ourselves off here. Note that we ignore ThreadDeath // in case this thread was being killed for some strange reason. if (e instanceof ThreadDeath) throw (ThreadDeath) e; else mgrActorFatalError( manager, new RemoteCodeException("Error in <ShellActorImpl.actorDeliver>:", e)); } }