/*******************************************************************************
 * 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;
/*
 *  $RCSfile: ConnectionHandler.java,v $
 *  $Revision: 1.15 $  $Date: 2005/08/24 20:39:08 $ 
 */


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 = (Object[]) 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;
		}
	}

}


