diff options
Diffstat (limited to 'plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/Expression.java')
-rw-r--r-- | plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/Expression.java | 2546 |
1 files changed, 0 insertions, 2546 deletions
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/Expression.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/Expression.java deleted file mode 100644 index 2ab151187..000000000 --- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/Expression.java +++ /dev/null @@ -1,2546 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -/* - * $RCSfile: Expression.java,v $ - * $Revision: 1.15 $ $Date: 2005/11/11 15:49:30 $ - */ -package org.eclipse.jem.internal.proxy.core; - -import java.text.MessageFormat; -import java.util.*; - -import org.eclipse.jem.internal.proxy.initParser.tree.*; - -/** - * This is implementation of IExpression. It encapsulates much of the processing required - * into a common form that will be turned into simple push/pop/evaluate type of interaction with the - * actual other side. All registry specific implementations of IExpression must subclass this class. - * <p> - * It will maintain a stack of the expressions. As the expressions come in they will be stacked if not - * able to be executed immediately. The expressions come to this class in an outside to inside order, - * but they need to be processed in an inside-out order instead. - * <p> - * Subclasses will be used for the different types of proxy interfaces. The abstract methods will - * then be the simple interface. - * <p> - * It is not meant for subclasses to override the actual create expression methods because the processing the stack - * is very sensitive and must execute in the proper sequence. So the create methods are final for this reason. - * <p> - * This class is not thread-safe. - * <p> - * This class also has API of its own and can be used by customers for advanced usage. Those advanced API are - * listed on each method as to whether it is customer API or implementers API (i.e. API for implementers of - * expression subclasses to use). - * - * - * @since 1.0.0 - */ -public abstract class Expression implements IExpression { - - /* - * We have stack here, but rather than create a class that does the - * stack protocol, will simply have some private methods to do - * the same thing for the stack. (Note: Can't use java.util.Stack - * because that is a synchronized class, and don't want the overhead). - * - * The purpose of the stack is to stack up expressions that have not yet - * been evaluated. - * - * Each expression type will control the content of what it pushes and pops. - * The expression type will be the last thing it pushes so that on popping - * we know what kind of expression is now completed and ready for evaluation. - */ - private ArrayList controlStack = new ArrayList(30); - - protected final ProxyFactoryRegistry registry; - protected final IStandardBeanProxyFactory beanProxyFactory; - protected Boolean traceFlag; - - /** - * Answer whether trace has been explicitly set. - * This is not in the IExpression interface because it is for advanced users. - * @return - * - * @since 1.1.0 - */ - public boolean isTraceSet() { - return traceFlag != null; - } - - /** - * Answer if trace is on. If not explicitly set this will answer false. - * Use {@link Expression#isTraceSet()} first to determine if this - * should be called or not. - * This is not in the IExpression interface because it is for advanced users. - * @return - * - * @since 1.1.0 - */ - public boolean isTrace() { - return traceFlag != null ? traceFlag.booleanValue() : false; - } - - /** - * Explicitly set the trace flag. This will only be honoured before any - * expressions have been created. After that this will be ignored. - * The trace is initially set to use default. Once set it cannot be unset. - * This is not in the IExpression interface because it is for advanced users. - * @param trace - * - * @since 1.1.0 - */ - public void setTrace(boolean trace) { - traceFlag = Boolean.valueOf(trace); - } - - /** - * Push an object onto the control stack. - * - * @param o - * - * @since 1.0.0 - */ - protected final void push(Object o) { - controlStack.add(o); - } - - /** - * Pop an object off of the control stack - * @return - * - * @since 1.0.0 - */ - protected final Object pop() { - return controlStack.remove(controlStack.size()-1); - } - - /** - * Peek at an object from the control stack. <code>fromTop</code> is how far from the top of the stack to look. - * If it one, then it is the top entry, two is the next one down. Zero is an invalid value for the parameter. - * @param fromTop How far from the top to peek. <code>1</code> is the top, not zero. - * @return - * - * @since 1.0.0 - */ - protected final Object peek(int fromTop) { - // 1 means the top, 2 is the next one down. - return controlStack.get(controlStack.size()-fromTop); - } - - /* - * Expression type constants. - */ - - /* - * ARRAY ACCESS expression. - * The expression stack will have: - * IExpression.ARRAYACCESS_ARRAY - * IExpression.ARRAYACCESS_INDEX (for 1 to n times depending on index count) - * PROCESS_EXPRESSION - * - * The value stack will have - * ARRAYACCESS - * Integer(index count) - */ - private static final Integer ARRAYACCESS_INDEX_1 = new Integer(1); // Use in normal case of one index count. Saves object creation. - - /* - * ARRAY CREATION expression. - * The expression stack will have: - * ARRAYCREATION_INITIALIZER - if hasInitializer - * IExpression.ARRAYCREATION_DIMENSION (for 0 to n times depending on dimension count) - * PROCESS_EXPRESSION - * - * The value stack will have - * ARRAYCREATION - * type (either a string representing the type, or an IBeanProxyType representing the type). - * Integer(dimension count) (if zero then there is an initializer) - * - * - * Note: Array Initializer works with this in that it will peek into the value stack two entries down - * to find the type of array it should be creating. - */ - private static final Integer ARRAY_CREATION_DIMENSION_1 = new Integer(1); // Use in normal case of one dimension. Save object creation. - private static final Integer ARRAY_CREATION_DIMENSION_0 = new Integer(0); // Use in normal case of initializer. Save object creation. - private static final ForExpression ARRAY_INITIALIZER = new ExpressionEnum(Integer.MIN_VALUE+1, "Array Initializer Internal"); //$NON-NLS-1$ - - /* - * ARRAY INITIALIZER expression - * The expression stack will have: - * IExpression.ARRAYINITIALIZER_EXPRESSION (for n times depending on number of expressions count) - * PROCESS_EXPRESSION - * - * The value stack will have - * ARRAYINITIALIZER - * type (either a string representing the type, or an IBeanProxyType representing the type). - * I.e. if array being created is int[][], the value pushed here will be int[]. This is because when created - * the array will wind up with int[expressioncount][] in the end. - * Integer (expression count) - * - * Note: Imbedded Array Initializers works with this in that it will peek into the value stack two entries down - * to find the type of array it should be creating. - */ - private static final Integer ARRAYINITIALIZER_COUNT_0 = new Integer(0); // Use in normal case of empty array. Save object creation. - private static final Integer ARRAYINITIALIZER_COUNT_1 = new Integer(1); // Use in normal case of one element array. Save object creation. - private static final Integer ARRAYINITIALIZER_COUNT_2 = new Integer(2); // Use in normal case of two element array. Save object creation. - - /* - * CAST expression. - * The expression stack will have: - * IExpression.CAST_EXPRESSION - * PROCESS_EXPRESSION - * - * The value stack will have: - * CAST - * type (either a string representing the type, or an IBeanProxyType representing the type). - */ - - /* - * CLASS INSTANCE CREATION expression. - * The expression stack will have: - * IExpression.CLASSINSTANCECREATION_ARGUMENT (for 0 to n times depending on argument count) - * PROCESS_EXPRESSION - * - * The value stack will have - * CLASSINSTANCECREATION - * type (either a string representing the type, or an IBeanProxyType representing the type). - * Integer(argument count) - * - * - * Note: Array Initializer works with this in that it will peek into the value stack two entries down - * to find the type of array it should be creating. - */ - private static final Integer CLASS_INSTANCE_CREATION_ARGUMENTS_1 = new Integer(1); // Use in normal case of one argument. Save object creation. - private static final Integer CLASS_INSTANCE_CREATION_ARGUMENTS_0 = new Integer(0); // Use in normal case of no arguments (default ctor). Save object creation. - - /* - * CONDITIONAL expression. - * Since this can cause skipping of expressions (e.g. if condition is false, then the true condition should not be evaluated), - * we need to have a process expression and process call to the other side for each expression so that it can - * determine if it should be ignored or not. - * - * The expression stack will have: - * IExpression.CONDITIONAL_CONDITION - * PROCESS_EXPRESSION - * IExpression.CONDITIONAL_TRUE - * PROCESS_EXPRESSION - * IExpression.CONDITIONAL_FALSE - * PROCESS_EXPRESSION - * - * The value stack will have: - * CONDITIONAL - * CONDITIONAL_CONDITION - * CONDITIONAL - * CONDITIONAL_TRUE - * CONDITIONAL - * CONDITIONAL_FALSE - * - */ - - /* - * PREFIX expression. - * The expression stack will have: - * IExpression.PREFIX_OPERAND - * PROCESS_EXPRESSION - * - * The value stack will have: - * PREFIX - * operator (using Integer prefix operator constants defined here) - */ - - /* - * INFIX expression. - * Since two types of infix operators (conditional and AND or) can cause skipping of expressions (e.g. once - * conditional and sees a false expression, the rest of the expressions are skipped and should not be evaluated), - * we need to have a process expression and process call to the other side for each expression so that it can - * determine if it should be ignored or not. - * - * The expression stack will have: - * IExpression.INFIX_LEFT - * PROCESS_EXPRESSION - * IExpression.INFIX_RIGHT - * PROCESS_EXPRESSION - * (for 0 to n times depending upon extended count) - * IExpression.INFIX_EXTENDED - * PROCESS_EXPRESSION - * - * The value stack will have: - * INFIX - * operator (using Integer infix operator constants defined here) - * IN_LEFT - * (for (extendedCount) times) This will cover the right one and all but last extended - * INFIX - * operator (using Integer infix operator constants defined here) - * IN_OTHER - * INFIX - * operator (using Integer infix operator constants defined here) - * IN_LAST (this is covers either the right one if no extended, or the last extended) - */ - - /* - * INSTANCEOF expression. - * The expression stack will have: - * IExpression.INSTANCEOF_EXPRESSION - * PROCESS_EXPRESSION - * - * The value stack will have: - * INSTANCEOF - * type (either a string representing the type, or an IBeanProxyType representing the type). - */ - - /* - * Field access expression. - * The expression stack will have: - * IExpression.FIELD_RECEIVER (if hasReceiver is true) - * PROCESS_EXPRESSION - * - * The value stack will have: - * FIELDACCESS - * name (the name of the field) - * Boolean (true if has receiver) - */ - - /* - * Method invocation expression. - * The expression stack will have: - * IExpression.METHOD_RECEIVER (if hasReceiver is true) - * IExpression.METHOD_ARGUMENT (0 to n times for how many arguments). - * PROCESS_EXPRESSION - * - * The value stack will have: - * METHODINVOCATION - * name (the name of the method) - * Boolean (true if has receiver) - * argCount (the number of arguments). - */ - private static final Integer METHOD_ARGUMENTS_1 = new Integer(1); // Use in normal case of one argument. Save object creation. - private static final Integer METHOD_ARGUMENTS_0 = new Integer(0); // Use in normal case of no arguments. Save object creation. - - - /* - * Assignment expression - * The expression stack will have: - * IExpression.ASSIGNMENT_RIGHT - * IExpression.ASSIGNMENT_LEFT - * PROCESS_EXPRESSION - * - * The value stack will have: - * ASSIGNMENT - * left expression (variable reference) - * right expression - */ - - /* - * Assignment proxy expression - * The expression stack will have: - * IExpression.ASSIGNMENT_RIGHT - * PROCESS_EXPRESSION - * - * The value stack will have: - * ASSIGNMENT_PROXY - * expression proxy (an expression proxy) - */ - - /* - * Next valid for expression stack. This is kept as a stack also. - * As the expressions come in, the appropriate order (in reverse) - * of expression types will be pushed, and then popped as they - * come in. - * - * Since we can't have an array list of ints, will simulate the - * stack here. - */ - private ForExpression[] nextForExpressionStack = new ForExpression[30]; - private int nextForExpressionStackPos = -1; // Position of top entry in stack. - private boolean expressionValid = true; // Is the expression currently valid. - private String invalidMsg = null; // Msg for being invalid if default msg not sufficient. - private List expressionProxies; // List of expression proxies. The index of the proxy is its id. This list must never shrink in size. - - // A MarkEntry. To allow restore in case of error. - private static class MarkEntry { - public int markID; - public int controlStackPos; // Position of control stack at time of mark. - public int nextExpressionStackPos; // Position of nextForExpression stack at time of mark. - public int expressionProxiesPos; // Position of expressionProxies list at time of mark. - } - - private int highestMarkID = 0; // Next mark id. '0' is invalid, as in no marks. This is incremented for each new mark. Never decremented. - private MarkEntry currentMarkEntry; // Just a convienence to the current mark entry so no need to look into the list every time. - private List markEntries; // Stack of mark entries. - - // This class is here so we can add our special internal ForExpression: PROCESS_EXPRESSION. These are never used outside Expression. - private static class ExpressionEnum extends ForExpression { - - public ExpressionEnum(int value, String name) { - super(value, name); - } - - } - - // This is pushed onto the next expression stack, and when it is popped, then the expression is complete and ready to be pushed to the proxy side. - private static final ForExpression PROCESS_EXPRESSION = new ExpressionEnum(Integer.MIN_VALUE, "Process Expression"); //$NON-NLS-1$ - - // This is pushed onto the next expression stack for end block and will test if this there to make sure that it is being called correctly. - private static final ForExpression BLOCKEND_EXPRESSION = new ExpressionEnum(PROCESS_EXPRESSION.getValue()-2, "End Block Expression"); //$NON-NLS-1$ - - // This is pushed onto the next expression stack for end try and will test if this there to make sure that it is being called correctly. - private static final ForExpression TRYEND_EXPRESSION = new ExpressionEnum(BLOCKEND_EXPRESSION.getValue()-1, "End Try Expression"); //$NON-NLS-1$ - - // This is pushed onto the next expression stack for catch and will test if this there to make sure that it is being called correctly. - private static final ForExpression TRYCATCH_EXPRESSION = new ExpressionEnum(TRYEND_EXPRESSION.getValue()-1, "Catch Expression"); //$NON-NLS-1$ - - - // This is pushed onto the next expression stack for begin thread transfer and will test if this there to make sure that it is being called correctly. - private static final ForExpression THREADTRANSFER_EXPRESSION = new ExpressionEnum(TRYCATCH_EXPRESSION.getValue()-1, "Catch Expression"); //$NON-NLS-1$ - - // This is pushed onto the next expression stack for end subexpression and will test if this there to make sure that it is being called correctly. - private static final ForExpression SUBEXPRESSIONEND_EXPRESSION = new ExpressionEnum(THREADTRANSFER_EXPRESSION.getValue()-2, "End Subexpression"); //$NON-NLS-1$ - - /** - * Check the for expression, and if legal, set to the next valid for expression type, - * if it can. If the stack entry is ROOTEXPRESSION, and the forExpression is ROOTEXPRESSION, - * then the expression is allowed, but it is not popped. It must be popped later when appropriate. - * <p> - * This is for "block" expressions. We don't want to pop down the stack passed the ROOTEXPRESSION - * that got added by the create block until we get an end block. That allows root expressions to - * be added to the block without the stack popping up past the block start in the stack. - * - * @param forExpression - * @throws IllegalStateException - * - * @since 1.0.0 - */ - protected final void checkForExpression(ForExpression forExpression) throws IllegalStateException { - if (expressionValid) { - if (nextForExpressionStackPos == -1) - if (forExpression == ForExpression.ROOTEXPRESSION) - return; // valid. We are at the root (i.e. nothing is waiting). - else - ; // invalid. drop through - else if (nextForExpressionStack[nextForExpressionStackPos] == forExpression) { - // Valid, either the root expression matched (We don't implicitly pop those. That needs to be done explicitly). - // Or we matched non-root, those will be popped. - if (forExpression != ForExpression.ROOTEXPRESSION) { - popForExpression(); // Pop the stack since stack not a root expression. - } - return; - } - } else { - String expMsg = invalidMsg != null ? MessageFormat.format(ProxyMessages.Expression_InInvalidStateDueTo_EXC_, new Object[] {invalidMsg}) : ProxyMessages.Expression_InInvalidState_EXC_; - throw new IllegalStateException(expMsg); - } - - // If we got here, then invalid. - ForExpression expected = nextForExpressionStackPos >= 0 ? nextForExpressionStack[nextForExpressionStackPos] : ForExpression.ROOTEXPRESSION; - expressionValid = false; - throw new IllegalStateException(MessageFormat.format(ProxyMessages.Expression_TypeSentInInvalidOrder_EXC_, new Object[] {forExpression, expected})); - } - - /** - * Pop the top for expression, whatever it is. - * @throws IllegalStateException thrown if try to pop through through the current mark entry. The endMark is the only one who can do this. - * @since 1.1.0 - */ - protected final void popForExpression() throws IllegalStateException { - if (expressionValid && nextForExpressionStackPos >= 0) { - nextForExpressionStackPos--; - if (currentMarkEntry != null && nextForExpressionStackPos < currentMarkEntry.nextExpressionStackPos) { - nextForExpressionStackPos++; // Restore to what it was - throwInvalidMarkNesting(); - } - } - } - - /* - * @throws IllegalStateException - * - * @since 1.1.0 - */ - private void throwInvalidMarkNesting() throws IllegalStateException { - expressionValid = false; - throw new IllegalStateException(MessageFormat.format(ProxyMessages.Expression_InvalidMarkNesting, new Object[] {new Integer(currentMarkEntry != null ? currentMarkEntry.markID : 0)})); - } - - /** - * Peek into the for expression stack to see if the top entry is the passed in value. It will - * not pop the stack nor throw any exceptions. - * - * @param forExpression The top expression flag will be compared against this value. - * @return <code>true</code> if the top expression equals the parameter passed in. - * - * @since 1.0.0 - */ - protected final boolean peekForExpression(ForExpression forExpression) { - if (expressionValid) { - if (nextForExpressionStackPos == -1) - if (forExpression == ForExpression.ROOTEXPRESSION) - return true; // valid. We are at the root (i.e. nothing is waiting). - else - ; // invalid. drop through - else if (nextForExpressionStack[nextForExpressionStackPos] == forExpression) - return true; // Valid, the top expression matched. - } - return false; - } - - /** - * Mark this expression as now invalid. - */ - protected final void markInvalid() { - expressionValid = false; - } - - /** - * Mark this expression as now invalid, but supply a message to go with it. - * - * @param msg - * - * @since 1.0.0 - */ - protected final void markInvalid(String msg) { - invalidMsg = msg; - markInvalid(); - } - - public void close() { - nextForExpressionStackPos = -1; - controlStack.clear(); - if (expressionProxies != null) - markAllProxiesNotResolved(expressionProxies); // They weren't processed, close must of been called early. - expressionProxies = null; - markEntries = null; - expressionValid = false; - closeProxy(); - } - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#isValid() - */ - public boolean isValid() { - return expressionValid; - } - - /* - * Check if the pending expression is ready for evaluation. - * It is complete if the next entry on the stack is a PROCESS_EXPRESSION - */ - private boolean expressionReady() { - if (nextForExpressionStackPos >= 0 && nextForExpressionStack[nextForExpressionStackPos] == PROCESS_EXPRESSION) { - checkForExpression(PROCESS_EXPRESSION); // pop it - return true; - } else - return false; - } - - /* - * Push the next expression type. - */ - private void pushForExpression(ForExpression nextExpression) { - if (++nextForExpressionStackPos >= nextForExpressionStack.length) { - // Increase stack size. - ForExpression[] newStack = new ForExpression[nextForExpressionStackPos*2]; // So room to grow without excessive allocations. - System.arraycopy(nextForExpressionStack, 0, newStack, 0, nextForExpressionStack.length); - nextForExpressionStack = newStack; - } - nextForExpressionStack[nextForExpressionStackPos] = nextExpression; - } - - /* - * Check if expression is complete, and if it is, process it. - */ - private void processExpression() { - while (expressionReady()) { - try { - // We've received all of the expressions for the expression, so process it. - int expType = ((InternalExpressionTypes) pop()).getValue(); - switch (expType) { - case InternalExpressionTypes.CAST_EXPRESSION_VALUE: - pushCastToProxy((IProxyBeanType) pop()); - break; - case InternalExpressionTypes.INSTANCEOF_EXPRESSION_VALUE: - pushInstanceofToProxy((IProxyBeanType) pop()); - break; - case InternalExpressionTypes.PREFIX_EXPRESSION_VALUE: - pushPrefixToProxy((PrefixOperator)pop()); - break; - case InternalExpressionTypes.INFIX_EXPRESSION_VALUE: - pushInfixToProxy((InfixOperator) pop(), (InternalInfixOperandType) pop()); - break; - case InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION_VALUE: - pushArrayAccessToProxy(((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.ARRAY_CREATION_EXPRESSION_VALUE: - pushArrayCreationToProxy((IProxyBeanType) pop(), ((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION_VALUE: - pushArrayInitializerToProxy((IProxyBeanType) pop(), ((Integer) pop()).intValue(), ((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION_VALUE: - pushClassInstanceCreationToProxy((IProxyBeanType) pop(), ((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.FIELD_ACCESS_EXPRESSION_VALUE: - pushFieldAccessToProxy(pop(), ((Boolean) pop()).booleanValue()); - break; - case InternalExpressionTypes.METHOD_EXPRESSION_VALUE: - pushMethodInvocationToProxy(pop(), ((Boolean) pop()).booleanValue(), ((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.CONDITIONAL_EXPRESSION_VALUE: - pushConditionalToProxy((InternalConditionalOperandType) pop()); - break; - case InternalExpressionTypes.ASSIGNMENT_PROXY_EXPRESSION_VALUE: - pushAssignmentToProxy((ExpressionProxy) pop()); - break; - case InternalExpressionTypes.ASSIGNMENT_EXPRESSION_VALUE: - pushAssignmentToProxy(); - break; - case InternalExpressionTypes.BLOCK_END_EXPRESSION_VALUE: - pushBlockEndToProxy(((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.TRY_END_EXPRESSION_VALUE: - pushTryEndToProxy(((Integer) pop()).intValue()); - break; - case InternalExpressionTypes.THROW_EXPRESSION_VALUE: - pushThrowToProxy(); - break; - case InternalExpressionTypes.IF_TEST_EXPRESSION_VALUE: - pushIfTestToProxy(); - break; - case InternalExpressionTypes.IF_ELSE_EXPRESSION_VALUE: - pushIfElseToProxy((InternalIfElseOperandType) pop()); - break; - case InternalExpressionTypes.SUBEXPRESSION_END_EXPRESSION_VALUE: - pushSubexpressionEndToProxy(((Integer) pop()).intValue()); - break; - default: - internalProcessUnknownExpressionType(expType); - break; - } - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - } - - - private void internalProcessUnknownExpressionType(int expressionType) throws IllegalArgumentException { - if (!processUnknownExpressionType(expressionType)) - throw new IllegalArgumentException(); - } - - /** - * An unknown expression type was found in the processing of expression stack. Subclasses can override - * to process new types of expressions. - * <p> - * Overrides must return <code>true</code> if they processed the expression type. If they return <code>false</code> - * it means they didn't understand it either and we should do default processing for unknow type. - * @param expressionType - * @return <code>true</code> if type was processed, <code>false</code> if not known by subclass either. - * - * @since 1.0.0 - */ - protected boolean processUnknownExpressionType(int expressionType) { - return false; - } - - /** - * Create the expression. - * - * @param registry - * - * @since 1.0.0 - */ - protected Expression(ProxyFactoryRegistry registry) { - this.registry = registry; - this.beanProxyFactory = this.registry.getBeanProxyFactory(); - } - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#getRegistry() - */ - public ProxyFactoryRegistry getRegistry() { - return registry; - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#invokeExpression() - */ - public final void invokeExpression() throws ThrowableProxy, IllegalStateException, NoExpressionValueException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); // We are at the root. - popForExpression(); // Get rid of any intermediate roots. - checkForExpression(ForExpression.ROOTEXPRESSION); // We should be at true root now. We don't have more than one intermediate root pushed in sequence. - List proxies = expressionProxies; - expressionProxies = null; - pushInvoke(processExpressionProxyCallbacks(proxies), proxies); - } finally { - markInvalid(); // Mark invalid so any new calls after this will fail. - close(); - } - } - - /* - * Process the expression proxy callbacks, if any. - * @return the number of proxies that have callbacks. - */ - private int processExpressionProxyCallbacks(List proxies) { - if (proxies != null) { - // Strip list down to only those with callbacks and send on. - int proxiesWithCallbacks = 0; - for (ListIterator eps = proxies.listIterator(); eps.hasNext();) { - ExpressionProxy proxy = (ExpressionProxy) eps.next(); - if (!proxy.hasListeners()) - eps.set(null); // Remove it from the list. No one cares. - else - proxiesWithCallbacks++; - } - return proxiesWithCallbacks; - } - return 0; - } - - /** - * Called to validate this is a valid proxy for this expression. This could happen - * if a proxy from another expression is sent to this expression. If the proxy - * is a bean proxy or is an expression proxy for this expression, then this - * just returns. Else it will throw the {@link IllegalArgumentException}. - * @param proxy - * @throws IllegalArgumentException if the proxy is an expression proxy for another expression. - * - * @since 1.1.0.1 - */ - private void validateProxy(IProxy proxy) throws IllegalArgumentException { - if (proxy != null && (proxy.isExpressionProxy() && ((ExpressionProxy) proxy).getExpression() != this)) - throw new IllegalArgumentException(ProxyMessages.Expression_InvalidProxy); - } - - /** - * Called by subclass to fill in the value of an expression proxy. See {@link Expression#pullProxyValue(int, List))} for an example of who would call it. - * @param ep - * @param beanproxy - * - * @since 1.1.0 - */ - protected void fireProxyResolved(ExpressionProxy ep, IBeanProxy beanproxy) { - ep.fireResolved(beanproxy); - } - - /** - * Called by subclass to fire proxy was not resolved. See {@link Expression#pullProxyValue(int, List))} for an example of who would call it. - * @param ep - * - * @since 1.1.0 - */ - protected void fireProxyNotResolved(ExpressionProxy ep) { - ep.fireNotResolved(); - } - - /** - * Called by subclass to fire proxy resolved to a void return type. See {@link Expression#pullProxyValue(int, List))} for an example of who would call it. - * @param ep - * - * @since 1.1.0 - */ - protected void fireProxyVoid(ExpressionProxy ep) { - ep.fireVoidResolved(); - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#getExpressionValue() - */ - public final IBeanProxy getExpressionValue() throws ThrowableProxy, NoExpressionValueException, IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); // We are at the root. - popForExpression(); // Get rid of any intermediate roots. - checkForExpression(ForExpression.ROOTEXPRESSION); // We should be at true root now. We don't have more than one intermediate root pushed in sequence. - List proxies = expressionProxies; - expressionProxies = null; - return pullProxyValue(processExpressionProxyCallbacks(proxies), proxies); // Get the top value. - } finally { - markInvalid(); // Mark invalid so any new calls after this will fail. - close(); - } - } - - - /** - * Mark the list of proxies as not resolved. - * - * @since 1.1.0 - */ - protected void markAllProxiesNotResolved(List proxies) { - if (proxies != null) { - for (ListIterator eps = proxies.listIterator(); eps.hasNext();) { - ExpressionProxy proxy = (ExpressionProxy) eps.next(); - if (proxy != null && proxy.hasListeners()) - fireProxyNotResolved(proxy); - } - } - } - - private int blockNumber = -1; // Current block number. This is always incrementing. - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createBlockBegin() - */ - public final int createBlockBegin() throws IllegalStateException { - try { - // Blocks are special, they can be anywhere at root, of could be the true or else clause of an if/else. - if (peekForExpression(ForExpression.ROOTEXPRESSION)) - checkForExpression(ForExpression.ROOTEXPRESSION); - else if (peekForExpression(ForExpression.IF_TRUE)) - checkForExpression(ForExpression.IF_TRUE); - else - checkForExpression(ForExpression.IF_ELSE); - - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(BLOCKEND_EXPRESSION); - pushForExpression(ForExpression.ROOTEXPRESSION); - - pushBlockBeginToProxy(++blockNumber); - push(new Integer(blockNumber)); - push(InternalExpressionTypes.BLOCK_END_EXPRESSION); - processExpression(); - return blockNumber; - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createBlockBreak(int) - */ - public final void createBlockBreak(int blockNumber) throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - pushBlockBreakToProxy(blockNumber); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createBlockEnd() - */ - public final void createBlockEnd() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - popForExpression(); // Remove the root expression since block is done. - checkForExpression(BLOCKEND_EXPRESSION); // This needs to be next for it to be valid. - processExpression(); // Now let it handle the previously pushed end block, containing the block number being ended. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createArrayAccess(int, int) - */ - public final void createArrayAccess(ForExpression forExpression, int indexCount) { - try { - checkForExpression(forExpression); - pushForExpression(PROCESS_EXPRESSION); - int i = indexCount; - while (i-- > 0) - pushForExpression(ForExpression.ARRAYACCESS_INDEX); - pushForExpression(ForExpression.ARRAYACCESS_ARRAY); - - push(indexCount == 1 ? ARRAYACCESS_INDEX_1 : new Integer(indexCount)); - push(InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createArrayCreation(int, java.lang.String, int) - */ - public final void createArrayCreation(ForExpression forExpression, String type, int dimensionExpressionCount) - throws IllegalStateException { - pushArrayCreation(forExpression, getProxyBeanType(type), dimensionExpressionCount); - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createArrayCreation(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.IProxyBeanType, int) - */ - public final void createArrayCreation(ForExpression forExpression, IProxyBeanType type, int dimensionExpressionCount) - throws IllegalStateException, IllegalArgumentException { - pushArrayCreation(forExpression, type, dimensionExpressionCount); - } - - private void pushArrayCreation(ForExpression forExpression, IProxyBeanType type, int dimensionExpressionCount) throws IllegalStateException, IllegalArgumentException { - try { - checkForExpression(forExpression); - validateProxy(type); - switch (dimensionExpressionCount) { - case 0: - push(ARRAY_CREATION_DIMENSION_0); - break; - case 1: - push(ARRAY_CREATION_DIMENSION_1); - break; - default: - push(new Integer(dimensionExpressionCount)); - break; - } - push(type); - push(InternalExpressionTypes.ARRAY_CREATION_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - if (dimensionExpressionCount == 0) - pushForExpression(ARRAY_INITIALIZER); - else { - while (dimensionExpressionCount-- > 0) - pushForExpression(ForExpression.ARRAYCREATION_DIMENSION); - } - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createArrayInitializer(int) - */ - public final void createArrayInitializer(int expressionCount) throws IllegalStateException { - try { - // This is special, we could be waiting for an array initializer or an array initializer expression. - // We will peek to see what it is and handle it. - if (peekForExpression(ARRAY_INITIALIZER)) - checkForExpression(ARRAY_INITIALIZER); - else - checkForExpression(ForExpression.ARRAYINITIALIZER_EXPRESSION); - - // At this point in time that stack may either have: - // array_type, array_creation - // strip_count, array_type, array_initializer - // So we can get the array type from peek(2), and get the command type from peek(1). - // Then if the command type is array_creation, strip_count will be inited to 0, while - // else it will be inited to peek(3). From that we can increment the strip_count to - // use for this initializer. - // - // We need to peek here because we will be adding various pushes to the stack and we - // need to get the info while it is still at the top of the stack. - Object arrayType = peek(2); - int stripCount = 0; - if (peek(1) == InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION) - stripCount = ((Integer) peek(3)).intValue(); - - switch (expressionCount) { - case 0: - push(ARRAYINITIALIZER_COUNT_0); - break; - case 1: - push(ARRAYINITIALIZER_COUNT_1); - break; - case 2: - push(ARRAYINITIALIZER_COUNT_2); - break; - default: - push(new Integer(expressionCount)); - break; - } - - if (arrayType instanceof String) { - String at = (String) arrayType; - int i = at.lastIndexOf("[]"); //$NON-NLS-1$ - if (i == -1) - throw new IllegalArgumentException(MessageFormat.format( - ProxyMessages.Expression_ArrayTypeNotAnArray_EXC_, new Object[] { arrayType})); - arrayType = getProxyBeanType(at); - } else if (!(arrayType instanceof IProxyBeanType)) { - throw new IllegalArgumentException(MessageFormat.format( - ProxyMessages.Expression_ArrayTypeNotAnArray_EXC_, new Object[] { arrayType})); - } - push(new Integer(++stripCount)); - push(arrayType); - push(InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - while (expressionCount-- > 0) - pushForExpression(ForExpression.ARRAYINITIALIZER_EXPRESSION); - - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createCastExpression(int, java.lang.String) - * A cast expression has one nested expression. - */ - public final void createCastExpression(ForExpression forExpression, String type) throws IllegalStateException { - pushCast(forExpression, getProxyBeanType(type)); // Push this onto the local stack to wait for completion. - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createCastExpression(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.IProxyBeanType) - */ - public final void createCastExpression(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException, IllegalArgumentException { - pushCast(forExpression, type); // Push this onto the local stack to wait for completion. - } - - /* - * Push for a cast. - */ - private void pushCast(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException, IllegalArgumentException { - try { - checkForExpression(forExpression); - validateProxy(type); - push(type); - push(InternalExpressionTypes.CAST_EXPRESSION); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.CAST_EXPRESSION); // The next expression must be for the cast expression. - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createClassInstanceCreation(int, java.lang.String, int) - */ - public final void createClassInstanceCreation(ForExpression forExpression, String type, int argumentCount) - throws IllegalStateException { - pushClassInstanceCreation(forExpression, getProxyBeanType(type), argumentCount); // Push this onto the local stack to wait for completion. - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createClassInstanceCreation(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.IProxyBeanType, int) - */ - public final void createClassInstanceCreation(ForExpression forExpression, IProxyBeanType type, int argumentCount) - throws IllegalStateException, IllegalArgumentException { - pushClassInstanceCreation(forExpression, type, argumentCount); // Push this onto the local stack to wait for completion. - } - - /* - * Push for a class instance creation - */ - private void pushClassInstanceCreation(ForExpression forExpression, IProxyBeanType type, int argumentCount) throws IllegalStateException, IllegalArgumentException { - try { - checkForExpression(forExpression); - validateProxy(type); - switch (argumentCount) { - case 0: - push(CLASS_INSTANCE_CREATION_ARGUMENTS_0); - break; - case 1: - push(CLASS_INSTANCE_CREATION_ARGUMENTS_1); - break; - default: - push(new Integer(argumentCount)); - break; - } - push(type); - push(InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - while (argumentCount-- > 0) - pushForExpression(ForExpression.CLASSINSTANCECREATION_ARGUMENT); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createConditionalExpression(int) - */ - public final void createConditionalExpression(ForExpression forExpression) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.CONDITIONAL_FALSE); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.CONDITIONAL_TRUE); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.CONDITIONAL_CONDITION); - - push(InternalConditionalOperandType.CONDITIONAL_FALSE); - push(InternalExpressionTypes.CONDITIONAL_EXPRESSION); - push(InternalConditionalOperandType.CONDITIONAL_TRUE); - push(InternalExpressionTypes.CONDITIONAL_EXPRESSION); - push(InternalConditionalOperandType.CONDITIONAL_TEST); - push(InternalExpressionTypes.CONDITIONAL_EXPRESSION); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createFieldAccess(int, java.lang.String, boolean) - */ - public final void createFieldAccess(ForExpression forExpression, String fieldName, boolean hasReceiver) throws IllegalStateException, IllegalArgumentException { - try { - // Only for string fieldnames is this invalid when no receiver because no way to determine receiver. (Don't handle implicit "this" yet for fields). - // For the accessor that takes a IFieldProxy we can get away with no receiver because the field proxy can determine if static or not, and if not - // static it will fail at evaluation time. - if (!hasReceiver) - throw new IllegalArgumentException(MessageFormat.format( - ProxyMessages.Expression_CannotHandleNoReceiveOnFieldAccess_EXC_, new Object[] { fieldName})); - pushFieldAccess(forExpression, fieldName, hasReceiver); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createIfElse(boolean) - */ - public final void createIfElse(boolean hasElseClause) throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - if (hasElseClause) { - pushForExpression(ForExpression.IF_ELSE); - } - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.IF_TRUE); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.IF_CONDITION); - - // We still push an else clause so that we know when finished. We don't have a pushForExpression for it because there - // won't be any. But the else clause processing will be on the push stack so that we can clean up when end of if stmt occurs. - push(InternalIfElseOperandType.ELSE_CLAUSE); - push(InternalExpressionTypes.IF_ELSE_EXPRESSION); - - push(InternalIfElseOperandType.TRUE_CLAUSE); - push(InternalExpressionTypes.IF_ELSE_EXPRESSION); - push(InternalExpressionTypes.IF_TEST_EXPRESSION); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * Push the field access. - * @param forExpression - * @param field String if field name, or IProxyField. - * @param hasReceiver - * @throws IllegalAccessException - * - * @since 1.1.0 - */ - private void pushFieldAccess(ForExpression forExpression, Object field, boolean hasReceiver) throws IllegalStateException { - try { - checkForExpression(forExpression); - push(hasReceiver ? Boolean.TRUE : Boolean.FALSE); // We have a receiver - push(field); - push(InternalExpressionTypes.FIELD_ACCESS_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - if (hasReceiver) - pushForExpression(ForExpression.FIELD_RECEIVER); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createInfixExpression(int, int, int) - */ - public final void createInfixExpression(ForExpression forExpression, InfixOperator operator, int extendedOperandCount) throws IllegalStateException { - try { - checkForExpression(forExpression); - push(InternalInfixOperandType.INFIX_LAST_OPERAND); - push(operator); - push(InternalExpressionTypes.INFIX_EXPRESSION); - int i = extendedOperandCount; - while (i-- > 0) { - push(InternalInfixOperandType.INFIX_OTHER_OPERAND); - push(operator); - push(InternalExpressionTypes.INFIX_EXPRESSION); - } - push(InternalInfixOperandType.INFIX_LEFT_OPERAND); - push(operator); - push(InternalExpressionTypes.INFIX_EXPRESSION); - - i = extendedOperandCount; - while (i-- > 0) { - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.INFIX_EXTENDED); - } - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.INFIX_RIGHT); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.INFIX_LEFT); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createInstanceofExpression(int, java.lang.String) - */ - public final void createInstanceofExpression(ForExpression forExpression, String type) throws IllegalStateException { - pushInstanceof(forExpression, getProxyBeanType(type)); // Push this onto the local stack to wait for completion. - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createInstanceofExpression(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.IProxyBeanType) - */ - public final void createInstanceofExpression(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException, IllegalArgumentException { - pushInstanceof(forExpression, type); // Push this onto the local stack to wait for completion. - } - - /* - * Push for a cast. - */ - private void pushInstanceof(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException, IllegalArgumentException { - try { - checkForExpression(forExpression); - validateProxy(type); - push(type); - push(InternalExpressionTypes.INSTANCEOF_EXPRESSION); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.INSTANCEOF_VALUE); // The next expression must be for the instance of expression. - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createMethodInvocation(int, java.lang.String, boolean, int) - */ - public final void createMethodInvocation(ForExpression forExpression, String name, boolean hasReceiver, int argumentCount) - throws IllegalStateException, IllegalArgumentException { - try { - // Only for string methodnames is this invalid when no receiver because no way to determine receiver. (Don't handle implicit "this" yet for methods). - // For the accessor that takes a IFieldProxy we can get away with no receiver because the field proxy can determine if static or not, and if not - // static it will fail at evaluation time. - if (!hasReceiver) - throw new IllegalArgumentException(MessageFormat.format( - ProxyMessages.Expression_MethodsNeedReceiver_EXC_, new Object[] { name})); - - pushMethodInvocation(forExpression, name, hasReceiver, argumentCount); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /** - * @param forExpression - * @param method String for method name, IMethodProxy otherwise. - * @param hasReceiver - * @param argumentCount - * @throws ThrowableProxy - * @throws NoExpressionValueException - * - * @since 1.1.0 - */ - private void pushMethodInvocation(ForExpression forExpression, Object method, boolean hasReceiver, int argumentCount) throws IllegalArgumentException, IllegalStateException { - try { - checkForExpression(forExpression); - switch (argumentCount) { - case 0: - push(METHOD_ARGUMENTS_0); - break; - case 1: - push(METHOD_ARGUMENTS_1); - break; - default: - push(new Integer(argumentCount)); - break; - } - push(hasReceiver ? Boolean.TRUE : Boolean.FALSE); - push(method); - push(InternalExpressionTypes.METHOD_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - while (argumentCount-- > 0) - pushForExpression(ForExpression.METHOD_ARGUMENT); - if (hasReceiver) - pushForExpression(ForExpression.METHOD_RECEIVER); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrefixExpression(int, org.eclipse.jem.internal.proxy.initParser.tree.PrefixOperator) - */ - public final void createPrefixExpression(ForExpression forExpression, PrefixOperator operator) throws IllegalStateException { - try { - checkForExpression(forExpression); - push(operator); - push(InternalExpressionTypes.PREFIX_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.PREFIX_OPERAND); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /** - * Create a new instance using the initialization string. The result must be compatible with the - * given type. This is not on the IExpression interface because it is not for use of regular - * customers. It is here for the allocation processer to create entries that are just strings. - * <p> - * This is not customer advanced API. This API for the implementers of registries and expression subclasses. - * - * @param forExpression - * @param initializationString - * @param type - * @throws IllegalStateException - * @throws IllegalArgumentException - * - * @since 1.1.0 - */ - public final void createNewInstance(ForExpression forExpression, String initializationString, IProxyBeanType type) throws IllegalStateException, IllegalArgumentException{ - try { - checkForExpression(forExpression); - validateProxy(type); - pushNewInstanceToProxy(initializationString, type); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createNull(int) - */ - public final void createNull(ForExpression forExpression) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(null); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTypeLiteral(int, java.lang.String) - */ - public final void createTypeLiteral(ForExpression forExpression, String type) throws IllegalStateException { - createProxyExpression(forExpression, getProxyBeanType(type)); - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTypeReceiver(java.lang.String) - */ - public final void createTypeReceiver(String type) throws IllegalStateException { - pushTypeReceiver(getProxyBeanType(type)); - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTypeReceiver(org.eclipse.jem.internal.proxy.core.IProxyBeanType) - */ - public final void createTypeReceiver(IProxyBeanType type) throws IllegalStateException, IllegalArgumentException { - validateProxy(type); - pushTypeReceiver(type); - } - - /* - * Push for a type receiver. - * @param type - * - * @since 1.0.0 - */ - private void pushTypeReceiver(IProxyBeanType type) throws IllegalStateException { - try { - // This is special because type receivers are only valid as the receiver for a field access or a method access. - // Since each has a different forExpression we need to test for one or the other. It doesn't make any difference - // which one it is, but it must be one or the other. - if (peekForExpression(ForExpression.FIELD_RECEIVER)) - checkForExpression(ForExpression.FIELD_RECEIVER); - else - checkForExpression(ForExpression.METHOD_RECEIVER); - - pushTypeReceiverToProxy(type); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * For all of the primitive types we will be creating a IBeanProxy for them. That is because that - * would be the expected result of the expression, and no need to get the other side involved. - */ - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, boolean) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, boolean value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, char) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, char value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, byte) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, byte value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, double) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, double value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, float) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, float value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, int) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, int value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, long) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, long value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, short) - */ - public final void createPrimitiveLiteral(ForExpression forExpression, short value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createStringLiteral(int, java.lang.String) - */ - public final void createStringLiteral(ForExpression forExpression, String value) throws IllegalStateException { - try { - checkForExpression(forExpression); - pushToProxy(beanProxyFactory.createBeanProxyWith(value)); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createProxyExpression(int, org.eclipse.jem.internal.proxy.core.IProxy) - */ - public final void createProxyExpression(ForExpression forExpression, IProxy proxy) throws IllegalStateException, IllegalArgumentException { - try { - checkForExpression(forExpression); - validateProxy(proxy); - pushToProxy(proxy); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createAssignmentExpression(int) - */ - public final void createAssignmentExpression(ForExpression forExpression) throws IllegalStateException { - try { - checkForExpression(forExpression); - push(InternalExpressionTypes.ASSIGNMENT_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.ASSIGNMENT_RIGHT); - pushForExpression(ForExpression.ASSIGNMENT_LEFT); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createAssignmentExpression(int) - */ - public final ExpressionProxy createProxyAssignmentExpression(ForExpression forExpression) throws IllegalStateException { - try { - checkForExpression(forExpression); - ExpressionProxy proxy = allocateExpressionProxy(NORMAL_EXPRESSION_PROXY); - push(proxy); - push(InternalExpressionTypes.ASSIGNMENT_PROXY_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.ASSIGNMENT_RIGHT); - processExpression(); // See if previous expression is ready for processing. - return proxy; - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /** - * Called by registries to create an expression proxy for a bean type. It is not in the interface because it should - * only be called by the proxy registry to create an expression proxy. It shouldn't be called outside of the registries - * because there may already exist in the registry the true IBeanTypeProxy, and that one should be used instead. - * <p> - * This is not customer advanced API. This API for the implementers of registries and expression subclasses. - * - * @param typeName - * @return expression proxy that is hooked up and will notify when resolved. It can be called at any time. The resolution will occur at this point in the - * execution stack, but since it will not interfere with the stack this is OK, other than it could throw a ClassNotFoundException on the - * execution. - * - * @since 1.1.0 - */ - public final IProxyBeanType createBeanTypeExpressionProxy(String typeName) { - IBeanTypeExpressionProxy proxy = (IBeanTypeExpressionProxy) allocateExpressionProxy(BEANTYPE_EXPRESSION_PROXY); - proxy.setTypeName(typeName); - // This can be sent at any time. It doesn't matter what is on the expression stack. It will be sent to be resolved immediately. - pushBeanTypeToProxy(proxy); - return proxy; - } - - /** - * Called by registries to create an expression proxy for a method. It is not in the interface because it should - * only be called by the proxy registry to create an expression proxy. It shouldn't be called outside of the registries - * because there may already exist in the registry the true IMethodProxy, and that one should be used instead. - * <p> - * This is not customer advanced API. This API for the implementers of registries and expression subclasses. - * - * @param declaringType - * @param methodName - * @param parameterTypes parameter types or <code>null</code> if no parameter types. - * @return - * - * @throws IllegalArgumentException - * @since 1.1.0 - */ - public final IProxyMethod createMethodExpressionProxy(IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes) throws IllegalArgumentException{ - validateProxy(declaringType); - if (parameterTypes != null && parameterTypes.length > 0) { - for (int i = 0; i < parameterTypes.length; i++) { - validateProxy(parameterTypes[i]); - } - } - ExpressionProxy proxy = allocateExpressionProxy(METHOD_EXPRESSION_PROXY); - // This can be sent at any time. It doesn't matter what is on the expression stack. It will be sent to be resolved immediately. - pushMethodToProxy(proxy, declaringType, methodName, parameterTypes); - return (IProxyMethod) proxy; - } - - /** - * Called by registries to create an expression proxy for a field. It is not in the interface because it should - * only be called by the proxy registry to create an expression proxy. It shouldn't be called outside of the registries - * because there may already exist in the registry the true IFieldProxy, and that one should be used instead. - * <p> - * This is not customer advanced API. This API for the implementers of registries and expression subclasses. - * - * @param declaringType - * @param fieldName - * @return - * - * @throws IllegalArgumentException - * @since 1.1.0 - */ - public final IProxyField createFieldExpressionProxy(IProxyBeanType declaringType, String fieldName) throws IllegalArgumentException { - validateProxy(declaringType); - ExpressionProxy proxy = allocateExpressionProxy(FIELD_EXPRESSION_PROXY); - // This can be sent at any time. It doesn't matter what is on the expression stack. It will be sent to be resolved immediately. - pushFieldToProxy(proxy, declaringType, fieldName); - return (IProxyField) proxy; - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createProxyReassignmentExpression(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.ExpressionProxy) - */ - public final void createProxyReassignmentExpression(ForExpression forExpression, ExpressionProxy proxy) throws IllegalStateException, IllegalArgumentException { - try { - checkForExpression(forExpression); - if (!proxy.isValidForReassignment()) - throw new IllegalArgumentException(MessageFormat.format(ProxyMessages.Expression_CreateProxyReassignmentExpression_InvalidForReassignment_EXC_, new Object[]{proxy.toString()})); - push(proxy); - push(InternalExpressionTypes.ASSIGNMENT_PROXY_EXPRESSION); - - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.ASSIGNMENT_RIGHT); - processExpression(); // See if previous expression is ready for processing. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - protected static final int NORMAL_EXPRESSION_PROXY = 0; - protected static final int BEANTYPE_EXPRESSION_PROXY = 1; - protected static final int METHOD_EXPRESSION_PROXY = 2; - protected static final int FIELD_EXPRESSION_PROXY = 3; - /** - * Allocate a new ExpressionProxy - * @return new ExpressionProxy. - * - * @since 1.1.0 - */ - protected final ExpressionProxy allocateExpressionProxy(int proxyType) { - if (expressionProxies == null) - expressionProxies = new ArrayList(); - // It is very important that this always creates a proxy id that is greater than all previous. This is - // so that it can be assured that proxies will be resolved in order of creation. - // Currently this is done here by using expressionProxies.size(). - ExpressionProxy proxy = createExpressionProxy(proxyType, expressionProxies.size()); - expressionProxies.add(proxy); - return proxy; - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createFieldAccess(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.IProxyField, boolean) - */ - public final void createFieldAccess(ForExpression forExpression, IProxyField fieldProxy, boolean hasReceiver) throws IllegalStateException, IllegalArgumentException { - validateProxy(fieldProxy); - pushFieldAccess(forExpression, fieldProxy, hasReceiver); - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createMethodInvocation(org.eclipse.jem.internal.proxy.initParser.tree.ForExpression, org.eclipse.jem.internal.proxy.core.IProxyMethod, boolean, int) - */ - public final void createMethodInvocation(ForExpression forExpression, IProxyMethod methodProxy, boolean hasReceiver, int argumentCount) throws IllegalArgumentException, - IllegalStateException { - validateProxy(methodProxy); - pushMethodInvocation(forExpression, methodProxy, hasReceiver, argumentCount); - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createSimpleFieldAccess(org.eclipse.jem.internal.proxy.core.IProxyField, org.eclipse.jem.internal.proxy.core.IProxy) - */ - public final ExpressionProxy createSimpleFieldAccess(IProxyField field, IProxy receiver) throws IllegalStateException, IllegalArgumentException { - validateProxy(field); - validateProxy(receiver); - ExpressionProxy result = createProxyAssignmentExpression(ForExpression.ROOTEXPRESSION); - createFieldAccess(ForExpression.ASSIGNMENT_RIGHT, field, receiver != null); - if (receiver != null) - createProxyExpression(ForExpression.FIELD_RECEIVER, receiver); - return result; - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createSimpleFieldSet(org.eclipse.jem.internal.proxy.core.IProxyField, org.eclipse.jem.internal.proxy.core.IProxy, org.eclipse.jem.internal.proxy.core.IProxy, boolean) - */ - public final ExpressionProxy createSimpleFieldSet(IProxyField field, IProxy receiver, IProxy value, boolean wantResult) throws IllegalStateException, IllegalArgumentException { - validateProxy(field); - validateProxy(receiver); - ExpressionProxy result = null; - ForExpression forExpression = ForExpression.ROOTEXPRESSION; - if (wantResult) { - result = createProxyAssignmentExpression(forExpression); - forExpression = ForExpression.ASSIGNMENT_RIGHT; - } - createAssignmentExpression(forExpression); - createFieldAccess(ForExpression.ASSIGNMENT_LEFT, field, receiver != null); - if (receiver != null) - createProxyExpression(ForExpression.FIELD_RECEIVER, receiver); - createProxyExpression(ForExpression.ASSIGNMENT_RIGHT, value); - return result; - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createSimpleMethodInvoke(org.eclipse.jem.internal.proxy.core.IMethodProxy, org.eclipse.jem.internal.proxy.core.IProxy, org.eclipse.jem.internal.proxy.core.IProxy[], boolean) - */ - public final ExpressionProxy createSimpleMethodInvoke(IProxyMethod method, IProxy receiver, IProxy[] arguments, boolean wantResult) - throws IllegalStateException, IllegalArgumentException { - validateProxy(method); - validateProxy(receiver); - if (arguments != null && arguments.length > 0) { - for (int i = 0; i < arguments.length; i++) { - validateProxy(arguments[i]); - } - } - ForExpression nextExpression = ForExpression.ROOTEXPRESSION; - ExpressionProxy result = null; - if (wantResult) { - result = createProxyAssignmentExpression(nextExpression); - nextExpression = ForExpression.ASSIGNMENT_RIGHT; - } - createMethodInvocation(nextExpression, method, receiver != null, arguments != null ? arguments.length : 0); - if (receiver != null) - createProxyExpression(ForExpression.METHOD_RECEIVER, receiver); - if (arguments != null) { - for (int i = 0; i < arguments.length; i++) { - createProxyExpression(ForExpression.METHOD_ARGUMENT, arguments[i]); - } - } - return result; - } - - private int subexpressionNumber = -1; // Current subexpression number. This is always incrementing. - - public void createSubexpression() throws IllegalStateException { - try { - // Subexpressions are special, they can be anywhere. - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(SUBEXPRESSIONEND_EXPRESSION); - pushForExpression(ForExpression.ROOTEXPRESSION); - - pushSubexpressionBeginToProxy(++subexpressionNumber); - push(new Integer(subexpressionNumber)); - push(InternalExpressionTypes.SUBEXPRESSION_END_EXPRESSION); - processExpression(); - return; - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - public void createSubexpressionEnd() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - popForExpression(); // Remove the root expression since block is done. - checkForExpression(SUBEXPRESSIONEND_EXPRESSION); // This needs to be next for it to be valid. - processExpression(); // Now let it handle the previously pushed end subexpression, containing the subexpression number being ended. - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - private int tryNumber = -1; // Current try number. This is always incrementing. - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTry() - */ - public final void createTry() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - pushForExpression(PROCESS_EXPRESSION); // Set up so that when reached we can process the TRY_END that we've pushed data for later in this method. - pushForExpression(TRYEND_EXPRESSION); // Must get a try end before we can process it. - pushForExpression(TRYCATCH_EXPRESSION); // Must get a catch/finally clause (or try end, which knows how to handle this). - pushForExpression(ForExpression.ROOTEXPRESSION); // Expecting root expressions for the try clause. - - pushTryBeginToProxy(++tryNumber); - push(new Integer(tryNumber)); - push(InternalExpressionTypes.TRY_END_EXPRESSION); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTryCatchClause(org.eclipse.jem.internal.proxy.core.IProxyBeanType, boolean) - */ - public final ExpressionProxy createTryCatchClause(IProxyBeanType exceptionType, boolean wantExceptionReturned) - throws IllegalStateException, IllegalArgumentException { - validateProxy(exceptionType); - return pushTryCatch(exceptionType, wantExceptionReturned); - } - - /* - * (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTryCatchClause(java.lang.String, boolean) - */ - public final ExpressionProxy createTryCatchClause(String exceptionType, boolean wantExceptionReturned) - throws IllegalStateException { - return pushTryCatch(getProxyBeanType(exceptionType), wantExceptionReturned); - } - - /** - * @param exceptionType - * @param wantExceptionReturned - * @return - * @throws IllegalStateException - * - * @since 1.1.0 - */ - private ExpressionProxy pushTryCatch(IProxyBeanType exceptionType, boolean wantExceptionReturned) throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - popForExpression(); // Remove the root expression since try or previous catch clause is done. - checkForExpression(TRYCATCH_EXPRESSION); // This needs to be next for it to be valid. - pushForExpression(TRYCATCH_EXPRESSION); // Set up for a following catch/finally clause. - pushForExpression(ForExpression.ROOTEXPRESSION); // Root expressions are next for the catch clause. - - int tryNumber = ((Integer) peek(2)).intValue(); // Get the try#. It should be in this place on the stack. - - ExpressionProxy ep = null; - if (wantExceptionReturned) - ep = allocateExpressionProxy(NORMAL_EXPRESSION_PROXY); - pushTryCatchClauseToProxy(tryNumber, exceptionType, ep); - - processExpression(); - return ep; - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTryEnd() - */ - public final void createTryEnd() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - popForExpression(); // Remove the root expression since try or previous catch clause is done. - if (peekForExpression(TRYCATCH_EXPRESSION)) - checkForExpression(TRYCATCH_EXPRESSION); // This may of been next if no finally clause was added. If a finally clause was added this would not be here. - checkForExpression(TRYEND_EXPRESSION); // And this needs to be after that to be valid. - - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createTryFinallyClause() - */ - public final void createTryFinallyClause() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - popForExpression(); // Remove the root expression since try or previous catch clause is done. - checkForExpression(TRYCATCH_EXPRESSION); // This needs to be next for it to be valid. - pushForExpression(ForExpression.ROOTEXPRESSION); // Root expressions are next for the finally clause. - - int tryNumber = ((Integer) peek(2)).intValue(); // Get the try#. It should be in this place on the stack. - - pushTryFinallyClauseToProxy(tryNumber); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createRethrow() - */ - public final void createRethrow() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - popForExpression(); // Remove the root expression since try or previous catch clause is done. - checkForExpression(TRYCATCH_EXPRESSION); // This needs to be next for it to be valid. - // It is in a valid state, so put the catch and root back on so that things work correctly. - pushForExpression(TRYCATCH_EXPRESSION); - pushForExpression(ForExpression.ROOTEXPRESSION); - - int tryNumber = ((Integer) peek(2)).intValue(); // Get the try#. It should be in this place on the stack. - - pushRethrowToProxy(tryNumber); - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /* (non-Javadoc) - * @see org.eclipse.jem.internal.proxy.core.IExpression#createThrow() - */ - public final void createThrow() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - push(InternalExpressionTypes.THROW_EXPRESSION); - pushForExpression(PROCESS_EXPRESSION); - pushForExpression(ForExpression.THROW_OPERAND); // The next expression must be for the throw value. - processExpression(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - public final int mark() throws IllegalStateException { - try { - checkForExpression(ForExpression.ROOTEXPRESSION); - ++highestMarkID; - currentMarkEntry = new MarkEntry(); - currentMarkEntry.markID = highestMarkID; - currentMarkEntry.controlStackPos = controlStack.size() - 1; - currentMarkEntry.nextExpressionStackPos = nextForExpressionStackPos; - currentMarkEntry.expressionProxiesPos = expressionProxies != null ? expressionProxies.size() - 1 : -1; - if (markEntries == null) - markEntries = new ArrayList(5); - markEntries.add(currentMarkEntry); - pushMarkToProxy(highestMarkID); - return highestMarkID; - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - public void endMark(int markNumber) throws IllegalStateException { - if (isValid()) { - // Can only do a valid end mark if we are at root. If not at root, we fall through and treat as invalid. - if (peekForExpression(ForExpression.ROOTEXPRESSION)) { - checkForExpression(ForExpression.ROOTEXPRESSION); // Now remove it if it should be removed. - // If the current mark number is not the same as the incoming mark number, we have improper nesting. - if (currentMarkEntry == null || currentMarkEntry.markID != markNumber) - throwInvalidMarkNesting(); // We have improper nesting. - // We are popping the current mark. Since we are valid, just move up one in the mark stack. - MarkEntry me = (MarkEntry) markEntries.remove(markEntries.size()-1); - if (!markEntries.isEmpty()) - currentMarkEntry = (MarkEntry) markEntries.get(markEntries.size()-1); - else - currentMarkEntry = null; - pushEndmarkToProxy(markNumber, false); - if (me.controlStackPos != controlStack.size()-1 || me.nextExpressionStackPos != nextForExpressionStackPos) - throwInvalidMarkNesting(); // The stacks should be back to the same size at this point for a valid end mark. - return; - } - } - - // It was invalid, or became invalid. - if (markEntries == null) - throwInvalidMarkNesting(); // We have no marks, so this is an invalid end mark. - - // We are invalid, need to pop to the given markNumber. - // Starting from the end we search back to find the entry for the given mark number. We do it - // from the end because it is more likely to be closer to the end than to the beginning. - for (int i = markEntries.size()-1; i >=0; i--) { - MarkEntry me = (MarkEntry) markEntries.get(i); - if (me.markID == markNumber) { - // Found it. - // Trim the control stack down to the size at time of mark. (No easy way to do this other than repeated remove's. - // We do it backwards to eliminate repeated shuffling of entries. - for (int j = controlStack.size()-1; j > me.controlStackPos; j--) { - controlStack.remove(j); - } - - // Trim the expression stack. This is simple, just reset the next entry pointer. - nextForExpressionStackPos = me.nextExpressionStackPos; - - if (expressionProxies != null) { - // Now we need to mark all of the expression proxies that occured after the mark as - // not resolved (since someone may be listening), and remove them, and reuse the proxies. - for (int j = expressionProxies.size()-1; j > me.expressionProxiesPos; j--) { - ExpressionProxy proxy = (ExpressionProxy) expressionProxies.remove(j); - if (proxy != null && proxy.hasListeners()) - fireProxyNotResolved(proxy); - } - } - - // Now that we know it is valid, we want to remove all of the mark entries above it in the stack - // since those are now invalid. We couldn't remove them as we were searching for the entry because - // if the entry wasn't found we didn't want to wipe out the probably valid ones. - for (int j = markEntries.size()-1; j >= i; j--) { - markEntries.remove(j); - } - - if (!markEntries.isEmpty()) - currentMarkEntry = (MarkEntry) markEntries.get(markEntries.size()-1); - else - currentMarkEntry = null; - pushEndmarkToProxy(markNumber, true); - expressionValid = true; - return; - } - } - throwInvalidMarkNesting(); // The mark number wasn't found, so this is an invalid end mark. - } - - /** - * Begin the transfer of the expression to another thread. - * <p> - * This is used when the expression needs to continue to be built up, but it needs - * to be done on a different thread. The reason for doing something special other - * than just using it on the other thread is that some proxy registries connections are - * tied through the thread. If you switched to another thread the connections would not - * be properly set up. - * This is not on the IExpression interface because even though it is API, it is tricky - * to use and so not exposed to everyone. Users can legitimately cast to Expression and - * use this as API for advanced use. - * <p> - * This is used to begin the transfer. It puts it into a state ready for the transfer. Calling this - * method will cause a synchronization of the expression up to the current level. This means - * that it will not return until the expression has been completely processed in the proxy registry - * up to this point. Typically the connection is a pipe where the instructions are just pushed onto - * it and the caller is not held up waiting for the registry to process it. - * <p> - * Then when the other thread is done, it will call beginTransferThread itself to signal that it is done - * and that the old thread can pick it up. Then the old thread will call transferThread to pick up processing. - * <p> - * It will be: - * <pre><code> - * ... expression stuff ... - * expression.beginTransferThread() - * ... do what is necessary to get to the other thread ... - * ... on other thread: - * expression.transferThread(); - * try { - * ... do your expression stuff on this thread ... - * } finally { - * expression.beginTransferThread(); // This is to return it to old thread. - * } - * ... tell old thread to pick up ... - * ... back on old thread: - * expression.transferThread(); - * ... do more expression stuff ... - * expression.invokeExpression(); - * </code></pre> - * - * @throws IllegalStateException - * @throws ThrowableProxy Thrown if there was an exception with the remote vm during this request. - * @since 1.1.0 - */ - public final void beginTransferThread() throws IllegalStateException, ThrowableProxy { - try { - pushForExpression(THREADTRANSFER_EXPRESSION); - pushBeginTransferThreadToProxy(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - /** - * Transfer the expression to the current thread. - * <p> - * This is called to actually transfer to the current thread. It must be the next call against - * the expression after the beginTransferThread, but on the new thread. - * <p> - * This is not on the IExpression interface because even though it is API, it is tricky - * to use and so not exposed to everyone. Users can legitimately cast to Expression and - * use this as API for advanced use. - * @see Expression#beginTransferThread() for a full explanation. - * @throws IllegalStateException - * - * @since 1.1.0 - */ - public final void transferThread() throws IllegalStateException { - try { - checkForExpression(THREADTRANSFER_EXPRESSION); - pushTransferThreadToProxy(); - } catch (RuntimeException e) { - markInvalid(); - throw e; - } - } - - - /** - * Get the IProxyBeanType for the type string sent in. - * @param type - * @return - * - * @since 1.1.0 - */ - protected IProxyBeanType getProxyBeanType(String type) { - return getRegistry().getBeanTypeProxyFactory().getBeanTypeProxy(this, type); - } - - /** - * Create the expression proxy subclass that is applicable for this kind of processor. - * @param proxyType type of proxy. {@link Expression#NORMAL_EXPRESSION_PROXY - * @param proxyID the id of the new expression proxy. - * - * @return - * - * @since 1.1.0 - */ - protected abstract ExpressionProxy createExpressionProxy(int proxyType, int proxyID); - - /** - * Push this proxy to the other side. It will simply take the proxy and push it onto - * its evaluation stack. It will be treated as the result of an expression. It's just - * that the expression was evaluatable on this side (since it is already a proxy). - * - * @param proxy - * - * @since 1.0.0 - */ - protected abstract void pushToProxy(IProxy proxy); - - /** - * Tell the other side we are complete. This will always be called after expression evaluation, or - * if expression was prematurely closed. - * <p> - * <b>Note:</b> The implementation must be able to handle multiple invocations, where the first call is a valid close and any - * subsequent call should be ignored. - * - * @throws ThrowableProxy - * - * @since 1.0.0 - */ - protected abstract void closeProxy(); - - /** - * Do invoke. This should simply make sure everything is done and throw any pending errors. - * <p> - * <b>Note:</b> The expression proxies MUST be resolved (callbacks called) in the order they are found in the expressionProxies list. This - * is so that the contract is followed that resolution notifications will occur in the order of creation. - * - * @param proxycount Number of Expression Proxies that need a callback. - * @param list of expression proxies. If proxycount > 0, then process the non-null entries in the list. They will be of type ExpressionProxy. - * @throws ThrowableProxy - * - * @since 1.0.0 - */ - protected abstract void pushInvoke(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException; - - /** - * Pull the top expression value from the evaluation stack. It will also under - * the covers call closeProxy. It also must process the expression proxy callbacks. It must do the expression proxy callbacks first, and then - * process the result value. If an error had occured sometime during processing, it should still process the proxy callbacks before throwing - * an exception. - * <p> - * <b>Note:</b> The expression proxies MUST be resolved (callbacks called) in the order they are found in the expressionProxies list. This - * is so that the contract is followed that resolution notifications will occur in the order of creation. Also <b>REQUIRED</b> is that - * the entire list must be processed of proxies must be processed by this call. It cannot do some or none. - * - * @param proxycount Number of Expression Proxies that need a callback. - * @param list of expression proxies. If proxycount > 0, then process the non-null entries in the list. They will be of type ExpressionProxy. - * @return The top level evaluation stack value. - * @throws ThrowableProxy - * @throws NoExpressionValueException - * - * @since 1.0.0 - */ - protected abstract IBeanProxy pullProxyValue(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException; - - /** - * Push to proxy the cast expression. The expression to use will be on the top of its evaluation stack. - * The result of the cast expression will be placed onto the evaluation stack. - * - * @param type Cast type. - * - * @since 1.0.0 - */ - protected abstract void pushCastToProxy(IProxyBeanType type); - - /** - * Push to proxy the instanceof expression. The expression to use will be on the top of its evaluation stack. - * The result of the instanceof expression will be placed onto the evaluation stack. - * - * @param type Instanceof type. - * - * @since 1.0.0 - */ - protected abstract void pushInstanceofToProxy(IProxyBeanType type); - - /** - * Push to proxy the infix operation. This is called on the completion of each operand of the expression. - * So it will be called a minimum of two times. - * - * @param operator The operator. - * @param operandType The operand type. left, other, or last. - * - * @since 1.0.0 - */ - protected abstract void pushInfixToProxy(InfixOperator operator, InternalInfixOperandType operandType); - - /** - * Push to proxy the prefix expression. The expression to use will be on top of its evaluation stack. - * The result of the prefix operation will be placed onto the evaluation stack. - * - * @param operator - * - * @see IExpressionConstants#PRE_MINUS - * @since 1.0.0 - */ - protected abstract void pushPrefixToProxy(PrefixOperator operator); - - - /** - * Push to proxy the array access. The result will be placed onto the evaluation stack. - * - * @param indexCount - * - * @since 1.0.0 - */ - protected abstract void pushArrayAccessToProxy(int indexCount); - - /** - * Push to proxy the array creation. The result will be placed onto the evaluation stack. - * @param type The array type. - * @param dimensionCount - * - * @since 1.0.0 - */ - protected abstract void pushArrayCreationToProxy(IProxyBeanType type, int dimensionCount); - - /** - * Push to proxy the array initializer. The resulting array will be placed onto the evaluation stack. - * @param type The array type. (must be an array type). - * @param stripDimCount the number of dimensions that must be stripped from the array type. This is needed - * because the first array initializer needs to be for the component type of the array (array minus one dimension), and - * each initializer after that needs one more dimension stripped off. But since we are working with possible expression - * proxies for "type", we can't create the appropriate component types of the array. So we need to tell the - * processor how many dims to strip from the original type (which is what is sent in on every initializer push, the original type). - * @param expressionCount - * - * @since 1.0.0 - */ - protected abstract void pushArrayInitializerToProxy(IProxyBeanType type, int stripDimCount, int expressionCount); - - /** - * Push to proxy the class instance creation. The resulting class instance will be placed onto the evaluation stack. - * - * @param type Class type. - * @param argumentCount The number of arguments. - * - * @since 1.0.0 - */ - protected abstract void pushClassInstanceCreationToProxy(IProxyBeanType type, int argumentCount); - - /** - * Push to proxy the type receiver. The resulting class will be placed onto the evaluation stack, along with it also - * being the expression type. - * @param type Class type. - * - * @since 1.0.0 - */ - protected abstract void pushTypeReceiverToProxy(IProxyBeanType type); - - /** - * Push to proxy the field access. The result value will be placed onto the evaluation stack. - * @param field The name of the field if string, or an IFieldProxy. - * @param hasReceiver Has receiver flag. - * - * @since 1.0.0 - */ - protected abstract void pushFieldAccessToProxy(Object field, boolean hasReceiver); - - /** - * Push to proxy the method invocation. The result value will be placed onto the evaluation stack. - * - * @param method String for method name or IProxyMethod - * @param hasReceiver - * @param argCount - * - * @since 1.0.0 - */ - protected abstract void pushMethodInvocationToProxy(Object method, boolean hasReceiver, int argCount); - - /** - * Push to proxy the conditional expression. This will be called on each part of expression. The expression type - * will be the current part (e.g. test, true, false). - * - * @param expressionType The expression type. - * - * @since 1.0.0 - */ - protected abstract void pushConditionalToProxy(InternalConditionalOperandType expressionType); - - /** - * Push to the proxy the expression proxy. Whatever the last expression value is will be assigned to the ExpressionProxy. - * - * @param proxy - * - * @since 1.1.0 - */ - protected abstract void pushAssignmentToProxy(ExpressionProxy proxy); - - /** - * Push the assignment expression. The operands are already on the stack. - * - * @since 1.1.0 - */ - protected abstract void pushAssignmentToProxy(); - - - /** - * Push the begin block expression. - * @param blockNumber - * - * @since 1.1.0 - */ - protected abstract void pushBlockBeginToProxy(int blockNumber); - - /** - * Push the end block expression. - * @param blockNumber - * - * @since 1.1.0 - */ - protected abstract void pushBlockEndToProxy(int blockNumber); - - /** - * Push the break block expression. - * @param blockNumber - * - * @since 1.1.0 - * - */ - protected abstract void pushBlockBreakToProxy(int blockNumber); - - /** - * Push the begin try expression. - * @param tryNumber - * - * @since 1.1.0 - */ - protected abstract void pushTryBeginToProxy(int tryNumber); - - /** - * Push the catch clause to proxy. - * @param tryNumber - * @param exceptionType - * @param ep ExpressionProxy to be assigned with the exception or <code>null</code> if exception is not to be assigned. - * - * @since 1.1.0 - */ - protected abstract void pushTryCatchClauseToProxy(int tryNumber, IProxyBeanType exceptionType, ExpressionProxy ep); - - /** - * Push the finally clause to proxy. - * @param tryNumber - * - * @since 1.1.0 - */ - protected abstract void pushTryFinallyClauseToProxy(int tryNumber); - - /** - * Push try end to proxy. - * @param tryNumber - * - * @since 1.1.0 - */ - protected abstract void pushTryEndToProxy(int tryNumber); - - /** - * Push the throw of the exception to proxy. - * @param exception - * - * @since 1.1.0 - */ - protected abstract void pushThrowToProxy(); - - /** - * Push a rethrow to proxy. - * @param tryNumber - * - * @since 1.1.0 - */ - protected abstract void pushRethrowToProxy(int tryNumber); - - /** - * Push the BeanType Expression proxy to be resolved on the execution side. - * @param proxy - * - * @since 1.1.0 - */ - protected abstract void pushBeanTypeToProxy(IBeanTypeExpressionProxy proxy); - - /** - * Push the Method Expression proxy to be resolved on the execution side. - * @param proxy - * @param declaringType - * @param methodName - * @param parameterTypes parameter types or <code>null</code> if no parameters. - * - * @since 1.1.0 - */ - protected abstract void pushMethodToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes); - - /** - * Push the Field Expression Proxy to be resolved on the execution side. - * @param proxy - * @param declaringType - * @param fieldName - * - * @since 1.1.0 - */ - protected abstract void pushFieldToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String fieldName); - - /** - * Push the If test condition to proxy. - * - * @since 1.1.0 - */ - protected abstract void pushIfTestToProxy(); - - /** - * Push a true or else clause to proxy. - * @param clauseType - * - * @since 1.1.0 - */ - protected abstract void pushIfElseToProxy(InternalIfElseOperandType clauseType); - - /** - * Push to proxy a new instance using an initialization string. - * @param initializationString - * @param resultType - * - * @since 1.1.0 - */ - protected abstract void pushNewInstanceToProxy(String initializationString, IProxyBeanType resultType); - - /** - * Push the mark id to proxy. - * - * @param markID - * - * @since 1.1.0 - */ - protected abstract void pushMarkToProxy(int markID); - - /** - * Push the end mark id to proxy. - * - * @param markID - * @param restore <code>true</code> if this is a restore due to error, <code>false</code> if this is just a normal end mark. - * - * @since 1.1.0 - */ - protected abstract void pushEndmarkToProxy(int markID, boolean restore); - - /** - * Push the begin transfer thread to proxy. - * - * - * @since 1.1.0 - */ - protected abstract void pushBeginTransferThreadToProxy() throws ThrowableProxy; - - /** - * Push the actual transfer to the current thread to proxy. - * - * - * @since 1.1.0 - */ - protected abstract void pushTransferThreadToProxy(); - - /** - * Push the subexpression begin to proxy. - * @param subexpressionNumber - * - * @since 1.1.0 - */ - protected abstract void pushSubexpressionBeginToProxy(int subexpressionNumber); - - /** - * Push the subexpression end to proxy. - * @param subexpressionNumber - * - * @since 1.1.0 - */ - protected abstract void pushSubexpressionEndToProxy(int subexpressionNumber); -} |