/* * (non-Javadoc) * * @see com.richhickey.foil.IRuntimeServer#processMessages() */ public Object processMessages(TextReader ins, TextWriter outs) { // lock(this) { proxyReader = ins; proxyWriter = outs; for (;;) { String resultMessage = null; String errorMesssage = null; String sin = null; ArrayList message = null; try { sin = slurpForm(ins); message = reader.readMessage(new StringReader(sin)); if (isMessage(":call", message)) //(:call cref marshall-flags marshall-value-depth-limit args ...) { ICallable c = (ICallable)message[1]; int marshallFlags = intArg(message[2]); int marshallDepth = intArg(message[3]); Object ret = c.invoke(message[4], message.GetRange(5, message.Count - 5)); resultMessage = createRetString(ret, marshaller, marshallFlags, marshallDepth); } else if (isMessage(":cref", message)) //(:cref member-type tref|"packageQualifiedTypeName" "memberName") { int memberType = intArg(message[1]); Type c = typeArg(message[2]); String memberName = stringArg(message[3]); ICallable ret = reflector.getCallable(memberType, c, memberName); resultMessage = createRetString(ret, marshaller, IBaseMarshallerFlags.MARSHALL_ID, 0); } else if (isMessage(":new", message)) //(:new tref marshall-flags marshall-value-depth-limit (args ...) property-inits ...) { Type c = typeArg(message[1]); int marshallFlags = intArg(message[2]); int marshallDepth = intArg(message[3]); ArrayList args = (ArrayList)message[4]; Object ret = reflector.createNew(c, args); //set props if (message.Count > 5) { reflector.setProps(ret, message.GetRange(5, message.Count - 5)); } resultMessage = createRetString(ret, marshaller, marshallFlags, marshallDepth); } else if (isMessage(":tref", message)) //(:tref "packageQualifiedTypeName") { Type c = typeArg(message[1]); resultMessage = createRetString(c, marshaller, IBaseMarshallerFlags.MARSHALL_ID, 1); } else if (isMessage(":free", message)) //(:free refid ...) { for (int i = 1; i < message.Count; i++) { Object id = message[i++]; int rev = intArg(message[i]); referenceManager.free(id, rev); } resultMessage = createRetString(null, marshaller, 0, 0); } else if (isMessage(":ret", message)) //only on callback, note will break out of message loop { return(message[1]); } else if (isMessage(":str", message)) //(:str refid) { resultMessage = createRetString(message[1].ToString(), marshaller, 0, 0); } else if (isMessage(":equals", message)) //(:equals ref1 ref2) { Object o1 = message[1]; Object o2 = message[2]; Boolean ret = (o1 == null) ? (o2 == null) : o1.Equals(o2); resultMessage = createRetString(ret?true:false, marshaller, 0, 0); } else if (isMessage(":vector", message)) { //(:vector tref|"packageQualifiedTypeName" length value ...) { Type c = typeArg(message[1]); int length = intArg(message[2]); Object ret = reflector.createVector(c , length , message.GetRange(3, message.Count - 3) ); resultMessage = createRetString(ret, marshaller, IBaseMarshallerFlags.MARSHALL_ID, 0); } else if (isMessage(":vget", message)) //(:vget aref marshall-flags marshall-value-depth-limit index) { int marshallFlags = intArg(message[2]); int marshallDepth = intArg(message[3]); int index = intArg(message[4]); Object ret = reflector.vectorGet(message[1], index); resultMessage = createRetString(ret, marshaller, marshallFlags, marshallDepth); } else if (isMessage(":vset", message)) //(:vset aref index value) { int index = intArg(message[2]); reflector.vectorSet(message[1], index, message[3]); resultMessage = createRetString(null, marshaller, 0, 0); } //Eric - For .net indexers else if (isMessage(":iget", message)) //(:iget indexable-object-ref marshall-flags marshall-value-depth-limit indexes...) { int marshallFlags = intArg(message[2]); int marshallDepth = intArg(message[3]); Object ret = reflector.indexerGet(message[1], message.GetRange(4, message.Count - 4)); resultMessage = createRetString(ret, marshaller, marshallFlags, marshallDepth); } else if (isMessage(":iset", message)) //(:iset indexable-object-ref indexes... value) { reflector.indexerSet(message[1], message.GetRange(2, message.Count - 2)); resultMessage = createRetString(null, marshaller, 0, 0); } else if (isMessage(":vlen", message)) //(:vlen aref) { Object ret = reflector.vectorLength(message[1]); resultMessage = createRetString(ret, marshaller, 0, 0); } else if (isMessage(":bases", message)) //(:bases tref|"packageQualifiedTypeName") { Type c = typeArg(message[1]); StringWriter sw = new StringWriter(); sw.Write("(:ret"); marshaller.marshallAsList(reflector.bases(c), sw, IBaseMarshallerFlags.MARSHALL_ID, 1); sw.Write(')'); resultMessage = sw.ToString(); } else if (isMessage(":type-of", message)) //(:type-of ref) { Type c = message[1].GetType(); resultMessage = createRetString(c, marshaller, IBaseMarshallerFlags.MARSHALL_ID, 1); } else if (isMessage(":is-a", message)) //(:is-a ref tref|"packageQualifiedTypeName") { Object o = message[1]; Type c = typeArg(message[2]); resultMessage = createRetString(c.IsInstanceOfType(o)?true:false, marshaller, 0, 0); } else if (isMessage(":hash", message)) //(:hash refid) { resultMessage = createRetString(message[1].GetHashCode(), marshaller, 0, 0); } else if (isMessage(":members", message)) //(:members :tref|"packageQualifiedTypeName") { Type c = typeArg(message[1]); StringWriter sw = new StringWriter(); sw.Write("(:ret"); reflector.members(c, sw); sw.Write(')'); resultMessage = sw.ToString(); } else if (isMessage(":marshall", message)) //(:marshall ref marshall-flags marshall-value-depth-limit) { Object ret = message[1]; int marshallFlags = intArg(message[2]); int marshallDepth = intArg(message[3]); resultMessage = createRetString(ret, marshaller, marshallFlags, marshallDepth); } else if (isMessage(":proxy", message)) //(:proxy marshall-flags marshall-value-depth-limit interface-trefs ...) { int marshallFlags = intArg(message[1]); int marshallDepth = intArg(message[2]); resultMessage = createRetString(reflector.makeProxy(this, marshallFlags, marshallDepth , message.GetRange(3, message.Count - 3)) , marshaller, IBaseMarshallerFlags.MARSHALL_ID, 0); } else if (isMessage(":err", message)) //only on callback, note will break out of message loop { //there was an error on the Lisp side during a proxy callback //will turn into an exception below errorMesssage = (String)message[1]; } else if (isMessage(":cnames", message)) { StringWriter sw = new StringWriter(); sw.Write("(:ret"); marshaller.marshallAsList( reflector.getClassNames(message[1], message.GetRange(2, message.Count - 2)) , sw, IBaseMarshallerFlags.MARSHALL_ID, 1); sw.Write(')'); resultMessage = sw.ToString(); } else { throw new Exception("unsupported message"); } } catch (Exception ex) { if (ex is IOException) { throw (IOException)ex; } else if (ex is TargetInvocationException) { while (ex.InnerException != null && ex is TargetInvocationException) { ex = ex.InnerException; } } outs.Write("(:err"); StringBuilder sb = new StringBuilder(); sb.Append(ex.Message); Exception ie = ex.InnerException; while (ie != null) { sb.AppendFormat(" {0}", ie.Message); ie = ie.InnerException; } Console.WriteLine("Thread:{0} - Exception:{1}", Thread.CurrentThread.Name, sb.ToString()); marshaller.marshallAtom(sb.ToString(), outs, 0, 0); marshaller.marshallAtom(String.Format("{0}{1}", sb.ToString(), ex.StackTrace), outs, 0, 0); outs.Write(')'); outs.Write('\n'); outs.Flush(); } if (resultMessage != null) { outs.Write(resultMessage); outs.Write('\n'); outs.Flush(); } else if (errorMesssage != null) { //there was an error on the Lisp side during a proxy callback //throw an exception to the calling code throw new IOException(errorMesssage); } } } }