/*******************************************************************************
 * Copyright (c) 2004 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
 *******************************************************************************/
/*
 *  $RCSfile: REMExpression.java,v $
 *  $Revision: 1.17 $  $Date: 2005/06/22 21:05:17 $ 
 */
package org.eclipse.jem.internal.proxy.remote;

import java.io.*;
import java.util.*;
import java.util.logging.Level;

import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.remote.*;
import org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.initParser.tree.*;
 
/**
 * The Remote proxy version of Expression.
 * 
 * @since 1.0.0
 */
public class REMExpression extends Expression {

	private IREMExpressionConnection connection;
	private boolean closed;	// Are we closed.
	
	protected Commands.ValueObject workerValue;	// A worker object so that we don't need to keep creating one and throwing it away.
	
	protected Map beanTypeCache;	// Use to cache pending BeanTypes. Used in conjunction with REMStandardBeanTypeFactory.
	protected Map methodsCache;	// Use to cache pending expression method proxies. Used in conjunction with REMProxyConsants.
	protected Map fieldsCache;	// Use to cache pending expression field proxies. Used in conjunction with REMProxyConsants.
	
	/*
	 * This is very special list. It tries to eliminate unneeded traffic. For example a mark immediately followed by an endmark does
	 * not need to be sent. Many expressions can look like: mark, endmark, endtransaction. This is a do nothing and we don't want
	 * to create a connection to just send this. So this list is used to queue up these and remove them too when found as not needed.
	 * 
	 *  However, this is very tricky because all pushToProxy transactions that actually do something MUST call the processPending() method 
	 *  first to make sure any pending transactions are submitted. Because once a real type transaction, such as assignment occurs, any
	 *  pending transaction is a valid transaction, and no longer a do-nothing transaction.
	 *  
	 *  Each transaction type uses a subclass of PendingTransaction to be an entry on the list.
	 *  
	 *  The pendings currently supported are:
	 *  mark/endmark
	 *  try/catch/endtry
	 *  block/endblock
	 *  
	 *  See each individual transaction type to see how it is handled.
	 */
	protected List pendingTransactions;
	
	/**
	 * PendingTransaction entry.
	 * 
	 * @since 1.1.0
	 */
	protected abstract static class PendingTransaction {
		
		/**
		 * The transaction is now being pushed. The implementation should
		 * actually do the push.
		 * 
		 * @param remExpression The REMExpression for this transaction.
		 * 
		 * @since 1.1.0
		 */
		public abstract void pushTransaction(REMExpression remExpression);
	}
	
	/**
	 * @param registry
	 * 
	 * @since 1.0.0
	 */
	public REMExpression(REMProxyFactoryRegistry registry) {
		super(registry);
	}
	
	/**
	 * Return the expression id for this REMExpression. This id is used on the remote vm to
	 * identify who the request is for.
	 * @return
	 * 
	 * @since 1.1.0
	 */
	protected int getREMExpressionID() {
		return this.hashCode();
	}
	/**
	 * Get the pending transactions list.
	 * @return
	 * 
	 * @since 1.1.0
	 */
	protected List getPendingTransactions() {
		if (pendingTransactions == null)
			pendingTransactions = new ArrayList();
		return pendingTransactions;
	}
	
	// Use this flag when debugging to test if errors are due to improper pending processing.
	// If true they will be treated as if not pending and will be executed immediately.
	private static final boolean EXECUTE_PENDING_IMMEDIATELY = false;
	protected void addPendingTransaction(PendingTransaction pending) {
		if (!EXECUTE_PENDING_IMMEDIATELY)
			getPendingTransactions().add(pending);
		else
			pending.pushTransaction(this);
	}

	private boolean sentData;	// Flag to indicate if we have sent anything yet to the remote vm. This is used for the pending optimizations.
	
	/**
	 * Have we sent any data in this transaction yet.
	 * @return
	 * 
	 * @since 1.1.0
	 */
	protected boolean haveSentData() {
		return sentData;
	}
	
	/**
	 * @return Returns the connection.
	 * 
	 * @since 1.1.0
	 */
	protected IREMExpressionConnection getConnection() {
		if (connection == null) {
			if (!sentData)
				getREMBeanProxyFactory().startTransaction();	// This is the first time we send data, so start transaction.
			
			sentData = true;	// If we are getting a transaction, that means we are sending data.
			connection = (IREMExpressionConnection) getREMRegistry().getFreeConnection();
			// This will actually not be stopped until closeproxy. There could be a slight problem if the expression is never closed.
			// But that shouldn't happen. This is to prevent any proxy that was released during the execution but was used by
			// the expression from being released on the remote vm until after the expression is finished.
			try {
				if (workerValue == null)
					workerValue = new Commands.ValueObject();
				if (expressionProcesserController == null) {
					byte trace = !isTraceSet() ? ExpressionCommands.TRACE_DEFAULT : (isTrace() ? ExpressionCommands.TRACE_ON : ExpressionCommands.TRACE_OFF); 
					connection.startExpressionProcessing(getREMExpressionID(), trace);	// It is a new expression.
				} else {
					fillProxy(expressionProcesserController, workerValue);
					connection.resumeExpression(getREMExpressionID(), workerValue);
					expressionProcesserController = null;
				}
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				throwIllegalStateException(IO_EXCEPTION_MSG);
			} catch (CommandException e) {
				ProxyPlugin.getPlugin().getLogger().log(e);
				if (!e.isRecoverable()) {
					connection.close();
					connection = null;
				}
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}	
		}
		return connection;
	}

	/**
	 * General IOException occurred msg.
	 */
	protected static final String IO_EXCEPTION_MSG = ProxyRemoteMessages.REMExpression_IOExceptionSeeLog_INFO_; 
	
	protected static final String COMMAND_EXCEPTION_MSG = ProxyRemoteMessages.REMExpression_CommandExceptionSeeLog_INFO_; 
	
	/**
	 * Throw an an illegal state exception if some general error, in particular an I/O or Command Exception
	 * occurred so that callers know there is something wrong.
	 * 
	 * @param msg
	 * @throws IllegalStateException
	 * 
	 * @since 1.0.0
	 */
	protected void throwIllegalStateException(String msg) throws IllegalStateException {
		throw new IllegalStateException(msg);
	}
	
