/*******************************************************************************
 * Copyright (c) 2001, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jem.internal.proxy.vm.remote;
/*


 */


import java.io.*;
import java.lang.reflect.Array;
import java.net.Socket;
import java.net.SocketException;
import java.util.*;

import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.remote.*;
import org.eclipse.jem.internal.proxy.initParser.*;
import org.eclipse.jem.internal.proxy.initParser.tree.NoExpressionValueException;

/**
 * This handles one connection.
 */

public class ConnectionHandler {	
		
	protected Socket socket;
	final protected RemoteVMServerThread server;
	final protected Thread connectionThread;
	protected DataInputStream in;
	protected DataOutputStream out;
	
	// Kludge: Bug in Linux 1.3.xxx of JVM. Closing a socket while the socket is being read/accept will not interrupt the
	// wait. Need to timeout to the socket read/accept before the socket close will be noticed. This has been fixed
	// in Linux 1.4. So on Linux 1.3 need to put timeouts in on those sockets that can be separately closed while reading/accepting.
	static boolean LINUX_1_3 = "linux".equalsIgnoreCase(System.getProperty("os.name")) && System.getProperty("java.version","").startsWith("1.3");	 //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
	
	/**
	 * This may be running as a callback, in that case there is no connectionThread.
	 */
	public ConnectionHandler(Socket sc, RemoteVMServerThread svr, Thread connectionThread) {
		socket = sc;
		server = svr;
		this.connectionThread = connectionThread;
		
		Integer bufSize = Integer.getInteger("proxyvm.bufsize"); //$NON-NLS-1$
		if (bufSize == null)
			bufSize = new Integer(5000);
			
		try {
			out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), bufSize.intValue()));
			in = new DataInputStream(new BufferedInputStream(socket.getInputStream(), bufSize.intValue()));
		} catch (IOException e) {
		}
			
	}
	
	/**
	 * Did this construct correctly.
	 * This is needed because an exception could be thrown in the ctor and
	 * that's not a good thing to do.
	 */
	public boolean isConnected() {
		return socket != null;
	}	
	
	/**
	 * Request the thread to close down.
	 */
	public void close() {
		if (socket != null) {
			try {
				Socket s = socket;
				socket = null;
				s.close();
			} catch (Exception e) {
			}
		}
	}
	
	// Map of ID to expression processers that are currently being processed.
	private Map expressionProcessors = new HashMap();
	
	/**
	 * Process and loop until told to stop. A callback_done will stop
	 * the loop and will return a result. Otherwise null is returned.
	 */
	public Object run() throws CommandException {
		Object result = null;		
		boolean shutdown = false;
		boolean closeWhenDone = true;
		Commands.ValueObject valueObject = new Commands.ValueObject();	// Working value object so not continually recreated.
		InvokableValueSender valueSender = new InvokableValueSender();	// Working valuesender so not continually recreated. 
		try {
			boolean doLoop = true;

			/**
			 * Note: In the cases below you will see a lot of finally clauses that null variables out.
			 * This is because this is a long running loop, and variables declared within blocks are not
			 * garbage collected until the method is terminated, so these variables once set would never
			 * be GC'd. The nulling at the end of the case makes sure that any of those objects set are
			 * now available for garbage collection when necessary.
			 */		
			while(doLoop && isConnected()) {
				byte cmd = 0;
				try {
					if (LINUX_1_3)
						socket.setSoTimeout(1000);	// Linux 1.3 bug, see comment on LINUX_1_3
					cmd = in.readByte();
					if (LINUX_1_3 && isConnected())
						socket.setSoTimeout(0);	// Linux 1.3 bug, see comment on LINUX_1_3
				} catch (InterruptedIOException e) {
					continue;	// Timeout, try again
				}
				switch (cmd) {
					case Commands.QUIT_CONNECTION:				
						doLoop = false;	
						break;	// Close this connection
						
					case Commands.TERMINATE_SERVER:
						doLoop = false;		
						shutdown = true;	// Shutdown everything
						break;
						
					case Commands.GET_CLASS:
						String className = in.readUTF();
						Class aClass = null;
						Class superClass = null;
						String superClassName = null;
						boolean added = false;
						try {
							aClass = Class.forName(className);	// Turns out using JNI format for array type will work fine.
								
							added = server.getIdentityID(aClass, valueObject);
							boolean isInterface = aClass.isInterface();
							boolean isAbstract = java.lang.reflect.Modifier.isAbstract(aClass.getModifiers());
							superClass = aClass.getSuperclass();
							superClassName = (superClass != null) ? superClass.getName() : ""; //$NON-NLS-1$
							out.writeByte(Commands.GET_CLASS_RETURN);
							out.writeInt(valueObject.objectID);
							out.writeBoolean(isInterface);
							out.writeBoolean(isAbstract);
							out.writeUTF(superClassName);
							out.flush();
						} catch (ClassNotFoundException e) {
							valueObject.set();
							Commands.sendErrorCommand(out, Commands.GET_CLASS_NOT_FOUND, valueObject);						
						} catch (ExceptionInInitializerError e) {
							sendException(e.getException(), valueObject, out);								
						} catch (LinkageError e) {
							sendException(e, valueObject, out);								
						} catch (Throwable e) {
							// Something bad, did we add a class? If we did remove it from the table.
							if (added)
								server.removeObject(server.getObject(valueObject.objectID));
							throw e;
						} finally {
							// clear out for GC to work.
							className = null;
							aClass = null;
							superClass = null;
							superClassName = null;
							valueObject.set();
						}
						break;
						
					case Commands.GET_CLASS_FROM_ID:
						int classID = in.readInt();
						try {
							aClass = (Class) server.getObject(classID);
							boolean isInterface = aClass.isInterface();
							boolean isAbstract = java.lang.reflect.Modifier.isAbstract(aClass.getModifiers());							
							superClass = aClass.getSuperclass();
							superClassName = (superClass != null) ? superClass.getName() : ""; //$NON-NLS-1$
							out.writeByte(Commands.GET_CLASS_ID_RETURN);
							out.writeUTF(aClass.getName());
							out.writeBoolean(isInterface);
							out.writeBoolean(isAbstract);
							out.writeUTF(superClassName);
							out.flush();
						} catch (ClassCastException e) {
							valueObject.set();
							Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject);
						} finally {	
							// clear out for GC to work.
							aClass = null;
							superClass = null;
							superClassName = null;
							valueObject.set();							
						}
						break;

					case Commands.GET_OBJECT_DATA:
						int objectID = in.readInt();
						Object anObject = null;
						try {
							anObject = server.getObject(objectID);
							valueObject.setObjectID(objectID, server.getIdentityID(anObject.getClass()));
							Commands.writeValue(out, valueObject, true);
						} catch (ClassCastException e) {
							valueObject.set();
							Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject);
						} finally {
							anObject = null;	// Clear out for GC to work
							valueObject.set();							
						}
						break;												
						
					case Commands.RELEASE_OBJECT:
						int id = in.readInt();
						server.removeObject(server.getObject(id));
						break;						

					case Commands.NEW_INIT_STRING:
						classID = in.readInt();	// ID Of class to do new upon.
						String initString = in.readUTF();	// The init string.
						Object newValue = null;
						Class theClass = null;
						try {
							theClass = (Class) server.getObject(classID);
							if (theClass == null) {
								// The class wasn't found. So imply ClassNotFound exception.
								throw new ClassNotFoundException();
							}
							
							InitializationStringParser parser = null;
							try {
								parser = InitializationStringParser.createParser(initString);
								newValue = parser.evaluate();								
								boolean primitive = parser.isPrimitive();
								// If expected class is Void.TYPE, that means don't test the type of the result
								// to verify if correct type, just return what it really is.
								if (theClass != Void.TYPE && primitive != theClass.isPrimitive()) {
									valueObject.set();
									Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject);
									continue;	// Goto next command.
								} 
								if (primitive) {
									try {
										// Need to do special tests for compatibility and assignment.
										sendObject(newValue, classID != Commands.VOID_TYPE ? classID : server.getIdentityID(parser.getExpectedType()), valueObject, out, true);	// This will make sure it goes out as the correct primitive type
									} catch (ClassCastException e) {
										// The returned type is not of the correct type for what is expected.
										valueObject.set();
										Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject);
										continue;	// Goto next command
									}									
								} else {
									if (newValue != null) {
										// Test to see if they are compatible. (Null can be assigned to any object,
										// so that is why it was tested out above).
										// If expected class is Void.TYPE, that means don't test the type of the result
										// to verify if correct type, just return what it really is.
										if (theClass != Void.TYPE && !theClass.isInstance(newValue)) {
											// The returned type is not of the correct type for what is expected.
											valueObject.set();
											Commands.sendErrorCommand(out, Commands.CLASS_CAST_EXCEPTION, valueObject);
											continue;	// Goto next command
										}
									}
									sendObject(newValue, NOT_A_PRIMITIVE, valueObject, out, true);	// Send out as an object.
								}
							} catch (InitializationStringEvaluationException e) {
								if (e instanceof EvaluationException) {
									// Want to return the real exception.
									sendException(e.getOriginalException(), valueObject, out);
								} else {
									// Couldn't be evaluated, return an error for this.
									setExceptionIntoValue(e.getOriginalException(), valueObject);
									Commands.sendErrorCommand(out, Commands.CANNOT_EVALUATE_STRING, valueObject);
								}
							} finally {
								parser = null;	// Clear out for GC to work
							}									
						} catch (Throwable e) {
							sendException(e, valueObject, out);
						} finally {
							// Clear out for GC to work
							initString = null;
							theClass = null;
							newValue = null;
							valueObject.set();							
						}	
						break;						
												
					case Commands.INVOKE:
						Object target = null;
						Object[] parms = null;						
						Class returnType = null;
						java.lang.reflect.Method aMethod = null;						
						try {					
							int methodID = in.readInt();	// ID of method to invoke
							aMethod = (java.lang.reflect.Method) server.getObject(methodID);	// Method to invoke
							Commands.readValue(in, valueObject);
							target = getInvokableObject(valueObject);	
							Commands.readValue(in, valueObject);
							if (valueObject.type == Commands.ARRAY_IDS) {
								// It is an array containing IDs, as it normally would be.
								valueSender.initialize(valueObject);
								Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
								parms = (Object[]) valueSender.getArray();
							} else {
								// It is all objects or null, so it should be an Object[] or null. If not, then this is an error.
								parms = (Object[]) valueObject.anObject;
							}
							
							if (!aMethod.isAccessible())
								aMethod.setAccessible(true);	// We will allow all to occur. Let access control be handled by IDE and compiler.
							newValue = aMethod.invoke(target, parms);
							returnType = aMethod.getReturnType();
							if (returnType.isPrimitive()) {
								int returnTypeID = server.getIdentityID(returnType);
								// Need to tell sendObject the correct primitive type.
								sendObject(newValue, returnTypeID, valueObject, out, true);
				
							} else {
								sendObject(newValue, NOT_A_PRIMITIVE, valueObject, out, true);	// Just send the object back. sendObject knows how to iterpret the type
							}									
						} catch (CommandException e) {
							throw e;	// Throw it again. These we don't want to come up as an exception proxy. These should end the thread.
						} catch (java.lang.reflect.InvocationTargetException e) {
							// This is a wrappered exception. Return the wrappered one so it looks like
							// it was the real one. (Sometimes the method being invoked is on a java.lang.reflect.Constructor.newInstance,
							// which in turn is an InvocationTargetException, so we will go until we don't have an InvocationTargetException.
							Throwable t = e;
							do {
								t = ((java.lang.reflect.InvocationTargetException) t).getTargetException();
							} while (t instanceof java.lang.reflect.InvocationTargetException);
							sendException(t, valueObject, out);
						} catch (Throwable e) {
							sendException(e, valueObject, out);	// Turn it into a exception proxy on the client.
						} finally {
							// Clear out for GC to work
							valueObject.set();
							parms = null;
							target = null;
							aMethod = null;
							returnType = null;
							newValue = null;
							valueSender.clear();
						}					
						break;
						
					case Commands.INVOKE_WITH_METHOD_PASSED:
						aClass = null;
						String methodName = null;
						Class[] parmTypes = null;
						target = null;
						parms = null;						
						returnType = null;
						aMethod = null;						
						
						try {
							Commands.readValue(in, valueObject);
							aClass = (Class) getInvokableObject(valueObject); // The class that has the method.
							methodName = in.readUTF();
							Commands.readValue(in, valueObject);
							if (valueObject.type == Commands.ARRAY_IDS) {
								// It is an array containing IDs, as it normally would be.
								valueSender.initialize(valueObject);
								Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
								parmTypes = (Class[]) valueSender.getArray();
							} else {
								// It null, so it should be an null. If not, then this is an error.
								parmTypes = null;
							}
							aMethod = aClass.getMethod(methodName, parmTypes);

							// Now we get the info for the invocation of the method and execute it.
							Commands.readValue(in, valueObject);
							target = getInvokableObject(valueObject);	
							Commands.readValue(in, valueObject);
							if (valueObject.type == Commands.ARRAY_IDS) {
								// It is an array containing IDs, as it normally would be.
								valueSender.initialize(valueObject);
								Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
								parms = (Object[]) valueSender.getArray();
							} else {
								// It is all objects or null, so it should be an Object[] or null. If not, then this is an error.
								parms = (Object[]) valueObject.anObject;
							}
							
							if (!aMethod.isAccessible())
								aMethod.setAccessible(true);	// We will allow all to occur. Let access control be handled by IDE and compiler.
							newValue = aMethod.invoke(target, parms);
							returnType = aMethod.getReturnType();
							if (returnType.isPrimitive()) {
								int returnTypeID = server.getIdentityID(returnType);
								// Need to tell sendObject the correct primitive type.
								sendObject(newValue, returnTypeID, valueObject, out, true);
				
							} else {
								sendObject(newValue, NOT_A_PRIMITIVE, valueObject, out, true);	// Just send the object back. sendObject knows how to iterpret the type
							}									
						} catch (CommandException e) {
							throw e;	// Throw it again. These we don't want to come up as an exception proxy. These should end the thread.
						} catch (java.lang.reflect.InvocationTargetException e) {
							// This is a wrappered exception. Return the wrappered one so it looks like
							// it was the real one. (Sometimes the method being invoked is on a java.lang.reflect.Constructor.newInstance,
							// which in turn is an InvocationTargetException, so we will go until we don't have an InvocationTargetException.
							Throwable t = e;
							do {
								t = ((java.lang.reflect.InvocationTargetException) t).getTargetException();
							} while (t instanceof java.lang.reflect.InvocationTargetException);
							sendException(t, valueObject, out);

						} catch (Throwable e) {
								sendException(e, valueObject, out);	// Turn it into a exception proxy on the client.
						} finally {
							aClass = null;
							methodName = null;
							parmTypes = null;
							// Clear out for GC to work
							valueObject.set();
							parms = null;
							target = null;
							aMethod = null;
							returnType = null;
							newValue = null;
							valueSender.clear();							
						}
						break;
						
					case Commands.GET_ARRAY_CONTENTS:
						try {
							target = server.getObject(in.readInt());	// Array to get the ids for.
							valueObject.setArrayIDS(new ArrayContentsRetriever(target), Array.getLength(target), Commands.OBJECT_CLASS);
							Commands.writeValue(out, valueObject, true);	// Write it back as a value command.
						} catch (CommandException e) {
							throw e;	// Throw it again. These we don't want to come up as an exception proxy. These should end the thread.
						} catch (Throwable e) {
							sendException(e, valueObject, out);	// Turn it into a exception proxy on the client.
						} finally {
							target = null;
							valueObject.set();
						}
						break;
						
					case Commands.CALLBACK_DONE:
						try {
							if (connectionThread != null) {
								valueObject.set();
								Commands.sendErrorCommand(out, Commands.UNKNOWN_COMMAND_SENT, valueObject);
							} else {
								try {
									Commands.readBackValue(in, valueObject, Commands.NO_TYPE_CHECK);
									if (valueObject.type == Commands.ARRAY_IDS) {
										// It is an array containing IDs, as it normally would be.
										valueSender.initialize(valueObject);
										Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
										result = valueSender.getArray();
									} else {
										result = getInvokableObject(valueObject);
									}
									doLoop = false; // We need to terminate and return result
									closeWhenDone = false; // Don't close, we will continue.
								} catch (CommandErrorException e) {
									// There was an command error on the other side. This means 
									// connection still good, but don't continue the callback processing.
									doLoop = false; // We need to terminate and return result
									closeWhenDone = false; // Don't close, we will continue.
									throw e;	// Let it go on out.
								}
							}
						} finally {
							valueObject.set();
							valueSender.clear();
						}
						break;
						
					case Commands.ERROR:
						try {
							// Got an error command. Don't know what to do but read the
							// value and simply print it out.
							Commands.readValue(in, valueObject);
							result = getInvokableObject(valueObject);
							System.out.println("Error sent to server: Result=" + result); //$NON-NLS-1$
						} finally {
							valueObject.set();
						}
						break;
					
					case Commands.EXPRESSION_TREE_COMMAND:
						try {
							processExpressionCommand(valueObject, valueSender);
						} finally {
							valueObject.set();
							valueSender.clear();
						}
						break;
						
					default:
						// Unknown command. We don't know how long it is, so we need to shut the connection down.
						System.err.println("Error: Invalid cmd send to server: Cmd=" + cmd); //$NON-NLS-1$
						doLoop = false;
						closeWhenDone = true;
						break;
				}
			}
		} catch (EOFException e) {
			// This is ok. It means that the connection on the other side was terminated.
			// So just accept this and go down.
		} catch (CommandException e) {
			throw e;
		} catch (SocketException e) {
			if (socket != null)
				throw new UnexpectedExceptionCommandException(false, e);	// socket null means a valid close request
		} catch (Throwable e) {
			e.printStackTrace();
		} finally {
			if (closeWhenDone) {
				try {
					for (Iterator itr = expressionProcessors.values().iterator(); itr.hasNext();) {
						ExpressionProcesserController exp = (ExpressionProcesserController) itr.next();
						exp.close();
					}
				} finally {
					expressionProcessors.clear();
				}

				if (in != null)
					try {
						in.close();
					} catch (Exception e) {
					}
				in = null;
				if (out != null)
					try {
						out.close();
					} catch (Exception e) {
					}
				out = null;
				close();
			}
		}
		
		if (closeWhenDone && connectionThread != null)
			server.removeConnectionThread(connectionThread);
		if (shutdown)
			server.requestShutdown();
			
		return result;
	}
	
	// A retriever is what handles the array get contents.
	private class ArrayContentsRetriever implements Commands.ValueRetrieve {
		int index=0;
		Object array;
		int length;
		int componentType;
		Commands.ValueObject worker = new Commands.ValueObject();
		
		
		public ArrayContentsRetriever(Object anArray) {
			array = anArray;
			length = Array.getLength(anArray);
			if (anArray.getClass().getComponentType().isPrimitive()) {
				componentType = server.getIdentityID(anArray.getClass().getComponentType());
			} else
				componentType = NOT_A_PRIMITIVE;
		}
		
		public Commands.ValueObject nextValue() {
			fillInValue(Array.get(array, index++), componentType, worker);
			return worker;
		}
	};

	
	private void processExpressionCommand(Commands.ValueObject valueObject, InvokableValueSender valueSender) throws IOException, CommandException {
		Integer expressionID = new Integer(in.readInt());
		byte cmdType = in.readByte();
		ExpressionProcesserController exp = null;
		switch (cmdType) {
			case ExpressionCommands.START_EXPRESSION_TREE_PROCESSING:
				byte trace = in.readByte();
				if (trace == ExpressionCommands.TRACE_DEFAULT)
					exp = new ExpressionProcesserController(server, this);
				else
					exp = new ExpressionProcesserController(server, this, trace == ExpressionCommands.TRACE_ON);
				expressionProcessors.put(expressionID, exp);
				break;
			case ExpressionCommands.TRANSFER_EXPRESSION_REQUEST:
				exp = (ExpressionProcesserController) expressionProcessors.remove(expressionID); 
				sendObject(exp, NOT_A_PRIMITIVE, valueObject, out, true);
				break;
			case ExpressionCommands.RESUME_EXPRESSION_REQUEST:
				Commands.readValue(in, valueObject);
				exp = (ExpressionProcesserController) getInvokableObject(valueObject); 
				expressionProcessors.put(expressionID, exp);
				break;
			case ExpressionCommands.PUSH_EXPRESSION:
				exp = (ExpressionProcesserController) expressionProcessors.get(expressionID);
				exp.process(in);
				break;
			case ExpressionCommands.SYNC_REQUEST:
				boolean haveProxies = in.readBoolean();	// See if we expression proxy ids that need to be resolved 
				if (haveProxies) {
					Commands.readValue(in, valueObject);
					valueSender.initialize(valueObject);
					Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
				}

				exp = (ExpressionProcesserController) expressionProcessors.get(expressionID);
				if (haveProxies)
					sendExpressionProxyResolutions(valueObject, (int[]) valueSender.getArray(), exp);
				if (exp.noErrors()) {
					valueObject.set(true); // Mark that all is good.
					Commands.writeValue(out, valueObject, true, true);
				} else {
					processExpressionError(exp, valueObject);
				}
				break;
			case ExpressionCommands.PULL_VALUE_REQUEST:
				haveProxies = in.readBoolean();	// See if we expression proxy ids that need to be resolved
				if (haveProxies) {
					Commands.readValue(in, valueObject);
					valueSender.initialize(valueObject);
					Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
				}

				exp = (ExpressionProcesserController) expressionProcessors.get(expressionID);
				if (haveProxies)
					sendExpressionProxyResolutions(valueObject, (int[]) valueSender.getArray(), exp);
				if (exp.noErrors()) {
					try {
						Object[] pulledValue = exp.pullValue();
						// Send back the command code for pull value. Don't flush. We will flush when all done.
						if (((Class) pulledValue[1]).isPrimitive()) {
							int returnTypeID = server.getIdentityID(pulledValue[1]);
							// Need to tell sendObject the correct primitive type.
							sendObject(pulledValue[0], returnTypeID, valueObject, out, true, true);
							
						} else {
							sendObject(pulledValue[0], NOT_A_PRIMITIVE, valueObject, out, true, true);	// Just send the object back. sendObject knows how to iterpret the type
						}
					} catch (NoExpressionValueException e) {
						sendNoValueErrorCommand(exp, valueObject);
					}
				} else 
					processExpressionError(exp, valueObject);
				break;
			case ExpressionCommands.END_EXPRESSION_TREE_PROCESSING:
				exp = (ExpressionProcesserController) expressionProcessors.remove(expressionID);
				exp.close();
				break;
		}
	}

	/*
	 * @param is
	 * @param exp
	 * 
	 * @since 1.1.0
	 */
	private void sendExpressionProxyResolutions(Commands.ValueObject valueObject, final int[] proxyIDs, final ExpressionProcesserController exp) throws CommandException {
		class ExpressionProxyRetriever implements Commands.ValueRetrieve {
			int index = 0;
			Object[] proxyResolution = new Object[2];
			Commands.ValueObject worker = new Commands.ValueObject();

			public Commands.ValueObject nextValue() {
				int proxyID = proxyIDs[index++];
				if (exp.pullExpressionProxyValue(proxyID, proxyResolution)) {
					if (proxyResolution[1] != Void.TYPE) {
						if (((Class) proxyResolution[1]).isPrimitive()) {
							int returnTypeID = server.getIdentityID(proxyResolution[1]);
							// Need to tell worker the correct primitive type.
							fillInValue(proxyResolution[0], returnTypeID, worker);
						} else {
							fillInValue(proxyResolution[0], NOT_A_PRIMITIVE, worker);
						}
					} else
						worker.setFlag(ExpressionCommands.EXPRESSIONPROXY_VOIDTYPE);	// It was resolved, but to not set due to void type of expression.
				} else
					worker.setFlag(ExpressionCommands.EXPRESSIONPROXY_NOTRESOLVED);	// It wasn't resolved.
				
				return worker;
			}
		};

		valueObject.setArrayIDS(new ExpressionProxyRetriever(), proxyIDs.length, Commands.OBJECT_CLASS);
		Commands.writeValue(out, valueObject, true, false);	// Write it back as a value command.

	}

	private void processExpressionError(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException {
		if (exp.isNoExpressionValue()) {
			sendNoValueErrorCommand(exp, valueObject);
		} else
			sendException(exp.getErrorThrowable(), valueObject, out);
	}

	/*
	 * @param exp
	 * @param valueObject
	 * @throws CommandException
	 * 
	 * @since 1.1.0
	 */
	private void sendNoValueErrorCommand(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException {
		setExceptionIntoValue(exp.getErrorThrowable(), valueObject);
		Commands.sendErrorCommand(out, ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION, valueObject);
	}

protected static final int NOT_A_PRIMITIVE = Commands.NOT_AN_ID;
protected static final int SEND_AS_IS = -2;	// This means sends as an object not as an id.
	
public static final int CLASS_ADDED = 1;
public static final int OBJECT_ADDED = 2;
public int fillInValue(Object object, int primitiveTypeID, Commands.ValueObject valueObject) {
	int added = 0;
	if (object == null) {
		valueObject.set();
	} else {
		int classID = 0;
		if (primitiveTypeID != NOT_A_PRIMITIVE && primitiveTypeID != SEND_AS_IS) {
			classID = primitiveTypeID;	// The object is really supposed to be a primitive of this type
			switch (classID) {
				case Commands.BOOLEAN_TYPE:
					valueObject.set(((Boolean) object).booleanValue());
					break;
				case Commands.INTEGER_TYPE:
					if (object instanceof Character)
						valueObject.set((int) ((Character) object).charValue());	// Because char can be widened to an int
					else
						valueObject.set(((Number) object).intValue());					
					break;
				case Commands.BYTE_TYPE:
					valueObject.set(((Number) object).byteValue());
					break;
				case Commands.CHARACTER_TYPE:
					valueObject.set(((Character) object).charValue());
					break;
				case Commands.DOUBLE_TYPE:
					if (object instanceof Character)
						valueObject.set((double) ((Character) object).charValue());	// Because char can be widened to a double
					else
						valueObject.set(((Number) object).doubleValue());					
					break;
				case Commands.FLOAT_TYPE:
					if (object instanceof Character)
						valueObject.set((float) ((Character) object).charValue());	// Because char can be widened to a float
					else
						valueObject.set(((Number) object).floatValue());					
					break;
				case Commands.SHORT_TYPE:
					valueObject.set(((Number) object).shortValue());
					break;
				case Commands.LONG_TYPE:
					if (object instanceof Character)
						valueObject.set((long) ((Character) object).charValue());	// Because char can be widened to a long
					else
						valueObject.set(((Number) object).longValue());					
					break;
			}
		} else {
			// It's not a primitive.
			boolean addObject = false, addClass = false;			
			Class objClass = object.getClass();
			classID = server.getIdentityID(objClass);
			if (classID == RemoteVMServerThread.ID_NOT_FOUND) {
				Commands.ValueObject classValue = new Commands.ValueObject();
				addClass = server.getIdentityID(objClass, classValue);
				if (addClass)
					added |= CLASS_ADDED;
				classID = classValue.objectID;
			}
		
			switch (classID) {
				case Commands.BYTE_CLASS:
					valueObject.set((Byte) object);
					break;
				case Commands.CHARACTER_CLASS:
					valueObject.set((Character) object);
					break;
				case Commands.DOUBLE_CLASS:
					valueObject.set((Double) object);
					break;
				case Commands.FLOAT_CLASS:
					valueObject.set((Float) object);
					break;
				case Commands.INTEGER_CLASS:
					valueObject.set((Integer) object);
					break;
				case Commands.LONG_CLASS:
					valueObject.set((Long) object);
					break;
				case Commands.SHORT_CLASS:
					valueObject.set((Short) object);
					break;
				case Commands.BOOLEAN_CLASS:
					valueObject.set((Boolean) object);
					break;
				case Commands.STRING_CLASS:
					valueObject.set((String) object);
					break;
				case Commands.BIG_DECIMAL_CLASS:
					valueObject.set(object, Commands.BIG_DECIMAL_CLASS);
					break;
				case Commands.BIG_INTEGER_CLASS:
					valueObject.set(object, Commands.BIG_INTEGER_CLASS);
					break;
				default:
					if (primitiveTypeID != SEND_AS_IS) {
						addObject = server.getIdentityID(object, valueObject);
						if (addObject) {
							added |= OBJECT_ADDED;			
							valueObject.setObjectID(valueObject.objectID, classID);
						} else
							valueObject.setObjectID(valueObject.objectID);
					} else
						valueObject.set(object, classID);
					break;
			}
		}
	}
	
	return added;
}

public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand) throws CommandException {
	sendObject(object, primitiveTypeID, valueObject, out, writeAsCommand, writeAsCommand);
}
public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand, boolean flush) throws CommandException {			
	int added = fillInValue(object, primitiveTypeID, valueObject);
	boolean sent = false;
	try {
		Commands.writeValue(out, valueObject, writeAsCommand, flush);	// Write it back as a value command.
		sent = true;
	} finally {
		if (!sent) {
			// Ending due to some problem, so clean up any added objects from the id table.
			if ((added & OBJECT_ADDED) != 0)
				server.removeObject(valueObject.objectID);
			if ((added & CLASS_ADDED) != 0)
				server.removeObject(valueObject.classID);
		}
	}
}
		
	
	public void sendException(Throwable e, Commands.ValueObject value, DataOutputStream out) throws CommandException {
		// Exception ocurred, return a value command with the exception within it.
		setExceptionIntoValue(e, value);
		Commands.sendErrorCommand(out, Commands.THROWABLE_SENT, value);		
	}

	public void setExceptionIntoValue(Throwable e, Commands.ValueObject value) {		
		server.getIdentityID(e, value);	// It should always create it so we don't need to know.
		int eID = value.objectID;
		Class eClass = e.getClass();							
		server.getIdentityID(eClass, value);
		int eClassID = value.objectID;
		value.setException(eID, eClassID);
	}
	
	/**
	 * From the valueObject, get an Object that is invokable (i.e. can be the target of an invoke, or one of its parms).
	 * If it is an array type, the a ValueSender is returned. The invoker needs to then cast this
	 * to a ValueSender and call the readArray routine.
	 */
	public Object getInvokableObject(final Commands.ValueObject value) {
		switch (value.type) {
			case Commands.NEW_OBJECT_ID:
			case Commands.OBJECT_ID:
				// These need to have access to the server to get the real object
				return server.getObject(value.objectID);						
			default:
				// These have all the info needed within the value object itself, so ask it.
				return value.getAsObject();
		}
	}
	
	// Helper class for getting an array.
	private class InvokableValueSender implements Commands.ValueSender {
		int index = 0;
		Object array;

		public InvokableValueSender() {
		}
				
		public InvokableValueSender(Commands.ValueObject arrayHeader) {
			initialize(arrayHeader);
		}
		
		public void initialize(Commands.ValueObject arrayHeader) {
			index = 0;
			Class arrayType = (Class) server.getObject(arrayHeader.classID);
			array = java.lang.reflect.Array.newInstance(arrayType, arrayHeader.anInt);
		}
		
		public void clear() {
			array = null;
			index = 0;
		}
		
		public Object getArray() {
			return array;
		}
					
		// A new value is being sent to the array
		public void sendValue(Commands.ValueObject value) {
			java.lang.reflect.Array.set(array, index++, getInvokableObject(value));	// add it to the array
		}
					
		// The next entry is an array too!
		public Commands.ValueSender nestedArray(Commands.ValueObject arrayHeader) {
			InvokableValueSender sender = new InvokableValueSender(arrayHeader);
			// Take the newly created array and put it into the current array.
			java.lang.reflect.Array.set(array, index++, sender.getArray());
			return sender;
		}
	}

}


