/*******************************************************************************
 * 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.11 $  $Date: 2005/05/18 23:11:26 $ 
 */
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)
					connection.startExpressionProcessing(getREMExpressionID());	// 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.getString("REMExpression.IOExceptionSeeLog_INFO_"); //$NON-NLS-1$
	
	protected static final String COMMAND_EXCEPTION_MSG = ProxyRemoteMessages.getString("REMExpression.CommandExceptionSeeLog_INFO_"); //$NON-NLS-1$
	
	/**
	 * 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 {
		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.
	}
}