	/**
	 * Return the registry as a REMProxyFactoryRegistry
	 * @return
	 * 
	 * @since 1.0.0
	 */
	protected final REMProxyFactoryRegistry getREMRegistry() {
		return (REMProxyFactoryRegistry) registry;
	}
	
	/**
	 * Return the bean proxy factory as a REMStandardBeanProxyFactory.
	 * @return
	 * 
	 * @since 1.0.0
	 */
	protected final REMStandardBeanProxyFactory getREMBeanProxyFactory() {
		return (REMStandardBeanProxyFactory) beanProxyFactory;
	}

	/**
	 * Process any pending transactions.
	 * <p>
	 * <b>Note: </b>It is required that all non-pending-participating transactions must
	 * call this method first to make sure pending transactions are sent. If this is
	 * not done, there will be errors in the expression.
	 * 
	 * 
	 * @since 1.1.0
	 */
	protected void processPendingTransactions() {
		if (pendingTransactions != null && !pendingTransactions.isEmpty()) {
			try {
				for (int i = 0; i < pendingTransactions.size(); i++) {
					((PendingTransaction) pendingTransactions.get(i)).pushTransaction(this);
				}
			} finally {
				pendingTransactions.clear();
			}
		}
	}
	
	/**
	 * Get the pending entry from top. If top is 1, then get top entry (i.e. last one added), 2 is next one. 
	 * @param fromTop
	 * @return entry requested, or <code>null</code> if no such entry.
	 * 
	 * @since 1.1.0
	 */
	protected PendingTransaction getPendingEntryFromTop(int fromTop) {
		if (pendingTransactions != null && pendingTransactions.size() >= fromTop) {
			return (PendingTransaction) pendingTransactions.get(pendingTransactions.size()-fromTop);
		} else
			return null;
	}
	
	/**
	 * Pop up the top entry from the pending transactions queue.
	 * @param fromTop how many entries to pop from the pending transaction list.
	 * 
	 * 
	 * @since 1.1.0
	 */
	protected void popPendingEntry(int fromTop) {
		if (pendingTransactions != null)
			if (pendingTransactions.size() > fromTop) {
				while(fromTop-- >0)
					pendingTransactions.remove(pendingTransactions.size()-1);
			} else
				pendingTransactions.clear();
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushToProxy(org.eclipse.jem.internal.proxy.core.IProxy)
	 */
	protected void pushToProxy(IProxy proxy) {
		if (proxy == null || proxy.isBeanProxy())
			pushToProxy((IBeanProxy) proxy);
		else
			pushToExpressionProxy((ExpressionProxy) proxy);
	}
	
	private void pushToProxy(IBeanProxy proxy) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push proxy command is:
			//	PushExpressionCommand(push to proxy) followed by:
			//		ValueObject containing the rendered proxy.
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_TO_PROXY_EXPRESSION_VALUE);
			if (proxy == null)
				workerValue.set();
			else
				((IREMBeanProxy) proxy).renderBean(workerValue);
			connection.pushValueObject(workerValue);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#closeProxy()
	 */
	protected void closeProxy() {
		if (!closed) {
			try {
				if (connection != null && connection.isConnected()) {
					try {
							connection.stopExpressionProcessing(getREMExpressionID());
					} catch (IOException e) {
						connection.close();
						ProxyPlugin.getPlugin().getLogger().log(e, Level.INFO);
						// Not throwing an illegal state here because we don't care, other than logging and not 
						// returning the connection to the registry that there was an error on close.
					} finally {
						getREMRegistry().returnConnection(connection);
					}
				}
			} finally {
				closed = true;
				if (sentData)
					getREMBeanProxyFactory().stopTransaction();	// Resume proxy releases. We've sent data at least once.
			}
		}
		methodsCache = null;
		fieldsCache = null;
		beanTypeCache = null;
		pendingTransactions = null;
		connection = null;
	}
	
	private static final Object VOIDTYPE = new Object();	// A void type was sent in expression proxy resolution.
	private static final Object NOTRESOLVED = new Object();	// A not resolved type was sent in expression proxy resolution.
	
	/*
	 * Get the sender to use for pulling the expression proxy resolutions.
	 */
	private BeanProxyValueSender getExpressionProxiesSender() {
		return new BeanProxyValueSender(getREMBeanProxyFactory()) {

			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.jem.internal.proxy.remote.BeanProxyValueSender#sendValue(org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
			 */
			public void sendValue(ValueObject value) {
				if (value.getType() == Commands.FLAG) {
					switch (value.anInt) {
						case ExpressionCommands.EXPRESSIONPROXY_NOTRESOLVED:
							array[index++] = NOTRESOLVED;
							break;
						case ExpressionCommands.EXPRESSIONPROXY_VOIDTYPE:
							array[index++] = VOIDTYPE;
							break;
						default:
							// Shouldn't happen.
							break;
					}
				} else
					super.sendValue(value);
			}
		};
	}
		
	/*
	 * Process the pulled expression proxy resolutions.
	 */
	private void processpulledExpressionProxies(List expressionProxies, BeanProxyValueSender sender) {

		// It is expected that each entry will coorespond to the next non-null expression proxy and will be the bean proxy or one of the special
		// types.
		int len = expressionProxies.size();
		int j = 0;
		Object[] resolveds = sender.getArray();
		for (int i = 0; i < len; i++) {
			ExpressionProxy ep = (ExpressionProxy) expressionProxies.get(i);
			if (ep != null) {
				Object resolved = resolveds[j++];
				if (resolved == NOTRESOLVED)
					fireProxyNotResolved(ep);
				else if (resolved == VOIDTYPE)
					fireProxyVoid(ep);
				else
					fireProxyResolved(ep, (IBeanProxy) resolved);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pullProxyValue(int, java.util.List)
	 */
	protected IBeanProxy pullProxyValue(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException {
		if (!haveSentData()) {
			markAllProxiesNotResolved(expressionProxies);
			return null;	// We haven't pushed any commands, so there is nothing to do. Don't create a connection for this.
		}
		// If there are any pending transactions at this point in time, there is no need to send them. They would be do nothings anyway.
		
		boolean processedExpressionProxies = false;
		IREMExpressionConnection lclConnection = getConnection();
		markInTransaction(lclConnection);
		try {
			Commands.ValueObject proxyids = null;
			BeanProxyValueSender sender = null;
			if (proxycount > 0) {
				proxyids = createExpressionProxiesValueObject(proxycount, expressionProxies);
				sender = getExpressionProxiesSender();
			}
			
			lclConnection.pullValue(getREMExpressionID(), proxyids, sender);
			// If we got this far, then if there are proxies, we need to process these too.
			if (proxycount > 0)
				processpulledExpressionProxies(expressionProxies, sender);
			processedExpressionProxies =true;
			lclConnection.getFinalValue(workerValue);	// Get the returned value.
			return getREMBeanProxyFactory().getBeanProxy(workerValue);
		} catch (CommandErrorException e) {
			try {
				if (e.getErrorCode() == ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION) {
					// Need to turn it into a Throwable.
					ThrowableProxy t = null;
					try {
						getREMBeanProxyFactory().getBeanProxy(e.getValue());	// This will cause a throw to occur, but we don't want it going out, we want to capture it.
					} catch (ThrowableProxy e1) {
						t = e1;
					}
					throw new REMNoExpressionValueException(t);
				}
				getREMBeanProxyFactory().processErrorReturn(e);
			} catch (CommandException e1) {
				ProxyPlugin.getPlugin().getLogger().log(e);
				if (!e.isRecoverable()) {
					lclConnection.close();
					throwIllegalStateException(COMMAND_EXCEPTION_MSG);
				}			
			}
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			if (!e.isRecoverable()) {
				lclConnection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		} finally {
			markEndTransaction(lclConnection);
			if (!processedExpressionProxies)
				markAllProxiesNotResolved(expressionProxies);	// We failed before we could process the expression proxies. So mark all as not resolved.
		}
		return null;
	}
	
	/**
	 * This is called by commands that write some data and will be reading data back immediately 
	 * (i.e. pull value and invoke expression). If we are on a callback thread and have the 
	 * used the connection from the callback thread, we need to tell the callback thread that
	 * it is in a transaction. This is needed because while reading data back there are
	 * sometimes calls back to the vm to get beantype data for new classes. This would 
	 * normally be through a new connection so that it doesn't get stuck in the middle of the
	 * data being sent back. But when running on a callback the same connection is used. So it
	 * would stick data in the middle of the return stream of data. To prevent this we need
	 * to tell the callback thread that it is in a transaction during this call so that any
	 * such new connection requests will get a new connection.
	 * <p>
	 * This is not nestable (i.e. the first markEndTransaction will set it false, even if several nested
	 * markInTransactions are called).
	 * <p>
	 * markEndTransaction must be called in ALL cases, such use try/finally.
	 * @param remConnection the connection to see check against and mark in transaction for.
	 * 
	 * 
	 * @since 1.1.0
	 */
	protected void markInTransaction(IREMExpressionConnection remConnection) {
		Thread thread = Thread.currentThread();
		if (thread instanceof REMCallbackThread) {
			// We are in a callback, and the callback connection is our connection, tell the callback that it is in transaction.
			REMCallbackThread callbackThread = (REMCallbackThread) thread;
			if (callbackThread.getConnection() == remConnection) {
				callbackThread.setIntransaction(true);
			}
		}
	}
	
	/**
	 * Mark end of transaction.
	 * @param remConn REMConnection to test and mark not in connection for.
	 * 
	 * @see REMExpression#markInTransaction(IREMExpressionConnection)
	 * @since 1.1.0
	 */
	protected void markEndTransaction(IREMExpressionConnection remConn) {
		Thread thread = Thread.currentThread();
		if (thread instanceof REMCallbackThread) {
			// We are in a callback, and the callback connection is our connection, tell the callback that it is in transaction.
			REMCallbackThread callbackThread = (REMCallbackThread) thread;
			if (callbackThread.getConnection() == remConn) {
				callbackThread.setIntransaction(false);
			}
		}		
	}

	/**
	 * @param expressionProxies
	 * 
	 * @since 1.1.0
	 */
	private Commands.ValueObject createExpressionProxiesValueObject(int actualCount, List expressionProxies) {
		class ExpressionProxyRetriever implements Commands.ValueRetrieve {
			Iterator expressionProxiesItr;
			Commands.ValueObject worker = new Commands.ValueObject();

			public ExpressionProxyRetriever(List expressionProxies) {
				this.expressionProxiesItr = expressionProxies.iterator();
			}

			public Commands.ValueObject nextValue() {
				worker.set(-1);
				while (expressionProxiesItr.hasNext()) {
					Object parm = expressionProxiesItr.next();
					if (parm != null) {
						worker.set(((ExpressionProxy) parm).getProxyID());
						break;
					}
				} 
				return worker;
			}
		};

		workerValue.setArrayIDS(new ExpressionProxyRetriever(expressionProxies), actualCount, Commands.INT);
		return workerValue;
	}

	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushCastToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
	 */
	protected void pushCastToProxy(IProxyBeanType type) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push cast to proxy command is:
			//	PushExpressionCommand(push cast to proxy) followed by:
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.CAST_EXPRESSION_VALUE);
			fillProxy(type, workerValue);
			connection.pushValueObject(workerValue);
		} catch (IOException e) {
			connection.close();			
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/**
	 * Push the proxy bean type in the format depending on expression proxy or beantype proxy.
	 * @param type
	 * @throws IOException
	 * 
	 * @since 1.1.0
	 */
	protected void fillProxy(IProxy type, Commands.ValueObject value) throws IOException {
		//		ValueObject containing the rendered bean type proxy if IBeanTypeProxy or int (for expression proxy id) if expression proxy.
		if (type.isBeanProxy()) {
			((IREMBeanProxy) type).renderBean(value);
		} else {
			ExpressionProxy ep = (ExpressionProxy) type;
			value.set(ep.getProxyID());
		}
	}
	
	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushInstanceofToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
	 */
	protected void pushInstanceofToProxy(IProxyBeanType type) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push instanceof to proxy command is:
			//	PushExpressionCommand(push instanceof to proxy) followed by:
			//		ValueObject containing the rendered bean type proxy or the String representing the name of class.
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.INSTANCEOF_EXPRESSION_VALUE);
			fillProxy(type, workerValue);
			connection.pushValueObject(workerValue);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushInfixToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InfixOperator, int)
	 */
	protected void pushInfixToProxy(InfixOperator operator, InternalInfixOperandType operandType) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push infix to proxy command is:
			//	PushExpressionCommand(push infix to proxy) followed by:
			//		byte: operator
			//		byte: operandType
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.INFIX_EXPRESSION_VALUE);
			connection.pushByte((byte) operator.getValue());
			connection.pushByte((byte) operandType.getValue());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}		
	}

	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushPrefixToProxy(org.eclipse.jem.internal.proxy.initParser.tree.PrefixOperator)
	 */
	protected void pushPrefixToProxy(PrefixOperator operator) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push prefix to proxy command is:
			//	PushExpressionCommand(push prefix to proxy) followed by:
			//		byte: operator
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PREFIX_EXPRESSION_VALUE);
			connection.pushByte((byte) operator.getValue());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayAccessToProxy(int)
	 */
	protected void pushArrayAccessToProxy(int indexCount) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push array access to proxy command is:
			//	PushExpressionCommand(push array acces to proxy) followed by:
			//		int: indexCount
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION_VALUE);
			connection.pushInt(indexCount);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayCreationToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType, int)
	 */
	protected void pushArrayCreationToProxy(IProxyBeanType type, int dimensionCount) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push array creation to proxy command is:
			//	PushExpressionCommand(push array creation to proxy) followed by:
			//		ValueObject containing the rendered bean type proxy or the expression proxy.
			//		int: dimension count
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ARRAY_CREATION_EXPRESSION_VALUE);
			fillProxy(type, workerValue);
			connection.pushValueObject(workerValue);
			connection.pushInt(dimensionCount);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	protected void pushArrayInitializerToProxy(IProxyBeanType type, int stripCount, int expressionCount) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push array initializer to proxy command is:
			//	PushExpressionCommand(push array initializer to proxy) followed by:
			//		ValueObject containing the rendered bean type proxy or expression proxy.
			//		int: strip count
			//		int: expression count
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION_VALUE);
			fillProxy(type, workerValue);
			connection.pushValueObject(workerValue);
			connection.pushInt(stripCount);
			connection.pushInt(expressionCount);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushClassInstanceCreationToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType, int)
	 */
	protected void pushClassInstanceCreationToProxy(IProxyBeanType type, int argumentCount) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push class instance creation to proxy command is:
			//	PushExpressionCommand(push class instance creation to proxy) followed by:
			//		ValueObject containing the rendered bean type proxy or the expression proxy
			//		int: argument count
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION_VALUE);
			fillProxy(type, workerValue);
			connection.pushValueObject(workerValue);
			connection.pushInt(argumentCount);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushTypeReceiverToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
	 */ 
	protected void pushTypeReceiverToProxy(IProxyBeanType type) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push type receiver to proxy command is:
			//	PushExpressionCommand(push type receiver to proxy) followed by:
			//		ValueObject containing the rendered bean type proxy or the expression proxy.
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.TYPERECEIVER_EXPRESSION_VALUE);
			fillProxy(type, workerValue);
			connection.pushValueObject(workerValue);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldAccessToProxy(java.lang.String, boolean)
	 */
	protected void pushFieldAccessToProxy(Object field, boolean hasReceiver) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push field access to proxy command is:
			//	PushExpressionCommand(push field access to proxy) followed by:
			//		Commands.Value: fieldName or IProxyField
			//		boolean: hasReceiver
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.FIELD_ACCESS_EXPRESSION_VALUE);
			if (field instanceof String) {
				workerValue.set((String) field);
			} else {
				fillProxy((IProxy) field, workerValue);
			}
			connection.pushValueObject(workerValue);
			connection.pushBoolean(hasReceiver);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodInvocationToProxy(java.lang.String, boolean, int)
	 */
	protected void pushMethodInvocationToProxy(Object method, boolean hasReceiver, int argCount) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push method invocation to proxy command is:
			//	PushExpressionCommand(push method invocation to proxy) followed by:
			//		Commands.ValueObject: methodName or IMethodProxy
			//		boolean: hasReceiver
			//		int: argCount
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.METHOD_EXPRESSION_VALUE);
			if (method instanceof String) {
				workerValue.set((String) method);
			} else {
				fillProxy((IProxy) method, workerValue);
			}
			connection.pushValueObject(workerValue);
			connection.pushBoolean(hasReceiver);
			connection.pushInt(argCount);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushConditionalToProxy(int)
	 */
	protected void pushConditionalToProxy(InternalConditionalOperandType expressionType) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push conditional to proxy command is:
			//	PushExpressionCommand(push conditional to proxy) followed by:
			//		byte: expression type
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.CONDITIONAL_EXPRESSION_VALUE);
			connection.pushByte((byte) expressionType.getValue());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/*
	 * A special one that takes the ThrowableProxy for no expression value and 
	 * wrappers it prints its stack trace instead, but still makes it a subclass
	 * of NoExpressionValueException.
	 * 
	 * @since 1.1.0
	 */
	private static class REMNoExpressionValueException extends NoExpressionValueException {
		/**
		 * Comment for <code>serialVersionUID</code>
		 * 
		 * @since 1.1.0
		 */
		private static final long serialVersionUID = 1692406777391812694L;


		public REMNoExpressionValueException(ThrowableProxy e) {
			super(e);
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Throwable#getLocalizedMessage()
		 */
		public String getLocalizedMessage() {
			return ((ThrowableProxy) getCause()).getProxyLocalizedMessage();
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Throwable#getMessage()
		 */
		public String getMessage() {
			return ((ThrowableProxy) getCause()).getProxyMessage();
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Throwable#printStackTrace()
		 */
		public void printStackTrace() {
			getCause().printStackTrace();
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Throwable#printStackTrace(java.io.PrintStream)
		 */
		public void printStackTrace(PrintStream s) {
			getCause().printStackTrace(s);
		}
		
		
		/* (non-Javadoc)
		 * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter)
		 */
		public void printStackTrace(PrintWriter s) {
			getCause().printStackTrace(s);
		}
	}
	
	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushInvoke(int, java.util.List)
	 */
	protected void pushInvoke(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException {
		if (!haveSentData()) {
			markAllProxiesNotResolved(expressionProxies);
			return;	// We haven't pushed any commands, so there is nothing to do. Don't create a connection for this.
		}
		// If at this point there are pending transactions, there is no need to send them because they would all be do-nothings.
		
		boolean processedExpressionProxies = false;
		IREMExpressionConnection lclConnection = getConnection();
		markInTransaction(lclConnection);
		try {
			Commands.ValueObject proxyids = null;
			BeanProxyValueSender sender = null;
			if (proxycount > 0) {
				proxyids = createExpressionProxiesValueObject(proxycount, expressionProxies);
				sender = getExpressionProxiesSender();
			}

			lclConnection.sync(getREMExpressionID(), proxyids, sender);
			
			// If we got this far, then if there are proxies, we need to process these too.
			if (proxycount > 0)
				processpulledExpressionProxies(expressionProxies, sender);
			processedExpressionProxies = true;
			lclConnection.getFinalValue(workerValue);	// We don't care what it is, we just need to see if there is an error.
		} catch (CommandErrorException e) {
			try {
				if (e.getErrorCode() == ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION) {
					// Need to turn it into a Throwable.
					ThrowableProxy t = null;
					try {
						getREMBeanProxyFactory().getBeanProxy(e.getValue());	// This will cause a throw to occur, but we don't want it going out, we want to capture it.
					} catch (ThrowableProxy e1) {
						t = e1;
					}
					throw new REMNoExpressionValueException(t);
				}
				getREMBeanProxyFactory().processErrorReturn(e);
			} catch (CommandException e1) {
				ProxyPlugin.getPlugin().getLogger().log(e);
				if (!e.isRecoverable()) {
					lclConnection.close();
					throwIllegalStateException(COMMAND_EXCEPTION_MSG);
				}			
			}
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			if (!e.isRecoverable()) {
				lclConnection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		} finally {
			markEndTransaction(lclConnection);
			if (!processedExpressionProxies)
				markAllProxiesNotResolved(expressionProxies);	// We failed before we could process the expression proxies. So mark all as not resolved.
		}
	}

	private static class REMBeanTypeExpressionProxy extends ExpressionProxy implements IBeanTypeExpressionProxy {
		
		private String typeName;
		
		/**
		 * @param proxyid
		 * 
		 * @since 1.1.0
		 */
		private REMBeanTypeExpressionProxy(int proxyid, Expression expression) {
			super(proxyid, BEANTYPE_EXPRESSION_PROXY, expression);
		}
		
		public void setTypeName(String typeName) {
			this.typeName = typeName;
		}
		
		public String getTypeName() {
			return typeName;
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy#toString()
		 */
		public String toString() {
			return super.toString()+" - "+getTypeName(); //$NON-NLS-1$
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
		 */
		public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameterTypes) {
			REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
			return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
		}
		
		
		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String[])
		 */
		public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes) {
			REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
			return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
		}
		
		public IProxyMethod getMethodProxy(IExpression expression, String methodName) {
			return getMethodProxy(expression, methodName, (IProxyBeanType[]) null);
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String)
		 */
		public IProxyField getFieldProxy(IExpression expression, String fieldName) {
			REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
			return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getFieldProxy(expression, this, fieldName);
		}
	}
	
	private static class REMMethodExpressionProxy extends ExpressionProxy implements IProxyMethod {
		
			/**
		 * @param proxyid
		 * @param proxyType
		 * @param expression
		 * 
		 * @since 1.1.0
		 */
		private REMMethodExpressionProxy(int proxyid, Expression expression) {
			super(proxyid, METHOD_EXPRESSION_PROXY, expression);
		}
	}
	
	private static class REMFieldExpressionProxy extends ExpressionProxy implements IProxyField {
		
			/**
		 * @param proxyid
		 * @param proxyType
		 * @param expression
		 * 
		 * @since 1.1.0
		 */
		private REMFieldExpressionProxy(int proxyid, Expression expression) {
			super(proxyid, FIELD_EXPRESSION_PROXY, expression);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#createExpressionProxy(int)
	 */
	protected ExpressionProxy createExpressionProxy(int proxyType, int proxyID) {
		switch (proxyType) {
			case NORMAL_EXPRESSION_PROXY:
			default:
				return new ExpressionProxy(proxyID, NORMAL_EXPRESSION_PROXY, this);
			
			case BEANTYPE_EXPRESSION_PROXY:
				return new REMBeanTypeExpressionProxy(proxyID, this);
				
			case METHOD_EXPRESSION_PROXY:
				return new REMMethodExpressionProxy(proxyID, this);
				
			case FIELD_EXPRESSION_PROXY:
				return new REMFieldExpressionProxy(proxyID, this);
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushAssignmentToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy)
	 */
	protected void pushAssignmentToProxy(ExpressionProxy proxy) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push assignment to proxy command is:
			//	PushExpressionCommand(push assignment to proxy) followed by:
			//		int: proxy id
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ASSIGNMENT_PROXY_EXPRESSION_VALUE);
			connection.pushInt(proxy.getProxyID());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}
	
	
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushAssignmentToProxy()
	 */
	protected void pushAssignmentToProxy() {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of the push assignment command is:
			//   PushAssignmentCommand.
			connection.pushExpressionCommand(getREMExpressionID(), (byte) InternalExpressionTypes.ASSIGNMENT_EXPRESSION_VALUE);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}
	

	private void pushToExpressionProxy(ExpressionProxy proxy) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to expression proxy command is:
			//	PushExpressionCommand(push expression proxy to proxy) followed by:
			//		int: proxy id
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_TO_EXPRESSION_PROXY_EXPRESSION_VALUE);
			connection.pushInt(proxy.getProxyID());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}

	}
	
	private static class BlockBegin extends PendingTransaction {
		public int blockNumber;
		
		public BlockBegin(int blockNumber) {
			this.blockNumber = blockNumber;
		}
		
		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push to block begin proxy command is:
				//	PushExpressionCommand(push block begin proxy to proxy) followed by:
				//		int: block id
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.BLOCK_BEGIN_EXPRESSION_VALUE);
				connection.pushInt(blockNumber);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			}			
		}
		
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockBeginToProxy(int)
	 */
	protected void pushBlockBeginToProxy(int blockNumber) {
		addPendingTransaction(new BlockBegin(blockNumber));
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockEndToProxy(int)
	 */
	protected void pushBlockEndToProxy(int blockNumber) {
		// See if the top pending transactions is BreakBlock(blockNumber). If it is then the BreakBlock can be thrown away.
		PendingTransaction topEntry = getPendingEntryFromTop(1);
		if (topEntry instanceof BlockBreak && ((BlockBreak) topEntry).blockNumber == blockNumber) {
			popPendingEntry(1);
			topEntry = getPendingEntryFromTop(1);
		}
		// See if the top pending transaction is now BeginBlock(blockNumber). If it is, then this transaction and the block begin
		// can be thrown away because they are an empty block.
		if (topEntry instanceof BlockBegin && ((BlockBegin) topEntry).blockNumber == blockNumber) {
			popPendingEntry(1);
			return;
		}
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to block end proxy command is:
			//	PushExpressionCommand(push block end proxy to proxy) followed by:
			//		int: block id
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.BLOCK_END_EXPRESSION_VALUE);
			connection.pushInt(blockNumber);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}
	
	private static class BlockBreak extends PendingTransaction {
		public int blockNumber;
		
		public BlockBreak(int blockNumber) {
			this.blockNumber = blockNumber;
		}
		
		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push to block break proxy command is:
				//	PushExpressionCommand(push block break proxy to proxy) followed by:
				//		int: block id
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.BLOCK_BREAK_EXPRESSION_VALUE);
				connection.pushInt(blockNumber);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			}
		}		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockBreakToProxy(int)
	 */
	protected void pushBlockBreakToProxy(int blockNumber) {
		// Even if there is no pending block begin for this block, we will pend the break.
		// This is so that if the break occurred just before the block end, then it can be ignored.
		addPendingTransaction(new BlockBreak(blockNumber));
	}

	private static class TryBegin extends PendingTransaction {

		public final int tryNumber;
		
		public TryBegin(int tryNumber) {
			this.tryNumber = tryNumber;
			
		}
		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push to try begin proxy command is:
				//	PushExpressionCommand(push try begin to proxy) followed by:
				//		int: try id
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.TRY_BEGIN_EXPRESSION_VALUE);
				connection.pushInt(tryNumber);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			}
		}
		
	}
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryBeginToProxy(int)
	 */
	protected void pushTryBeginToProxy(int tryNumber) {
		addPendingTransaction(new TryBegin(tryNumber));
	}

	private static class TryCatch extends PendingTransaction {

		public final int tryNumber;
		private final IProxyBeanType exceptionType;
		private final ExpressionProxy ep;

		public TryCatch(int tryNumber, IProxyBeanType exceptionType, ExpressionProxy ep) {
			this.tryNumber = tryNumber;
			this.exceptionType = exceptionType;
			this.ep = ep;
		}
		
		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push to try begin proxy command is:
				//	PushExpressionCommand(push try begin to proxy) followed by:
				//		int: try id
				//		object: expression type (as beantype or as expression proxy)
				//		int: proxy id or (-1 if null).
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.TRY_CATCH_EXPRESSION_VALUE);
				connection.pushInt(tryNumber);
				remExpression.fillProxy(exceptionType, remExpression.workerValue);
				connection.pushValueObject(remExpression.workerValue);
				if (ep != null)
					connection.pushInt(ep.getProxyID());
				else
					connection.pushInt(-1);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			} catch (CommandException e) {
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				if (!e.isRecoverable()) {
					connection.close();
					remExpression.throwIllegalStateException(COMMAND_EXCEPTION_MSG);
				}			
			}
		}
		
	}
	/*
	 *  (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryCatchClauseToProxy(int, org.eclipse.jem.internal.proxy.core.IProxyBeanType, org.eclipse.jem.internal.proxy.core.ExpressionProxy)
	 */
	protected void pushTryCatchClauseToProxy(int tryNumber, IProxyBeanType exceptionType, ExpressionProxy ep) {
		addPendingTransaction(new TryCatch(tryNumber, exceptionType, ep));
	}

	private static class TryFinally extends PendingTransaction {
		
		public final int tryNumber;

		public TryFinally(int tryNumber) {
			this.tryNumber = tryNumber;
			
		}

		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push to try begin proxy command is:
				//	PushExpressionCommand(push try finally to proxy) followed by:
				//		int: try id
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.TRY_FINALLY_EXPRESSION_VALUE);
				connection.pushInt(tryNumber);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			}
		}
		
	}
	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryFinallyClauseToProxy(int)
	 */
	protected void pushTryFinallyClauseToProxy(int tryNumber) {
		addPendingTransaction(new TryFinally(tryNumber));
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryEndToProxy(int)
	 */
	protected void pushTryEndToProxy(int tryNumber) {
		// This is a little tricky. We need to find if there is nothing but try/catch/finally for this tryNumber on the pending
		// transactions up to the try begin, if there is nothing else, then we can throw the entire try away. That
		// means there was no code at all in any of the try/catch/finally blocks.
		int fromTop = 0;
		while (true) {
			PendingTransaction topEntry = getPendingEntryFromTop(++fromTop);
			if (topEntry instanceof TryFinally) {
				if (((TryFinally) topEntry).tryNumber != tryNumber)
					break;	// We met a finally that wasn't ours, so entire try group must be sent.
			} else if (topEntry instanceof TryCatch) {
				if (((TryCatch) topEntry).tryNumber != tryNumber)
					break;	// We met a catch that wasn't ours, so entire try group must be sent.
			} else if (topEntry instanceof TryBegin) {
				if (((TryBegin) topEntry).tryNumber == tryNumber) {
					// We've met our try begin, and nothing but empty catch/finally in between, so the entire group can be thrown away
					popPendingEntry(fromTop);
					return;
				} else
					break;	// We've hit a try begin that wasn't ours, so the entire try group must be sent.	
			} else
				break;	// We've hit something other than our try group, so process everything.
		}
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to try begin proxy command is:
			//	PushExpressionCommand(push try end to proxy) followed by:
			//		int: try id
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.TRY_END_EXPRESSION_VALUE);
			connection.pushInt(tryNumber);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushThrowToProxy()
	 */
	protected void pushThrowToProxy() {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to try begin proxy command is:
			//	PushExpressionCommand(push throw to proxy)
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.THROW_EXPRESSION_VALUE);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushRethrowToProxy(int)
	 */
	protected void pushRethrowToProxy(int tryNumber) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to rethow proxy command is:
			//	PushExpressionCommand(push rethrow to proxy)
			//		int: try id
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.RETHROW_EXPRESSION_VALUE);
			connection.pushInt(tryNumber);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushBeanTypeToProxy(org.eclipse.jem.internal.proxy.core.IBeanTypeExpressionProxy)
	 */
	protected void pushBeanTypeToProxy(IBeanTypeExpressionProxy proxy) {
		// Push beantype to proxy is sent out of sequence without respect to where in expression we are,
		// so no need to handle pending transactions at this point. They would not affect the result
		// of this call.
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to beanType proxy command is:
			//	PushExpressionCommand(push bean type expression proxy)
			//		int: proxy id
			//		string: typename
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_BEANTYPE_EXPRESSIONPROXY_EXPRESSION_VALUE);
			REMBeanTypeExpressionProxy ep = (REMBeanTypeExpressionProxy) proxy;
			connection.pushInt(ep.getProxyID());
			connection.pushString(ep.getTypeName());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy, org.eclipse.jem.internal.proxy.core.IProxyBeanType, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
	 */
	protected void pushMethodToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes) {
		// Push method to proxy is sent out of sequence without respect to where in expression we are,
		// so no need to handle pending transactions at this point. They would not affect the result
		// of this call.

		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to method proxy command is:
			//	PushExpressionCommand(push method type expression proxy)
			//		int: proxy id
			//		ValueObject: containing the rendered bean type proxy or the expression proxy for the declaring type
			//		string: method name
			//		int: number of parameter types
			//		ValueObject(s): containing the rendered bean type proxy or the expression proxy for the parameter types.
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_METHOD_EXPRESSIONPROXY_EXPRESSION_VALUE);
			connection.pushInt(proxy.getProxyID());
			fillProxy(declaringType, workerValue);
			connection.pushValueObject(workerValue);
			connection.pushString(methodName);
			if (parameterTypes == null || parameterTypes.length == 0)
				connection.pushInt(0);
			else {
				connection.pushInt(parameterTypes.length);
				for (int i = 0; i < parameterTypes.length; i++) {
					fillProxy(parameterTypes[i], workerValue);
					connection.pushValueObject(workerValue);					
				}
			}
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy, org.eclipse.jem.internal.proxy.core.IProxyBeanType, java.lang.String)
	 */
	protected void pushFieldToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String fieldName) {
		// Push field to proxy is sent out of sequence without respect to where in expression we are,
		// so no need to handle pending transactions at this point. They would not affect the result
		// of this call.

		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to field proxy command is:
			//	PushExpressionCommand(push field type expression proxy)
			//		int: proxy id
			//		ValueObject: containing the rendered bean type proxy or the expression proxy for the declaring type
			//		string: field name
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_FIELD_EXPRESSIONPROXY_EXPRESSION_VALUE);
			connection.pushInt(proxy.getProxyID());
			fillProxy(declaringType, workerValue);
			connection.pushValueObject(workerValue);
			connection.pushString(fieldName);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}
	
	/**
	 * Get the map of IProxyMethods for a beantype. Meant to be used only in conjunction with REMProxyConstants.
	 * It is here so the REMProxyConstants can store pending proxies per expression.
	 * 
	 * @param beanType
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public Map getMethods(IProxyBeanType beanType) {
		if (methodsCache == null)
			methodsCache = new HashMap();
		Map methods = (Map) methodsCache.get(beanType.getTypeName());
		if(methods == null){
			methods = new HashMap(20);
			methodsCache.put(beanType.getTypeName(),methods);
		}
		return methods;	
	}
	
	/**
	 * Get the map of IProxyFields for a beantype. Meant to be used only in conjunction with REMProxyConstants.
	 * It is here so the REMProxyConstants can store pending proxies per expression.
	 * 
	 * @param beanType
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public Map getFields(IProxyBeanType beanType) {
		if (fieldsCache == null)
			fieldsCache = new HashMap();
		Map fields = (Map) fieldsCache.get(beanType.getTypeName());
		if(fields == null){
			fields = new HashMap(20);
			fieldsCache.put(beanType.getTypeName(),fields);
		}
		return fields;	
	}
	
	/**
	 * Get the map of IProxyBeanTypes for a beantype name. Meant to be used only in conjunction with REMSgtandardBeanTypeFactory.
	 * It is here so the REMStandardBeanTypeFactory can store pending proxies per expression.
	 * 
	 * @param beanType
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public IProxyBeanType getBeanType(String beanTypeName) {
		if (beanTypeCache == null)
			beanTypeCache = new HashMap();
		return (IProxyBeanType) beanTypeCache.get(beanTypeName);
	}
	
	/**
	 * Add the beantype expression proxy to the map of bean type expression proxies. Used in conjunction with REMStandardBeanTypeFactory.
	 * It is here so the REMStandardBeanTypeFactory can store pending proxies per expression.
	 * @param beanTypeName
	 * @param beantype
	 * 
	 * @since 1.1.0
	 */
	public void addBeanType(String beanTypeName, IProxyBeanType beantype) {
		beanTypeCache.put(beanTypeName, beantype);
	}
	
	/**
	 * Remove the beantype expression proxy from the map. This is called because there was a rollback due to an endmark.
	 * @param beanTypeName
	 * 
	 * @since 1.1.0
	 */
	public void removeBeanType(String beanTypeName) {
		beanTypeCache.remove(beanTypeName);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushIfTestToProxy()
	 */
	protected void pushIfTestToProxy() {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push if test to proxy command is:
			//	PushExpressionCommand(push if test to proxy)
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.IF_TEST_EXPRESSION_VALUE);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushIfElseToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InternalIfElseOperandType)
	 */
	protected void pushIfElseToProxy(InternalIfElseOperandType clauseType) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push conditional to proxy command is:
			//	PushExpressionCommand(push if/else clause to proxy) followed by:
			//		byte: clause type
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.IF_ELSE_EXPRESSION_VALUE);
			connection.pushByte((byte) clauseType.getValue());
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jem.internal.proxy.core.Expression#pushNewInstanceToProxy(java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType)
	 */
	protected void pushNewInstanceToProxy(String initializationString, IProxyBeanType resultType) {
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push new instance from initstring to proxy command is:
			//	PushExpressionCommand(push new instance to proxy) followed by:
			//		string: init string
			//		ValueObject: containing the rendered bean type proxy or the expression proxy for the declaring type
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.NEW_INSTANCE_VALUE);
			connection.pushString(initializationString);
			fillProxy(resultType, workerValue);
			connection.pushValueObject(workerValue);			
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		} catch (CommandException e) {
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			if (!e.isRecoverable()) {
				connection.close();
				throwIllegalStateException(COMMAND_EXCEPTION_MSG);
			}			
		}
	}

	private static class Mark extends PendingTransaction {
		public int markID;
		
		public Mark(int markID) {
			this.markID = markID;
		}
		
		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push mark to proxy command is:
				//	PushExpressionCommand(push mark to proxy) followed by:
				//		int: markID
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.MARK_VALUE);
				connection.pushInt(markID);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			}
		}
		
	}
	
	protected void pushMarkToProxy(int markID) {
		addPendingTransaction(new Mark(markID));
	}

	protected void pushEndmarkToProxy(int markID, boolean restore) {
		// See if the top pending transaction is now Mark(markID). If it is, then this transaction and the mark begin
		// can be thrown away because they are an empty block.
		PendingTransaction topEntry = getPendingEntryFromTop(1);
		if (topEntry instanceof Mark && ((Mark) topEntry).markID == markID) {
			popPendingEntry(1);
			return;
		}
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push end mark to proxy command is:
			//	PushExpressionCommand(push end mark to proxy) followed by:
			//		int: markID
			//		boolean: restore
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ENDMARK_VALUE);
			connection.pushInt(markID);
			connection.pushBoolean(restore);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
	}

	// This is the expression processor controller used to transfer.
	// This is the guy that maintains continuity of the transaction as
	// it is passed from one connection to another.
	protected IBeanProxy expressionProcesserController;	
	protected void pushBeginTransferThreadToProxy() throws ThrowableProxy {
		// If the controller is not null, that means we had already requested a transfer
		// but had not used it in this thread so there is no need to do anything. It
		// will be handled when switching back to the other thread.
		// If the connection is null, no need to do anything since there is no connection
		// to transfer.
		if (connection != null && expressionProcesserController == null) {
			IREMExpressionConnection lclConnection = getConnection();
			markInTransaction(lclConnection);
			try {
				workerValue.set();
				lclConnection.transferExpression(getREMExpressionID(), workerValue);
				expressionProcesserController = getREMBeanProxyFactory().getBeanProxy(workerValue);
				getREMRegistry().returnConnection(lclConnection);
				this.connection = null;
			} catch (CommandException e) {
				ProxyPlugin.getPlugin().getLogger().log(e);
				if (!e.isRecoverable()) {
					lclConnection.close();
					throwIllegalStateException(COMMAND_EXCEPTION_MSG);
				}			
			} finally {
				markEndTransaction(lclConnection);
			}
		}
	}

	protected void pushTransferThreadToProxy() {
		// Don't need to do anything. The next time we need to push data across, we will get a connection and the getConnection()
		// will hook up the expression processor controller for us. This way if nothing happens in this thread then we won't
		// waste communication time on it.
	}

	private static class SubexpressionBegin extends PendingTransaction {
		public int subexpressionNumber;
		
		public SubexpressionBegin(int subexpressionNumber) {
			this.subexpressionNumber = subexpressionNumber;
		}
		
		public void pushTransaction(REMExpression remExpression) {
			IREMExpressionConnection connection = remExpression.getConnection();
			try {
				// Format of push to subexpression begin proxy command is:
				//	PushExpressionCommand(push subexpression begin proxy to proxy) followed by:
				//		int: subexpression id
				connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.SUBEXPRESSION_BEGIN_EXPRESSION_VALUE);
				connection.pushInt(subexpressionNumber);
			} catch (IOException e) {
				connection.close();
				ProxyPlugin.getPlugin().getLogger().log(e);
				remExpression.markInvalid(e.getLocalizedMessage());
				remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
			}			
		}
		
	}

	protected void pushSubexpressionBeginToProxy(int subexpressionNumber) {
		addPendingTransaction(new SubexpressionBegin(subexpressionNumber));
	}

	protected void pushSubexpressionEndToProxy(int subexpressionNumber) {
		// See if the top pending transactions is SubexpressionBegin(subexpressionNumber). If it is then the SubexpressionBegin can be thrown away.
		PendingTransaction topEntry = getPendingEntryFromTop(1);
		if (topEntry instanceof SubexpressionBegin && ((SubexpressionBegin) topEntry).subexpressionNumber == subexpressionNumber) {
			popPendingEntry(1);
			topEntry = getPendingEntryFromTop(1);
		}
		processPendingTransactions();
		IREMExpressionConnection connection = getConnection();
		try {
			// Format of push to block end proxy command is:
			//	PushExpressionCommand(push subexpression end proxy to proxy) followed by:
			//		int: subexpression id
			connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.SUBEXPRESSION_END_EXPRESSION_VALUE);
			connection.pushInt(subexpressionNumber);
		} catch (IOException e) {
			connection.close();
			ProxyPlugin.getPlugin().getLogger().log(e);
			markInvalid(e.getLocalizedMessage());
			throwIllegalStateException(IO_EXCEPTION_MSG);
		}
		}
}
