[82257] Batching with proxies, phase I, Swing/AWT/Base Beans.
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoProxyConstants.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoProxyConstants.java
index 10020aa..5f86239 100644
--- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoProxyConstants.java
+++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoProxyConstants.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: BeaninfoProxyConstants.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:44:20 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:28 $
*/
package org.eclipse.jem.internal.beaninfo.adapters;
@@ -26,7 +26,7 @@
*/
public final class BeaninfoProxyConstants {
- private static final String REGISTRY_KEY = "org.eclipse.jem.internal.beaninfo.adapters.BeaninfoProxyConstants:"; //$NON-NLS-1$
+ private static final Object REGISTRY_KEY = new Object();
private final IMethodProxy introspectProxy;
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeanInfoCacheController.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeanInfoCacheController.java
index 1520ddb..9abdb21 100644
--- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeanInfoCacheController.java
+++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeanInfoCacheController.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: BeanInfoCacheController.java,v $
- * $Revision: 1.7 $ $Date: 2005/05/04 15:13:15 $
+ * $Revision: 1.8 $ $Date: 2005/05/11 19:01:28 $
*/
package org.eclipse.jem.internal.beaninfo.core;
@@ -27,7 +27,6 @@
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.change.ChangeDescription;
-import org.eclipse.emf.ecore.change.ChangePackage;
import org.eclipse.emf.ecore.change.impl.EObjectToChangesMapEntryImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
@@ -864,8 +863,6 @@
return ce;
}
- protected static final ChangePackage CP = ChangePackage.eINSTANCE; // TODO When emf bug 80491 if fixed.
-
/**
* Get the cache resource for the given java class.
* <p>
@@ -890,29 +887,17 @@
boolean waitForJob = false;
synchronized (ce) {
if (ce.getPendingResource() != null) {
-// // We are waiting to write it out, so just make a copy of it and use it. (After EMF bug 80547 fix is available.
-// Resource cres = ce.getPendingOverrideResource();
-// ResourceSet rset = cres.getResourceSet();
-// Resource copyRes = rset.createResource(cres.getURI().appendSegment("temporary"));
-// copyRes.getContents().addAll(EcoreUtil.copyAll(cres.getContents()));
-// return copyRes;
- // TODO EMF bug 80547 is available, we can simply return a copy of the resource when it is a pending resource instead of
- // waiting for the cache job to finish. Because then we can make a copy with no problem.
- // Actually copy won't work because it refers directly to classes in the other project's resource set. So
- // when loading using the copied version, it creates incorrect linkages. Need a copy that turns outside refs into proxies
- // so when needed again they will be resolved.
- // Need to create a special ECoreUtil.Copier that overrides copyReferences and changes any values that are not copied,
- // i.e. came from outside the copy set, into new proxies pointing the URI of original ref value. This way it will
- // be reresolved under the project resource set instead of the original rset. Actually only needed if resource set
- // for ref value different resource set than ours being copied. But it doesn't buy anything to add that overhead.
- // This should still be faster than waiting for the save to disk and then reading it back in again.
+ // We have one pending. So wait until write cache job is done, and then load it in.
+ // Note: Can't just copy the pending resource because it has references to JavaClasses
+ // and these could be in a different project (since this could be a workspace wide class).
+ // We would get the wrong java classes then when we apply it.
waitForJob = true;
if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
BeaninfoPlugin.getPlugin().getLogger().log("Using pending class cache.", Level.FINER);
}
}
if (waitForJob)
- waitForCacheSaveJob(); // This is part of the fix which can go away when 80547 is available.
+ waitForCacheSaveJob();
try {
return jclass.eResource().getResourceSet().getResource(
@@ -925,45 +910,20 @@
return null;
}
} else {
-// synchronized (ce) {
-// if (ce.getPendingOverrideResource() != null) {
-// if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
-// BeaninfoPlugin.getPlugin().getLogger().log("Using pending cache.", Level.FINER);
-//
-// // We are waiting to write it out, so just make a copy of it and use it.
-// Resource cres = ce.getPendingOverrideResource();
-// ResourceSet rset = cres.getResourceSet();
-// Resource copyRes = rset.createResource(cres.getURI().appendSegment("temporary"));
-// copyRes.getContents().addAll(EcoreUtil.copyAll(cres.getContents()));
-// return copyRes;
-// }
-// }
boolean waitForJob = false;
synchronized (ce) {
- if (ce.getPendingResource() != null) {
-// // We are waiting to write it out, so just make a copy of it and use it. (After EMF bug 80547 fix is available.
-// Resource cres = ce.getPendingOverrideResource();
-// ResourceSet rset = cres.getResourceSet();
-// Resource copyRes = rset.createResource(cres.getURI().appendSegment("temporary"));
-// copyRes.getContents().addAll(EcoreUtil.copyAll(cres.getContents()));
-// return copyRes;
- // TODO EMF bug 80547 is available, we can simply return a copy of the resource when it is a pending resource instead of
- // waiting for the cache job to finish. Because then we can make a copy with no problem.
- // Actually copy won't work because it refers directly to classes in the other project's resource set. So
- // when loading using the copied version, it creates incorrect linkages. Need a copy that turns outside refs into proxies
- // so when needed again they will be resolved.
- // Need to create a special ECoreUtil.Copier that overrides copyReferences and changes any values that are not copied,
- // i.e. came from outside the copy set, into new proxies pointing the URI of original ref value. This way it will
- // be reresolved under the project resource set instead of the original rset. Actually only needed if resource set
- // for ref value different resource set than ours being copied. But it doesn't buy anything to add that overhead.
- // This should still be faster than waiting for the save to disk and then reading it back in again.
+ if (ce.getPendingOverrideResource() != null) {
+ // We have one pending. So wait until write cache job is done, and then load it in.
+ // Note: Can't just copy the pending resource because it has references to JavaClasses
+ // and these could be in a different project (since this could be a workspace wide class).
+ // We would get the wrong java classes then when we apply it.
waitForJob = true;
if (BeaninfoPlugin.getPlugin().getLogger().isLoggingLevel(Level.FINER))
BeaninfoPlugin.getPlugin().getLogger().log("Using pending override cache.", Level.FINER);
}
}
if (waitForJob)
- waitForCacheSaveJob(); // This is part of the fix which can go away when 80547 is available.
+ waitForCacheSaveJob();
try {
return jclass.eResource().getResourceSet().getResource(
@@ -1395,8 +1355,7 @@
static {
SAVE_CACHE_OPTIONS = new HashMap(3);
SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_SAVE_TYPE_INFORMATION, Boolean.TRUE);
- // SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
- // TODO when we step up to EMF 2.1, bug 80502 should fix this.
+ SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
SAVE_CACHE_OPTIONS.put(XMLResource.OPTION_ENCODING, "UTF-8");
}
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/impl/PropertyDecoratorImpl.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/impl/PropertyDecoratorImpl.java
index 4d1cf5b..57d46a8 100644
--- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/impl/PropertyDecoratorImpl.java
+++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/impl/PropertyDecoratorImpl.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.beaninfo.impl;
/*
* $RCSfile: PropertyDecoratorImpl.java,v $
- * $Revision: 1.11 $ $Date: 2005/04/14 19:05:36 $
+ * $Revision: 1.12 $ $Date: 2005/05/11 19:01:28 $
*/
@@ -1148,14 +1148,14 @@
* @see org.eclipse.jem.internal.beaninfo.PropertyDecorator#isWriteable()
*/
public boolean isWriteable() {
- return !(getWriteMethod() == null && getField() == null);
+ return getWriteMethod() != null || (getField() != null && !isFieldReadOnly());
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.beaninfo.PropertyDecorator#isReadable()
*/
public boolean isReadable() {
- return !(getReadMethod() == null && getField() == null);
+ return getReadMethod() != null || getField() != null;
}
diff --git a/plugins/org.eclipse.jem.proxy/.options b/plugins/org.eclipse.jem.proxy/.options
index 699ac69..95c080f 100644
--- a/plugins/org.eclipse.jem.proxy/.options
+++ b/plugins/org.eclipse.jem.proxy/.options
@@ -2,6 +2,8 @@
org.eclipse.jem.proxy/remote/debug/ioconsole=false
org.eclipse.jem.proxy/remote/debug/vmtraceout=false
org.eclipse.jem.proxy/remote/debug/notimeouts=false
+org.eclipse.jem.proxy/debug/traceexpressions=false
+org.eclipse.jem.proxy/debug/traceexpressionstimethreshold=100
org.eclipse.jem.proxy/debug/logtrace=default
org.eclipse.jem.proxy/debug/logtracefile=default
org.eclipse.jem.proxy/debug/loglevel=default
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/InitializationStringEvaluationException.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/InitializationStringEvaluationException.java
index e3dfbfc..8844fb6 100644
--- a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/InitializationStringEvaluationException.java
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/InitializationStringEvaluationException.java
@@ -11,19 +11,18 @@
*******************************************************************************/
/*
* $RCSfile: InitializationStringEvaluationException.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:55:20 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
public class InitializationStringEvaluationException extends Exception {
- protected Throwable originalException;
public InitializationStringEvaluationException(Throwable exc){
- originalException = exc;
+ super(exc);
}
public Throwable getOriginalException(){
- return originalException;
+ return getCause();
}
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/AbstractEnum.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/AbstractEnum.java
new file mode 100644
index 0000000..010b0bc
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/AbstractEnum.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 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: AbstractEnum.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * Base abstract implementation of the enum.
+ * @since 1.1.0
+ */
+public abstract class AbstractEnum implements Enum {
+
+ /**
+ * The name of the enumerator.
+ */
+ private final String name;
+
+ /**
+ * The <code>int</code> value of the enumerator.
+ */
+ private final int value;
+
+ /**
+ * Creates an initialized instance.
+ *
+ * @param value
+ * the <code>int</code> value of the enumerator.
+ * @param name
+ * the name of the enumerator.
+ */
+ protected AbstractEnum(int value, String name) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Returns the name of the enumerator.
+ *
+ * @return the name.
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the <code>int</code> value of the enumerator.
+ *
+ * @return the value.
+ */
+ public final int getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the name of the enumerator.
+ *
+ * @return the name.
+ */
+ public final String toString() {
+ return name;
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/Enum.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/Enum.java
new file mode 100644
index 0000000..7d2fb3e
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/Enum.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 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: Enum.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * TypeSafe enumerations for the IExpression processing.
+ *
+ * @since 1.1.0
+ */
+public interface Enum {
+
+ /**
+ * Returns the name of the enumerator.
+ *
+ * @return the name.
+ */
+ String getName();
+
+ /**
+ * Returns the <code>int</code> value of the enumerator.
+ *
+ * @return the value.
+ */
+ int getValue();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ExpressionProcesser.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ExpressionProcesser.java
index 82e969d..4def2a7 100644
--- a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ExpressionProcesser.java
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ExpressionProcesser.java
@@ -10,20 +10,19 @@
*******************************************************************************/
/*
* $RCSfile: ExpressionProcesser.java,v $
- * $Revision: 1.7 $ $Date: 2005/02/16 14:38:04 $
+ * $Revision: 1.8 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.initParser.tree;
import java.lang.reflect.*;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.List;
import org.eclipse.jem.internal.proxy.common.AmbiguousMethodException;
import org.eclipse.jem.internal.proxy.common.MethodHelper;
-import org.eclipse.jem.internal.proxy.initParser.EvaluationException;
-import org.eclipse.jem.internal.proxy.initParser.tree.IExpressionConstants.NoExpressionValueException;
+import org.eclipse.jem.internal.proxy.initParser.InitializationStringEvaluationException;
+import org.eclipse.jem.internal.proxy.initParser.InitializationStringParser;
/**
* Expression processing. This does the actual expression processing with the live objects.
@@ -36,6 +35,145 @@
public class ExpressionProcesser {
/**
+ * A variable reference for a field access.
+ *
+ * @since 1.1.0
+ */
+ protected static class FieldAccessReference extends VariableReference {
+
+ private final Field field;
+ private final Object receiver;
+
+ /**
+ * Use this to construct a FieldAccessReference. This will do checks to make sure
+ * it is valid so that exceptions won't be thrown later when actually dereferenced.
+ *
+ * @param field
+ * @param receiver
+ * @return
+ * @throws IllegalArgumentException
+ *
+ * @since 1.1.0
+ */
+ public static FieldAccessReference createFieldAccessReference(Field field, Object receiver) throws IllegalArgumentException {
+ // If static, then receiver is ignored.
+ if (!Modifier.isStatic(field.getModifiers())) {
+ if (!field.getDeclaringClass().isInstance(receiver))
+ throw new IllegalArgumentException("Field receiver does not match the type of the field: Field: "+field.getType()+" receiver: "+(receiver!=null ? receiver.getClass() : null));
+ }
+ field.setAccessible(true); // Make it always accessible. Trust it.
+ return new FieldAccessReference(field, receiver);
+ }
+
+ protected FieldAccessReference(Field field, Object receiver) {
+ this.field = field;
+ this.receiver = receiver;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser.VariableReference#dereference()
+ */
+ public Object dereference() {
+ try {
+ return field.get(receiver);
+ } catch (IllegalArgumentException e) {
+ // Shouldn't occur. Already tested for this.
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // Shouldn't occur. Already tested for this.
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser.VariableReference#set(java.lang.Object, java.lang.Class)
+ */
+ public Object set(Object value, Class type) throws IllegalArgumentException, IllegalAccessException {
+ field.set(receiver, value);
+ return field.get(receiver); // Just in case some conversion happened. Technically it is not the value set but the retrieved when in an assignment.
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "FieldAccess{"+field.toString()+"} on "+receiver.toString();
+ }
+ }
+
+ /**
+ * A variable reference for an Array access. It will reference only the last indexed entry of the array.
+ * For example if <code>x[3][4]</code> is the access, then what will be given to this reference will be
+ * the array entry at x[3][4], not the x array itself.
+ *
+ * @since 1.1.0
+ */
+ protected static class ArrayAccessReference extends VariableReference {
+
+
+ private final Object array;
+ private final int index;
+
+ /**
+ * Use this to construct an array access reference. This will do checks to make sure
+ * it is valid so that exceptions won't be thrown later when actually dereferenced.
+ *
+ * @param array
+ * @param index
+ * @return
+ * @throws IllegalArgumentException
+ *
+ * @since 1.1.0
+ */
+ public static ArrayAccessReference createArrayAccessReference(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+ int len = Array.getLength(array);
+ if (index < 0 || len <= index)
+ throw new ArrayIndexOutOfBoundsException("Index: "+index+" size:"+len);
+ return new ArrayAccessReference(array, index);
+ }
+ /**
+ * Construct the reference with the array and the index of the entry being referenced.
+ * @param array
+ * @param index
+ *
+ * @since 1.1.0
+ */
+ protected ArrayAccessReference(Object array, int index) {
+ this.array = array;
+ this.index = index;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.VariableReference#dereference()
+ */
+ public Object dereference() {
+ return Array.get(array, index);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.VariableReference#set(java.lang.Object, java.lang.Class)
+ */
+ public Object set(Object value, Class type) throws IllegalArgumentException {
+ Array.set(array, index, value);
+ return Array.get(array, index); // In case there was some conversion applied. Technically it is not the value set but the retrieved when in an assignment.
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "ArrayAccess["+index+"]: "+array.toString();
+ }
+ }
+
+ /**
* The expression result stack and the expression result type stack.
* The type stack is used to be expected type of the corresponding
* expression result. This is needed for converting to primitives
@@ -64,10 +202,112 @@
*
* @see org.eclipse.jem.internal.proxy.initParser.MethodHelper#NULL_TYPE
*/
- private ArrayList expressionStack = new ArrayList(10);
- private ArrayList expressionTypeStack = new ArrayList(10);
+ private List expressionStack = new ArrayList(10);
+ private List expressionTypeStack = new ArrayList(10);
/**
+ * List of the expression proxies. The index into the list is the
+ * same as the expression proxy id.
+ */
+ private ArrayList expressionProxies; // It is array list because we want to call ensureCapacity and that is not available on List.
+
+ /**
+ * An error has occurred. At this point all subcommands will simply make sure they flush the input stream
+ * correctly, but they do not process it.
+ *
+ * @since 1.0.0
+ */
+ private boolean errorOccurred = false;
+ private boolean novalueException = false;
+
+ private Throwable exception = null; // Was there another kind of exception that was caught.
+
+ /**
+ * Process all other exceptions then the NoExpressionValueException. This can be called from usage code so that if there was an error
+ * in setting up for a call to the processer it can be logged.
+ *
+ * @param e
+ *
+ * @since 1.0.0
+ */
+ public final void processException(Throwable e) {
+ // Process all other exceptions.
+ novalueException = false;
+ while (e.getCause() != null)
+ e = e.getCause();
+ if (traceOn) {
+ System.out.println();
+ System.out.print("***** >>>\tException: ");
+ System.out.println(e);
+ }
+ throwException(e); // Treat as a throw to let try/catches expressions handle it.
+ }
+
+ /**
+ * This is a syntax exception. This means data coming across is corrupted in
+ * some way so no further processing should occur.
+ * @param e
+ *
+ * @since 1.1.0
+ */
+ protected final void processSyntaxException(Throwable e) {
+ errorOccurred = true;
+ novalueException = false;
+ exception = e;
+ }
+
+ /**
+ * Process a NoExpressionValueException. Don't wrapper these.
+ * @param e
+ *
+ * @since 1.1.0
+ */
+ protected final void processSyntaxException(NoExpressionValueException e) {
+ if (traceOn)
+ printTrace("Expression has no value", false);
+ try {
+ errorOccurred = true;
+ novalueException = true;
+ exception = e;
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Return whether there are any errors.
+ *
+ * @return <code>true</code> if no errors.
+ *
+ * @since 1.0.0
+ */
+ public boolean noErrors() {
+ return !errorOccurred;
+ }
+
+ /**
+ * Return whether the error is a NoExpressionValueException or not.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public boolean isNoExpressionValue() {
+ return novalueException;
+ }
+
+ /**
+ * Return the throwable if a Throwable was caught.
+ *
+ * @return The throwable, or <code>null</code> if not set.
+ *
+ * @since 1.0.0
+ */
+ public Throwable getErrorThrowable() {
+ return exception;
+ }
+
+ /**
* Push the expression value and its expected type.
* @param o
* @param type
@@ -78,20 +318,39 @@
expressionStack.add(o);
expressionTypeStack.add(type);
}
+
+ /**
+ * Pop just the expression value. It is imperitive that the expression type
+ * is popped immediately following. Separated the methods so that we
+ * don't need to create an array to return two values. This will dereference
+ * any variable references.
+ *
+ * @return The value.
+ * @throws NoExpressionValueException
+ *
+ * @since 1.0.0
+ */
+ protected final Object popExpression() throws NoExpressionValueException {
+ return popExpression(true);
+ }
/**
* Pop just the expression value. It is imperitive that the expression type
* is popped immediately following. Separated the methods so that we
* don't need to create an array to return two values.
*
+ * @param deReference If the top expression is a Reference, then dereference it.
* @return The value.
- * @throws ThrowableProxy
+ * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected final Object popExpression() throws NoExpressionValueException {
+ protected final Object popExpression(boolean deReference) throws NoExpressionValueException {
try {
- return expressionStack.remove(expressionStack.size()-1);
+ Object result = expressionStack.remove(expressionStack.size()-1);
+ if (deReference && result instanceof VariableReference)
+ result = ((VariableReference) result).dereference();
+ return result;
} catch (IndexOutOfBoundsException e) {
throw new NoExpressionValueException();
}
@@ -106,6 +365,8 @@
* <p>
* When done, <code>popExpressions(int count)</code> must be called to
* clean them out since they were processed.
+ * <p>
+ * This will not dereference the expression. It is the job of the caller to do this.
*
* @param fromTop <code>1</code> is the top one, <code>2</code> is the next one down.
* @return The entry from the top that was requested.
@@ -123,7 +384,8 @@
}
/**
- * Remove the top <code>count</code> items.
+ * Remove the top <code>count</code> items. This will not cause dereferencing to occur. It
+ * removes the corresponding type stack entries.
*
* @param count
* @throws NoExpressionValueException
@@ -133,8 +395,10 @@
protected final void popExpressions(int count) throws NoExpressionValueException {
try {
int remove = expressionStack.size()-1;
- while (count-- > 0)
- expressionStack.remove(remove--);
+ while (count-- > 0) {
+ expressionStack.remove(remove);
+ expressionTypeStack.remove(remove--);
+ }
} catch (IndexOutOfBoundsException e) {
throw new NoExpressionValueException();
}
@@ -152,7 +416,6 @@
*
* @param allowVoid Allow void types if <code>true</code>
* @return The type.
- * @throws ThrowableProxy
* @throws NoExpressionValueException
* @since 1.0.0
*/
@@ -160,7 +423,7 @@
try {
Class result = (Class) expressionTypeStack.remove(expressionTypeStack.size()-1);
if (!allowVoid && result == Void.TYPE)
- throw new NoExpressionValueException();
+ throw new NoExpressionValueException("Expression was void.");
return result;
} catch (IndexOutOfBoundsException e) {
@@ -199,46 +462,159 @@
}
/**
- * Remove the top <code>count</code> items.
- *
- * @param count
- * @throws NoExpressionValueException
- *
- * @since 1.0.0
- */
- protected final void popExpressionTypes(int count) throws NoExpressionValueException {
- try {
- int remove = expressionTypeStack.size()-1;
- while (count-- > 0)
- expressionTypeStack.remove(remove--);
- } catch (IndexOutOfBoundsException e) {
- throw new NoExpressionValueException();
- }
- }
-
- /**
* Flag indicating expression should be ignored and not processed.
* This happens because of few cases, like conditional and, that
* if one returns false, the rest of the expressions in that conditional and
* expression should be ignored and not processed.
* <p>
- * It is an int so that those expressions that can initiate an ignore can
- * know if it is thiers or not. Only when it decrements to zero will ignore
- * be over. Those expressions that can start an ignore must increment the
- * ignore counter if the ignore counter is on, but ignore the expression,
- * and decrement it when they are complete.
+ * It is an Object that acts as an enum for the type of expression that initiated the ignore.
+ * If it is <code>null</code> then no one is ignoring.
* <p>
* All of the pushTo...Proxy methods must test this for this to work correctly.
+ * Each expression has some way of testing that their particular nesting of
+ * expressions is complete and they can turn off the ignore flag.
+ * <p>
+ * Only one type of ignore can exist at a time.
*/
- protected int ignoreExpression = 0;
+ protected Object ignoreExpression = null;
+
+
+ private List saveStates;
/**
- * Create the IDEExpression
+ * Are we tracing or not.
+ */
+ protected final boolean traceOn;
+ private final long thresholdTime;
+ private long startExpressionStepTime;
+ private long startExpressionTime;
+ private long lastExpressionEndTime;
+
+ /**
+ * Trace head of this expression. So that traces from different expressions can be distinquished.
+ * It is simply an monotonically increasing counter. It is the header string for any trace output.
+ */
+ protected final String traceHeader;
+
+ private int indent = 0; // Indented for certain block expressions.
+
+ /*
+ * Trace counter. It is incremented once for each expression and assigned to the traceId of the expression.
+ */
+ private static int TRACE_COUNTER;
+
+ /**
+ * Create the Expression without tracing.
* @param registry
*
* @since 1.0.0
*/
public ExpressionProcesser() {
+ this(false, -1);
+ }
+
+ /**
+ * Create the expression, and set the tracing mode and threshold time. Use -1
+ * for default time of 100ms.
+ * @param traceOn
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProcesser(boolean traceOn, long threshold) {
+ this.traceOn = traceOn;
+ if (traceOn) {
+ traceHeader = "**"+(++TRACE_COUNTER)+':';
+ System.out.print(traceHeader);
+ System.out.println(" Start expression");
+ this.thresholdTime = threshold != -1 ? threshold : 100;
+ lastExpressionEndTime = startExpressionTime = System.currentTimeMillis();
+ } else {
+ traceHeader = null;
+ thresholdTime = 100;
+ }
+ }
+
+ /**
+ * Trace msg helper. Should only be called if traceOn is true. This method is only used to start a new trace message.
+ * The caller is must call printTraceEnd at the end.
+ *
+ * @param msg message to print
+ * @param ignore are we ignoring the expression, or is it being processed (this just alters the trace output slightly).
+ *
+ * @since 1.1.0
+ */
+ protected void printTrace(String msg, boolean ignore) {
+ startExpressionStepTime = System.currentTimeMillis();
+ long sinceLastExpression = startExpressionStepTime - lastExpressionEndTime;
+ System.out.print(traceHeader);
+ if (sinceLastExpression > 0) {
+ System.out.print('(');
+ if (sinceLastExpression > thresholdTime)
+ System.out.print("***");
+ System.out.print(sinceLastExpression);
+ System.out.print("ms)");
+ }
+ System.out.print('\t');
+ if (!ignore)
+ System.out.print("\t");
+ else
+ System.out.print("##\t");
+
+ printIndent();
+ System.out.print(msg);
+ }
+
+ /**
+ * print the indent. It will not do a new line before nor after.
+ *
+ * @since 1.1.0
+ */
+ protected void printIndent() {
+ for(int i=indent; i>0; i--) {
+ System.out.print(" ");
+ }
+ }
+
+ protected void printTraceEnd() {
+ long stop = System.currentTimeMillis()-startExpressionStepTime;
+ if (stop > 0) {
+ System.out.print(" (");
+ if (stop > thresholdTime)
+ System.out.print("***");
+ System.out.print(stop);
+ System.out.print("ms)");
+ }
+ System.out.println();
+ lastExpressionEndTime = System.currentTimeMillis();
+ }
+
+ /**
+ * Do an indent (undent) according to indent flag.
+ * @param indent <code>true</code> to increment indent, or otherwise decrement.
+ *
+ * @since 1.1.0
+ */
+ protected void indent(boolean indent) {
+ this.indent += (indent ? 1 : -1);
+ if (this.indent < 0)
+ this.indent = 0;
+ }
+
+ /**
+ * Print the object and type. It will not end with a newline char, so one will be needed afterwards.
+ *
+ * @param o
+ * @param t
+ *
+ * @since 1.1.0
+ */
+ protected void printObjectAndType(Object o, Class t) {
+ System.out.print(' ');
+ System.out.print("Object-");
+ System.out.print(o);
+ System.out.print(" Type-");
+ System.out.print(t);
+ System.out.print(' ');
}
/**
@@ -247,8 +623,25 @@
* @since 1.0.0
*/
public final void close() {
- expressionStack.clear();
- expressionTypeStack.clear();
+ boolean firstClose = expressionStack != null;
+ if (firstClose && traceOn) {
+ printTrace("End expression", false);
+ long totalTime = System.currentTimeMillis()-startExpressionTime;
+ System.out.print(" Total expression evaluation time: ");
+ System.out.print(totalTime);
+ System.out.print("ms.");
+ }
+ try {
+ expressionStack = null;
+ expressionTypeStack = null;
+ expressionProxies = null;
+ exception = null;
+ catchThrowable = null;
+ saveStates = null;
+ } finally {
+ if (firstClose && traceOn)
+ printTraceEnd();
+ }
}
/**
@@ -257,16 +650,108 @@
*
* @param value The value array to store the value and type into.
* @throws NoExpressionValueException
- *
* @since 1.0.0
*/
public final void pullValue(Object[] value) throws NoExpressionValueException {
- value[0] = popExpression();
- value[1] = popExpressionType(false);
+ if (traceOn)
+ printTrace("Pull value:", false);
+ try {
+ value[0] = popExpression();
+ value[1] = popExpressionType(false);
+ } finally {
+ if (traceOn) {
+ printObjectAndType(value[0], (Class) value[1]);
+ printTraceEnd();
+ }
+ }
close();
}
/**
+ * Pull the value of the expression proxy, dereferencing it if necessary. This is for resolution only purposes at the
+ * end of the expression being processed. Not meant for general access to the value of expression proxy. Use
+ * {@link ExpressionProcesser#getExpressionProxyValue(int, Object[])} instead for general access to the value.
+ *
+ * @param proxyid
+ * @param value
+ * @throws NoExpressionValueException
+ *
+ * @since 1.1.0
+ */
+ public final void pullExpressionProxyValue(int proxyid, Object[] value) throws NoExpressionValueException {
+ getExpressionProxyValue(proxyid, value, true, true);
+ }
+
+ /**
+ * Get the expression proxy value. If the expression has not yet been evaluated it will
+ * return false. If it has it will return true.
+ * @param proxyid
+ * @param value put value into value[0] and the type into value[1].
+ * @return <code>true</code> if successful, or <code>false</code> if the expression proxy was never resolved or doesn't exist.
+ *
+ * @since 1.1.0
+ */
+ public boolean getExpressionProxyValue(int proxyid, Object[] value) {
+ try {
+ return getExpressionProxyValue(proxyid, value, true, false);
+ } catch (NoExpressionValueException e) {
+ return false;
+ }
+ }
+
+ /*
+ * Internal method use to actually get the value, but to distinquish between pull and get of the public interface.
+ * Get will process the errors as normal execution errors, while pull will throw the errors. finalTrace is when
+ * this is the final call to return the values to the client. We will trace the results in that case.
+ * Return true if successful.
+ */
+ private boolean getExpressionProxyValue(int proxyid, Object[] value, boolean pull, boolean finalTrace) throws NoExpressionValueException {
+ // Note: This will throw the exceptions right away since this is called from outside to fill in the value and
+ // so we are holding such exceptions.
+ boolean doTrace = finalTrace && traceOn;
+ try {
+ if (expressionProxies != null && expressionProxies.size() > proxyid) {
+ InternalExpressionProxy proxy = (InternalExpressionProxy) expressionProxies.get(proxyid);
+ if (proxy != null && proxy.isSet()) {
+ value[0] = proxy.getValue();
+ if (value[0] instanceof VariableReference)
+ value[0] = ((VariableReference) value[0]).dereference(); // Here we want the final current value.
+ value[1] = proxy.getType();
+ if (doTrace)
+ if (value[1] != Void.TYPE) {
+ printTrace("Return Proxy #" + proxyid + " Resolved to", false);
+ printObjectAndType(value[0], (Class) value[1]);
+ } else
+ printTrace("Return Proxy #" + proxyid + " Resolved to void.", false);
+ return true;
+
+ } else {
+ if (doTrace)
+ printTrace("Return Proxy #" + proxyid + ": Not resolved", false);
+ NoExpressionValueException e = new NoExpressionValueException("Expression Proxy never set.");
+ if (pull)
+ throw e;
+ else
+ processSyntaxException(e);
+ return false;
+ }
+ } else {
+ if (doTrace)
+ printTrace("Return Proxy #" + proxyid + ": Never created.", false);
+ NoExpressionValueException e = new NoExpressionValueException("Expression proxy doesn't exist.");
+ if (pull)
+ throw e;
+ else
+ processSyntaxException(e);
+ return false;
+ }
+ } finally {
+ if (doTrace)
+ printTraceEnd();
+ }
+ }
+
+ /**
* Push the expression (just a value) onto the stack.
*
* @param o
@@ -275,28 +760,81 @@
* @since 1.0.0
*/
public final void pushExpression(Object o, Class t) {
- if (ignoreExpression>0)
- return;
- pushExpressionValue(o, t);
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ if (traceOn) {
+ printTrace("Push: ", ignore);
+ printObjectAndType(o, t);
+ }
+ try {
+ if (ignore)
+ return;
+ pushExpressionValue(o, t);
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Get the value of the expression proxy (from proxy id), and push the value onto the stack.
+ *
+ * @param proxyid The proxy id of the ExpressionProxy to push as a value.
+ *
+ * @since 1.0.0
+ */
+ public final void pushExpressionProxy(int proxyid) {
+ boolean ignore =(ignoreExpression != null || errorOccurred);
+ if (traceOn)
+ printTrace("Push Expression Proxy #"+proxyid, ignore);
+ try {
+ if (ignore)
+ return;
+ if (expressionProxies != null && expressionProxies.size() > proxyid) {
+ InternalExpressionProxy proxy = (InternalExpressionProxy) expressionProxies.get(proxyid);
+ if (proxy != null && proxy.isSet()) {
+ if (traceOn)
+ printObjectAndType(proxy.getValue(), proxy.getType());
+ pushExpressionValue(proxy.getValue(), proxy.getType()); // Can push a VariableReference. This is ok. When used it will then deref with the current value.
+ } else
+ processSyntaxException(new NoExpressionValueException());
+ } else
+ processSyntaxException(new NoExpressionValueException());
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
}
/**
* Push a cast onto stack. The type passed in is either a String (with classname to cast to) or the
* type to cast to.
* @param type To cast to. If <code>String</code> then convert to type (using something like <code>Class.forName()</code>) or it is a Class
- * @throws NoExpressionValueException
- * @throws ClassCastException
*
* @since 1.0.0
*/
- public final void pushCast(Class type) throws NoExpressionValueException, ClassCastException {
- if (ignoreExpression>0)
- return;
-
- Object exp = popExpression();
- Class exptype = popExpressionType(false);
-
- pushExpressionValue(castBean(type, exp, exptype), type);
+ public final void pushCast(Class type) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ if (traceOn)
+ printTrace("Cast to: "+type, ignore);
+ try {
+ if (ignore)
+ return;
+
+ try {
+ Object exp = popExpression();
+ Class exptype = popExpressionType(false);
+
+ pushExpressionValue(castBean(type, exp, exptype), type);
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
}
/**
@@ -308,6 +846,9 @@
* <p>
* However if can't be cast for primitive or if not an instance of the
* returntype for objects, a ClassCastException will be raised.
+ * <p>
+ * This is a helper method for expression processer to cast a bean. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
*
* @param returnType
* @param bean
@@ -410,12 +951,17 @@
/**
* Return the primitive type that the wrapper bean represents (i.e. Boolean instance returns Boolean.TYPE)
+ * <p>
+ * This is a helper method for expression processer to get the primitive type. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
+
* @param bean
- * @return
+ * @return the primitive type class of the given bean.
+ * @throws IllegalArgumentException if bean is <code>null</code> or not of the type that can be converted to a primitive.
*
* @since 1.0.0
*/
- protected final Class getPrimitiveType(Object bean) {
+ protected final Class getPrimitiveType(Object bean) throws IllegalArgumentException {
if (bean instanceof Boolean)
return Boolean.TYPE;
else if (bean instanceof Integer)
@@ -436,29 +982,176 @@
throw new IllegalArgumentException(bean != null ? bean.getClass().getName() : "null"); //$NON-NLS-1$
}
+ private static final Object IFELSE_IGNORE = "IF/ELSE IGNORE"; // Flag for if/else in ingore
+ private int ifElseNesting = 0; // Nesting of if/else expressions.
+ private int ifElseIgnoreNestCount = 0; // When ignoring if/else expressions, ignore until this nest count.
+ private boolean ifElseSkipTruePart;
+
+
+ /**
+ * Push an if test expression.
+ * @param hasElseClause
+ *
+ * @since 1.0.0
+ */
+ public final void pushIfElse() {
+ try {
+ boolean ignore = true;
+ try {
+ if (errorOccurred)
+ return;
+ // Slightly different here in that if an ignoring occurred we still need to process at least part of it so that
+ // we can get the expression grouping correct.
+ ifElseNesting++; // We have the test.
+
+ if (ignoreExpression != null)
+ return;
+ ignore = false;
+ } finally {
+ if (traceOn)
+ printTrace("If test condition", ignore);
+ }
+
+ try {
+ Object condition = popExpression();
+ Class type = popExpressionType(false);
+ if (type != Boolean.TYPE)
+ throwClassCast(Boolean.TYPE, condition);
+ if (traceOn) {
+ System.out.print(" Test Result="+condition);
+ printTraceEnd();
+ indent(true);
+ printTrace("Begin True Expression.", ignore);
+ printTraceEnd();
+ indent(true);
+ }
+ if (((Boolean) condition).booleanValue()) {
+ // Condition was true.
+ // Do nothing. Let true condition be processed.
+ } else {
+ // Condition was false.
+ ifElseSkipTruePart = true; // Tell the true condition should be ignored.
+ ignoreExpression = IFELSE_IGNORE;
+ ifElseIgnoreNestCount = ifElseNesting;
+ }
+ // We don't put anything back on the stack because the condition test is not ever returned.
+ // The appropriate true or false condition evaluation will be left on the stack.
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Push an if/else clause. It can be any clause of the if (true, or false clause).
+ * @param clauseType
+ *
+ * @since 1.0.0
+ */
+ public final void pushIfElse(InternalIfElseOperandType clauseType) {
+ try {
+ boolean ignore = true;
+ if (errorOccurred)
+ return;
+ // Slightly different here in that if an ignoring occurred we still need to process at least part of it so that
+ // we can get the expression grouping correct.
+ switch (clauseType.getValue()) {
+ case InternalIfElseOperandType.TRUE_CLAUSE_VALUE:
+ if (traceOn) {
+ indent(false);
+ printTrace("Begin False Expression.", ignore);
+ printTraceEnd();
+ indent(true);
+ }
+ if (ifElseSkipTruePart && ignoreExpression == IFELSE_IGNORE && ifElseIgnoreNestCount == ifElseNesting) {
+ // stop ignoring, we've ignored the true condition of interest.
+ ignoreExpression = null;
+ return; // However, leave because since this condition was ignored.
+ }
+ break;
+ case InternalIfElseOperandType.ELSE_CLAUSE_VALUE:
+ if (traceOn) {
+ indent(false);
+ indent(false);
+ printTrace("End IF/ELSE Expression.", ignore);
+ printTraceEnd();
+ }
+ int currentNesting = ifElseNesting--;
+ if (ignoreExpression == IFELSE_IGNORE && ifElseIgnoreNestCount == currentNesting) {
+ // stop ignoring, we've ignored the false condition of interest.
+ ignoreExpression = null;
+ return; // However, leave because since this condition was ignored.
+ }
+ }
+
+ if (ignoreExpression != null)
+ return;
+ ignore = false;
+
+
+ try {
+ switch (clauseType.getValue()) {
+ case InternalIfElseOperandType.TRUE_CLAUSE_VALUE:
+ ifElseSkipTruePart = false; // Tell the false condition should be ignored.
+ ignoreExpression = IFELSE_IGNORE;
+ ifElseIgnoreNestCount = ifElseNesting;
+ break;
+ case InternalIfElseOperandType.ELSE_CLAUSE_VALUE:
+ // There's nothing to do, if it was ignored due to true, we wouldn't of gotton here.
+ // If it wasn't ignored, then the result of the false expression is on the stack, which is what it should be.
+ break;
+ }
+ } catch (RuntimeException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
/**
* Push the instanceof expression. The type passed in is either a String (with classname to test against) or the
* type to test against.
* @param type To test against.
- * @throws NoExpressionValueException
- *
* @since 1.0.0
*/
- public final void pushInstanceof(Class type) throws NoExpressionValueException {
- if (ignoreExpression>0)
- return;
-
- Object exp = popExpression();
- Class exptype = popExpressionType(false);
- pushExpressionValue(isInstance(type, exp, exptype) ? Boolean.TRUE : Boolean.FALSE, Boolean.TYPE);
+ public final void pushInstanceof(Class type) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ if (traceOn)
+ printTrace("Instanceof type: "+type, ignore);
+ try {
+ if (ignore)
+ return;
+
+ try {
+ Object exp = popExpression();
+ Class exptype = popExpressionType(false);
+ pushExpressionValue(Boolean.valueOf(isInstance(type, exp, exptype)), Boolean.TYPE);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (RuntimeException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
}
/**
* Test if instance of. It will make sure that primitive to non-primitive is not permitted.
* This is a true instance of, which means null IS NOT AN instance of any type. This is
* different then assignable from, in that case null can be assigned to any class type.
- *
+ * <p>
+ * This is a helper method for expression processer to do isInstance. Since it is a helper method it doesn't
+ * check nor process exceptions.
+
* @param type
* @param bean
* @param beanType
@@ -472,109 +1165,282 @@
else
return type.isInstance(bean);
}
+
+ /**
+ * Push new instance from string.
+ * @param initializationString
+ * @param resultType expected result type. If it isn't of that type, a classcast will be processed.
+ * @param classloader classloader to use for finding classes, or <code>null</code> to use classloader of InitializationStringParser.class.
+ *
+ * @since 1.1.0
+ */
+ public final void pushNewInstanceFromString(String initializationString, Class resultType, ClassLoader classloader) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ if (traceOn)
+ printTrace("New instance from string: \""+initializationString+"\" Type="+resultType, ignore);
+ try {
+ if (ignore)
+ return;
+
+ try {
+ InitializationStringParser parser = InitializationStringParser.createParser(initializationString, classloader);
+ Object newValue = parser.evaluate();
+ newValue = castBean(resultType, newValue, parser.getExpectedType());
+ pushExpressionValue(newValue, resultType);
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (InitializationStringEvaluationException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
- private static final String[] PRE_OPER_TO_STRING;
- static {
- PRE_OPER_TO_STRING = new String[IExpressionConstants.PRE_MAX+1];
- PRE_OPER_TO_STRING[IExpressionConstants.PRE_PLUS] = "+"; //$NON-NLS-1$
- PRE_OPER_TO_STRING[IExpressionConstants.PRE_MINUS] = "-"; //$NON-NLS-1$
- PRE_OPER_TO_STRING[IExpressionConstants.PRE_COMPLEMENT] = "~"; //$NON-NLS-1$
- PRE_OPER_TO_STRING[IExpressionConstants.PRE_NOT] = "!"; //$NON-NLS-1$
+ }
+
+ /**
+ * Push prefix expression.
+ * @param operator
+ * @since 1.0.0
+ */
+ public final void pushPrefix(PrefixOperator operator) {
+ try {
+ if (ignoreExpression != null || errorOccurred) {
+ if (traceOn)
+ printTrace("Prefix: \'"+operator+"\'", true);
+ return;
+ }
+
+ if (operator == PrefixOperator.PRE_PLUS)
+ return; // Do nothing. "+" doesn't affect the result of the current top expression.
+
+ if (traceOn)
+ printTrace("Prefix: \'"+operator+"\' ", false);
+
+ try {
+ Object exp = popExpression();
+ Class exptype = popExpressionType(false);
+ if (!exptype.isPrimitive())
+ throwInvalidPrefix(operator, exp);
+
+ int primTypeEnum = getEnumForPrimitive(exptype);
+ switch (operator.getValue()) {
+ case PrefixOperator.PRE_MINUS_VALUE:
+ switch (primTypeEnum) {
+ case BOOLEAN:
+ throwInvalidPrefix(operator, exp);
+ case BYTE:
+ exp = new Integer(-((Number) exp).byteValue());
+ break;
+ case CHAR:
+ exp = new Integer(-((Character) exp).charValue());
+ break;
+ case DOUBLE:
+ exp = new Double(-((Number) exp).doubleValue());
+ break;
+ case FLOAT:
+ exp = new Float(-((Number) exp).floatValue());
+ break;
+ case INT:
+ exp = new Integer(-((Number) exp).intValue());
+ break;
+ case LONG:
+ exp = new Long(-((Number) exp).longValue());
+ break;
+ case SHORT:
+ exp = new Integer(-((Number) exp).shortValue());
+ break;
+ }
+ exptype = getPrimitiveType(exp); // It can actually change the type.
+ break;
+
+ case PrefixOperator.PRE_COMPLEMENT_VALUE:
+ switch (primTypeEnum) {
+ case BOOLEAN:
+ case DOUBLE:
+ case FLOAT:
+ throwInvalidPrefix(operator, exp);
+ case BYTE:
+ exp = new Integer(~((Number) exp).byteValue());
+ break;
+ case CHAR:
+ exp = new Integer(~((Character) exp).charValue());
+ break;
+ case INT:
+ exp = new Integer(~((Number) exp).intValue());
+ break;
+ case LONG:
+ exp = new Long(~((Number) exp).longValue());
+ break;
+ case SHORT:
+ exp = new Integer(~((Number) exp).shortValue());
+ break;
+ }
+ exptype = getPrimitiveType(exp); // It can actually change the type.
+ break;
+ case PrefixOperator.PRE_NOT_VALUE:
+ switch (primTypeEnum) {
+ case BOOLEAN:
+ exp = !((Boolean) exp).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+ break;
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ throwInvalidPrefix(operator, exp);
+ }
+ break;
+ }
+
+ if (traceOn)
+ printObjectAndType(exp, exptype);
+ pushExpressionValue(exp, exptype); // Push the result back on the stack.
+
+ } catch (IllegalArgumentException e) {
+ processSyntaxException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (RuntimeException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
}
/**
- * Push prefix expression.
- * @param operator The operator from IExpressionConstants
+ * Assign the right expression to the left expression.
+ * @since 1.1.0
+ */
+ public final void pushAssignment() {
+ if (ignoreExpression != null || errorOccurred) {
+ if (traceOn) {
+ printTrace("Assignment", true);
+ printTraceEnd();
+ }
+ return;
+ }
+
+ try {
+ // KLUDGE: The only reason leftValue/refType are outside of try/finally is because
+ // of tracing. pushExpression() does its own trace statements, so we need to end
+ // our trace before calling pushExpression.
+ Object leftValue;
+ Class refType;
+ try {
+ if (traceOn)
+ printTrace("Assignment: ", false);
+ // The order on the stack is right then left operand.
+ // First the right operand
+ Object value = popExpression();
+ Class type = popExpressionType(false);
+
+ // Next the left operand, should be a reference.
+ VariableReference left = (VariableReference) popExpression(false); // Don't dereference it.
+ refType = popExpressionType(false);
+
+ if (traceOn)
+ printObjectAndType(left, refType);
+
+ leftValue = left.set(value, type);
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
+ // Now do assignment and return the value to the stack.
+ pushExpression(leftValue, refType); // The type of the result is the type of the reference.
+
+ } catch (IllegalArgumentException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (IllegalAccessException e) {
+ processException(e);
+ } catch (RuntimeException e) {
+ processException(e);
+ }
+
+ }
+
+ /**
+ * Assign the expression proxy to the top expression value.
+ *
+ * @param proxy
+ *
+ * @since 1.1.0
+ */
+ public final void pushAssignment(InternalExpressionProxy proxy) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ try {
+ if (traceOn) {
+ printTrace("Assign to Proxy #"+proxy.getProxyID(), ignore);
+ }
+ if (ignore)
+ return;
+
+ try {
+ assignToExpressionProxyFromTopStackEntry(proxy);
+ if (traceOn)
+ printObjectAndType(proxy.getValue(), proxy.getType());
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (RuntimeException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
+ }
+
+ /**
+ * Assign the top stack entry to the new expression proxy and allocate it for callback later.
+ * @param proxy
* @throws NoExpressionValueException
*
- * @see IExpressionConstants#PRE_MINUS
- * @since 1.0.0
+ * @since 1.1.0
*/
- public final void pushPrefix(int operator) throws NoExpressionValueException {
- if (ignoreExpression>0)
- return;
-
- if (operator == IExpressionConstants.PRE_PLUS)
- return; // Do nothing. "+" doesn't affect the result of the current top expression.
-
- Object exp = popExpression();
- Class exptype = popExpressionType(false);
- if (!exptype.isPrimitive())
- throwInvalidPrefix(operator, exp);
-
- int primTypeEnum = getEnumForPrimitive(exptype);
- switch (operator) {
- case IExpressionConstants.PRE_MINUS:
- switch (primTypeEnum) {
- case BOOLEAN:
- throwInvalidPrefix(operator, exp);
- case BYTE:
- exp = new Integer(-((Number) exp).byteValue());
- break;
- case CHAR:
- exp = new Integer(-((Character) exp).charValue());
- break;
- case DOUBLE:
- exp = new Double(-((Number) exp).doubleValue());
- break;
- case FLOAT:
- exp = new Float(-((Number) exp).floatValue());
- break;
- case INT:
- exp = new Integer(-((Number) exp).intValue());
- break;
- case LONG:
- exp = new Long(-((Number) exp).longValue());
- break;
- case SHORT:
- exp = new Integer(-((Number) exp).shortValue());
- break;
- }
- exptype = getPrimitiveType(exp); // It can actually change the type.
- break;
-
- case IExpressionConstants.PRE_COMPLEMENT:
- switch (primTypeEnum) {
- case BOOLEAN:
- case DOUBLE:
- case FLOAT:
- throwInvalidPrefix(operator, exp);
- case BYTE:
- exp = new Integer(~((Number) exp).byteValue());
- break;
- case CHAR:
- exp = new Integer(~((Character) exp).charValue());
- break;
- case INT:
- exp = new Integer(~((Number) exp).intValue());
- break;
- case LONG:
- exp = new Long(~((Number) exp).longValue());
- break;
- case SHORT:
- exp = new Integer(~((Number) exp).shortValue());
- break;
- }
- exptype = getPrimitiveType(exp); // It can actually change the type.
- break;
- case IExpressionConstants.PRE_NOT:
- switch (primTypeEnum) {
- case BOOLEAN:
- exp = !((Boolean) exp).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
- break;
- case BYTE:
- case CHAR:
- case DOUBLE:
- case FLOAT:
- case INT:
- case LONG:
- case SHORT:
- throwInvalidPrefix(operator, exp);
- }
- break;
- }
-
- pushExpressionValue(exp, exptype); // Push the result back on the stack.
+ protected void assignToExpressionProxyFromTopStackEntry(InternalExpressionProxy proxy) throws NoExpressionValueException {
+ Object value = getExpression(1);
+ Class type = getExpressionType(1, true);
+ if (value instanceof VariableReference)
+ value = ((VariableReference) value).dereference(); // Here we want the final current value.
+
+ proxy.setProxy(value, type);
+ allocateExpressionProxy(proxy);
+ }
+
+ /**
+ * Allocate an expression proxy. This is used to make an expression proxy known to the processor. The expression proxy must
+ * have been setProxy() at this point. This is used to assign from the top of the stack or to add from outside an evaluated proxy
+ * to be used later by others.
+ *
+ * @param proxy
+ *
+ * @since 1.1.0
+ */
+ public void allocateExpressionProxy(InternalExpressionProxy proxy) {
+ int minSize = proxy.getProxyID()+1;
+ if (expressionProxies == null)
+ expressionProxies = new ArrayList(minSize+10); // Allow room to grow ten more.
+ else if (expressionProxies.size() < minSize)
+ expressionProxies.ensureCapacity(minSize+10); // Allow room to grow ten more.
+ int fill = minSize-expressionProxies.size(); // Number of "null" fill entries needed. Probably shouldn't occur, but to be safe.
+ if (fill > 0) {
+ while (--fill > 0)
+ expressionProxies.add(null);
+ expressionProxies.add(proxy);
+ } else
+ expressionProxies.set(proxy.getProxyID(), proxy); // Already large enough, replace entry.
+
}
/**
@@ -596,13 +1462,18 @@
/**
* Get the enum constant for the type of primitive passed in.
+ * <p>
+ * This is a helper method for expression processer to get the enum for the primitive type. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
+
* @param primitiveType
* @return
+ * @throws IllegalArgumentException if type is not a primitive.
*
* @see ExpressionProcesser#BOOLEAN
* @since 1.0.0
*/
- protected final int getEnumForPrimitive(Class primitiveType) {
+ protected final int getEnumForPrimitive(Class primitiveType) throws IllegalArgumentException {
if (primitiveType == Boolean.TYPE)
return BOOLEAN;
else if (primitiveType == Integer.TYPE)
@@ -620,564 +1491,595 @@
else if (primitiveType == Short.TYPE)
return SHORT;
else
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(primitiveType != null ? primitiveType.getName() : "null");
}
- private void throwInvalidPrefix(int operator, Object exp) throws IllegalArgumentException {
- throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.InvalidOperandOfPrefixOperator_EXC_"), new Object[] {exp != null ? exp.toString() : null, PRE_OPER_TO_STRING[operator]})); //$NON-NLS-1$
- }
-
- private static final String[] IN_OPER_TO_STRING;
- static {
- IN_OPER_TO_STRING = new String[IExpressionConstants.IN_MAX+1];
- IN_OPER_TO_STRING[IExpressionConstants.IN_AND] = "&"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_CONDITIONAL_AND] = "&&"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_CONDITIONAL_OR] = "||"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_DIVIDE] = "/"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_EQUALS] = "=="; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_GREATER] = ">"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_GREATER_EQUALS] = ">="; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_LEFT_SHIFT] = "<<"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_LESS] = "<"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_LESS_EQUALS] = "<="; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_MINUS] = "-"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_NOT_EQUALS] = "!="; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_OR] = "|"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_PLUS] = "+"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_REMAINDER] = "%"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_RIGHT_SHIFT_SIGNED] = ">>"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED] = ">>>"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_TIMES] = "*"; //$NON-NLS-1$
- IN_OPER_TO_STRING[IExpressionConstants.IN_XOR] = "^"; //$NON-NLS-1$
- }
-
+ private void throwInvalidPrefix(PrefixOperator operator, Object exp) throws IllegalArgumentException {
+ throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.InvalidOperandOfPrefixOperator_EXC_"), new Object[] {exp != null ? exp.toString() : null, operator.toString()})); //$NON-NLS-1$
+ }
+ private static final Object INFIX_IGNORE = "INFIX IGNORE"; // Flag for infix in ingore
+ private int infixNesting = 0; // Nesting of infix expressions.
+ private int infixIgnoreNestCount = 0; // When ignoring infix expressions, ignore until this nest count.
/**
* Push the infix expression onto the stack.
* @param operator
- * @param operandType The operator type from IExpressionConstants.IN_*
- * @throws NoExpressionValueException
- *
- * @see IExpressionConstants#IN_AND
+ * @param operandType The operator type. Left, right, other.
* @since 1.0.0
*/
- public final void pushInfix(int operator, int operandType) throws NoExpressionValueException {
- boolean wasIgnoring = ignoreExpression>0;
- if (wasIgnoring)
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- ignoreExpression++; // Increment it so that entire expression is ignored because we already are in an ignore.
- else if (operandType == IInternalExpressionConstants.INFIX_LAST_OPERAND)
- ignoreExpression--; // Decrement it because we have reached the end.
- if (ignoreExpression>0)
- return; // We are still ignoring.
-
- if (wasIgnoring && operandType == IInternalExpressionConstants.INFIX_LAST_OPERAND)
- return; // We've received the last operand but we were ignoring, but the value of the entire expression is still the top stack value.
-
- Object right = null;
- Class rightType = null;
- if (operandType != IInternalExpressionConstants.INFIX_LEFT_OPERAND) {
- // We are not the left operand, so the stack has the right on the top, followed by the left.
- right = popExpression();
- rightType = popExpressionType(false);
- }
-
- Object value = popExpression();
- Class valueType = popExpressionType(false);
+ public final void pushInfix(InfixOperator operator, InternalInfixOperandType operandType) {
+ try {
+ boolean ignore = true;
+ try {
+ if (errorOccurred) {
+ return;
+ }
+ // Slightly different here in that if an ignored occurred we still need to process at least part of it so that
+ // we can get the expression grouping correct.
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ infixNesting++;
+ else if (operandType == InternalInfixOperandType.INFIX_LAST_OPERAND) {
+ int currentNest = infixNesting--;
+ if (ignoreExpression == INFIX_IGNORE && currentNest == infixIgnoreNestCount) {
+ // We were ignoring, and it was this expression that was being ignore.
+ // We have received the last operand of the nested expression that was being ignored,
+ // so we can stop ignoring. But we still leave since the value of the expression is on the
+ // top of the stack.
+ ignoreExpression = null;
+ return;
+ }
+ }
+
+ if (ignoreExpression != null)
+ return;
+ ignore = false;
+ } finally {
+ if (traceOn)
+ printTrace("Infix: "+operator, ignore);
+ }
+
+ try {
+ Object right = null;
+ Class rightType = null;
+ if (operandType != InternalInfixOperandType.INFIX_LEFT_OPERAND) {
+ // We are not the left operand, so the stack has the right on the top, followed by the left.
+ right = popExpression();
+ rightType = popExpressionType(false);
+ }
+
+ Object value = popExpression();
+ Class valueType = popExpressionType(false);
+
+ switch (operator.getValue()) {
+ case InfixOperator.IN_AND_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidBitType(valueType, InfixOperator.IN_AND);
+ testValidBitType(rightType, InfixOperator.IN_AND);
+ if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) & getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it is int. (even two shorts together produce an int).
+ value = new Integer(getInt(value) & getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_CONDITIONAL_AND_VALUE:
+ // This is tricky.
+ // First if this is left type, then just continue.
+ // Else if this other or last, then need to make it the new value.
+ if (operandType != InternalInfixOperandType.INFIX_LEFT_OPERAND) {
+ value = right;
+ valueType = rightType;
+ }
+
+ //If the value is now false, we need to ignore the rest.
+ if (valueType != Boolean.TYPE)
+ throwInvalidInfix(operator, value);
+ if (!((Boolean) value).booleanValue() && operandType != InternalInfixOperandType.INFIX_LAST_OPERAND)
+ startInfixIgnore(); // Start ignoring because we know the value of the expression at this point. It is false.
+ break;
+ case InfixOperator.IN_CONDITIONAL_OR_VALUE:
+ // This is tricky.
+ // First if this is left type, then just continue.
+ // Else if this other or last, then need to make it the new value.
+ if (operandType != InternalInfixOperandType.INFIX_LEFT_OPERAND) {
+ value = right;
+ valueType = rightType;
+ }
+
+ //If the value is now true, we need to ignore the rest.
+ if (valueType != Boolean.TYPE)
+ throwInvalidInfix(operator, value);
+ if (((Boolean) value).booleanValue() && operandType != InternalInfixOperandType.INFIX_LAST_OPERAND)
+ startInfixIgnore(); // Start ignoring because we know the value of the expression at this point. It is true.
+ break;
+ case InfixOperator.IN_DIVIDE_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_DIVIDE);
+ testValidArithmeticType(rightType, InfixOperator.IN_DIVIDE);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, the result will be double.
+ value = new Double(getDouble(value) / getDouble(right));
+ valueType = Double.TYPE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, the result will be float.
+ value = new Float(getFloat(value) / getFloat(right));
+ valueType = Float.TYPE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) / getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it will result in an int, even if both sides are short.
+ value = new Integer(getInt(value) / getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_EQUALS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+ // We should never get extended operator for this, but we'll ignore the possibility.
+ if (valueType.isPrimitive() && rightType.isPrimitive()) {
+ // Primitives require more testing than just ==. boolean primitives
+ if (valueType == Boolean.TYPE || rightType == Boolean.TYPE) {
+ // If either side is a boolean, then the other side needs to be boolean for it to even try to be true.
+ if (valueType != Boolean.TYPE || valueType != Boolean.TYPE)
+ value = Boolean.FALSE;
+ else
+ value = (((Boolean) value).booleanValue() == ((Boolean) right).booleanValue()) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Now do number tests since not boolean primitive, only numbers are left
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, compare as double.
+ value = (getDouble(value) == getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, compare as float.
+ value = (getFloat(value) == getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the compare as long.
+ value = (getLong(value) == getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Else it will compare as int, even if both sides are short.
+ value = (getInt(value) == getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ }
+ } else if (valueType.isPrimitive() || rightType.isPrimitive())
+ value = Boolean.FALSE; // Can't be true if one side prim and the other isn't
+ else {
+ // Just do object ==
+ value = (value == right) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ valueType = Boolean.TYPE; // We know result will be a boolean.
+ break;
+ case InfixOperator.IN_GREATER_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_GREATER);
+ testValidArithmeticType(rightType, InfixOperator.IN_GREATER);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, compare will be double.
+ value = (getDouble(value) > getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, compare will be float.
+ value = (getFloat(value) > getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, compare will be long.
+ value = (getLong(value) > getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Else compare will be int, even if both sides are short.
+ value = (getInt(value) > getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ valueType = Boolean.TYPE; // We know result will be a boolean.
+ break;
+ case InfixOperator.IN_GREATER_EQUALS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_GREATER_EQUALS);
+ testValidArithmeticType(rightType, InfixOperator.IN_GREATER_EQUALS);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, compare will be double.
+ value = (getDouble(value) >= getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, compare will be float.
+ value = (getFloat(value) >= getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, compare will be long.
+ value = (getLong(value) >= getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Else compare will be int, even if both sides are short.
+ value = (getInt(value) >= getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ valueType = Boolean.TYPE; // We know result will be a boolean.
+ break;
+ case InfixOperator.IN_LEFT_SHIFT_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidBitType(valueType, InfixOperator.IN_LEFT_SHIFT);
+ testValidBitType(rightType, InfixOperator.IN_LEFT_SHIFT);
+ if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) << getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it is int. (even two shorts together produce an int).
+ value = new Integer(getInt(value) << getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_LESS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_LESS);
+ testValidArithmeticType(rightType, InfixOperator.IN_LESS);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, compare will be double.
+ value = (getDouble(value) < getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, compare will be float.
+ value = (getFloat(value) < getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, compare will be long.
+ value = (getLong(value) < getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Else compare will be int, even if both sides are short.
+ value = (getInt(value) < getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ valueType = Boolean.TYPE; // We know result will be a boolean.
+ break;
+ case InfixOperator.IN_LESS_EQUALS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_LESS_EQUALS);
+ testValidArithmeticType(rightType, InfixOperator.IN_LESS_EQUALS);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, compare will be double.
+ value = (getDouble(value) <= getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, compare will be float.
+ value = (getFloat(value) <= getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, compare will be long.
+ value = (getLong(value) <= getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Else compare will be int, even if both sides are short.
+ value = (getInt(value) <= getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ valueType = Boolean.TYPE; // We know result will be a boolean.
+ break;
+ case InfixOperator.IN_MINUS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_MINUS);
+ testValidArithmeticType(rightType, InfixOperator.IN_MINUS);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, the result will be double.
+ value = new Double(getDouble(value) - getDouble(right));
+ valueType = Double.TYPE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, the result will be float.
+ value = new Float(getFloat(value) - getFloat(right));
+ valueType = Float.TYPE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) - getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it will result in an int, even if both sides are short.
+ value = new Integer(getInt(value) - getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_NOT_EQUALS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+ // We should never get extended operator for this, but we'll ignore the possibility.
+ if (valueType.isPrimitive() && rightType.isPrimitive()) {
+ // Primitives require more testing than just ==. boolean primitives
+ if (valueType == Boolean.TYPE || rightType == Boolean.TYPE) {
+ // If either side is a boolean, then the other side needs to be boolean for it to even try to be true.
+ if (valueType != Boolean.TYPE || valueType != Boolean.TYPE)
+ value = Boolean.TRUE;
+ else
+ value = (((Boolean) value).booleanValue() != ((Boolean) right).booleanValue()) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Now do number tests since not boolean primitive, only numbers are left
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, compare as double.
+ value = (getDouble(value) != getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, compare as float.
+ value = (getFloat(value) != getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the compare as long.
+ value = (getLong(value) != getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
+ } else {
+ // Else it will compare as int, even if both sides are short.
+ value = (getInt(value) != getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ }
+ } else if (valueType.isPrimitive() || rightType.isPrimitive())
+ value = Boolean.TRUE; // Must be true if one side prim and the other isn't
+ else {
+ // Just do object !=
+ value = (value != right) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ valueType = Boolean.TYPE; // We know result will be a boolean.
+ break;
+ case InfixOperator.IN_OR_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidBitType(valueType, InfixOperator.IN_OR);
+ testValidBitType(rightType, InfixOperator.IN_OR);
+ if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) | getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it is int. (even two shorts together produce an int).
+ value = new Integer(getInt(value) | getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_PLUS_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND) {
+ if (valueType == String.class) {
+ // Special. left argument is a string, so we want to store a string buffer instead
+ // since we know we will be appending to it.
+ value = new StringBuffer((String) value);
+ }
+ break; // Do nothing with first operand
+ }
+
+ testValidPlusType(valueType, rightType);
+ if (valueType == String.class || rightType == String.class) {
+ // Special we have a string on one side. Need to do it as strings instead.
+ // We are going to be tricky in that we will store a StringBuffer on the stack (if not last operand)
+ // but call it a string.
+ StringBuffer sb = null;
+ if (valueType == String.class) {
+ sb = (StringBuffer) value; // We know that if the value (left) is string type, we've already converted it to buffer.
+ } else {
+ // The right is the one that introduces the string, so we change the value over to a string buffer.
+ sb = new StringBuffer(((String) right).length()+16); // We can't put the value in yet, need to get left into it.
+ appendToBuffer(sb, value, valueType); // Put the left value in now
+ value = sb;
+ valueType = String.class; // Make it a string class
+ }
+ appendToBuffer(sb, right, rightType);
+ // Now if we are the last operand, we should get rid of the buffer and put a true string back in.
+ if (operandType == InternalInfixOperandType.INFIX_LAST_OPERAND)
+ value = sb.toString();
+ } else if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, the result will be double.
+ value = new Double(getDouble(value) + getDouble(right));
+ valueType = Double.TYPE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, the result will be float.
+ value = new Float(getFloat(value) + getFloat(right));
+ valueType = Float.TYPE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) + getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it will result in an int, even if both sides are short.
+ value = new Integer(getInt(value) + getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_REMAINDER_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_REMAINDER);
+ testValidArithmeticType(rightType, InfixOperator.IN_REMAINDER);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, the result will be double.
+ value = new Double(getDouble(value) % getDouble(right));
+ valueType = Double.TYPE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, the result will be float.
+ value = new Float(getFloat(value) % getFloat(right));
+ valueType = Float.TYPE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) % getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it will result in an int, even if both sides are short.
+ value = new Integer(getInt(value) % getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_RIGHT_SHIFT_SIGNED_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidBitType(valueType, InfixOperator.IN_RIGHT_SHIFT_SIGNED);
+ testValidBitType(rightType, InfixOperator.IN_RIGHT_SHIFT_SIGNED);
+ if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) >> getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it is int. (even two shorts together produce an int).
+ value = new Integer(getInt(value) >> getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_RIGHT_SHIFT_UNSIGNED_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidBitType(valueType, InfixOperator.IN_RIGHT_SHIFT_UNSIGNED);
+ testValidBitType(rightType, InfixOperator.IN_RIGHT_SHIFT_UNSIGNED);
+ if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) >>> getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it is int. (even two shorts together produce an int).
+ value = new Integer(getInt(value) >>> getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_TIMES_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidArithmeticType(valueType, InfixOperator.IN_TIMES);
+ testValidArithmeticType(rightType, InfixOperator.IN_TIMES);
+ if (valueType == Double.TYPE || rightType == Double.TYPE) {
+ // If either side is double, the result will be double.
+ value = new Double(getDouble(value) * getDouble(right));
+ valueType = Double.TYPE;
+ } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
+ // If either side is float, the result will be float.
+ value = new Float(getFloat(value) * getFloat(right));
+ valueType = Float.TYPE;
+ } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) * getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it will result in an int, even if both sides are short.
+ value = new Integer(getInt(value) * getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ case InfixOperator.IN_XOR_VALUE:
+ if (operandType == InternalInfixOperandType.INFIX_LEFT_OPERAND)
+ break; // Do nothing with first operand
+
+ testValidBitType(valueType, InfixOperator.IN_XOR);
+ testValidBitType(rightType, InfixOperator.IN_XOR);
+ if (valueType == Long.TYPE || rightType == Long.TYPE) {
+ // If either side is long, the result will be long.
+ value = new Long(getLong(value) ^ getLong(right));
+ valueType = Long.TYPE;
+ } else {
+ // Else it is int. (even two shorts together produce an int).
+ value = new Integer(getInt(value) ^ getInt(right));
+ valueType = Integer.TYPE;
+ }
+ break;
+ }
+
+ if (traceOn)
+ printObjectAndType(value, valueType);
+ pushExpressionValue(value, valueType); // Push the result back on the stack.
+
+ } catch (IllegalArgumentException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (RuntimeException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
+ }
- switch (operator) {
- case IExpressionConstants.IN_AND:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidBitType(valueType, IExpressionConstants.IN_AND);
- testValidBitType(rightType, IExpressionConstants.IN_AND);
- if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) & getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it is int. (even two shorts together produce an int).
- value = new Integer(getInt(value) & getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_CONDITIONAL_AND:
- // This is tricky.
- // First if this is left type, then just continue.
- // Else if this other or last, then need to make it the new value.
- if (operandType != IInternalExpressionConstants.INFIX_LEFT_OPERAND) {
- value = right;
- valueType = rightType;
- }
-
- //If the value is now false, we need to ignore the rest.
- if (valueType != Boolean.TYPE)
- throwInvalidInfix(operator, value);
- if (!((Boolean) value).booleanValue() && operandType != IInternalExpressionConstants.INFIX_LAST_OPERAND)
- ++ignoreExpression; // Start ignoring since current value is now false.
- break;
- case IExpressionConstants.IN_CONDITIONAL_OR:
- // This is tricky.
- // First if this is left type, then just continue.
- // Else if this other or last, then need to make it the new value.
- if (operandType != IInternalExpressionConstants.INFIX_LEFT_OPERAND) {
- value = right;
- valueType = rightType;
- }
-
- //If the value is now true, we need to ignore the rest.
- if (valueType != Boolean.TYPE)
- throwInvalidInfix(operator, value);
- if (((Boolean) value).booleanValue() && operandType != IInternalExpressionConstants.INFIX_LAST_OPERAND)
- ++ignoreExpression; // Start ignoring since current value is now true.
- break;
- case IExpressionConstants.IN_DIVIDE:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_DIVIDE);
- testValidArithmeticType(rightType, IExpressionConstants.IN_DIVIDE);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, the result will be double.
- value = new Double(getDouble(value) / getDouble(right));
- valueType = Double.TYPE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, the result will be float.
- value = new Float(getFloat(value) / getFloat(right));
- valueType = Float.TYPE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) / getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it will result in an int, even if both sides are short.
- value = new Integer(getInt(value) / getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_EQUALS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
- // We should never get extended operator for this, but we'll ignore the possibility.
- if (valueType.isPrimitive() && rightType.isPrimitive()) {
- // Primitives require more testing than just ==. boolean primitives
- if (valueType == Boolean.TYPE || rightType == Boolean.TYPE) {
- // If either side is a boolean, then the other side needs to be boolean for it to even try to be true.
- if (valueType != Boolean.TYPE || valueType != Boolean.TYPE)
- value = Boolean.FALSE;
- else
- value = (((Boolean) value).booleanValue() == ((Boolean) right).booleanValue()) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Now do number tests since not boolean primitive, only numbers are left
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, compare as double.
- value = (getDouble(value) == getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, compare as float.
- value = (getFloat(value) == getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the compare as long.
- value = (getLong(value) == getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Else it will compare as int, even if both sides are short.
- value = (getInt(value) == getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
- }
- }
- } else if (valueType.isPrimitive() || rightType.isPrimitive())
- value = Boolean.FALSE; // Can't be true if one side prim and the other isn't
- else {
- // Just do object ==
- value = (value == right) ? Boolean.TRUE : Boolean.FALSE;
- }
- valueType = Boolean.TYPE; // We know result will be a boolean.
- break;
- case IExpressionConstants.IN_GREATER:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_GREATER);
- testValidArithmeticType(rightType, IExpressionConstants.IN_GREATER);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, compare will be double.
- value = (getDouble(value) > getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, compare will be float.
- value = (getFloat(value) > getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, compare will be long.
- value = (getLong(value) > getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Else compare will be int, even if both sides are short.
- value = (getInt(value) > getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
- }
- valueType = Boolean.TYPE; // We know result will be a boolean.
- break;
- case IExpressionConstants.IN_GREATER_EQUALS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_GREATER_EQUALS);
- testValidArithmeticType(rightType, IExpressionConstants.IN_GREATER_EQUALS);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, compare will be double.
- value = (getDouble(value) >= getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, compare will be float.
- value = (getFloat(value) >= getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, compare will be long.
- value = (getLong(value) >= getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Else compare will be int, even if both sides are short.
- value = (getInt(value) >= getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
- }
- valueType = Boolean.TYPE; // We know result will be a boolean.
- break;
- case IExpressionConstants.IN_LEFT_SHIFT:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidBitType(valueType, IExpressionConstants.IN_LEFT_SHIFT);
- testValidBitType(rightType, IExpressionConstants.IN_LEFT_SHIFT);
- if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) << getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it is int. (even two shorts together produce an int).
- value = new Integer(getInt(value) << getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_LESS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_LESS);
- testValidArithmeticType(rightType, IExpressionConstants.IN_LESS);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, compare will be double.
- value = (getDouble(value) < getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, compare will be float.
- value = (getFloat(value) < getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, compare will be long.
- value = (getLong(value) < getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Else compare will be int, even if both sides are short.
- value = (getInt(value) < getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
- }
- valueType = Boolean.TYPE; // We know result will be a boolean.
- break;
- case IExpressionConstants.IN_LESS_EQUALS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_LESS_EQUALS);
- testValidArithmeticType(rightType, IExpressionConstants.IN_LESS_EQUALS);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, compare will be double.
- value = (getDouble(value) <= getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, compare will be float.
- value = (getFloat(value) <= getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, compare will be long.
- value = (getLong(value) <= getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Else compare will be int, even if both sides are short.
- value = (getInt(value) <= getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
- }
- valueType = Boolean.TYPE; // We know result will be a boolean.
- break;
- case IExpressionConstants.IN_MINUS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_MINUS);
- testValidArithmeticType(rightType, IExpressionConstants.IN_MINUS);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, the result will be double.
- value = new Double(getDouble(value) - getDouble(right));
- valueType = Double.TYPE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, the result will be float.
- value = new Float(getFloat(value) - getFloat(right));
- valueType = Float.TYPE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) - getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it will result in an int, even if both sides are short.
- value = new Integer(getInt(value) - getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_NOT_EQUALS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
- // We should never get extended operator for this, but we'll ignore the possibility.
- if (valueType.isPrimitive() && rightType.isPrimitive()) {
- // Primitives require more testing than just ==. boolean primitives
- if (valueType == Boolean.TYPE || rightType == Boolean.TYPE) {
- // If either side is a boolean, then the other side needs to be boolean for it to even try to be true.
- if (valueType != Boolean.TYPE || valueType != Boolean.TYPE)
- value = Boolean.TRUE;
- else
- value = (((Boolean) value).booleanValue() != ((Boolean) right).booleanValue()) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Now do number tests since not boolean primitive, only numbers are left
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, compare as double.
- value = (getDouble(value) != getDouble(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, compare as float.
- value = (getFloat(value) != getFloat(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the compare as long.
- value = (getLong(value) != getLong(right)) ? Boolean.TRUE : Boolean.FALSE;
- } else {
- // Else it will compare as int, even if both sides are short.
- value = (getInt(value) != getInt(right)) ? Boolean.TRUE : Boolean.FALSE;
- }
- }
- } else if (valueType.isPrimitive() || rightType.isPrimitive())
- value = Boolean.TRUE; // Must be true if one side prim and the other isn't
- else {
- // Just do object !=
- value = (value != right) ? Boolean.TRUE : Boolean.FALSE;
- }
- valueType = Boolean.TYPE; // We know result will be a boolean.
- break;
- case IExpressionConstants.IN_OR:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidBitType(valueType, IExpressionConstants.IN_OR);
- testValidBitType(rightType, IExpressionConstants.IN_OR);
- if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) | getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it is int. (even two shorts together produce an int).
- value = new Integer(getInt(value) | getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_PLUS:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND) {
- if (valueType == String.class) {
- // Special. left argument is a string, so we want to store a string buffer instead
- // since we know we will be appending to it.
- value = new StringBuffer((String) value);
- }
- break; // Do nothing with first operand
- }
-
- testValidPlusType(valueType, rightType);
- if (valueType == String.class || rightType == String.class) {
- // Special we have a string on one side. Need to do it as strings instead.
- // We are going to be tricky in that we will store a StringBuffer on the stack (if not last operand)
- // but call it a string.
- StringBuffer sb = null;
- if (valueType == String.class) {
- sb = (StringBuffer) value; // We know that if the value (left) is string type, we've already converted it to buffer.
- } else {
- // The right is the one that introduces the string, so we change the value over to a string buffer.
- sb = new StringBuffer(((String) right).length()+16); // We can't put the value in yet, need to get left into it.
- appendToBuffer(sb, value, valueType); // Put the left value in now
- value = sb;
- valueType = String.class; // Make it a string class
- }
- appendToBuffer(sb, right, rightType);
- // Now if we are the last operand, we should get rid of the buffer and put a true string back in.
- if (operandType == IInternalExpressionConstants.INFIX_LAST_OPERAND)
- value = sb.toString();
- } else if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, the result will be double.
- value = new Double(getDouble(value) + getDouble(right));
- valueType = Double.TYPE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, the result will be float.
- value = new Float(getFloat(value) + getFloat(right));
- valueType = Float.TYPE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) + getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it will result in an int, even if both sides are short.
- value = new Integer(getInt(value) + getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_REMAINDER:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_REMAINDER);
- testValidArithmeticType(rightType, IExpressionConstants.IN_REMAINDER);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, the result will be double.
- value = new Double(getDouble(value) % getDouble(right));
- valueType = Double.TYPE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, the result will be float.
- value = new Float(getFloat(value) % getFloat(right));
- valueType = Float.TYPE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) % getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it will result in an int, even if both sides are short.
- value = new Integer(getInt(value) % getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_RIGHT_SHIFT_SIGNED:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidBitType(valueType, IExpressionConstants.IN_RIGHT_SHIFT_SIGNED);
- testValidBitType(rightType, IExpressionConstants.IN_RIGHT_SHIFT_SIGNED);
- if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) >> getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it is int. (even two shorts together produce an int).
- value = new Integer(getInt(value) >> getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidBitType(valueType, IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED);
- testValidBitType(rightType, IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED);
- if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) >>> getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it is int. (even two shorts together produce an int).
- value = new Integer(getInt(value) >>> getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_TIMES:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidArithmeticType(valueType, IExpressionConstants.IN_TIMES);
- testValidArithmeticType(rightType, IExpressionConstants.IN_TIMES);
- if (valueType == Double.TYPE || rightType == Double.TYPE) {
- // If either side is double, the result will be double.
- value = new Double(getDouble(value) * getDouble(right));
- valueType = Double.TYPE;
- } else if (valueType == Float.TYPE || rightType == Float.TYPE) {
- // If either side is float, the result will be float.
- value = new Float(getFloat(value) * getFloat(right));
- valueType = Float.TYPE;
- } else if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) * getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it will result in an int, even if both sides are short.
- value = new Integer(getInt(value) * getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- case IExpressionConstants.IN_XOR:
- if (operandType == IInternalExpressionConstants.INFIX_LEFT_OPERAND)
- break; // Do nothing with first operand
-
- testValidBitType(valueType, IExpressionConstants.IN_XOR);
- testValidBitType(rightType, IExpressionConstants.IN_XOR);
- if (valueType == Long.TYPE || rightType == Long.TYPE) {
- // If either side is long, the result will be long.
- value = new Long(getLong(value) ^ getLong(right));
- valueType = Long.TYPE;
- } else {
- // Else it is int. (even two shorts together produce an int).
- value = new Integer(getInt(value) ^ getInt(right));
- valueType = Integer.TYPE;
- }
- break;
- }
-
- pushExpressionValue(value, valueType); // Push the result back on the stack.
+ /**
+ * Start ignoring rest of the current infix expression.
+ *
+ * @since 1.1.0
+ */
+ private void startInfixIgnore() {
+ ignoreExpression = INFIX_IGNORE;
+ infixIgnoreNestCount = infixNesting; // Ignore until we get back to the current nesting.
+
}
/**
* Get int value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
* Anything else will cause a class cast error.
- *
+ * <p>
+ * This is a helper method for expression processer to get the int value of the object. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
* @param bean
- * @return
+ * @return the int value of the number/character
+ * @throws ClassCastException
*
* @since 1.0.0
*/
- protected final int getInt(Object bean) {
+ protected final int getInt(Object bean) throws ClassCastException {
return (bean instanceof Number) ? ((Number) bean).intValue() : ((Character) bean).charValue();
}
/**
* Get float value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
* Anything else will cause a class cast error.
- *
- * @param bean
- * @return
- *
+ * <p>
+ * This is a helper method for expression processer to get the float value of the object. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
+ * @param bean
+ * @return float value of the Number/character
+ * @throws ClassCastException
* @since 1.0.0
*/
- protected final float getFloat(Object bean) {
+ protected final float getFloat(Object bean) throws ClassCastException {
return (bean instanceof Number) ? ((Number) bean).floatValue() : ((Character) bean).charValue();
}
/**
* Get double value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
* Anything else will cause a class cast error.
+ * <p>
+ * This is a helper method for expression processer to get the float value of the object. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
*
* @param bean
- * @return
- *
+ * @return double value of the Number/Character.
+ * @throws ClassCastException
* @since 1.0.0
*/
- protected final double getDouble(Object bean) {
+ protected final double getDouble(Object bean) throws ClassCastException {
return (bean instanceof Number) ? ((Number) bean).doubleValue() : ((Character) bean).charValue();
}
/**
* Get long value of the primitive wrapper bean passed in (must be either a <code>Number/code> or <code>Character</code>.
* Anything else will cause a class cast error.
+ * <p>
+ * This is a helper method for expression processer to get the float value of the object. Since it is a helper method it doesn't
+ * check nor process the exception. It throws it. Callers must handle it as they see fit.
*
* @param bean
* @return
- *
+ * @throws ClassCastException
* @since 1.0.0
*/
- protected final long getLong(Object bean) {
+ protected final long getLong(Object bean) throws ClassCastException {
return (bean instanceof Number) ? ((Number) bean).longValue() : ((Character) bean).charValue();
}
- private void throwInvalidInfix(int operator, Object value) throws IllegalArgumentException {
- throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.InvalidOperandOfOperator_EXC_"), new Object[] {value != null ? value.toString() : null, IN_OPER_TO_STRING[operator]})); //$NON-NLS-1$
+ private void throwInvalidInfix(InfixOperator operator, Object value) throws IllegalArgumentException {
+ throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.InvalidOperandOfOperator_EXC_"), new Object[] {value != null ? value.toString() : null, operator.toString()})); //$NON-NLS-1$
}
- private void testValidBitType(Class type, int operator) {
+ private void testValidBitType(Class type, InfixOperator operator) {
if (!type.isPrimitive() || type == Boolean.TYPE || type == Double.TYPE|| type == Float.TYPE)
throwInvalidInfix(operator, type);
}
- private void testValidArithmeticType(Class type, int operator) {
+ private void testValidArithmeticType(Class type, InfixOperator operator) {
if (!type.isPrimitive() || type == Boolean.TYPE)
throwInvalidInfix(operator, type);
}
@@ -1187,8 +2089,8 @@
if (left == String.class || right == String.class)
return; // As long as one side is string. Anything is valid.
// If neither is string, then standard arithmetic test.
- testValidArithmeticType(left, IExpressionConstants.IN_PLUS);
- testValidArithmeticType(right, IExpressionConstants.IN_PLUS);
+ testValidArithmeticType(left, InfixOperator.IN_PLUS);
+ testValidArithmeticType(right, InfixOperator.IN_PLUS);
}
private void appendToBuffer(StringBuffer sb, Object value, Class valueType) {
@@ -1233,48 +2135,67 @@
* Push the array access expression.
*
* @param indexCount Number of dimensions being accessed
- * @throws NoExpressionValueException
- *
* @since 1.0.0
*/
- public final void pushArrayAccess(int indexCount) throws NoExpressionValueException {
- if (ignoreExpression>0)
- return;
+ public final void pushArrayAccess(int indexCount) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
- // We need to pop off the args. The topmost will be the rightmost index, and the bottom most will be the array itself.
- int[] arguments = new int[indexCount];
- // Fill the arg array in reverse order.
- for(int i=indexCount-1; i >= 0; i--) {
- Object index = popExpression();
- Class indexType = popExpressionType(false);
- if (indexType.isPrimitive() && (indexType == Integer.TYPE || indexType == Short.TYPE || indexType == Character.TYPE || indexType == Byte.TYPE)) {
- arguments[i] = getInt(index);
- } else
- throwClassCast(Integer.TYPE, index);
+ if (traceOn) {
+ printTrace("Array Access["+indexCount+']', ignore);
}
-
- Object array = popExpression();
- Class arrayType = popExpressionType(false);
- if (arrayType.isArray()) {
- // First figure out how many dimensions are available. Stop when we hit indexcount because we won't be going further.
- int dimcount = 0;
- Class[] componentTypes = new Class[indexCount]; //
- Class componentType = arrayType;
- while (dimcount < indexCount && componentType.isArray()) {
- componentTypes[dimcount++] = componentType = componentType.getComponentType();
- }
+ try {
+ if (ignore)
+ return;
- if (dimcount < indexCount)
- throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.XIsGreaterThanNumberOfDimensionsInArray_EXC_"), new Object[] {new Integer(indexCount), new Integer(dimcount)})); //$NON-NLS-1$
-
- // Now start accessing one index at a time.
- Object value = array; // Final value, start with full array.
- for(int i=0; i<indexCount; i++) {
- value = Array.get(value, arguments[i]);
+ try {
+ // We need to pop off the args. The topmost will be the rightmost index, and the bottom most will be the array itself.
+ int[] arguments = new int[indexCount];
+ // Fill the arg array in reverse order.
+ for(int i=indexCount-1; i >= 0; i--) {
+ Object index = popExpression();
+ Class indexType = popExpressionType(false);
+ if (indexType.isPrimitive() && (indexType == Integer.TYPE || indexType == Short.TYPE || indexType == Character.TYPE || indexType == Byte.TYPE)) {
+ arguments[i] = getInt(index);
+ } else
+ throwClassCast(Integer.TYPE, index);
+ }
+
+ Object array = popExpression();
+ Class arrayType = popExpressionType(false);
+ if (arrayType.isArray()) {
+ // First figure out how many dimensions are available. Stop when we hit indexcount because we won't be going further.
+ int dimcount = 0;
+ Class[] componentTypes = new Class[indexCount]; //
+ Class componentType = arrayType;
+ while (dimcount < indexCount && componentType.isArray()) {
+ componentTypes[dimcount++] = componentType = componentType.getComponentType();
+ }
+
+ if (dimcount < indexCount)
+ throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.XIsGreaterThanNumberOfDimensionsInArray_EXC_"), new Object[] {new Integer(indexCount), new Integer(dimcount)})); //$NON-NLS-1$
+
+ // Now start accessing one index at a time, stop just before the last one. The last one will be turned into an ArrayAccessReference.
+ Object value = array; // Final value, start with full array.
+ int pullCount = indexCount-1;
+ for(int i=0; i<pullCount; i++) {
+ value = Array.get(value, arguments[i]);
+ }
+ ArrayAccessReference arrayValue = ArrayAccessReference.createArrayAccessReference(value, arguments[pullCount]);
+ if (traceOn)
+ printObjectAndType(arrayValue, componentTypes[pullCount]);
+ pushExpressionValue(arrayValue, componentTypes[pullCount]);
+ } else
+ throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.NotAnArray_EXC_"), new Object[] {arrayType})); //$NON-NLS-1$
+
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (RuntimeException e) {
+ processException(e);
}
- pushExpressionValue(value, componentTypes[indexCount-1]);
- } else
- throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.NotAnArray_EXC_"), new Object[] {arrayType})); //$NON-NLS-1$
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
}
/**
@@ -1282,154 +2203,193 @@
*
* @param arrayType The type of the array
* @param dimensionCount The number of dimensions being initialized. Zero if using an initializer.
- * @throws NoExpressionValueException
- *
* @since 1.0.0
*/
- public final void pushArrayCreation(Class arrayType, int dimensionCount) throws NoExpressionValueException {
- if (ignoreExpression>0)
- return;
+ public final void pushArrayCreation(Class arrayType, int dimensionCount) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ if (traceOn)
+ printTrace("Array Creation: "+arrayType.getName()+'['+dimensionCount+']', ignore);
- if (dimensionCount == 0) {
- // The top value is the array itself, from the array initializer.
- // So we do nothing.
- } else {
- // Strip off dimensionCounts from the array type, e.g.
- // ArrayType is int[][][]
- // Dimensioncount is 2
- // Then we need to strip two componenttypes off of the array type
- // wind up with int[]
- // This is necessary because Array.new will add those dimensions back
- // on through the dimension count.
- Class componentType = arrayType;
- for(int i=0; i < dimensionCount && componentType != null; i++)
- componentType = componentType.getComponentType();
- if (componentType == null)
- throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.ArraytypeHasFewerDimensionsThanRequested_EXC_"), new Object[] {arrayType, new Integer(dimensionCount)})); //$NON-NLS-1$
+ try {
+ if (ignore)
+ return;
- // We need to pull in the dimension initializers. They are stacked in reverse order.
- int[] dimInit = new int[dimensionCount];
- for(int i=dimensionCount-1; i >= 0; i--) {
- Object index = popExpression();
- Class dimType = popExpressionType(false);
- if (dimType.isPrimitive() && (dimType == Integer.TYPE || dimType == Short.TYPE || dimType == Character.TYPE || dimType == Byte.TYPE)) {
- dimInit[i] = getInt(index);
- } else
- throwClassCast(Integer.TYPE, index);
+ try {
+ if (dimensionCount == 0) {
+ // The top value is the array itself, from the array initializer.
+ // So we do nothing.
+ } else {
+ // Strip off dimensionCounts from the array type, e.g.
+ // ArrayType is int[][][]
+ // Dimensioncount is 2
+ // Then we need to strip two componenttypes off of the array type
+ // wind up with int[]
+ // This is necessary because Array.new will add those dimensions back
+ // on through the dimension count.
+ Class componentType = arrayType;
+ for(int i=0; i < dimensionCount && componentType != null; i++)
+ componentType = componentType.getComponentType();
+ if (componentType == null)
+ throw new IllegalArgumentException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.ArraytypeHasFewerDimensionsThanRequested_EXC_"), new Object[] {arrayType, new Integer(dimensionCount)})); //$NON-NLS-1$
+
+ // We need to pull in the dimension initializers. They are stacked in reverse order.
+ int[] dimInit = new int[dimensionCount];
+ for(int i=dimensionCount-1; i >= 0; i--) {
+ Object index = popExpression();
+ Class dimType = popExpressionType(false);
+ if (dimType.isPrimitive() && (dimType == Integer.TYPE || dimType == Short.TYPE || dimType == Character.TYPE || dimType == Byte.TYPE)) {
+ dimInit[i] = getInt(index);
+ } else
+ throwClassCast(Integer.TYPE, index);
+ }
+
+ // Finally create the array.
+ Object array = Array.newInstance(componentType, dimInit);
+ pushExpressionValue(array, arrayType);
+ }
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
}
-
- // Finally create the array.
- Object array = Array.newInstance(componentType, dimInit);
- pushExpressionValue(array, arrayType);
+ } finally {
+ if (traceOn)
+ printTraceEnd();
}
+
}
/**
* Push the array initializer request.
*
- * @param arrayType The type of the array to create, minus one dimension.
+ * @param arrayType The original type of the array to create.
+ * @param stripCount the count of how many dimensions to strip to get the type needed for this initializer.
* @param expressionCount
- * @throws NoExpressionValueException
- *
* @since 1.0.0
*/
- public final void pushArrayInitializer(Class arrayType, int expressionCount) throws NoExpressionValueException {
- if (ignoreExpression>0)
- return;
-
- Object[] dimValues = null;
- if (expressionCount > 0) {
- // We need to pull in the initializers. They are stacked in reverse order.
- dimValues = new Object[expressionCount];
- for (int i = expressionCount - 1; i >= 0; i--) {
- Object dimValue = dimValues[i] = popExpression();
- Class dimType = popExpressionType(false);
- if (arrayType.isPrimitive()) {
- if (dimValue == null || !dimType.isPrimitive())
- throwClassCast(arrayType, dimType);
- // A little trickier. Can assign short to an int, but can't assign long to an int. Widening is permitted.
- if (arrayType != dimType) {
- int compEnum = getEnumForPrimitive(arrayType);
- int dimEnum = getEnumForPrimitive(dimType);
- if (compEnum == BOOLEAN || dimEnum == BOOLEAN)
+ public final void pushArrayInitializer(Class arrayType, int stripCount, int expressionCount) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+
+ if (traceOn)
+ printTrace("Initialize Array: "+arrayType.getName()+'{'+expressionCount+'}', ignore);
+
+ try {
+ if (ignore)
+ return;
+
+ try {
+ if (!arrayType.isArray()) {
+ // It is not an array type.
+ throw new ClassCastException(MessageFormat.format(InitparserTreeMessages.getString("ExpressionProcesser.CannotCastXToY_EXC_"), new Object[] {arrayType, "array"}));
+ }
+ // Strip off the number of dimensions specified.
+ while(stripCount-->0) {
+ arrayType = arrayType.getComponentType();
+ }
+ Object[] dimValues = null;
+ if (expressionCount > 0) {
+ // We need to pull in the initializers. They are stacked in reverse order.
+ dimValues = new Object[expressionCount];
+ for (int i = expressionCount - 1; i >= 0; i--) {
+ Object dimValue = dimValues[i] = popExpression();
+ Class dimType = popExpressionType(false);
+ if (arrayType.isPrimitive()) {
+ if (dimValue == null || !dimType.isPrimitive())
+ throwClassCast(arrayType, dimType);
+ // A little trickier. Can assign short to an int, but can't assign long to an int. Widening is permitted.
+ if (arrayType != dimType) {
+ int compEnum = getEnumForPrimitive(arrayType);
+ int dimEnum = getEnumForPrimitive(dimType);
+ if (compEnum == BOOLEAN || dimEnum == BOOLEAN)
+ throwClassCast(arrayType, dimType);
+ int dimValueAsInt = getInt(dimValue);
+ switch (compEnum) {
+ case BYTE :
+ // Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
+ // Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
+ // however, at this point in time we no longer know this. So we will simply allow it.
+ if (dimEnum > INT || dimValueAsInt > Byte.MAX_VALUE || dimValueAsInt < Byte.MIN_VALUE)
+ throwClassCast(arrayType, dimType);
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Byte((byte)dimValueAsInt);
+ break;
+ case SHORT :
+ // Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
+ // Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
+ // however, at this point in time we no longer know this. So we will simply allow it.
+ if (dimEnum > INT || dimValueAsInt > Short.MAX_VALUE || dimValueAsInt < Short.MIN_VALUE)
+ throwClassCast(arrayType, dimType);
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Short((short)dimValueAsInt);
+ break;
+ case CHAR :
+ // Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
+ // Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
+ // however, at this point in time we no longer know this. So we will simply allow it.
+ if (dimEnum > INT || dimValueAsInt > Character.MAX_VALUE || dimValueAsInt < Character.MIN_VALUE)
+ throwClassCast(arrayType, dimType);
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Character((char)dimValueAsInt);
+ break;
+ case INT :
+ // Can accept byte, short, char, or int. Can't accept long, double, float at all.
+ if (dimEnum > INT)
+ throwClassCast(arrayType, dimType);
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Integer(dimValueAsInt);
+ break;
+ case LONG :
+ // Can accept byte, short, char, int, or long. Can't accept double, float at all.
+ if (dimEnum > LONG)
+ throwClassCast(arrayType, dimType);
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Long(getLong(dimValue));
+ break;
+ case FLOAT :
+ // Can accept byte, short, char, int, long, or float. Can't accept double at all.
+ if (dimEnum > FLOAT)
+ throwClassCast(arrayType, dimType);
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Float(getFloat(dimValue));
+ break;
+ case DOUBLE :
+ // But need to be changed to appropriate type for the array.set to work.
+ dimValues[i] = new Double(getDouble(dimValue));
+ break;
+
+ }
+ }
+ // Compatible, so ok.
+ } else if (dimType != MethodHelper.NULL_TYPE && !arrayType.isAssignableFrom(dimType)) {
+ // If it is NULL_TYPE, then this is a pushed null. This is always assignable to a non-primitive.
+ // So we don't enter here in that case. However, a null that was returned from some expression
+ // won't have a NULL_TYPE, it will instead have the expected return type. That must be used
+ // in the assignment instead. That is because in java it uses the expected type to determine
+ // compatibility, not the actual type.
throwClassCast(arrayType, dimType);
- int dimValueAsInt = getInt(dimValue);
- switch (compEnum) {
- case BYTE :
- // Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
- // Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
- // however, at this point in time we no longer know this. So we will simply allow it.
- if (dimEnum > INT || dimValueAsInt > Byte.MAX_VALUE || dimValueAsInt < Byte.MIN_VALUE)
- throwClassCast(arrayType, dimType);
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Byte((byte)dimValueAsInt);
- break;
- case SHORT :
- // Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
- // Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
- // however, at this point in time we no longer know this. So we will simply allow it.
- if (dimEnum > INT || dimValueAsInt > Short.MAX_VALUE || dimValueAsInt < Short.MIN_VALUE)
- throwClassCast(arrayType, dimType);
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Short((short)dimValueAsInt);
- break;
- case CHAR :
- // Can accept byte, short, char, or int as long as value is <= byte max. Can't accept long, double, float at all.
- // Note: This isn't actually true. The max/min test is only valid if the value is a literal, not an expression,
- // however, at this point in time we no longer know this. So we will simply allow it.
- if (dimEnum > INT || dimValueAsInt > Character.MAX_VALUE || dimValueAsInt < Character.MIN_VALUE)
- throwClassCast(arrayType, dimType);
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Character((char)dimValueAsInt);
- break;
- case INT :
- // Can accept byte, short, char, or int. Can't accept long, double, float at all.
- if (dimEnum > INT)
- throwClassCast(arrayType, dimType);
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Integer(dimValueAsInt);
- break;
- case LONG :
- // Can accept byte, short, char, int, or long. Can't accept double, float at all.
- if (dimEnum > LONG)
- throwClassCast(arrayType, dimType);
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Long(getLong(dimValue));
- break;
- case FLOAT :
- // Can accept byte, short, char, int, long, or float. Can't accept double at all.
- if (dimEnum > FLOAT)
- throwClassCast(arrayType, dimType);
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Float(getFloat(dimValue));
- break;
- case DOUBLE :
- // But need to be changed to appropriate type for the array.set to work.
- dimValues[i] = new Double(getDouble(dimValue));
- break;
-
}
}
- // Compatible, so ok.
- } else if (dimType != MethodHelper.NULL_TYPE && !arrayType.isAssignableFrom(dimType)) {
- // If it is NULL_TYPE, then this is a pushed null. This is always assignable to a non-primitive.
- // So we don't enter here in that case. However, a null that was returned from some expression
- // won't have a NULL_TYPE, it will instead have the expected return type. That must be used
- // in the assignment instead. That is because in java it uses the expected type to determine
- // compatibility, not the actual type.
- throwClassCast(arrayType, dimType);
+
}
+
+ // Now we finally create the array.
+ Object array = Array.newInstance(arrayType, new int[] {expressionCount});
+ for (int i = 0; i < expressionCount; i++) {
+ Array.set(array, i, dimValues[i]);
+ }
+
+ pushExpressionValue(array, array.getClass()); // Adjust to true array type, not the incoming type (which is one dimension too small).
+
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
}
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
- }
-
- // Now we finally create the array.
- Object array = Array.newInstance(arrayType, new int[] {expressionCount});
- for (int i = 0; i < expressionCount; i++) {
- Array.set(array, i, dimValues[i]);
- }
-
- pushExpressionValue(array, array.getClass()); // Adjust to true array type, not the incoming type (which is one dimension too small).
}
/**
@@ -1437,160 +2397,818 @@
*
* @param type The type to create an instance of
* @param argumentCount The number of arguments (which are stored on the stack). * @throws NoExpressionValueException
- * @throws EvaluationException
- * @throws IllegalArgumentException
- * @throws InstantiationException
- * @throws IllegalAccessException
- * @throws InvocationTargetException
- *
* @since 1.0.0
*/
- public final void pushClassInstanceCreation(Class type, int argumentCount) throws NoExpressionValueException, EvaluationException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
- if (ignoreExpression>0)
- return;
-
- // We need to pull in the arguments. They are stacked in reverse order.
- Object value = null; // The new instance.
- if (argumentCount > 0) {
- Object[] args = new Object[argumentCount];
- Class[] argTypes = new Class[argumentCount];
- for (int i = argumentCount - 1; i >= 0; i--) {
- args[i] = popExpression();
- argTypes[i] = popExpressionType(false);
- }
-
- // Now we need to find the appropriate constructor.
- Constructor ctor;
- try {
- ctor = MethodHelper.findCompatibleConstructor(type, argTypes);
- } catch (NoSuchMethodException e) {
- throw new EvaluationException(e);
- } catch (AmbiguousMethodException e) {
- throw new EvaluationException(e);
- }
- value = ctor.newInstance(args);
- } else {
- // No args, just do default ctor.
- value = type.newInstance();
- }
+ public final void pushClassInstanceCreation(Class type, int argumentCount) {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
- pushExpressionValue(value, type);
+ if (traceOn)
+ printTrace("Create Class: "+type+" (", ignore);
+ try {
+ if (ignore)
+ return;
+
+ try {
+ // We need to pull in the arguments. They are stacked in reverse order.
+ Object value = null; // The new instance.
+ if (argumentCount > 0) {
+ Object[] args = new Object[argumentCount];
+ Class[] argTypes = new Class[argumentCount];
+ for (int i = argumentCount - 1; i >= 0; i--) {
+ args[i] = popExpression();
+ argTypes[i] = popExpressionType(false);
+ }
+
+ // Now we need to find the appropriate constructor.
+ Constructor ctor;
+ ctor = MethodHelper.findCompatibleConstructor(type, argTypes);
+ if (traceOn) {
+ System.out.print(ctor);
+ System.out.print(')');
+ }
+ value = ctor.newInstance(args);
+ } else {
+ // No args, just do default ctor.
+ if (traceOn) {
+ System.out.print("Default ctor)");
+ }
+ value = type.newInstance();
+ }
+
+ pushExpressionValue(value, type);
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (InstantiationException e) {
+ processException(e);
+ } catch (IllegalAccessException e) {
+ processException(e);
+ } catch (InvocationTargetException e) {
+ processException(e);
+ } catch (NoSuchMethodException e) {
+ processException(e);
+ } catch (AmbiguousMethodException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
}
/**
* Push the field access expression.
- * @param fieldName
+ * @param field String for fieldname, or a java.lang.reflect.Field.
+ * @param fieldIsString <code>true</code> if field is a string name, and not a java.lang.reflect.Field.
* @param hasReceiver
- * @throws NoExpressionValueException
- * @throws SecurityException
- * @throws NoSuchFieldException
- * @throws IllegalArgumentException
- * @throws IllegalAccessException
*
* @since 1.0.0
*/
- public final void pushFieldAccess(String fieldName, boolean hasReceiver) throws NoExpressionValueException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
- if (ignoreExpression>0)
- return;
-
- // Get the receiver off of the stack.
- Object receiver = popExpression();
- Class receiverType = popExpressionType(false);
+ public final void pushFieldAccess(Object field, boolean fieldIsString, boolean hasReceiver) {
+ try {
+ if (ignoreExpression != null || errorOccurred) {
+ if (traceOn)
+ printTrace("Field Access", true);
+ return;
+ }
- // Find the field.
- Field field = receiverType.getField(fieldName);
- // Access the field.
- Object value = field.get(receiver);
- Class valueType = field.getType();
- pushExpressionValue(value, valueType);
+ if (traceOn)
+ printTrace("Field Access: ", false);
+ try {
+ // Get the receiver off of the stack.
+ Object receiver = null;
+ Class receiverType = null;
+ if (hasReceiver) {
+ receiver = popExpression();
+ receiverType = popExpressionType(false);
+ }
+
+ // Find the field.
+ Field reflectField = fieldIsString ? receiverType.getField((String) field) : (Field) field;
+ // Access the field.
+ Object value = FieldAccessReference.createFieldAccessReference(reflectField, receiver);
+ Class valueType = reflectField.getType();
+ if (traceOn) {
+ System.out.print("Field: ");
+ System.out.print(reflectField);
+ System.out.print(">");
+ printObjectAndType(value, valueType);
+ }
+
+ pushExpressionValue(value, valueType);
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (NoSuchFieldException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+
}
/**
* Push the method invocation expression.
- * @param methodName
+ * @param method
+ * @param methodIsString <code>true</code> if method is a string (so string name) or else it is a java.lang.reflect.Method.
* @param hasReceiver
* @param argCount
- * @throws NoExpressionValueException
- * @throws EvaluationException
- * @throws IllegalArgumentException
- * @throws IllegalAccessException
- * @throws InvocationTargetException
- *
* @since 1.0.0
*/
- public final void pushMethodInvocation(String methodName, boolean hasReceiver, int argCount) throws NoExpressionValueException, EvaluationException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
- if (ignoreExpression>0)
- return;
-
- // We need to pull in the arguments. They are stacked in reverse order.
- Object[] args = new Object[argCount];
- Class[] argTypes = new Class[argCount];
- for (int i = argCount - 1; i >= 0; i--) {
- args[i] = popExpression();
- argTypes[i] = popExpressionType(false);
- }
-
- // Now get receiver
- Object receiver = popExpression();
- Class receiverType = popExpressionType(false);
-
- // Now we need to find the appropriate method.
- Method method;
+ public final void pushMethodInvocation(Object method, boolean methodIsString, boolean hasReceiver, int argCount) {
try {
- method = MethodHelper.findCompatibleMethod(receiverType, methodName, argTypes);
- } catch (NoSuchMethodException e) {
- throw new EvaluationException(e);
- } catch (AmbiguousMethodException e) {
- throw new EvaluationException(e);
+ if (ignoreExpression != null || errorOccurred) {
+ if (traceOn)
+ printTrace("Invoke", true);
+ return;
+ }
+
+ if (traceOn)
+ printTrace("Invoke: ", false);
+
+ try {
+ // We need to pull in the arguments. They are stacked in reverse order.
+ Object[] args = new Object[argCount];
+ Class[] argTypes = new Class[argCount];
+ for (int i = argCount - 1; i >= 0; i--) {
+ args[i] = popExpression();
+ argTypes[i] = popExpressionType(false);
+ }
+
+ // Now get receiver
+ Object receiver = null;
+ Class receiverType = null;
+ if (hasReceiver) {
+ receiver = popExpression();
+ receiverType = popExpressionType(false);
+ }
+
+ // Now we need to find the appropriate method. If it is a string then there must be a receiver, otherwise no way to know.
+ Method reflectMethod;
+ if (methodIsString) {
+ reflectMethod = MethodHelper.findCompatibleMethod(receiverType, (String) method, argTypes);
+ } else
+ reflectMethod = (Method) method;
+
+ if (traceOn && reflectMethod != null) {
+ System.out.print("Method: ");
+ System.out.print(reflectMethod);
+ }
+
+ Object value = reflectMethod.invoke(receiver, args);
+
+ if (traceOn) {
+ System.out.print(" returns: ");
+ printObjectAndType(value, reflectMethod.getReturnType());
+ }
+ pushExpressionValue(value, reflectMethod.getReturnType());
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (IllegalAccessException e) {
+ processException(e);
+ } catch (InvocationTargetException e) {
+ processException(e);
+ } catch (NoSuchMethodException e) {
+ processException(e);
+ } catch (AmbiguousMethodException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
}
- Object value = method.invoke(receiver, args);
-
- pushExpressionValue(value, method.getReturnType());
+
}
+ private static final Object CONDITIONAL_IGNORE = "CONDITIONAL IGNORE"; // Flag for conditional in ingore
+ private int conditionalNesting = 0; // Nesting of conditional expressions.
+ private int conditionalIgnoreNestCount = 0; // When ignoring conditional expressions, ignore until this nest count.
+ private boolean skipTruePart;
+
/**
+ * Push a conditional expression. It can be any clause of the conditional (test, true, or false clause).
* @param expressionType
*
* @since 1.0.0
*/
- public final void pushConditional(int expressionType) throws NoExpressionValueException {
- boolean wasIgnoring = ignoreExpression>0;
- if (wasIgnoring) {
- if (expressionType == IExpressionConstants.CONDITIONAL_CONDITION)
- ignoreExpression+=2; // Increment it twice so that entire expression is ignored because we already are in an ignore.
- else
- ignoreExpression--; // Decrement it because we have ignored one of the expressions.
- if (ignoreExpression>0)
- return; // We are still ignoring.
- }
-
- switch (expressionType) {
- case IExpressionConstants.CONDITIONAL_CONDITION:
- Object condition = popExpression();
- Class type = popExpressionType(false);
- if (type != Boolean.TYPE)
- throwClassCast(Boolean.TYPE, condition);
- if (((Boolean) condition).booleanValue()) {
- // Condition was true.
- // Do nothing. Let true condition be processed.
- } else {
- // Condition was false.
- ++ignoreExpression; // Tell the true condition it should be ignored.
+ public final void pushConditional(InternalConditionalOperandType expressionType) {
+ try {
+ boolean ignore = true;
+ try {
+ if (errorOccurred)
+ return;
+ // Slightly different here in that if an ignoring occurred we still need to process at least part of it so that
+ // we can get the expression grouping correct.
+ switch (expressionType.getValue()) {
+ case InternalConditionalOperandType.CONDITIONAL_TEST_VALUE:
+ conditionalNesting++;
+ break;
+ case InternalConditionalOperandType.CONDITIONAL_TRUE_VALUE:
+ if (skipTruePart && ignoreExpression == CONDITIONAL_IGNORE && conditionalIgnoreNestCount == conditionalNesting) {
+ // stop ignoring, we've ignored the true condition of interest.
+ ignoreExpression = null;
+ return; // However, leave because since this condition was ignored.
+ }
+ break;
+ case InternalConditionalOperandType.CONDITIONAL_FALSE_VALUE:
+ int currentNesting = conditionalNesting--;
+ if (ignoreExpression == CONDITIONAL_IGNORE && conditionalIgnoreNestCount == currentNesting) {
+ // stop ignoring, we've ignored the false condition of interest.
+ ignoreExpression = null;
+ return; // However, leave because since this condition was ignored.
+ }
}
- // We don't put anything back on the stack because the condition test is not ever returned.
- // The appropriate true or false condition will be left on the stack.
- break;
- case IExpressionConstants.CONDITIONAL_TRUE:
- if (!wasIgnoring) {
- // true was processed, so now tell false to not process.
- // The true condition and type will be left on top of the stack.
- ++ignoreExpression;
+
+ if (ignoreExpression != null)
+ return;
+ ignore = false;
+ } finally {
+ if (traceOn)
+ printTrace("Conditional "+expressionType, ignore);
+ }
+
+ try {
+ switch (expressionType.getValue()) {
+ case InternalConditionalOperandType.CONDITIONAL_TEST_VALUE:
+ Object condition = popExpression();
+ Class type = popExpressionType(false);
+ if (type != Boolean.TYPE)
+ throwClassCast(Boolean.TYPE, condition);
+ if (((Boolean) condition).booleanValue()) {
+ // Condition was true.
+ // Do nothing. Let true condition be processed.
+ } else {
+ // Condition was false.
+ skipTruePart = true; // Tell the true condition should be ignored.
+ ignoreExpression = CONDITIONAL_IGNORE;
+ conditionalIgnoreNestCount = conditionalNesting;
+ }
+ // We don't put anything back on the stack because the condition test is not ever returned.
+ // The appropriate true or false condition evaluation will be left on the stack.
+ break;
+ case InternalConditionalOperandType.CONDITIONAL_TRUE_VALUE:
+ skipTruePart = false; // Tell the false condition should be ignored.
+ ignoreExpression = CONDITIONAL_IGNORE;
+ conditionalIgnoreNestCount = conditionalNesting;
+ break;
+ case InternalConditionalOperandType.CONDITIONAL_FALSE_VALUE:
+ // There's nothing to do, if it was ignored due to true, we wouldn't of gotton here.
+ // If it wasn't ignored, then the result of the false expression is on the stack, which is what it should be.
+ break;
}
- break;
- case IExpressionConstants.CONDITIONAL_FALSE:
- // There's nothing to do, if it was ignored due to true, then true is on the stack.
- // If it wasn't ignored, then false expression is on the stack, which is what it should be.
- break;
+ } catch (RuntimeException e) {
+ processException(e);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
}
}
+
+ private static final Object BLOCK_IGNORE = "BLOCK IGNORE";
+ private int[] blocks; // Stack of block numbers currently evaluating.
+ private int topBlock = -1; // Top block index.
+ private int breakBlock = -1; // Block number we are breaking to.
+
+ /**
+ * Push a begin block.
+ * @param blockNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushBlockBegin(int blockNumber) {
+ if (traceOn) {
+ printTrace("Begin Block #"+blockNumber, errorOccurred);
+ indent(true);
+ }
+ try {
+ if (errorOccurred)
+ return;
+ // We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
+ if (blocks == null)
+ blocks = new int[10];
+ if (++topBlock >= blocks.length) {
+ int[] newList = new int[blocks.length*2];
+ System.arraycopy(blocks, 0, newList, 0, blocks.length);
+ blocks = newList;
+ }
+ blocks[topBlock] = blockNumber;
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Push a block end. The current block must be the given number, or it is an error.
+ *
+ * @param blockNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushBlockEnd(int blockNumber) {
+ try {
+ if (traceOn) {
+ indent(false);
+ printTrace("End Block #"+blockNumber, errorOccurred);
+ }
+ if (errorOccurred)
+ return;
+ // We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
+ if (blocks == null || topBlock < 0 || blocks[topBlock] != blockNumber) {
+ processSyntaxException(new IllegalStateException("End Blocks received out of order."));
+ } else {
+ topBlock--;
+ if (ignoreExpression == BLOCK_IGNORE && blockNumber == breakBlock) {
+ ignoreExpression = null;
+ }
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Skip all following until we hit the requested block number.
+ * @param blockNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushBlockBreak(int blockNumber) {
+ try {
+ if (traceOn)
+ printTrace("Break Block #"+blockNumber, errorOccurred);
+ if (errorOccurred)
+ return;
+ if (ignoreExpression == null) {
+ ignoreExpression = BLOCK_IGNORE; // Start ignoring expressions until we hit the block number end block.
+ breakBlock = blockNumber;
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ private static final Object TRY_THROW_IGNORE = "TRY THROW IGNORE";
+ private static final Object TRY_FINAL_IGNORE = "TRY FINAL IGNORE";
+ private int[] trys; // Stack of try numbers currently evaluating.
+ // Stack of trys in catch clause (i.e. starting executing a catch/final clause for the try). Corresponds with try from same index in trys. Contains the throwable for the catch.
+ // This is used to know we are executing a catch (entry not null) and for the rethrow short-hand to rethrow the same exception within the catch.
+ private Throwable[] trysInCatch;
+ private int topTry = -1; // Top try index.
+ private int breakTry = -1; // Try number we are breaking to.
+ private Throwable catchThrowable; // The throwable to check catches against.
+
+ /**
+ * Push a try statement.
+ * @param tryNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushTryBegin(int tryNumber) {
+ try {
+ if (traceOn) {
+ printTrace("Begin Try #"+tryNumber, errorOccurred);
+ indent(true);
+ }
+
+ if (errorOccurred)
+ return;
+ // We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
+ if (trys == null) {
+ trys = new int[10];
+ trysInCatch = new Throwable[10];
+ }
+ if (++topTry >= trys.length) {
+ int[] newList = new int[trys.length*2];
+ System.arraycopy(trys, 0, newList, 0, trys.length);
+ trys = newList;
+ Throwable[] newCatches = new Throwable[trys.length];
+ System.arraycopy(trysInCatch, 0, newCatches, 0, trysInCatch.length);
+ trysInCatch = newCatches;
+ }
+ trys[topTry] = tryNumber;
+ trysInCatch[topTry] = null;
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Throw the top stack entry. It must be an exception.
+ *
+ *
+ * @since 1.1.0
+ */
+ public final void pushThrowException() {
+ try {
+ boolean ignore = (ignoreExpression != null || errorOccurred);
+ if (traceOn)
+ printTrace("Throw exception: ", ignore);
+
+ if (ignore)
+ return;
+
+ try {
+ Object t = popExpression();
+ popExpressionType(false);
+ if (traceOn) {
+ System.out.print(t);
+ }
+ throwException((Throwable) t);
+ } catch (NoExpressionValueException e) {
+ processSyntaxException(e);
+ } catch (ClassCastException e) {
+ processException(e);
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Throw this exception (means throw through the expression being processed, not throw for this thread).
+ * @param exception
+ *
+ * @since 1.1.0
+ */
+ protected final void throwException(Throwable exception) {
+ if (topTry == -1) {
+ // There are no tries, so treat this as a syntax error.
+ processSyntaxException(exception);
+ } else if (trysInCatch[topTry] == null) {
+ // We are not in a catch clause of the top try. So do a throw ignore for toptry.
+ ignoreExpression = TRY_THROW_IGNORE;
+ breakTry = trys[topTry];
+ catchThrowable = exception;
+ } else {
+ // We are in a catch of the top try. So do a throw to finally instead.
+ ignoreExpression = TRY_FINAL_IGNORE;
+ trysInCatch[topTry] = FINAL_CATCH;
+ breakTry = trys[topTry];
+ catchThrowable = exception;
+ }
+ }
+
+ /**
+ * Push a catch clause
+ * @param tryNumber
+ * @param exceptionType
+ * @param expressionProxy
+ *
+ * @since 1.1.0
+ */
+ public final void pushTryCatchClause(int tryNumber, Class exceptionType, InternalExpressionProxy expressionProxy) {
+ try {
+ if (traceOn) {
+ indent(false);
+ if (expressionProxy == null)
+ printTrace("Catch Try #"+tryNumber+" ("+exceptionType+')', errorOccurred);
+ else
+ printTrace("Catch Try #"+tryNumber+" ("+exceptionType+") Return exception in proxy #"+expressionProxy.getProxyID(), errorOccurred);
+ indent(true);
+ }
+
+ if (errorOccurred)
+ return;
+
+ // We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
+ if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
+ processSyntaxException(new IllegalStateException("Catch received out of order."));
+ } else {
+ if (ignoreExpression == null) {
+ // Normal flow, no throw in progress, so just ignore now until the finally or end try reached.
+ ignoreExpression = TRY_FINAL_IGNORE;
+ breakTry = tryNumber;
+ } else if (ignoreExpression == TRY_THROW_IGNORE && tryNumber == breakTry) {
+ // We are here due to a throw occuring in this try block, see if for us, and if it is, stop ignoring.
+ // Else just continue ignoring.
+ if (exceptionType.isInstance(catchThrowable)) {
+ // For us, so just turn everything back on, except mark that we are in the catch phase.
+ ignoreExpression = null;
+ trysInCatch[topTry] = catchThrowable; // This is so that we know if we throw again that we should not catch anything.
+ breakTry = -1;
+ if (expressionProxy != null) {
+ expressionProxy.setProxy(catchThrowable, catchThrowable.getClass());
+ allocateExpressionProxy(expressionProxy);
+ }
+ if (traceOn) {
+ System.out.print(" Caught: ");
+ System.out.print(catchThrowable);
+ }
+ catchThrowable = null;
+ }
+ }
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ // This is used only so that finally clause can indicate it was executing so that end expression knows this.
+ private static final Throwable FINAL_CATCH = new RuntimeException();
+
+ /**
+ * Push the try finally clause.
+ * @param tryNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushTryFinallyClause(int tryNumber) {
+ try {
+ if (traceOn) {
+ indent(false);
+ printTrace("Finally Try #"+tryNumber, errorOccurred);
+ indent(true);
+ }
+ if (errorOccurred)
+ return;
+ // We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
+ if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
+ processSyntaxException(new IllegalStateException("Finally received out of order."));
+ } else {
+ if (tryNumber == breakTry && (ignoreExpression == TRY_THROW_IGNORE || ignoreExpression == TRY_FINAL_IGNORE)) {
+ // We are here due to a throw occuring in this try block or a catch was reached (in which case all intervening catch's were ignored).
+ // Now do a normal execution. If we are here due to a throw that wasn't cleared (either no catch or another throw occured within the catch)
+ // then we leave it uncleared so that try/end may rethrow it.
+ ignoreExpression = null;
+ trysInCatch[topTry] = FINAL_CATCH; // We are in the finally clause of a exception being thrown within this try.
+ breakTry = -1;
+ if (traceOn)
+ System.out.print(" Executing finally.");
+ }
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Rethrow the caught exception. This is a shortcut for:
+ * } catch (Exception e) {
+ * ... do stuff ...
+ * throw e;
+ * }
+ * @param tryNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushTryRethrow(int tryNumber) {
+ if (traceOn)
+ printTrace("Rethrow Try #"+tryNumber, errorOccurred || ignoreExpression != null);
+
+ try {
+ if (errorOccurred)
+ return;
+ // We are not checking ignore because we need to make sure this is not called out of order.
+ if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
+ processSyntaxException(new IllegalStateException("Rethrow received out of order."));
+ } else if (ignoreExpression == null) {
+ if (trysInCatch[topTry] == null || trysInCatch[topTry] == FINAL_CATCH)
+ processSyntaxException(new IllegalStateException("Retry received outside of an executing catch clause"));
+ else {
+ throwException(trysInCatch[topTry]);
+ }
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ public final void pushTryEnd(int tryNumber) {
+ if (traceOn) {
+ indent(false);
+ printTrace("End Try #"+tryNumber, errorOccurred);
+ }
+ try {
+ if (errorOccurred)
+ return;
+ // We are not checking ignore because this is a structural concept instead of executable expressions, so we need to keep track of these.
+ if (trys == null || topTry < 0 || trys[topTry] != tryNumber) {
+ processSyntaxException(new IllegalStateException("Try/end received out of order."));
+ } else {
+ boolean inCatch = trysInCatch[topTry] != null;
+ trysInCatch[topTry] = null;
+ topTry--;
+ if (inCatch || (tryNumber == breakTry && (ignoreExpression == TRY_THROW_IGNORE || ignoreExpression == TRY_FINAL_IGNORE))) {
+ // We are here due to a throw or normal flow through a catch. Either way if there is a throwable still pending, we rethrow.
+ ignoreExpression = null;
+ breakTry = -1;
+ if (catchThrowable != null)
+ throwException(catchThrowable);
+ }
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
+ /**
+ * Class used to save the state at time of mark. It will
+ * be used to restore state if error.
+ *
+ * @since 1.1.0
+ */
+ protected class SaveState {
+ public int markID;
+
+ // Block state
+ public int topBlock;
+ public int breakBlock;
+
+ // Try state
+ public int topTry;
+ public int breakTry;
+ public Throwable catchThrowable;
+
+ // Error state
+ public boolean errorOccurred;
+ public boolean novalueException;
+ public Throwable exception;
+ public Object ignoreExpression;
+
+ // Expression stack state
+ public int expressionStackPos;
+
+ // If/else state
+ public int ifElseNesting;
+ public int ifElseIgnoreNestCount;
+ public boolean ifElseSkipTruePart;
+
+ // Other
+ public int indent;
+ public int expressionProxyPos;
+
+ /**
+ * Construct and save the state.
+ *
+ * @param markNumber
+ *
+ * @since 1.1.0
+ */
+ public SaveState(int markID) {
+ this.markID = markID;
+
+ ExpressionProcesser ep = ExpressionProcesser.this;
+ this.topBlock = ep.topBlock;
+ this.breakBlock = ep.breakBlock;
+
+ this.topTry = ep.topTry;
+ this.breakTry = ep.breakTry;
+ this.catchThrowable = ep.catchThrowable;
+
+ this.errorOccurred = ep.errorOccurred;
+ this.novalueException = ep.novalueException;
+ this.exception = ep.exception;
+ this.ignoreExpression = ep.ignoreExpression;
+
+ this.expressionStackPos = expressionStack.size()-1;
+
+ this.ifElseNesting = ep.ifElseNesting;
+ this.ifElseIgnoreNestCount = ep.ifElseIgnoreNestCount;
+ this.ifElseSkipTruePart = ep.ifElseSkipTruePart;
+
+ this.indent = ep.indent;
+ this.expressionProxyPos = expressionProxies != null ? expressionProxies.size()-1 : -1;
+ }
+
+ /**
+ * Restore the state.
+ *
+ *
+ * @since 1.1.0
+ */
+ public void restoreState() {
+ ExpressionProcesser ep = ExpressionProcesser.this;
+ ep.topBlock = this.topBlock;
+ ep.breakBlock = this.breakBlock;
+
+ ep.topTry = this.topTry;
+ ep.breakTry = this.breakTry;
+ ep.catchThrowable = this.catchThrowable;
+ if (trysInCatch != null) {
+ for (int i = topTry + 1; i < ep.trysInCatch.length; i++) {
+ ep.trysInCatch[i] = null;
+ }
+ }
+
+ ep.errorOccurred = this.errorOccurred;
+ ep.novalueException = ep.novalueException;
+ ep.exception = this.exception;
+ ep.ignoreExpression = this.ignoreExpression;
+
+ // Pop stack down to saved state.
+ for (int i = expressionStack.size()-1; i > this.expressionStackPos; i--) {
+ expressionStack.remove(i);
+ expressionTypeStack.remove(i);
+ }
+
+ ep.ifElseNesting = this.ifElseNesting;
+ ep.ifElseIgnoreNestCount = this.ifElseIgnoreNestCount;
+ ep.ifElseSkipTruePart = this.ifElseSkipTruePart;
+
+ ep.indent = this.indent;
+
+ if (expressionProxies != null) {
+ for (int i = expressionProxies.size() - 1; i > this.expressionProxyPos; i--) {
+ expressionProxies.remove(i);
+ }
+ }
+
+ // These settings can't cross mark boundaries, so reset them to not set. This is in case we were in this state somewhere
+ // in the mark when the restore occurred.
+ ep.conditionalIgnoreNestCount = 0;
+ ep.conditionalNesting = 0;
+ ep.skipTruePart = false;
+
+ ep.infixIgnoreNestCount = 0;
+ ep.infixNesting = 0;
+ }
+ }
+
+ /**
+ * Create the save state with the given id.
+ * @param markID
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected SaveState createSaveState(int markID) {
+ return new SaveState(markID);
+ }
+
+ /**
+ * Push the start of a mark.
+ * @param markNumber
+ *
+ * @since 1.1.0
+ */
+ public final void pushMark(int markNumber) {
+ if (traceOn)
+ printTrace("Mark#"+markNumber, false);
+
+ if (saveStates == null)
+ saveStates = new ArrayList();
+ saveStates.add(createSaveState(markNumber));
+
+ if (traceOn)
+ printTraceEnd();
+ }
+
+ /**
+ * Push the end mark. If there is no error, it will simply
+ * remove it and all save states in the map after it. If there
+ * is an error it will do this plus it will restore the state.
+ * <p>
+ * It is assumed that the calls are coming in correct order from
+ * the server so we won't check validity.
+ *
+ * @param markID
+ * @param restore
+ *
+ * @since 1.1.0
+ */
+ public final void pushEndmark(int markID, boolean restore) {
+ if (traceOn)
+ printTrace("End Mark#"+markID+" Restored="+restore, false);
+
+ try {
+ if (saveStates != null) {
+ // Start from the end (since that is where it most likely will be) and start
+ // search, removing the end one until we reach the markID.
+ for (int i = saveStates.size() - 1; i >= 0; i--) {
+ SaveState state = (SaveState) saveStates.remove(i);
+ if (state.markID == markID) {
+ // We found it.
+ if (restore)
+ state.restoreState();
+ return;
+ }
+ }
+ // But to be safe, if we got here, this is bad. We tried restore a mark we didn't have.
+ processSyntaxException(new IllegalStateException("Tried to do an end mark on a non-existing markID (" + markID + ')'));
+ }
+ } finally {
+ if (traceOn)
+ printTraceEnd();
+ }
+ }
+
}
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ForExpression.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ForExpression.java
new file mode 100644
index 0000000..18e1ee0
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/ForExpression.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 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: ForExpression.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * Enum for the forExpression parameters.
+ * <p>
+ * This is not meant to be subclassed by customers.
+ * @since 1.1.0
+ */
+public class ForExpression extends AbstractEnum {
+
+ /**
+ * forExpression: Creating a root expression
+ */
+ public static final int ROOTEXPRESSION_VALUE = 0;
+
+ public static final ForExpression ROOTEXPRESSION = new ForExpression(ROOTEXPRESSION_VALUE, "Root");
+
+ /**
+ * forExpression: Creating the array expression for an array access (i.e. the array to access)
+ */
+ public static final int ARRAYACCESS_ARRAY_VALUE = 1;
+
+ public static final ForExpression ARRAYACCESS_ARRAY = new ForExpression(ARRAYACCESS_ARRAY_VALUE, "Array Access: Array Operand");
+
+ /**
+ * forExpression: Creating an index expression for an array access (i.e. one of the expressions within the <code>[]</code>).
+ */
+ public static final int ARRAYACCESS_INDEX_VALUE = 2;
+
+ public static final ForExpression ARRAYACCESS_INDEX = new ForExpression(ARRAYACCESS_INDEX_VALUE, "Array Access: Index");
+
+ /**
+ * forExpression: Creating an dimension expression for an array creation (i.e. one of the expressions within the <code>[]</code>).
+ */
+ public static final int ARRAYCREATION_DIMENSION_VALUE = 3;
+
+ public static final ForExpression ARRAYCREATION_DIMENSION = new ForExpression(ARRAYCREATION_DIMENSION_VALUE, "Array Access: Dimension");
+
+ /**
+ * forExpression: Creating an expression for an array initializer (i.e. one of the expressions with the <code>{}</code>). Special case is that
+ * array initializers are valid as an expression within an array initializer and it doesn't use a for expression.
+ */
+ public static final int ARRAYINITIALIZER_EXPRESSION_VALUE = 4;
+
+ public static final ForExpression ARRAYINITIALIZER_EXPRESSION = new ForExpression(ARRAYINITIALIZER_EXPRESSION_VALUE, "Array Initializer");
+
+ /**
+ * forExpression: Creating the expression for the cast (i.e. the expresion after the <code>(type)</code>).
+ */
+ public static final int CAST_EXPRESSION_VALUE = 5;
+
+ public static final ForExpression CAST_EXPRESSION = new ForExpression(CAST_EXPRESSION_VALUE, "Cast");
+
+ /**
+ * forExpression: Creating the argument expression for the new instance.
+ */
+ public static final int CLASSINSTANCECREATION_ARGUMENT_VALUE = 6;
+
+ public static final ForExpression CLASSINSTANCECREATION_ARGUMENT = new ForExpression(CLASSINSTANCECREATION_ARGUMENT_VALUE,
+ "Class Instance Creation: Argument");
+
+ /**
+ * forExpression: Creating the condition for a conditional expression.
+ */
+ public static final int CONDITIONAL_CONDITION_VALUE = 7;
+
+ public static final ForExpression CONDITIONAL_CONDITION = new ForExpression(CONDITIONAL_CONDITION_VALUE, "Conditional: Condition");
+
+ /**
+ * forExpression: Creating the true (then) expression for a conditional expression.
+ */
+ public static final int CONDITIONAL_TRUE_VALUE = 8;
+
+ public static final ForExpression CONDITIONAL_TRUE = new ForExpression(CONDITIONAL_TRUE_VALUE, "Conditional: True");
+
+ /**
+ * forExpression: Creating the false (else) condition for a conditional expression.
+ */
+ public static final int CONDITIONAL_FALSE_VALUE = 9;
+
+ public static final ForExpression CONDITIONAL_FALSE = new ForExpression(CONDITIONAL_FALSE_VALUE, "Conditional: False");
+
+ /**
+ * forExpression: Creating the receiver for a field access (i.e. the expression before the ".")
+ */
+ public static final int FIELD_RECEIVER_VALUE = 10;
+
+ public static final ForExpression FIELD_RECEIVER = new ForExpression(FIELD_RECEIVER_VALUE, "Field Access: Receiver");
+
+ /**
+ * forExpression: Creating the left operand of an infix expression.
+ */
+ public static final int INFIX_LEFT_VALUE = 11;
+
+ public static final ForExpression INFIX_LEFT = new ForExpression(INFIX_LEFT_VALUE, "Infix: Left");
+
+ /**
+ * forExpression: Creating the right operand of an infix expression.
+ */
+ public static final int INFIX_RIGHT_VALUE = 12;
+
+ public static final ForExpression INFIX_RIGHT = new ForExpression(INFIX_RIGHT_VALUE, "Infix: Right");
+
+ /**
+ * forExpression: Creating an extended operand of an infix expression.
+ */
+ public static final int INFIX_EXTENDED_VALUE = 13;
+
+ public static final ForExpression INFIX_EXTENDED = new ForExpression(INFIX_EXTENDED_VALUE, "Infix: Extended");
+
+ /**
+ * forExpression: Creating the value expression of an instanceof.
+ */
+ public static final int INSTANCEOF_VALUE_VALUE = 14;
+
+ public static final ForExpression INSTANCEOF_VALUE = new ForExpression(INSTANCEOF_VALUE_VALUE, "Instanceof");
+
+ /**
+ * forExpression: Creating a receiver expression for a method invocation.
+ */
+ public static final int METHOD_RECEIVER_VALUE = 15;
+
+ public static final ForExpression METHOD_RECEIVER = new ForExpression(METHOD_RECEIVER_VALUE, "Method Invoke: Receiver");
+
+ /**
+ * forExpression: Creating an argument for a method invocation.
+ */
+ public static final int METHOD_ARGUMENT_VALUE = 16;
+
+ public static final ForExpression METHOD_ARGUMENT = new ForExpression(METHOD_ARGUMENT_VALUE, "Method Invoke: Argument");
+
+ /**
+ * forExpression: Creating the operand expression for a prefix operator.
+ */
+ public static final int PREFIX_OPERAND_VALUE = 17;
+
+ public static final ForExpression PREFIX_OPERAND = new ForExpression(PREFIX_OPERAND_VALUE, "Prefix: Operand");
+
+ /**
+ * forExpression: Creating the right operand of an assignment operator.
+ *
+ * @since 1.1.0
+ */
+ public static final int ASSIGNMENT_RIGHT_VALUE = 18;
+
+ public static final ForExpression ASSIGNMENT_RIGHT = new ForExpression(ASSIGNMENT_RIGHT_VALUE, "Assignment: Right");
+
+ /**
+ * forExpression: Creating the left operand of an assignment operator.
+ * <p>
+ * Note: The left expression can only be a FieldAccess or ArrayAccess.
+ */
+ public static final int ASSIGNMENT_LEFT_VALUE = 19;
+
+ public static final ForExpression ASSIGNMENT_LEFT = new ForExpression(ASSIGNMENT_LEFT_VALUE, "Assignment: Left");
+
+ /**
+ * forExpression: Creating the throw operand of the throw expression.
+ */
+ public static final int THROW_OPERAND_VALUE = 20;
+
+ public static final ForExpression THROW_OPERAND = new ForExpression(THROW_OPERAND_VALUE, "Throw operand");
+
+ /**
+ * forExpression: Creating the if conditional operand of the if expression.
+ */
+ public static final int IF_CONDITION_VALUE = 21;
+
+ public static final ForExpression IF_CONDITION = new ForExpression(IF_CONDITION_VALUE, "If condition");
+
+ /**
+ * forExpression: Creating the if true clause of the if expression.
+ */
+ public static final int IF_TRUE_VALUE = 22;
+
+ public static final ForExpression IF_TRUE = new ForExpression(IF_TRUE_VALUE, "If true clause");
+
+ /**
+ * forExpression: Creating the if else clause of the if expression.
+ */
+ public static final int IF_ELSE_VALUE = 23;
+
+ public static final ForExpression IF_ELSE = new ForExpression(IF_ELSE_VALUE, "If else clause");
+
+
+ /**
+ * This is not private, but protected only so that proxy core can add an internal ForExpression enum.
+ * <p>
+ * This is not meant to be subclassed by customers.
+ * @param value
+ * @param name
+ *
+ * @since 1.1.0
+ */
+ protected ForExpression(int value, String name) {
+ super(value, name);
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IExpressionConstants.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IExpressionConstants.java
index 984efa6..8b61eaa 100644
--- a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IExpressionConstants.java
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IExpressionConstants.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: IExpressionConstants.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:55:20 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.initParser.tree;
@@ -22,253 +22,5 @@
* @since 1.0.0
*/
public interface IExpressionConstants {
-
- /**
- * The expression (or some nested expression) did not return a value. I.e. it was <code>void</code>.
- * This would occur only if the value of expression was being retrieved through getExpressionValue,
- * or if a nested expression was used, since in that case the value would of been used as an
- * argument or receiver to another expression.
- *
- * @since 1.0.0
- */
- public static class NoExpressionValueException extends Exception {
-
- /**
- * Construct with no arguments.
- *
- * @since 1.0.0
- */
- public NoExpressionValueException() {
- super();
- }
-
- /**
- * Construct with a message.
- *
- * @param message
- *
- * @since 1.0.0
- */
- public NoExpressionValueException(String message) {
- super(message);
- }
- }
-
- /**
- * Infix times "*"
- */
- int IN_TIMES = 0;
-
- /**
- * Infix divide "/"
- */
- int IN_DIVIDE = 1;
-
- /**
- * Infix remainder "%"
- */
- int IN_REMAINDER = 2;
-
- /**
- * Infix plus "+"
- */
- int IN_PLUS = 3;
-
- /**
- * Infix minus "-"
- */
- int IN_MINUS = 4;
-
- /**
- * Infix left shift "<<"
- */
- int IN_LEFT_SHIFT = 5;
-
- /**
- * Infix right shift signed ">>"
- */
- int IN_RIGHT_SHIFT_SIGNED = 6;
-
- /**
- * Infix right shift unsigned ">>>"
- */
- int IN_RIGHT_SHIFT_UNSIGNED = 7;
-
- /**
- * Infix less "<"
- */
- int IN_LESS = 8;
-
- /**
- * Infix greater ">"
- */
- int IN_GREATER = 9;
-
- /**
- * Infix less than or equals "<="
- */
- int IN_LESS_EQUALS = 10;
-
- /**
- * Infix Greater than or equlas ">="
- */
- int IN_GREATER_EQUALS = 11;
-
- /**
- * Infix equals "=="
- */
- int IN_EQUALS = 12;
-
- /**
- * Infix not equals "!="
- */
- int IN_NOT_EQUALS = 13;
-
- /**
- * Infix exclusive or "^"
- */
- int IN_XOR = 14;
-
- /**
- * Infix bitwise and "&"
- */
- int IN_AND = 15;
-
- /**
- * Infix bitwise or "|"
- */
- int IN_OR = 16;
-
- /**
- * Infix Conditional logical and "&&"
- */
- int IN_CONDITIONAL_AND = 17;
-
- /**
- * Infix Conditional logical or "||"
- */
- int IN_CONDITIONAL_OR = 18;
-
- /**
- * Max value of Infix operators.
- */
- int IN_MAX = 18;
-
- /**
- * Prefix plus "+"
- */
- int PRE_PLUS = 0;
-
- /**
- * Prefix minus "-"
- */
- int PRE_MINUS = 1;
-
- /**
- * Prefix bitwise complement "~"
- */
- int PRE_COMPLEMENT = 2;
-
- /**
- * Prefix logical not "!"
- */
- int PRE_NOT = 3;
-
- /**
- * Max value of the Prefix operators.
- */
- int PRE_MAX = 3;
-
- /**
- * forExpression: Creating a root expression
- */
- int ROOTEXPRESSION = 0;
-
- /**
- * forExpression: Creating the array expression for an array access (i.e. the array to access)
- */
- int ARRAYACCESS_ARRAY = 1;
-
- /**
- * forExpression: Creating an index expression for an array access (i.e. one of the expressions within the <code>[]</code>).
- */
- int ARRAYACCESS_INDEX = 2;
-
- /**
- * forExpression: Creating an dimension expression for an array creation (i.e. one of the expressions within the <code>[]</code>).
- */
- int ARRAYCREATION_DIMENSION = 3;
-
- /**
- * forExpression: Creating an expression for an array initializer (i.e. one of the expressions with the <code>{}</code>).
- * Special case is that array initializers are valid as an expression within an array initializer and it doesn't use
- * a for expression.
- */
- int ARRAYINITIALIZER_EXPRESSION = 4;
-
- /**
- * forExpression: Creating the expression for the cast (i.e. the expresion after the <code>(type)</code>).
- */
- int CAST_EXPRESSION = 5;
-
- /**
- * forExpression: Creating the argument expression for the new instance.
- */
- int CLASSINSTANCECREATION_ARGUMENT = 6;
-
- /**
- * forExpression: Creating the condition for a conditional expression.
- */
- int CONDITIONAL_CONDITION = 7;
-
- /**
- * forExpression: Creating the true (then) expression for a conditional expression.
- */
- int CONDITIONAL_TRUE = 8;
-
- /**
- * forExpression: Creating the false (else) condition for a conditional expression.
- */
- int CONDITIONAL_FALSE = 9;
-
- /**
- * forExpression: Creating the receiver for a field access (i.e. the expression before the ".")
- */
- int FIELD_RECEIVER = 10;
-
- /**
- * forExpression: Creating the left operand of an infix expression.
- */
- int INFIX_LEFT = 11;
-
- /**
- * forExpression: Creating the right operand of an infix expression.
- */
- int INFIX_RIGHT = 12;
-
- /**
- * forExpression: Creating an extended operand of an infix expression.
- */
- int INFIX_EXTENDED = 13;
-
- /**
- * forExpression: Creating the value expression of an instanceof.
- */
- int INSTANCEOF_VALUE = 14;
-
- /**
- * forExpression: Creating a receiver expression for a method invocation.
- */
- int METHOD_RECEIVER = 15;
-
- /**
- * forExpression: Creating an argument for a method invocation.
- */
- int METHOD_ARGUMENT = 16;
-
- /**
- * forExpression: Creating the operand expression for a prefix operator.
- */
- int PREFIX_OPERAND = 17;
}
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IInternalExpressionConstants.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IInternalExpressionConstants.java
deleted file mode 100644
index 8167b61..0000000
--- a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/IInternalExpressionConstants.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-/*
- * $RCSfile: IInternalExpressionConstants.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:55:20 $
- */
-package org.eclipse.jem.internal.proxy.initParser.tree;
-
-/**
- * These constants are for communicating between the IDE and the proxy side
- * for expression evaluation.
- *
- * @since 1.0.0
- */
-public interface IInternalExpressionConstants {
-
- /**
- * ARRAY ACCESS Expression
- */
- int ARRAY_ACCESS_EXPRESSION = 1;
-
- /**
- * ARRAY CREATION Expression
- */
- int ARRAY_CREATION_EXPRESSION = 2;
-
- /**
- * ARRAY INITIALIZER expression
- */
- int ARRAY_INITIALIZER_EXPRESSION = 3;
-
- /**
- * CAST Expression.
- */
- int CAST_EXPRESSION = 4;
-
- /**
- * CONDITIONAL expression
- */
- int CONDITIONAL_EXPRESSION = 5;
-
- /**
- * CLASS INSTANCE CREATION expression
- */
- int CLASS_INSTANCE_CREATION_EXPRESSION = 6;
-
- /**
- * FIELD ACCESS expression.
- */
- int FIELD_ACCESS_EXPRESSION = 7;
-
- /**
- * INSTANCEOF Expression.
- */
- int INSTANCEOF_EXPRESSION = 8;
-
- /**
- * Infix expression
- */
- int INFIX_EXPRESSION = 9;
-
- /**
- * Method expression.
- */
- int METHOD_EXPRESSION = 10;
-
- /**
- * Prefix expression
- */
- int PREFIX_EXPRESSION = 11;
-
- /**
- * Push to proxy expression.
- */
- int PUSH_TO_PROXY_EXPRESSION = 12;
-
- /**
- * Type literal Expression.
- */
- int TYPELITERAL_EXPRESSION = 13;
-
- /**
- * Type receiver expression.
- */
- int TYPERECEIVER_EXPRESSION = 14;
-
-
- /**
- * Used in Infix processing. Left operand on expression stack
- */
- int INFIX_LEFT_OPERAND = 0;
-
- /**
- * Used in Infix processing. Other operand (but not last) on expression stack
- */
- int INFIX_OTHER_OPERAND = 1;
-
- /**
- * Used in Infix processing. Rightmost (last) operand on expression stack
- */
- int INFIX_LAST_OPERAND = 2;
-}
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InfixOperator.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InfixOperator.java
new file mode 100644
index 0000000..f74f672
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InfixOperator.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 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: InfixOperator.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * Enum for Infix operator
+ *
+ * @since 1.1.0
+ */
+public class InfixOperator extends AbstractEnum {
+
+ /**
+ * Infix times "*"
+ */
+ public static final int IN_TIMES_VALUE = 0;
+
+ public static final InfixOperator IN_TIMES = new InfixOperator(IN_TIMES_VALUE, "Infix *");
+
+ /**
+ * Infix divide "/"
+ */
+ public static final int IN_DIVIDE_VALUE = 1;
+
+ public static final InfixOperator IN_DIVIDE = new InfixOperator(IN_DIVIDE_VALUE, "Infix /");
+
+ /**
+ * Infix remainder "%"
+ */
+ public static final int IN_REMAINDER_VALUE = 2;
+
+ public static final InfixOperator IN_REMAINDER = new InfixOperator(IN_REMAINDER_VALUE, "Infix %");
+
+ /**
+ * Infix plus "+"
+ */
+ public static final int IN_PLUS_VALUE = 3;
+
+ public static final InfixOperator IN_PLUS = new InfixOperator(IN_PLUS_VALUE, "Infix +");
+
+ /**
+ * Infix minus "-"
+ */
+ public static final int IN_MINUS_VALUE = 4;
+
+ public static final InfixOperator IN_MINUS = new InfixOperator(IN_MINUS_VALUE, "Infix -");
+
+ /**
+ * Infix left shift " < <"
+ */
+ public static final int IN_LEFT_SHIFT_VALUE = 5;
+
+ public static final InfixOperator IN_LEFT_SHIFT = new InfixOperator(IN_LEFT_SHIFT_VALUE, "Infix <<");
+
+ /**
+ * Infix right shift signed ">>"
+ */
+ public static final int IN_RIGHT_SHIFT_SIGNED_VALUE = 6;
+
+ public static final InfixOperator IN_RIGHT_SHIFT_SIGNED = new InfixOperator(IN_RIGHT_SHIFT_SIGNED_VALUE, "Infix >>");
+
+ /**
+ * Infix right shift unsigned ">>>"
+ */
+ public static final int IN_RIGHT_SHIFT_UNSIGNED_VALUE = 7;
+
+ public static final InfixOperator IN_RIGHT_SHIFT_UNSIGNED = new InfixOperator(IN_RIGHT_SHIFT_UNSIGNED_VALUE, "Infix >>>");
+
+ /**
+ * Infix less " <"
+ */
+ public static final int IN_LESS_VALUE = 8;
+
+ public static final InfixOperator IN_LESS = new InfixOperator(IN_LESS_VALUE, "Infix <");
+
+ /**
+ * Infix greater ">"
+ */
+ public static final int IN_GREATER_VALUE = 9;
+
+ public static final InfixOperator IN_GREATER = new InfixOperator(IN_GREATER_VALUE, "Infix >");
+
+ /**
+ * Infix less than or equals " <="
+ */
+ public static final int IN_LESS_EQUALS_VALUE = 10;
+
+ public static final InfixOperator IN_LESS_EQUALS = new InfixOperator(IN_LESS_EQUALS_VALUE, "Infix <=");
+
+ /**
+ * Infix Greater than or equlas ">="
+ */
+ public static final int IN_GREATER_EQUALS_VALUE = 11;
+
+ public static final InfixOperator IN_GREATER_EQUALS = new InfixOperator(IN_GREATER_EQUALS_VALUE, "Infix >=");
+
+ /**
+ * Infix equals "=="
+ */
+ public static final int IN_EQUALS_VALUE = 12;
+
+ public static final InfixOperator IN_EQUALS = new InfixOperator(IN_EQUALS_VALUE, "Infix ==");
+
+ /**
+ * Infix not equals "!="
+ */
+ public static final int IN_NOT_EQUALS_VALUE = 13;
+
+ public static final InfixOperator IN_NOT_EQUALS = new InfixOperator(IN_NOT_EQUALS_VALUE, "Infix !=");
+
+ /**
+ * Infix exclusive or "^"
+ */
+ public static final int IN_XOR_VALUE = 14;
+
+ public static final InfixOperator IN_XOR = new InfixOperator(IN_XOR_VALUE, "Infix ^");
+
+ /**
+ * Infix bitwise and "&"
+ */
+ public static final int IN_AND_VALUE = 15;
+
+ public static final InfixOperator IN_AND = new InfixOperator(IN_AND_VALUE, "Infix &");
+
+ /**
+ * Infix bitwise or "|"
+ */
+ public static final int IN_OR_VALUE = 16;
+
+ public static final InfixOperator IN_OR = new InfixOperator(IN_OR_VALUE, "Infix |");
+
+ /**
+ * Infix Conditional logical and "&&"
+ */
+ public static final int IN_CONDITIONAL_AND_VALUE = 17;
+
+ public static final InfixOperator IN_CONDITIONAL_AND = new InfixOperator(IN_CONDITIONAL_AND_VALUE, "Infix &&");
+
+ /**
+ * Infix Conditional logical or "||"
+ */
+ public static final int IN_CONDITIONAL_OR_VALUE = 18;
+
+ public static final InfixOperator IN_CONDITIONAL_OR = new InfixOperator(IN_CONDITIONAL_OR_VALUE, "Ifnix ||");
+
+ /**
+ * Return the infix operator for the given enum value.
+ * @param value
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static InfixOperator get(int value) {
+ switch (value) {
+ case IN_TIMES_VALUE:
+ return IN_TIMES;
+ case IN_DIVIDE_VALUE:
+ return IN_DIVIDE;
+ case IN_REMAINDER_VALUE:
+ return IN_REMAINDER;
+ case IN_PLUS_VALUE:
+ return IN_PLUS;
+ case IN_MINUS_VALUE:
+ return IN_MINUS;
+ case IN_LEFT_SHIFT_VALUE:
+ return IN_LEFT_SHIFT;
+ case IN_RIGHT_SHIFT_SIGNED_VALUE:
+ return IN_RIGHT_SHIFT_SIGNED;
+ case IN_RIGHT_SHIFT_UNSIGNED_VALUE:
+ return IN_RIGHT_SHIFT_UNSIGNED;
+ case IN_LESS_VALUE:
+ return IN_LESS;
+ case IN_GREATER_VALUE:
+ return IN_GREATER;
+ case IN_LESS_EQUALS_VALUE:
+ return IN_LESS_EQUALS;
+ case IN_GREATER_EQUALS_VALUE:
+ return IN_GREATER_EQUALS;
+ case IN_EQUALS_VALUE:
+ return IN_EQUALS;
+ case IN_NOT_EQUALS_VALUE:
+ return IN_NOT_EQUALS;
+ case IN_XOR_VALUE:
+ return IN_XOR;
+ case IN_AND_VALUE:
+ return IN_AND;
+ case IN_OR_VALUE:
+ return IN_OR;
+ case IN_CONDITIONAL_AND_VALUE:
+ return IN_CONDITIONAL_AND;
+ case IN_CONDITIONAL_OR_VALUE:
+ return IN_CONDITIONAL_OR;
+ }
+ return null;
+ }
+
+ private InfixOperator(int value, String name) {
+ super(value, name);
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalConditionalOperandType.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalConditionalOperandType.java
new file mode 100644
index 0000000..3723651
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalConditionalOperandType.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 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: InternalConditionalOperandType.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * Internal class for the Conditional operand type. Not meant to be used by customers.
+ *
+ * @since 1.1.0
+ */
+public class InternalConditionalOperandType extends AbstractEnum {
+
+ /**
+ * Used in Conditional processing. False operand on expression stack
+ */
+ public final static int CONDITIONAL_FALSE_VALUE = 0;
+
+ public final static InternalConditionalOperandType CONDITIONAL_FALSE = new InternalConditionalOperandType(CONDITIONAL_FALSE_VALUE,
+ "Conditional False Operand Flag");
+
+ /**
+ * Used in Conditional processing. True operand on expression stack
+ */
+ public final static int CONDITIONAL_TRUE_VALUE = 1;
+
+ public final static InternalConditionalOperandType CONDITIONAL_TRUE = new InternalConditionalOperandType(CONDITIONAL_TRUE_VALUE,
+ "Conditional True Operand Flag");
+
+ /**
+ * Used in Conditional processing. Test operand on expression stack
+ */
+ public final static int CONDITIONAL_TEST_VALUE = 2;
+
+ public final static InternalConditionalOperandType CONDITIONAL_TEST = new InternalConditionalOperandType(CONDITIONAL_TEST_VALUE,
+ "Conditional Test Operand Flag");
+
+ /**
+ * Return the enum for the given value.
+ * @param value
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static InternalConditionalOperandType get(int value) {
+ switch (value) {
+ case CONDITIONAL_FALSE_VALUE:
+ return CONDITIONAL_FALSE;
+ case CONDITIONAL_TRUE_VALUE:
+ return CONDITIONAL_TRUE;
+ case CONDITIONAL_TEST_VALUE:
+ return CONDITIONAL_TEST;
+ }
+ return null;
+ }
+
+ private InternalConditionalOperandType(int value, String name) {
+ super(value, name);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalExpressionProxy.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalExpressionProxy.java
new file mode 100644
index 0000000..f913089
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalExpressionProxy.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * $RCSfile: InternalExpressionProxy.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+
+/**
+ * This interface is used for expression proxies in the evaluation side (in {@link org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser}).
+ * <p>
+ * It is meant to be implemented only by users of the ExpressionProcessor.
+ *
+ * @since 1.1.0
+ */
+public interface InternalExpressionProxy {
+
+ /**
+ * Get the id of the proxy.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public int getProxyID();
+
+ /**
+ * Called by ExpressionProcesser to give the expression proxy its value and type, i.e. it has been evaluated.
+ * <p>
+ * The type may not be the actual type of the value, it may be a superclass of it. It is the type that the proxy
+ * represents from the return of the expression. For instance it may of returned null but it is supposed to be
+ * java.lang.String. Or it is supposed to be a primitive int, since we can't store that, we need to store
+ * an Integer value with the type indicating it is Interger.TYPE.
+ *
+ * @param value
+ * @param type
+ *
+ * @since 1.1.0
+ */
+ public void setProxy(Object value, Class type);
+
+ /**
+ * Get the value of the proxy.
+ * <p>
+ * Note: The value may be a {@link VariableReference}, in which
+ * case further dereferencing may be with the returned value.
+ * @return the value of the proxy, it may be an ExpressionProcesser.VariableReference.
+ *
+ * @since 1.1.0
+ */
+ public Object getValue();
+
+ /**
+ * Get the type of the proxy.
+ * @return
+ *
+ * @see InternalExpressionProxy#setProxy(Object, Class) for what type means.
+ * @since 1.1.0
+ */
+ public Class getType();
+
+ /**
+ * Return whether the proxy has had a value/class set into it yet.
+ * @return <code>true</code> if it has been set.
+ *
+ * @since 1.1.0
+ */
+ public boolean isSet();
+}
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalExpressionTypes.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalExpressionTypes.java
new file mode 100644
index 0000000..b6ebbc9
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalExpressionTypes.java
@@ -0,0 +1,276 @@
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * These constants are for communicating between the IDE and the proxy side for expression evaluation. It is not meant to be used by customers.
+ *
+ * @since 1.0.0
+ */
+public class InternalExpressionTypes extends AbstractEnum {
+
+ /**
+ * ARRAY ACCESS Expression
+ */
+ public final static int ARRAY_ACCESS_EXPRESSION_VALUE = 1;
+
+ public final static InternalExpressionTypes ARRAY_ACCESS_EXPRESSION = new InternalExpressionTypes(ARRAY_ACCESS_EXPRESSION_VALUE,
+ "Array Access Expression");
+
+ /**
+ * ARRAY CREATION Expression
+ */
+ public final static int ARRAY_CREATION_EXPRESSION_VALUE = 2;
+
+ public final static InternalExpressionTypes ARRAY_CREATION_EXPRESSION = new InternalExpressionTypes(ARRAY_CREATION_EXPRESSION_VALUE,
+ "Array Creation Expression");
+
+ /**
+ * ARRAY INITIALIZER expression
+ */
+ public final static int ARRAY_INITIALIZER_EXPRESSION_VALUE = 3;
+
+ public final static InternalExpressionTypes ARRAY_INITIALIZER_EXPRESSION = new InternalExpressionTypes(ARRAY_INITIALIZER_EXPRESSION_VALUE,
+ "Array Initializer Expression");
+
+ /**
+ * CAST Expression.
+ */
+ public final static int CAST_EXPRESSION_VALUE = 4;
+
+ public final static InternalExpressionTypes CAST_EXPRESSION = new InternalExpressionTypes(CAST_EXPRESSION_VALUE, "Cast Expression");
+
+ /**
+ * CONDITIONAL expression
+ */
+ public final static int CONDITIONAL_EXPRESSION_VALUE = 5;
+
+ public final static InternalExpressionTypes CONDITIONAL_EXPRESSION = new InternalExpressionTypes(CONDITIONAL_EXPRESSION_VALUE,
+ "Conditional Expression");
+
+ /**
+ * CLASS INSTANCE CREATION expression
+ */
+ public final static int CLASS_INSTANCE_CREATION_EXPRESSION_VALUE = 6;
+
+ public final static InternalExpressionTypes CLASS_INSTANCE_CREATION_EXPRESSION = new InternalExpressionTypes(
+ CLASS_INSTANCE_CREATION_EXPRESSION_VALUE, "Class Instance Creation Expression");
+
+ /**
+ * FIELD ACCESS expression.
+ */
+ public final static int FIELD_ACCESS_EXPRESSION_VALUE = 7;
+
+ public final static InternalExpressionTypes FIELD_ACCESS_EXPRESSION = new InternalExpressionTypes(FIELD_ACCESS_EXPRESSION_VALUE,
+ "Field Access Expression");
+
+ /**
+ * INSTANCEOF Expression.
+ */
+ public final static int INSTANCEOF_EXPRESSION_VALUE = 8;
+
+ public final static InternalExpressionTypes INSTANCEOF_EXPRESSION = new InternalExpressionTypes(INSTANCEOF_EXPRESSION_VALUE,
+ "Instanceof Expression");
+
+ /**
+ * Infix expression
+ */
+ public final static int INFIX_EXPRESSION_VALUE = 9;
+
+ public final static InternalExpressionTypes INFIX_EXPRESSION = new InternalExpressionTypes(INFIX_EXPRESSION_VALUE, "Infix Expression");
+
+ /**
+ * Method expression.
+ */
+ public final static int METHOD_EXPRESSION_VALUE = 10;
+
+ public final static InternalExpressionTypes METHOD_EXPRESSION = new InternalExpressionTypes(METHOD_EXPRESSION_VALUE, "Method Invoke Expression");
+
+ /**
+ * Prefix expression
+ */
+ public final static int PREFIX_EXPRESSION_VALUE = 11;
+
+ public final static InternalExpressionTypes PREFIX_EXPRESSION = new InternalExpressionTypes(PREFIX_EXPRESSION_VALUE, "Prefix Expression");
+
+ /**
+ * Push to proxy expression.
+ */
+ public final static int PUSH_TO_PROXY_EXPRESSION_VALUE = 12;
+
+ public final static InternalExpressionTypes PUSH_TO_PROXY_EXPRESSION = new InternalExpressionTypes(PUSH_TO_PROXY_EXPRESSION_VALUE,
+ "Push to Proxy Expression");
+
+ /**
+ * Push BeanType expression proxy expression.
+ */
+ public final static int PUSH_BEANTYPE_EXPRESSIONPROXY_EXPRESSION_VALUE = 13;
+
+ public final static InternalExpressionTypes PUSH_BEANTYPE_EXPRESSIONPROXY_EXPRESSION = new InternalExpressionTypes(PUSH_BEANTYPE_EXPRESSIONPROXY_EXPRESSION_VALUE,
+ "Push BeanType ExpressionProxy Expression");
+
+
+ /**
+ * Type receiver expression.
+ */
+ public final static int TYPERECEIVER_EXPRESSION_VALUE = 14;
+
+ public final static InternalExpressionTypes TYPERECEIVER_EXPRESSION = new InternalExpressionTypes(TYPERECEIVER_EXPRESSION_VALUE,
+ "Type Receiver Expression");
+
+ /**
+ * Assignment to an ExpressionProxy expression.
+ */
+ public final static int ASSIGNMENT_PROXY_EXPRESSION_VALUE = 15;
+
+ public final static InternalExpressionTypes ASSIGNMENT_PROXY_EXPRESSION = new InternalExpressionTypes(ASSIGNMENT_PROXY_EXPRESSION_VALUE,
+ "Assignment to Proxy Expression");
+
+ /**
+ * Push expression proxy value expression.
+ */
+ public final static int PUSH_TO_EXPRESSION_PROXY_EXPRESSION_VALUE = 16;
+
+ public final static InternalExpressionTypes PUSH_TO_EXPRESSION_PROXY_EXPRESSION = new InternalExpressionTypes(
+ PUSH_TO_EXPRESSION_PROXY_EXPRESSION_VALUE, "Push to Expression Proxy Expression");
+
+ /**
+ * Assignment expression.
+ */
+ public final static int ASSIGNMENT_EXPRESSION_VALUE = 17;
+
+ public final static InternalExpressionTypes ASSIGNMENT_EXPRESSION = new InternalExpressionTypes(ASSIGNMENT_EXPRESSION_VALUE,
+ "Assignment Expression");
+
+ /**
+ * Block End expression.
+ */
+ public final static int BLOCK_BEGIN_EXPRESSION_VALUE = 18;
+
+ public final static InternalExpressionTypes BLOCK_BEGIN_EXPRESSION = new InternalExpressionTypes(BLOCK_BEGIN_EXPRESSION_VALUE,
+ "Begin block Expression");
+
+ /**
+ * Block End expression.
+ */
+ public final static int BLOCK_BREAK_EXPRESSION_VALUE = 19;
+
+ public final static InternalExpressionTypes BLOCK_BREAK_EXPRESSION = new InternalExpressionTypes(BLOCK_BREAK_EXPRESSION_VALUE,
+ "Break block Expression");
+
+ /**
+ * Block End expression.
+ */
+ public final static int BLOCK_END_EXPRESSION_VALUE = 20;
+
+ public final static InternalExpressionTypes BLOCK_END_EXPRESSION = new InternalExpressionTypes(BLOCK_END_EXPRESSION_VALUE,
+ "End block Expression");
+
+ /**
+ * Try Begin expression.
+ */
+ public final static int TRY_BEGIN_EXPRESSION_VALUE = 21;
+
+ public final static InternalExpressionTypes TRY_BEGIN_EXPRESSION = new InternalExpressionTypes(TRY_BEGIN_EXPRESSION_VALUE,
+ "Begin try Expression");
+
+ /**
+ * Try Catch expression.
+ */
+ public final static int TRY_CATCH_EXPRESSION_VALUE = 22;
+
+ public final static InternalExpressionTypes TRY_CATCH_EXPRESSION = new InternalExpressionTypes(TRY_CATCH_EXPRESSION_VALUE,
+ "Try catch Expression");
+
+ /**
+ * Try Finally expression.
+ */
+ public final static int TRY_FINALLY_EXPRESSION_VALUE = 23;
+
+ public final static InternalExpressionTypes TRY_FINALLY_EXPRESSION = new InternalExpressionTypes(TRY_FINALLY_EXPRESSION_VALUE,
+ "Try finally Expression");
+
+ /**
+ * Try End expression.
+ */
+ public final static int TRY_END_EXPRESSION_VALUE = 24;
+
+ public final static InternalExpressionTypes TRY_END_EXPRESSION = new InternalExpressionTypes(TRY_END_EXPRESSION_VALUE,
+ "End try Expression");
+
+ /**
+ * Throw expression.
+ */
+ public final static int THROW_EXPRESSION_VALUE = 25;
+
+ public final static InternalExpressionTypes THROW_EXPRESSION = new InternalExpressionTypes(THROW_EXPRESSION_VALUE,
+ "Throw Expression");
+
+ /**
+ * Rethrow expression.
+ */
+ public final static int RETHROW_EXPRESSION_VALUE = 26;
+
+ public final static InternalExpressionTypes RETHROW_EXPRESSION = new InternalExpressionTypes(RETHROW_EXPRESSION_VALUE,
+ "Rethrow Expression");
+
+ /**
+ * Push Method Lookup expression proxy expression.
+ */
+ public final static int PUSH_METHOD_EXPRESSIONPROXY_EXPRESSION_VALUE = 27;
+
+ public final static InternalExpressionTypes PUSH_METHOD_EXPRESSIONPROXY_EXPRESSION = new InternalExpressionTypes(PUSH_METHOD_EXPRESSIONPROXY_EXPRESSION_VALUE,
+ "Push Method ExpressionProxy Expression");
+
+ /**
+ * Push Field Lookup expression proxy expression.
+ */
+ public final static int PUSH_FIELD_EXPRESSIONPROXY_EXPRESSION_VALUE = 28;
+
+ public final static InternalExpressionTypes PUSH_FIELD_EXPRESSIONPROXY_EXPRESSION = new InternalExpressionTypes(PUSH_FIELD_EXPRESSIONPROXY_EXPRESSION_VALUE,
+ "Push Field ExpressionProxy Expression");
+
+ /**
+ * Push If/else (the clauses) expression proxy expression.
+ */
+ public final static int IF_ELSE_EXPRESSION_VALUE = 29;
+
+ public final static InternalExpressionTypes IF_ELSE_EXPRESSION = new InternalExpressionTypes(IF_ELSE_EXPRESSION_VALUE,
+ "Push If/else Expression");
+
+ /**
+ * Push If/else condition test expression proxy expression.
+ */
+ public final static int IF_TEST_EXPRESSION_VALUE = 30;
+
+ public final static InternalExpressionTypes IF_TEST_EXPRESSION = new InternalExpressionTypes(IF_TEST_EXPRESSION_VALUE,
+ "Push If Test Expression");
+
+
+ /**
+ * Push new instance from init string proxy expression.
+ */
+ public final static int NEW_INSTANCE_VALUE = 31;
+
+ public final static InternalExpressionTypes NEW_INSTANCE = new InternalExpressionTypes(NEW_INSTANCE_VALUE,
+ "Push New Instance Expression");
+
+
+ /**
+ * Push mark proxy expression.
+ */
+ public final static int MARK_VALUE = 32;
+
+ public final static InternalExpressionTypes MARK = new InternalExpressionTypes(MARK_VALUE,
+ "Push Mark Expression");
+
+ /**
+ * Push end mark proxy expression.
+ */
+ public final static int ENDMARK_VALUE = 33;
+
+ public final static InternalExpressionTypes ENDMARK = new InternalExpressionTypes(ENDMARK_VALUE,
+ "Push End Mark Expression");
+
+ private InternalExpressionTypes(int value, String name) {
+ super(value, name);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalIfElseOperandType.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalIfElseOperandType.java
new file mode 100644
index 0000000..8707a27
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalIfElseOperandType.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 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: InternalIfElseOperandType.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * Internal class for the If/else operand type. Not meant to be used by customers.
+ *
+ * @since 1.1.0
+ */
+public class InternalIfElseOperandType extends AbstractEnum {
+
+ /**
+ * Used in If/else processing. False clause on expression stack
+ */
+ public final static int ELSE_CLAUSE_VALUE = 0;
+
+ public final static InternalIfElseOperandType ELSE_CLAUSE = new InternalIfElseOperandType(ELSE_CLAUSE_VALUE,
+ "Else Clause Flag");
+
+ /**
+ * Used in If/else processing. If operand on expression stack
+ */
+ public final static int TRUE_CLAUSE_VALUE = 1;
+
+ public final static InternalIfElseOperandType TRUE_CLAUSE = new InternalIfElseOperandType(TRUE_CLAUSE_VALUE,
+ "If True Clause Flag");
+
+ /**
+ * Return the enum for the given value.
+ * @param value
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static InternalIfElseOperandType get(int value) {
+ switch (value) {
+ case ELSE_CLAUSE_VALUE:
+ return ELSE_CLAUSE;
+ case TRUE_CLAUSE_VALUE:
+ return TRUE_CLAUSE;
+ }
+ return null;
+ }
+
+ private InternalIfElseOperandType(int value, String name) {
+ super(value, name);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalInfixOperandType.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalInfixOperandType.java
new file mode 100644
index 0000000..e4b2e89
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/InternalInfixOperandType.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 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: InternalInfixOperandType.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+
+/**
+ * Internal class for the Prefix operand type. Not meant to be used by customers.
+ * @since 1.1.0
+ */
+public class InternalInfixOperandType extends AbstractEnum {
+
+ /**
+ * Used in Infix processing. Left operand on expression stack
+ */
+ public final static int INFIX_LEFT_OPERAND_VALUE = 0;
+ public final static InternalInfixOperandType INFIX_LEFT_OPERAND = new InternalInfixOperandType(INFIX_LEFT_OPERAND_VALUE, "Infix Left Operand Flag");
+ /**
+ * Used in Infix processing. Other operand (but not last) on expression stack
+ */
+ public final static int INFIX_OTHER_OPERAND_VALUE = 1;
+ public final static InternalInfixOperandType INFIX_OTHER_OPERAND = new InternalInfixOperandType(INFIX_OTHER_OPERAND_VALUE,
+ "Infix Other Operand Flag");
+ /**
+ * Used in Infix processing. Rightmost (last) operand on expression stack
+ */
+ public final static int INFIX_LAST_OPERAND_VALUE = 2;
+ public final static InternalInfixOperandType INFIX_LAST_OPERAND = new InternalInfixOperandType(INFIX_LAST_OPERAND_VALUE, "Infix Last Operand Flag");
+
+ /**
+ * Return the enum for the given value.
+ * @param value
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static InternalInfixOperandType get(int value) {
+ switch (value) {
+ case INFIX_LAST_OPERAND_VALUE:
+ return INFIX_LAST_OPERAND;
+ case INFIX_LEFT_OPERAND_VALUE:
+ return INFIX_LEFT_OPERAND;
+ case INFIX_OTHER_OPERAND_VALUE:
+ return INFIX_OTHER_OPERAND;
+ }
+ return null;
+ }
+
+ private InternalInfixOperandType(int value, String name) {
+ super(value, name);
+ }
+}
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/NoExpressionValueException.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/NoExpressionValueException.java
new file mode 100644
index 0000000..406da02
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/NoExpressionValueException.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 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: NoExpressionValueException.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+
+/**
+ * The expression (or some nested expression) did not return a value. I.e. it was <code>void</code>.
+ * This would occur only if the value of expression was being retrieved through getExpressionValue,
+ * or if a nested expression was used, since in that case the value would of been used as an
+ * argument or receiver to another expression.
+ *
+ * @since 1.0.0
+ */
+public class NoExpressionValueException extends Exception {
+
+ /**
+ * Construct with no arguments.
+ *
+ * @since 1.0.0
+ */
+ public NoExpressionValueException() {
+ super();
+ }
+
+ public NoExpressionValueException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Construct with a message.
+ *
+ * @param message
+ *
+ * @since 1.0.0
+ */
+ public NoExpressionValueException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/PrefixOperator.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/PrefixOperator.java
new file mode 100644
index 0000000..6cc2a9c
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/PrefixOperator.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 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: PrefixOperator.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+/**
+ * Enum for prefix operator.
+ *
+ * @since 1.1.0
+ */
+public class PrefixOperator extends AbstractEnum {
+
+ /**
+ * Prefix plus "+"
+ */
+ public static final int PRE_PLUS_VALUE = 0;
+
+ public static final PrefixOperator PRE_PLUS = new PrefixOperator(PRE_PLUS_VALUE, "Prefix +");
+
+ /**
+ * Prefix minus "-"
+ */
+ public static final int PRE_MINUS_VALUE = 1;
+
+ public static final PrefixOperator PRE_MINUS = new PrefixOperator(PRE_MINUS_VALUE, "Prefix -");
+
+ /**
+ * Prefix bitwise complement "~"
+ */
+ public static final int PRE_COMPLEMENT_VALUE = 2;
+
+ public static final PrefixOperator PRE_COMPLEMENT = new PrefixOperator(PRE_COMPLEMENT_VALUE, "Prefix ~");
+
+ /**
+ * Prefix logical not "!"
+ */
+ public static final int PRE_NOT_VALUE = 3;
+
+ public static final PrefixOperator PRE_NOT = new PrefixOperator(PRE_NOT_VALUE, "Prefix !");
+
+ /**
+ * Return the prefix operator for the given enum value.
+ * @param value
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static PrefixOperator get(int value) {
+ switch (value) {
+ case PRE_PLUS_VALUE:
+ return PRE_PLUS;
+ case PRE_MINUS_VALUE:
+ return PRE_MINUS;
+ case PRE_COMPLEMENT_VALUE:
+ return PRE_COMPLEMENT;
+ case PRE_NOT_VALUE:
+ return PRE_NOT;
+ }
+ return null;
+ }
+
+ private PrefixOperator(int value, String name) {
+ super(value, name);
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/VariableReference.java b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/VariableReference.java
new file mode 100644
index 0000000..a4cd136
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/initParser/org/eclipse/jem/internal/proxy/initParser/tree/VariableReference.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * $RCSfile: VariableReference.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.initParser.tree;
+
+
+/**
+ * This represents a Variable Reference value. A variable reference value can be on the left
+ * side of an assignment (e.g. field or array access) or on any side
+ * of any expression. When on the left side of an assignment, then the
+ * value can assigned to. Such as <code>x[3] = 4</code>. Or it is value
+ * that can be used in expressions, such as <code>x[3] + 2</code>.
+ * <p>
+ * When dereferenced, the value is given (see {@link VariableReference#dereference()}) as
+ * the result or it is set with a value and then deferenced (see {@link VariableReference#set(Object, Class)}).
+ * <p>
+ * The type of the reference is the type stored in the corresponding expressionTypeStack entry. This is the type
+ * for assignment, and the type for dereferenced.
+ * @since 1.1.0
+ */
+public abstract class VariableReference {
+
+ /**
+ * Dereference the value.
+ * @return the dereferenced value. Such as the result of <code>x[3]</code>. The type of the reference
+ * is the type stored in the corresponding expressionTypeStack entry for this reference.
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ *
+ * @since 1.1.0
+ */
+ public abstract Object dereference();
+
+ /**
+ * Set the value into the variable and dereference it. Once it is set it is
+ * no longer a reference and must be dereferenced.
+ * @param value value to set to.
+ * @param type type of the value being set. It may be of use to the reference or maybe not.
+ * @return the dereferenced value after being set. The type of the dereferenced value
+ * is the type stored in the corresponding expressionTypeStack entry for this reference.
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ *
+ * @since 1.1.0
+ */
+ public abstract Object set(Object value, Class type) throws IllegalArgumentException, IllegalAccessException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IStandardAwtBeanProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IStandardAwtBeanProxyFactory.java
index bcd32d9..43bb8a5 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IStandardAwtBeanProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IStandardAwtBeanProxyFactory.java
@@ -11,10 +11,11 @@
*******************************************************************************/
/*
* $RCSfile: IStandardAwtBeanProxyFactory.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:47 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
+import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.core.IBeanProxyFactory;
/**
* The Standard awt bean proxy factory.
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/JavaStandardAwtBeanConstants.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/JavaStandardAwtBeanConstants.java
index 6405364..c40e9c2 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/JavaStandardAwtBeanConstants.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/JavaStandardAwtBeanConstants.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: JavaStandardAwtBeanConstants.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:47 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -37,7 +37,7 @@
*/
public final class JavaStandardAwtBeanConstants {
- public static final String REGISTRY_KEY = "STANDARDPROXYAWTCONSTANTS:"; //$NON-NLS-1$
+ public static final Object REGISTRY_KEY = new Object();
final boolean AWTLoaded; // AWT may not be available. So non-ui JVM's don't have AWT.
final boolean AWTRegistered; // AWT was registered to be used in this VM. It may be registered, but still not available.
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
index 5f63f80..3b4258b 100644
--- 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
@@ -10,19 +10,19 @@
*******************************************************************************/
/*
* $RCSfile: Expression.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
import java.text.MessageFormat;
-import java.util.ArrayList;
+import java.util.*;
import org.eclipse.jem.internal.proxy.initParser.tree.*;
/**
- * This is an internal implementation of Expression. It encapsulates much of the processing required
+ * 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.
+ * 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,
@@ -31,11 +31,12 @@
* 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 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.
+ * 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.
*
+ *
* @since 1.0.0
*/
public abstract class Expression implements IExpression {
@@ -107,7 +108,6 @@
* ARRAYACCESS
* Integer(index count)
*/
- private static final Integer ARRAYACCESS = new Integer(IInternalExpressionConstants.ARRAY_ACCESS_EXPRESSION);
private static final Integer ARRAYACCESS_INDEX_1 = new Integer(1); // Use in normal case of one index count. Saves object creation.
/*
@@ -126,10 +126,9 @@
* 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 ARRAYCREATION = new Integer(IInternalExpressionConstants.ARRAY_CREATION_EXPRESSION);
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 int ARRAY_INITIALIZER = -1; // Local because only needed her for expression.
+ private static final ForExpression ARRAY_INITIALIZER = new ExpressionEnum(Integer.MIN_VALUE+1, "Array Initializer Internal");
/*
* ARRAY INITIALIZER expression
@@ -147,7 +146,6 @@
* 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 = new Integer(IInternalExpressionConstants.ARRAY_INITIALIZER_EXPRESSION);
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.
@@ -162,7 +160,6 @@
* CAST
* type (either a string representing the type, or an IBeanProxyType representing the type).
*/
- private static final Integer CAST = new Integer(IInternalExpressionConstants.CAST_EXPRESSION);
/*
* CLASS INSTANCE CREATION expression.
@@ -179,7 +176,6 @@
* 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 CLASSINSTANCECREATION = new Integer(IInternalExpressionConstants.CLASS_INSTANCE_CREATION_EXPRESSION);
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.
@@ -206,10 +202,6 @@
* CONDITIONAL_FALSE
*
*/
- private static final Integer CONDITIONAL = new Integer(IInternalExpressionConstants.CONDITIONAL_EXPRESSION);
- private static final Integer CONDITIONAL_TEST = new Integer(IExpressionConstants.CONDITIONAL_CONDITION);
- private static final Integer CONDITIONAL_TRUEEXP = new Integer(IExpressionConstants.CONDITIONAL_TRUE);
- private static final Integer CONDITIONAL_FALSEXP = new Integer(IExpressionConstants.CONDITIONAL_FALSE);
/*
* PREFIX expression.
@@ -221,15 +213,6 @@
* PREFIX
* operator (using Integer prefix operator constants defined here)
*/
- private static final Integer PREFIX = new Integer(IInternalExpressionConstants.PREFIX_EXPRESSION);
- private static final Integer[] PREFIX_OPERATORS;
- static {
- PREFIX_OPERATORS = new Integer[IExpressionConstants.PRE_MAX+1];
- PREFIX_OPERATORS[IExpressionConstants.PRE_PLUS] = new Integer(IExpressionConstants.PRE_PLUS);
- PREFIX_OPERATORS[IExpressionConstants.PRE_MINUS] = new Integer(IExpressionConstants.PRE_MINUS);
- PREFIX_OPERATORS[IExpressionConstants.PRE_COMPLEMENT] = new Integer(IExpressionConstants.PRE_COMPLEMENT);
- PREFIX_OPERATORS[IExpressionConstants.PRE_NOT] = new Integer(IExpressionConstants.PRE_NOT);
- }
/*
* INFIX expression.
@@ -259,33 +242,6 @@
* operator (using Integer infix operator constants defined here)
* IN_LAST (this is covers either the right one if no extended, or the last extended)
*/
- private static final Integer INFIX = new Integer(IInternalExpressionConstants.INFIX_EXPRESSION);
- private static final Integer IN_LEFT = new Integer(IInternalExpressionConstants.INFIX_LEFT_OPERAND);
- private static final Integer IN_OTHER= new Integer(IInternalExpressionConstants.INFIX_OTHER_OPERAND);
- private static final Integer IN_LAST = new Integer(IInternalExpressionConstants.INFIX_LAST_OPERAND);
- private static final Integer[] INFIX_OPERATORS;
- static {
- INFIX_OPERATORS = new Integer[IExpressionConstants.IN_MAX+1];
- INFIX_OPERATORS[IExpressionConstants.IN_AND] = new Integer(IExpressionConstants.IN_AND);
- INFIX_OPERATORS[IExpressionConstants.IN_CONDITIONAL_AND] = new Integer(IExpressionConstants.IN_CONDITIONAL_AND);
- INFIX_OPERATORS[IExpressionConstants.IN_CONDITIONAL_OR] = new Integer(IExpressionConstants.IN_CONDITIONAL_OR);
- INFIX_OPERATORS[IExpressionConstants.IN_DIVIDE] = new Integer(IExpressionConstants.IN_DIVIDE);
- INFIX_OPERATORS[IExpressionConstants.IN_EQUALS] = new Integer(IExpressionConstants.IN_EQUALS);
- INFIX_OPERATORS[IExpressionConstants.IN_GREATER] = new Integer(IExpressionConstants.IN_GREATER);
- INFIX_OPERATORS[IExpressionConstants.IN_GREATER_EQUALS] = new Integer(IExpressionConstants.IN_GREATER_EQUALS);
- INFIX_OPERATORS[IExpressionConstants.IN_LEFT_SHIFT] = new Integer(IExpressionConstants.IN_LEFT_SHIFT);
- INFIX_OPERATORS[IExpressionConstants.IN_LESS] = new Integer(IExpressionConstants.IN_LESS);
- INFIX_OPERATORS[IExpressionConstants.IN_LESS_EQUALS] = new Integer(IExpressionConstants.IN_LESS_EQUALS);
- INFIX_OPERATORS[IExpressionConstants.IN_MINUS] = new Integer(IExpressionConstants.IN_MINUS);
- INFIX_OPERATORS[IExpressionConstants.IN_NOT_EQUALS] = new Integer(IExpressionConstants.IN_NOT_EQUALS);
- INFIX_OPERATORS[IExpressionConstants.IN_OR] = new Integer(IExpressionConstants.IN_OR);
- INFIX_OPERATORS[IExpressionConstants.IN_PLUS] = new Integer(IExpressionConstants.IN_PLUS);
- INFIX_OPERATORS[IExpressionConstants.IN_REMAINDER] = new Integer(IExpressionConstants.IN_REMAINDER);
- INFIX_OPERATORS[IExpressionConstants.IN_RIGHT_SHIFT_SIGNED] = new Integer(IExpressionConstants.IN_RIGHT_SHIFT_SIGNED);
- INFIX_OPERATORS[IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED] = new Integer(IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED);
- INFIX_OPERATORS[IExpressionConstants.IN_TIMES] = new Integer(IExpressionConstants.IN_TIMES);
- INFIX_OPERATORS[IExpressionConstants.IN_XOR] = new Integer(IExpressionConstants.IN_XOR);
- }
/*
* INSTANCEOF expression.
@@ -297,7 +253,6 @@
* INSTANCEOF
* type (either a string representing the type, or an IBeanProxyType representing the type).
*/
- private static final Integer INSTANCEOF = new Integer(IInternalExpressionConstants.INSTANCEOF_EXPRESSION);
/*
* Field access expression.
@@ -310,7 +265,6 @@
* name (the name of the field)
* Boolean (true if has receiver)
*/
- private static final Integer FIELDACCESS = new Integer(IInternalExpressionConstants.FIELD_ACCESS_EXPRESSION);
/*
* Method invocation expression.
@@ -325,10 +279,33 @@
* Boolean (true if has receiver)
* argCount (the number of arguments).
*/
- private static final Integer METHODINVOCATION = new Integer(IInternalExpressionConstants.METHOD_EXPRESSION);
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.
@@ -339,39 +316,109 @@
* Since we can't have an array list of ints, will simulate the
* stack here.
*/
- private int[] nextForExpressionStack = new int[30];
+ private ForExpression[] nextForExpressionStack = new ForExpression[30];
private int nextForExpressionStackPos = -1; // Position of top entry in stack.
- private static final int INVALID = -2; // Mark that this expression is now invalid. (Goes into nextForExpressionStackSize)
+ 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 static final int PROCESS_EXPRESSION = Integer.MIN_VALUE; // This is pushed onto the next expression stack, and went it is popped, then the expression is complete
+ 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");
+
+ // 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(Integer.MIN_VALUE-2, "End Block Expression");
+
+ // 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(Integer.MIN_VALUE-3, "End Try Expression");
+
+ // 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(Integer.MIN_VALUE-4, "Catch Expression");
+
/**
* Check the for expression, and if legal, set to the next valid for expression type,
- * if it can.
+ * 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(int forExpression) throws IllegalStateException {
- if (nextForExpressionStackPos != INVALID) {
+ protected final void checkForExpression(ForExpression forExpression) throws IllegalStateException {
+ if (expressionValid) {
if (nextForExpressionStackPos == -1)
- if (forExpression == IExpressionConstants.ROOTEXPRESSION)
+ 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)
- return; // Valid, the top expression matched.
+ 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.getString("Expression.InInvalidStateDueTo_EXC_"), new Object[] {invalidMsg}) : ProxyMessages.getString("Expression.InInvalidState_EXC_"); //$NON-NLS-1$ //$NON-NLS-2$
throw new IllegalStateException(expMsg);
}
// If we got here, then invalid.
- nextForExpressionStackPos = INVALID;
- throw new IllegalStateException(ProxyMessages.getString("Expression.TypeSentInInvalidOrder_EXC_")); //$NON-NLS-1$
+ ForExpression expected = nextForExpressionStack[nextForExpressionStackPos];
+ expressionValid = false;
+ throw new IllegalStateException(MessageFormat.format(ProxyMessages.getString("Expression.TypeSentInInvalidOrder_EXC_"), new Object[] {forExpression, expected})); //$NON-NLS-1$
+ }
+
+ /**
+ * 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.getString("Expression.InvalidMarkNesting"), new Object[] {new Integer(currentMarkEntry != null ? currentMarkEntry.markID : 0)})); //$NON-NLS-1$
}
/**
@@ -383,10 +430,10 @@
*
* @since 1.0.0
*/
- protected final boolean peekForExpression(int forExpression) {
- if (nextForExpressionStackPos != INVALID) {
+ protected final boolean peekForExpression(ForExpression forExpression) {
+ if (expressionValid) {
if (nextForExpressionStackPos == -1)
- if (forExpression == IExpressionConstants.ROOTEXPRESSION)
+ if (forExpression == ForExpression.ROOTEXPRESSION)
return true; // valid. We are at the root (i.e. nothing is waiting).
else
; // invalid. drop through
@@ -400,9 +447,7 @@
* Mark this expression as now invalid.
*/
protected final void markInvalid() {
- nextForExpressionStackPos = INVALID;
- controlStack.clear();
- closeProxy();
+ expressionValid = false;
}
/**
@@ -417,6 +462,25 @@
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
@@ -432,10 +496,10 @@
/*
* Push the next expression type.
*/
- private void pushForExpression(int nextExpression) {
+ private void pushForExpression(ForExpression nextExpression) {
if (++nextForExpressionStackPos >= nextForExpressionStack.length) {
// Increase stack size.
- int[] newStack = new int[nextForExpressionStackPos*2]; // So room to grow without excessive allocations.
+ ForExpression[] newStack = new ForExpression[nextForExpressionStackPos*2]; // So room to grow without excessive allocations.
System.arraycopy(nextForExpressionStack, 0, newStack, 0, nextForExpressionStack.length);
nextForExpressionStack = newStack;
}
@@ -445,54 +509,69 @@
/*
* Check if expression is complete, and if it is, process it.
*/
- private void processExpression() throws ThrowableProxy, NoExpressionValueException {
+ private void processExpression() {
while (expressionReady()) {
try {
// We've received all of the expressions for the expression, so process it.
- int expType = ((Integer) pop()).intValue();
+ int expType = ((InternalExpressionTypes) pop()).getValue();
switch (expType) {
- case IInternalExpressionConstants.CAST_EXPRESSION:
- pushCastToProxy(pop());
+ case InternalExpressionTypes.CAST_EXPRESSION_VALUE:
+ pushCastToProxy((IProxyBeanType) pop());
break;
- case IInternalExpressionConstants.INSTANCEOF_EXPRESSION:
- pushInstanceofToProxy(pop());
+ case InternalExpressionTypes.INSTANCEOF_EXPRESSION_VALUE:
+ pushInstanceofToProxy((IProxyBeanType) pop());
break;
- case IInternalExpressionConstants.PREFIX_EXPRESSION:
- pushPrefixToProxy(((Integer)pop()).intValue());
+ case InternalExpressionTypes.PREFIX_EXPRESSION_VALUE:
+ pushPrefixToProxy((PrefixOperator)pop());
break;
- case IInternalExpressionConstants.INFIX_EXPRESSION:
- pushInfixToProxy(((Integer) pop()).intValue(), ((Integer) pop()).intValue());
+ case InternalExpressionTypes.INFIX_EXPRESSION_VALUE:
+ pushInfixToProxy((InfixOperator) pop(), (InternalInfixOperandType) pop());
break;
- case IInternalExpressionConstants.ARRAY_ACCESS_EXPRESSION:
+ case InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION_VALUE:
pushArrayAccessToProxy(((Integer) pop()).intValue());
break;
- case IInternalExpressionConstants.ARRAY_CREATION_EXPRESSION:
- pushArrayCreationToProxy(pop(), ((Integer) pop()).intValue());
+ case InternalExpressionTypes.ARRAY_CREATION_EXPRESSION_VALUE:
+ pushArrayCreationToProxy((IProxyBeanType) pop(), ((Integer) pop()).intValue());
break;
- case IInternalExpressionConstants.ARRAY_INITIALIZER_EXPRESSION:
- pushArrayInitializerToProxy(pop(), ((Integer) pop()).intValue());
+ case InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION_VALUE:
+ pushArrayInitializerToProxy((IProxyBeanType) pop(), ((Integer) pop()).intValue(), ((Integer) pop()).intValue());
break;
- case IInternalExpressionConstants.CLASS_INSTANCE_CREATION_EXPRESSION:
- pushClassInstanceCreationToProxy(pop(), ((Integer) pop()).intValue());
+ case InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION_VALUE:
+ pushClassInstanceCreationToProxy((IProxyBeanType) pop(), ((Integer) pop()).intValue());
break;
- case IInternalExpressionConstants.FIELD_ACCESS_EXPRESSION:
- pushFieldAccessToProxy((String) pop(), ((Boolean) pop()).booleanValue());
+ case InternalExpressionTypes.FIELD_ACCESS_EXPRESSION_VALUE:
+ pushFieldAccessToProxy(pop(), ((Boolean) pop()).booleanValue());
break;
- case IInternalExpressionConstants.METHOD_EXPRESSION:
- pushMethodInvocationToProxy((String) pop(), ((Boolean) pop()).booleanValue(), ((Integer) pop()).intValue());
+ case InternalExpressionTypes.METHOD_EXPRESSION_VALUE:
+ pushMethodInvocationToProxy(pop(), ((Boolean) pop()).booleanValue(), ((Integer) pop()).intValue());
break;
- case IInternalExpressionConstants.CONDITIONAL_EXPRESSION:
- pushConditionalToProxy(((Integer) pop()).intValue());
+ 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;
default:
internalProcessUnknownExpressionType(expType);
}
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -500,6 +579,7 @@
}
}
+
private void internalProcessUnknownExpressionType(int expressionType) throws IllegalArgumentException {
if (!processUnknownExpressionType(expressionType))
throw new IllegalArgumentException();
@@ -532,51 +612,192 @@
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(IExpressionConstants.ROOTEXPRESSION); // We are at the root.
- pushInvoke();
+ 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 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(IExpressionConstants.ROOTEXPRESSION); // We are at the root.
- return pullProxyValue(); // Get the top value.
+ 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.
+ 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(int forExpression, int indexCount) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createArrayAccess(ForExpression forExpression, int indexCount) {
try {
checkForExpression(forExpression);
pushForExpression(PROCESS_EXPRESSION);
int i = indexCount;
while (i-- > 0)
- pushForExpression(IExpressionConstants.ARRAYACCESS_INDEX);
- pushForExpression(IExpressionConstants.ARRAYACCESS_ARRAY);
+ pushForExpression(ForExpression.ARRAYACCESS_INDEX);
+ pushForExpression(ForExpression.ARRAYACCESS_ARRAY);
push(indexCount == 1 ? ARRAYACCESS_INDEX_1 : new Integer(indexCount));
- push(ARRAYACCESS);
+ push(InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION);
processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -585,84 +806,79 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createArrayCreation(int, java.lang.String, int)
*/
- public final void createArrayCreation(int forExpression, String type, int dimensionExpressionCount)
- throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
- try {
- checkForExpression(forExpression);
- pushArrayCreation(type, dimensionExpressionCount); // Push this onto the local stack to wait for completion.
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
- } catch (RuntimeException e) {
- markInvalid();
- throw e;
- }
+ 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(int, org.eclipse.jem.internal.proxy.core.IBeanTypeProxy, int)
+ * @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(int forExpression, IBeanTypeProxy type, int dimensionExpressionCount)
- throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
+ public final void createArrayCreation(ForExpression forExpression, IProxyBeanType type, int dimensionExpressionCount)
+ throws IllegalStateException {
+ pushArrayCreation(forExpression, type, dimensionExpressionCount);
+ }
+
+ private void pushArrayCreation(ForExpression forExpression, IProxyBeanType type, int dimensionExpressionCount) throws IllegalStateException {
try {
checkForExpression(forExpression);
- pushArrayCreation(type, dimensionExpressionCount); // Push this onto the local stack to wait for completion.
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+
+ 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;
- }
- }
-
- private void pushArrayCreation(Object type, int dimensionExpressionCount) {
- 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(ARRAYCREATION);
-
- pushForExpression(PROCESS_EXPRESSION);
- if (dimensionExpressionCount == 0)
- pushForExpression(ARRAY_INITIALIZER);
- else {
- while(dimensionExpressionCount-- >0)
- pushForExpression(IExpressionConstants.ARRAYCREATION_DIMENSION);
}
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createArrayInitializer(int)
*/
- public final void createArrayInitializer(int expressionCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
+ 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(IExpressionConstants.ARRAYINITIALIZER_EXPRESSION);
-
- Object arrayType = peek(2); // Get the type from the value stack. Do before I mess up the stack.
-
+ 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);
@@ -677,97 +893,87 @@
push(new Integer(expressionCount));
break;
}
-
+
if (arrayType instanceof String) {
- // Need to remove the end set of "[]" to reduce by one dimension.
String at = (String) arrayType;
int i = at.lastIndexOf("[]"); //$NON-NLS-1$
if (i == -1)
- throw new IllegalArgumentException(MessageFormat.format(ProxyMessages.getString("Expression.ArrayTypeNotAnArray_EXC_"), new Object[] {arrayType})); //$NON-NLS-1$
- arrayType = at.substring(0, i);
- } else if (arrayType instanceof IArrayBeanTypeProxy) {
- arrayType = ((IArrayBeanTypeProxy) arrayType).getComponentType();
- } else
- throw new IllegalArgumentException(MessageFormat.format(ProxyMessages.getString("Expression.ArrayTypeNotAnArray_EXC_"), new Object[] {arrayType})); //$NON-NLS-1$
+ throw new IllegalArgumentException(MessageFormat.format(
+ ProxyMessages.getString("Expression.ArrayTypeNotAnArray_EXC_"), new Object[] { arrayType})); //$NON-NLS-1$
+ arrayType = getProxyBeanType(at);
+ } else if (!(arrayType instanceof IProxyBeanType)) {
+ throw new IllegalArgumentException(MessageFormat.format(
+ ProxyMessages.getString("Expression.ArrayTypeNotAnArray_EXC_"), new Object[] { arrayType})); //$NON-NLS-1$
+ }
+ push(new Integer(++stripCount));
push(arrayType);
- push(ARRAYINITIALIZER);
-
+ push(InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION);
+
pushForExpression(PROCESS_EXPRESSION);
- while(expressionCount-->0)
- pushForExpression(IExpressionConstants.ARRAYINITIALIZER_EXPRESSION);
-
- processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ 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(int forExpression, String type) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
- pushCast(forExpression, type); // Push this onto the local stack to wait for completion.
+ 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(int, org.eclipse.jem.internal.proxy.core.IBeanTypeProxy)
+ /*
+ * (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(int forExpression, IBeanTypeProxy type) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createCastExpression(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException {
pushCast(forExpression, type); // Push this onto the local stack to wait for completion.
}
/*
* Push for a cast.
*/
- private void pushCast(int forExpression, Object type) throws ThrowableProxy, NoExpressionValueException {
+ private void pushCast(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException {
try {
checkForExpression(forExpression);
push(type);
- push(CAST);
- pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.CAST_EXPRESSION); // The next expression must be for the cast expression.
- processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ 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(int forExpression, String type, int argumentCount)
- throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
- pushClassInstanceCreation(forExpression, type, argumentCount); // Push this onto the local stack to wait for completion.
+ 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(int, org.eclipse.jem.internal.proxy.core.IBeanTypeProxy, int)
+ /*
+ * (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(int forExpression, IBeanTypeProxy type, int argumentCount)
- throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
+ public final void createClassInstanceCreation(ForExpression forExpression, IProxyBeanType type, int argumentCount)
+ throws IllegalStateException {
pushClassInstanceCreation(forExpression, type, argumentCount); // Push this onto the local stack to wait for completion.
}
/*
* Push for a class instance creation
*/
- private void pushClassInstanceCreation(int forExpression, Object type, int argumentCount) throws ThrowableProxy, NoExpressionValueException {
+ private void pushClassInstanceCreation(ForExpression forExpression, IProxyBeanType type, int argumentCount) throws IllegalStateException {
try {
checkForExpression(forExpression);
switch (argumentCount) {
@@ -782,50 +988,38 @@
break;
}
push(type);
- push(CLASSINSTANCECREATION);
-
+ push(InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION);
+
pushForExpression(PROCESS_EXPRESSION);
- while(argumentCount-- >0)
- pushForExpression(IExpressionConstants.CLASSINSTANCECREATION_ARGUMENT);
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ 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(int forExpression) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createConditionalExpression(ForExpression forExpression) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.CONDITIONAL_FALSE);
+ pushForExpression(ForExpression.CONDITIONAL_FALSE);
pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.CONDITIONAL_TRUE);
+ pushForExpression(ForExpression.CONDITIONAL_TRUE);
pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.CONDITIONAL_CONDITION);
-
- push(CONDITIONAL_FALSEXP);
- push(CONDITIONAL);
- push(CONDITIONAL_TRUEEXP);
- push(CONDITIONAL);
- push(CONDITIONAL_TEST);
- push(CONDITIONAL);
+ 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 (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -835,26 +1029,73 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createFieldAccess(int, java.lang.String, boolean)
*/
- public final void createFieldAccess(int forExpression, String fieldName, boolean hasReceiver) throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
+ public final void createFieldAccess(ForExpression forExpression, String fieldName, boolean hasReceiver) throws IllegalStateException, IllegalArgumentException {
try {
- checkForExpression(forExpression);
+ // 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(ProxyMessages.getString("Expression.CannotHandleNoReceiveOnFieldAccess_EXC_")); //$NON-NLS-1$
-
- push(hasReceiver ? Boolean.TRUE : Boolean.FALSE); // We have a receiver
- push(fieldName);
- push(FIELDACCESS);
+ throw new IllegalArgumentException(MessageFormat.format(
+ ProxyMessages.getString("Expression.CannotHandleNoReceiveOnFieldAccess_EXC_"), new Object[] { fieldName})); //$NON-NLS-1$
+ 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(IExpressionConstants.FIELD_RECEIVER);
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ pushForExpression(ForExpression.FIELD_RECEIVER);
+ processExpression(); // See if previous expression is ready for processing.
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -864,39 +1105,32 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createInfixExpression(int, int, int)
*/
- public final void createInfixExpression(int forExpression, int operator, int extendedOperandCount) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createInfixExpression(ForExpression forExpression, InfixOperator operator, int extendedOperandCount) throws IllegalStateException {
try {
checkForExpression(forExpression);
- Integer inoperator = INFIX_OPERATORS[operator];
- push(IN_LAST);
- push(inoperator);
- push(INFIX);
+ push(InternalInfixOperandType.INFIX_LAST_OPERAND);
+ push(operator);
+ push(InternalExpressionTypes.INFIX_EXPRESSION);
int i = extendedOperandCount;
- while(i-->0) {
- push(IN_OTHER);
- push(inoperator);
- push(INFIX);
+ while (i-- > 0) {
+ push(InternalInfixOperandType.INFIX_OTHER_OPERAND);
+ push(operator);
+ push(InternalExpressionTypes.INFIX_EXPRESSION);
}
- push(IN_LEFT);
- push(inoperator);
- push(INFIX);
-
+ push(InternalInfixOperandType.INFIX_LEFT_OPERAND);
+ push(operator);
+ push(InternalExpressionTypes.INFIX_EXPRESSION);
+
i = extendedOperandCount;
- while(i-->0) {
- pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.INFIX_EXTENDED);
+ while (i-- > 0) {
+ pushForExpression(PROCESS_EXPRESSION);
+ pushForExpression(ForExpression.INFIX_EXTENDED);
}
pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.INFIX_RIGHT);
+ pushForExpression(ForExpression.INFIX_RIGHT);
pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.INFIX_LEFT);
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ pushForExpression(ForExpression.INFIX_LEFT);
+ processExpression(); // See if previous expression is ready for processing.
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -906,99 +1140,129 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createInstanceofExpression(int, java.lang.String)
*/
- public final void createInstanceofExpression(int forExpression, String type) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
- pushInstanceof(forExpression, type); // Push this onto the local stack to wait for completion.
+ 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(int, org.eclipse.jem.internal.proxy.core.IBeanTypeProxy)
+ /*
+ * (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(int forExpression, IBeanTypeProxy type) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createInstanceofExpression(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException {
pushInstanceof(forExpression, type); // Push this onto the local stack to wait for completion.
}
/*
* Push for a cast.
*/
- private void pushInstanceof(int forExpression, Object type) throws ThrowableProxy, NoExpressionValueException {
+ private void pushInstanceof(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException {
try {
checkForExpression(forExpression);
push(type);
- push(INSTANCEOF);
- pushForExpression(PROCESS_EXPRESSION);
- pushForExpression(IExpressionConstants.INSTANCEOF_VALUE); // The next expression must be for the instance of expression.
- processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ 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(int forExpression, String name, boolean hasReceiver, int argumentCount)
- throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
+ public final void createMethodInvocation(ForExpression forExpression, String name, boolean hasReceiver, int argumentCount)
+ throws IllegalStateException, IllegalArgumentException {
try {
- checkForExpression(forExpression);
+ // 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.getString("Expression.MethodsNeedReceiver_EXC_"), new Object[] {name})); //$NON-NLS-1$
+ throw new IllegalArgumentException(MessageFormat.format(
+ ProxyMessages.getString("Expression.MethodsNeedReceiver_EXC_"), new Object[] { name})); //$NON-NLS-1$
- 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(name);
- push(METHODINVOCATION);
-
- pushForExpression(PROCESS_EXPRESSION);
- while (argumentCount-- > 0)
- pushForExpression(IExpressionConstants.METHOD_ARGUMENT);
- if (hasReceiver)
- pushForExpression(IExpressionConstants.METHOD_RECEIVER);
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
+ pushMethodInvocation(forExpression, name, hasReceiver, argumentCount);
} catch (RuntimeException e) {
markInvalid();
throw e;
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IExpression#createPrefixExpression(int, int)
+ /**
+ * @param forExpression
+ * @param method String for method name, IMethodProxy otherwise.
+ * @param hasReceiver
+ * @param argumentCount
+ * @throws ThrowableProxy
+ * @throws NoExpressionValueException
+ *
+ * @since 1.1.0
*/
- public final void createPrefixExpression(int forExpression, int operator) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ private void pushMethodInvocation(ForExpression forExpression, Object method, boolean hasReceiver, int argumentCount) throws IllegalArgumentException, IllegalStateException {
try {
checkForExpression(forExpression);
- push(PREFIX_OPERATORS[operator]);
- push(PREFIX);
-
+ 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);
- pushForExpression(IExpressionConstants.PREFIX_OPERAND);
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- throw e;
- } catch (NoExpressionValueException e) {
+ 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.
+ * @param forExpression
+ * @param initializationString
+ * @param type
+ *
+ * @since 1.1.0
+ */
+ public final void createNewInstance(ForExpression forExpression, String initializationString, IProxyBeanType type) {
+ try {
+ checkForExpression(forExpression);
+ pushNewInstanceToProxy(initializationString, type);
+ processExpression();
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1008,17 +1272,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createNull(int)
*/
- public final void createNull(int forExpression) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createNull(ForExpression forExpression) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(null);
processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1028,34 +1286,22 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createTypeLiteral(int, java.lang.String)
*/
- public final void createTypeLiteral(int forExpression, String type) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
- try {
- checkForExpression(forExpression);
- pushTypeLiteralToProxy(type);
- processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
- } catch (RuntimeException e) {
- markInvalid();
- throw e;
- }
+ 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 ThrowableProxy, IllegalStateException, NoExpressionValueException {
- pushTypeReceiver(type);
+ 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.IBeanTypeProxy)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IExpression#createTypeReceiver(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
*/
- public final void createTypeReceiver(IBeanTypeProxy type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException {
+ public final void createTypeReceiver(IProxyBeanType type) throws IllegalStateException {
pushTypeReceiver(type);
}
@@ -1065,24 +1311,18 @@
*
* @since 1.0.0
*/
- private void pushTypeReceiver(Object type) throws ThrowableProxy, NoExpressionValueException {
+ 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(FIELD_RECEIVER))
- checkForExpression(FIELD_RECEIVER);
+ if (peekForExpression(ForExpression.FIELD_RECEIVER))
+ checkForExpression(ForExpression.FIELD_RECEIVER);
else
- checkForExpression(METHOD_RECEIVER);
+ checkForExpression(ForExpression.METHOD_RECEIVER);
pushTypeReceiverToProxy(type);
processExpression(); // See if previous expression is ready for processing.
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1098,17 +1338,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, boolean)
*/
- public final void createPrimitiveLiteral(int forExpression, boolean value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, boolean value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1118,17 +1352,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, char)
*/
- public final void createPrimitiveLiteral(int forExpression, char value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, char value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1138,17 +1366,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, byte)
*/
- public final void createPrimitiveLiteral(int forExpression, byte value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, byte value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1158,17 +1380,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, double)
*/
- public final void createPrimitiveLiteral(int forExpression, double value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, double value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1178,17 +1394,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, float)
*/
- public final void createPrimitiveLiteral(int forExpression, float value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, float value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1198,17 +1408,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, int)
*/
- public final void createPrimitiveLiteral(int forExpression, int value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, int value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1218,17 +1422,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, long)
*/
- public final void createPrimitiveLiteral(int forExpression, long value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, long value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1238,17 +1436,11 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createPrimitiveLiteral(int, short)
*/
- public final void createPrimitiveLiteral(int forExpression, short value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createPrimitiveLiteral(ForExpression forExpression, short value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} catch (RuntimeException e) {
markInvalid();
throw e;
@@ -1258,17 +1450,306 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IExpression#createStringLiteral(int, java.lang.String)
*/
- public final void createStringLiteral(int forExpression, String value) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createStringLiteral(ForExpression forExpression, String value) throws IllegalStateException {
try {
checkForExpression(forExpression);
pushToProxy(beanProxyFactory.createBeanProxyWith(value));
processExpression();
- } catch (ThrowableProxy e) {
+ } catch (RuntimeException e) {
markInvalid();
throw e;
- } catch (NoExpressionValueException 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 {
+ try {
+ checkForExpression(forExpression);
+ 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.
+ *
+ * @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.
+ *
+ * @param declaringType
+ * @param methodName
+ * @param parameterTypes parameter types or <code>null</code> if no parameter types.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public final IProxyMethod createMethodExpressionProxy(IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes) {
+ 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.
+ * @param declaringType
+ * @param fieldName
+ *
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public final IProxyField createFieldExpressionProxy(IProxyBeanType declaringType, String fieldName) {
+ 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("Invalid expression type for reassignment:"+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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 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 {
+ 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;
@@ -1276,41 +1757,214 @@
}
/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IExpression#createProxyExpression(int, org.eclipse.jem.internal.proxy.core.IBeanProxy)
+ * @see org.eclipse.jem.internal.proxy.core.IExpression#createTryEnd()
*/
- public final void createProxyExpression(int forExpression, IBeanProxy proxy) throws IllegalStateException, ThrowableProxy, NoExpressionValueException {
+ public final void createTryEnd() throws IllegalStateException {
try {
- checkForExpression(forExpression);
- pushToProxy(proxy);
+ 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 (ThrowableProxy e) {
- markInvalid();
- throw e;
- } catch (NoExpressionValueException e) {
- markInvalid();
- throw e;
} 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.
+ }
+
+
+ /**
+ * 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
- * @throws ThrowableProxy
*
* @since 1.0.0
*/
- protected abstract void pushToProxy(IBeanProxy proxy) throws ThrowableProxy;
-
+ protected abstract void pushToProxy(IProxy proxy);
+
/**
- * Tell the other side we are complete. This is only called for invoked expressions,
- * i.e. no return value.
+ * 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
*
@@ -1320,177 +1974,324 @@
/**
* 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() throws ThrowableProxy, NoExpressionValueException;
+ 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.
+ * 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() throws ThrowableProxy, NoExpressionValueException;
+ 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. It may be either <code>String</code> (the value is the type to be searched for) or <code>IBeanTypeProxy</code> (it is of that type that the proxy is wrappering).
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
+ * @param type Cast type.
*
* @since 1.0.0
*/
- protected abstract void pushCastToProxy(Object type) throws ThrowableProxy, NoExpressionValueException;
+ 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. It may be either <code>String</code> (the value is the type to be searched for) or <code>IBeanTypeProxy</code> (it is of that type that the proxy is wrappering).
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
+ * @param type Instanceof type.
*
* @since 1.0.0
*/
- protected abstract void pushInstanceofToProxy(Object type) throws ThrowableProxy, NoExpressionValueException;
+ 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, the values are from IExpressionConstants infix operators.
- * @param operandType The operand type. left, other, or last. The values are from the IInternalExpressionConstants infix operations.
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
+ * @param operator The operator.
+ * @param operandType The operand type. left, other, or last.
*
- * @see IExpressionConstants#IN_AND
- * @see IInternalExpressionConstants#INFIX_LAST_OPERAND
* @since 1.0.0
*/
- protected abstract void pushInfixToProxy(int operator, int operandType) throws ThrowableProxy, NoExpressionValueException;
+ 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 The operator, the values are from IExpressionConstants prefix operators.
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
+ * @param operator
*
* @see IExpressionConstants#PRE_MINUS
* @since 1.0.0
*/
- protected abstract void pushPrefixToProxy(int operator) throws ThrowableProxy, NoExpressionValueException;
-
- /**
- * Push to proxy the type literal string. The result of the type literal string will be placed onto the evaluation
- * stack.
- *
- * @param type
- * @throws ThrowableProxy
- *
- * @since 1.0.0
- */
- protected abstract void pushTypeLiteralToProxy(String type) throws ThrowableProxy;
+ protected abstract void pushPrefixToProxy(PrefixOperator operator);
+
/**
* Push to proxy the array access. The result will be placed onto the evaluation stack.
*
* @param indexCount
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected abstract void pushArrayAccessToProxy(int indexCount) throws ThrowableProxy, NoExpressionValueException;
+ 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. (must be an array type) It may be either <code>String</code> (the value is the type to be searched for) or <code>IBeanTypeProxy</code> (it is of that type that the proxy is wrappering).
+ * @param type The array type.
* @param dimensionCount
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected abstract void pushArrayCreationToProxy(Object type, int dimensionCount) throws ThrowableProxy, NoExpressionValueException;
+ 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 minus one dimension. (must be an array type) It may be either <code>String</code> (the value is the type to be searched for) or <code>IBeanTypeProxy</code> (it is of that type that the proxy is wrappering).
+ * @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
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected abstract void pushArrayInitializerToProxy(Object type, int expressionCount) throws ThrowableProxy, NoExpressionValueException;
+ 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. It may be either <code>String</code> (the value is the type to be searched for) or <code>IBeanTypeProxy</code> (it is of that type that the proxy is wrappering).
+ * @param type Class type.
* @param argumentCount The number of arguments.
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected abstract void pushClassInstanceCreationToProxy(Object type, int argumentCount) throws ThrowableProxy, NoExpressionValueException;
+ 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. It may be either <code>String</code> (the value is the type to be searched for) or <code>IBeanTypeProxy</code> (it is of that type that the proxy is wrappering).
- * @throws ThrowableProxy
+ * @param type Class type.
*
* @since 1.0.0
*/
- protected abstract void pushTypeReceiverToProxy(Object type) throws ThrowableProxy;
+ protected abstract void pushTypeReceiverToProxy(IProxyBeanType type);
/**
* Push to proxy the field access. The result value will be placed onto the evaluation stack.
- * @param fieldName The name of the field.
+ * @param field The name of the field if string, or an IFieldProxy.
* @param hasReceiver Has receiver flag.
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected abstract void pushFieldAccessToProxy(String fieldName, boolean hasReceiver) throws ThrowableProxy, NoExpressionValueException;
+ 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 methodName
+ * @param method String for method name or IProxyMethod
* @param hasReceiver
* @param argCount
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- protected abstract void pushMethodInvocationToProxy(String methodName, boolean hasReceiver, int argCount) throws ThrowableProxy, NoExpressionValueException;
+ 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, one of IExpressionConstants.CONDITIONAL_* constants.
- * @throws ThrowableProxy
- * @throws NoExpressionValueException
+ * @param expressionType The expression type.
*
- * @see IExpressionConstants#CONDITIONAL_CONDITION
* @since 1.0.0
*/
- protected abstract void pushConditionalToProxy(int expressionType) throws ThrowableProxy, NoExpressionValueException;
+ 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);
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ExpressionProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ExpressionProxy.java
new file mode 100644
index 0000000..9b816ab
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ExpressionProxy.java
@@ -0,0 +1,339 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * $RCSfile: ExpressionProxy.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.core;
+
+import java.util.EventObject;
+import java.util.logging.Level;
+
+
+/**
+ * This is a proxy for an IExpression evaluation value. It is used as a place holder proxy value for result of an expression, and
+ * then the value can be used in a later expression, or at the end, it can callback and return a proxy in the IDE
+ * side in a callback for usage later on outside of the IExpression.
+ * <p>
+ * After receiving the resolved event, listeners should not hold onto the ExpressionProxy because it would then be invalid. At that
+ * point they should instead hold onto the resolved bean proxy.
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IExpression#assignExpressionProxy()
+ * @see org.eclipse.jem.internal.proxy.core.IExpression#createExpressionProxyExpression(int, ExpressionProxy)
+ * @since 1.1.0
+ */
+public class ExpressionProxy implements IProxy {
+
+ /**
+ * The event object for the resolved event of the proxy listener.
+ * <p>
+ * The source will be the ExpressionProxy that is being resolved.
+ * @since 1.1.0
+ */
+ public static class ProxyEvent extends EventObject {
+
+ private final IBeanProxy proxy;
+
+ /**
+ * @param source the expression proxy for the event.
+ * @param proxy the bean proxy the expression proxy (source) resolved to.
+ *
+ * @since 1.1.0
+ */
+ public ProxyEvent(ExpressionProxy source, IBeanProxy proxy) {
+ super(source);
+ this.proxy = proxy;
+ }
+
+ /**
+ * Construct the event with no proxy. Used for not resolved and void.
+ * @param source
+ *
+ * @since 1.1.0
+ */
+ public ProxyEvent(ExpressionProxy source) {
+ this(source, null);
+ }
+
+ /**
+ * Get the proxy value that the expression proxy (source) resolved to.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IBeanProxy getProxy() {
+ return proxy;
+ }
+ }
+
+ /**
+ * Listener for expression proxy events.
+ *
+ * @since 1.1.0
+ */
+ public interface ProxyListener {
+ /**
+ * The expression proxy has been resolved. The event contains the resolved proxy.
+ * At this point, any listeners should no longer hold onto the ExpressionProxy
+ * because it is now invalid. They should hold onto the resolved bean proxy instead.
+ *
+ * @param event
+ *
+ * @since 1.1.0
+ */
+ public void proxyResolved(ProxyEvent event);
+
+ /**
+ * This is called for ExpressionProxies that have a callback listener, but the proxy
+ * was never resolved. This means that the expression that assigns to the proxy was
+ * not executed. In this case the event does not have a bean proxy in it.
+ *
+ * @param event
+ *
+ * @since 1.1.0
+ */
+ public void proxyNotResolved(ProxyEvent event);
+
+ /**
+ * This is called for ExpressionProxies that were assigned to an expression that
+ * had a <code>VOID</code> return type. This is usually for method invocations that
+ * have a void return type. In this case the event does not have a bean proxy in it.
+ * @param event
+ *
+ * @since 1.1.0
+ */
+ public void proxyVoid(ProxyEvent event);
+ }
+
+ /**
+ * An implementation of ProxyListener that does nothing. It can be
+ * used as a superclass for individual listeners that are only interested
+ * in some of the events.
+ *
+ * @since 1.1.0
+ */
+ public static class ProxyAdapter implements ProxyListener {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyListener#proxyNotResolved(org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent)
+ */
+ public void proxyNotResolved(ProxyEvent event) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyListener#proxyResolved(org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent)
+ */
+ public void proxyResolved(ProxyEvent event) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyListener#proxyVoid(org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent)
+ */
+ public void proxyVoid(ProxyEvent event) {
+ }
+ }
+
+ final private int proxyID;
+ final private int proxyType;
+ private ListenerList listenerList;
+ private Expression expression;
+
+ /**
+ * Create with the given proxy id.
+ * @param proxyid
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProxy(int proxyid, int proxyType, Expression expression) {
+ this.proxyID = proxyid;
+ this.proxyType = proxyType;
+ this.expression = expression;
+ }
+
+ /**
+ * Get the expression this proxy is for.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public Expression getExpression() {
+ return expression;
+ }
+
+ /**
+ * Used internally in expression to get the proxy type.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected final int getProxyType() {
+ return proxyType;
+ }
+
+ /**
+ * Return the proxy id.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public final int getProxyID() {
+ return proxyID;
+ }
+
+ /**
+ * Add a listener. If listener already added, it has no effect.
+ * @param listener
+ *
+ * @since 1.1.0
+ */
+ public void addProxyListener(ProxyListener listener) {
+ if (listenerList == null)
+ listenerList = new ListenerList();
+ listenerList.add(listener);
+ }
+
+ /**
+ * Remove a listener. If listener not already added, then no error.
+ * @param listener
+ *
+ * @since 1.1.0
+ */
+ public void removeProxyListener(ProxyListener listener) {
+ if (listenerList != null)
+ listenerList.remove(listener);
+ }
+
+ /**
+ * Used by internal subclasses or Expression to know if anyone is listening.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected final boolean hasListeners() {
+ return listenerList != null && !listenerList.isEmpty();
+ }
+
+ /**
+ * The proxy has been fired (one of the events has occurred). Subclasses should clean
+ * up and not hold onto anything that would be expensive in case the proxy is still
+ * held onto be someone. For example the default clears the listener list.
+ * <p>
+ * <b>Note:</b> Subclasses must call super.dispose().
+ *
+ * @since 1.1.0
+ */
+ protected void dispose() {
+ listenerList = null;
+ expression = null;
+ }
+
+ /**
+ * Used by internal subclasses or by Expression to fire the resolved event. Once fired all listeners are removed.
+ * This is because only one kind of firing can be done for a expression proxy and then the proxy is dead. This
+ * prevents listeners from being held on to if any one accidently still holds the proxy.
+ * @param proxy
+ *
+ * @since 1.1.0
+ */
+ protected void fireResolved(IBeanProxy proxy) {
+ if (hasListeners()) {
+ ProxyEvent event = new ProxyEvent(this, proxy);
+ Object[] listeners = listenerList.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ try {
+ ((ProxyListener) listeners[i]).proxyResolved(event);
+ } catch (RuntimeException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e, Level.WARNING);
+ }
+ }
+ }
+ dispose();
+ }
+
+ /**
+ * Used by internal subclasses or by Expression to fire the not resolved event. Once fired all listeners are removed.
+ * This is because only one kind of firing can be done for a expression proxy and then the proxy is dead. This
+ * prevents listeners from being held on to if any one accidently still holds the proxy.
+ *
+ * @since 1.1.0
+ */
+ protected void fireNotResolved() {
+ if (hasListeners()) {
+ ProxyEvent event = new ProxyEvent(this);
+ Object[] listeners = listenerList.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ try {
+ ((ProxyListener) listeners[i]).proxyNotResolved(event);
+ } catch (RuntimeException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e, Level.WARNING);
+ }
+
+ }
+ }
+ dispose();
+ }
+
+ /**
+ * Used by internal subclasses or by Expression to fire the void resolved event. Once fired all listeners are removed.
+ * This is because only one kind of firing can be done for a expression proxy and then the proxy is dead. This
+ * prevents listeners from being held on to if any one accidently still holds the proxy.
+ *
+ * @since 1.1.0
+ */
+ protected void fireVoidResolved() {
+ if (hasListeners()) {
+ ProxyEvent event = new ProxyEvent(this);
+ Object[] listeners = listenerList.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ try {
+ ((ProxyListener) listeners[i]).proxyVoid(event);
+ } catch (RuntimeException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e, Level.WARNING);
+ }
+
+ }
+ }
+ dispose();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return false;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return true;
+ }
+
+ /**
+ * Is this proxy valid for reassignment. By default only if the type is NORMAL_EXPRESSION_PROXY.
+ * Subclasses may override and return true in their cases.
+ *
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public boolean isValidForReassignment() {
+ return getProxyType() == Expression.NORMAL_EXPRESSION_PROXY;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return super.toString()+": "+getProxyID();
+ }
+}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanProxy.java
index 923ccfd..bbdda08 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanProxy.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: IBeanProxy.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -21,7 +21,7 @@
* Creation date: (12/3/99 11:37:01 AM)
* @author: Joe Winchester
*/
-public interface IBeanProxy {
+public interface IBeanProxy extends IProxy {
/**
* equals: Equal if:
* 1) This proxy == (identity) to the other object
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeExpressionProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeExpressionProxy.java
new file mode 100644
index 0000000..2726d05
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeExpressionProxy.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 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: IBeanTypeExpressionProxy.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.core;
+
+
+/**
+ * An internal interface for the registries to create the appropriate beantype expression proxy.
+ * Not to be implemented or referenced by customers.
+ * @since 1.1.0
+ */
+public interface IBeanTypeExpressionProxy extends IProxyBeanType {
+
+ /**
+ * Allow the expression to set the type name.
+ * @param typeName
+ *
+ * @since 1.1.0
+ */
+ public void setTypeName(String typeName);
+}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeProxy.java
index 4617cf1..596b688 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IBeanTypeProxy.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: IBeanTypeProxy.java,v $
- * $Revision: 1.6 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.7 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
@@ -21,7 +21,7 @@
*
* @author: Joe Winchester
*/
-public interface IBeanTypeProxy extends IBeanProxy {
+public interface IBeanTypeProxy extends IBeanProxy, IProxyBeanType {
/**
* Find the most compatible constructor (out of the declared constructors). This means it will
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallback.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallback.java
index 47a6ae8..c95e775 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallback.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallback.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.core;
/*
* $RCSfile: ICallback.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:53:45 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
import java.io.InputStream;
@@ -33,13 +33,13 @@
* It will be called whenever the callback
* occurred. It will be on its own thread.
* A particular thread cannot be requested.
- *
+ * <p>
* The implementation MUST return. This is
* because the callback will not be completed
* until it is returned, and the process will
* not continue on the remote vm until it is
* returned.
- *
+ * <p>
* The value returned must either be an
* IBeanProxy or IBeanProxy[]. It is typed
* to Object to allow either one, but it
@@ -60,20 +60,20 @@
* It will be called whenever the callback
* occurred. It will be on its own thread.
* A particular thread cannot be requested.
- *
+ * <p>
* The parms will be an array of IBeanProxys,
* or an entry could be another array of IBeanProxys,
* or null if null was sent to callBackWithParms.
* The final component of any entry will be an
* IBeanProxy. It is up to the developers to
* agree on the format of the parms.
- *
+ * <p>
* The implementation MUST return. This is
* because the callback will not be completed
* until it is returned, and the process will
* not continue on the remote vm until it is
* returned.
- *
+ * <p>
* The value returned must either be an
* IBeanProxy or IBeanProxy[]. It is typed
* to Object to allow either one, but it
@@ -95,20 +95,20 @@
* It will be called whenever the callback
* occurred. It will be on its own thread.
* A particular thread cannot be requested.
- *
+ * <p>
* The parm will be an object. This occurs
* if remote vm just wanted to send some objects.
* They will not be proxies. It is recommended
* that this be used only for small items. For
* anything large, the callbackStream should be
* used instead.
- *
+ * <p>
* The implementation MUST return. This is
* because the callback will not be completed
* until it is returned, and the process will
* not continue on the remote vm until it is
* returned.
- *
+ * <p>
* The value returned must either be an
* IBeanProxy or IBeanProxy[]. It is typed
* to Object to allow either one, but it
@@ -130,13 +130,13 @@
* It will be called whenever the callback stream
* occurred. It will be on its own thread.
* A particular thread cannot be requested.
- *
+ * <p>
* The callback should continue to read from the InputStream
* until it returns -1 indicating no more data. The stream can
* be closed. In that case the next time the remote vm wants to
* send data it will first check that the stream has not been closed.
* If it has, it will raise an exception on that side.
- *
+ * <p>
* The implementation MUST return. This is
* because the callback will not be completed
* until it is returned, and the process will
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallbackRegistry.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallbackRegistry.java
index d9ede51..2b2b16d 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallbackRegistry.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ICallbackRegistry.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: ICallbackRegistry.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
/**
@@ -50,6 +50,18 @@
public void registerCallback(IBeanProxy callbackProxy, ICallback cb);
/**
+ * Same as {@link ICallbackRegistry#registerCallback(IBeanProxy, ICallback) registerCallback} except that
+ * it is deferred off into an expression.
+ *
+ * @param callbackProxy
+ * @param cb
+ * @param expression
+ *
+ * @since 1.1.0
+ */
+ public void registerCallback(IProxy callbackProxy, ICallback cb, IExpression expression);
+
+ /**
* Deregister the callback proxy. This will remove it from the
* registry and release the callback.
*
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IConstructorProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IConstructorProxy.java
index 9fbc11e..c7bc36a 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IConstructorProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IConstructorProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.core;
/*
* $RCSfile: IConstructorProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -37,4 +37,6 @@
IBeanProxy newInstanceCatchThrowableExceptions();
IBeanProxy newInstanceCatchThrowableExceptions(IBeanProxy[] creationArguments);
+IBeanTypeProxy[] getParameterTypes();
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IDimensionBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IDimensionBeanProxy.java
similarity index 81%
rename from plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IDimensionBeanProxy.java
rename to plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IDimensionBeanProxy.java
index c119743..56c1264 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IDimensionBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IDimensionBeanProxy.java
@@ -1,4 +1,4 @@
-package org.eclipse.jem.internal.proxy.awt;
+package org.eclipse.jem.internal.proxy.core;
/*******************************************************************************
* Copyright (c) 2001, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
@@ -11,14 +11,16 @@
*******************************************************************************/
/*
* $RCSfile: IDimensionBeanProxy.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:47 $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
*/
-import org.eclipse.jem.internal.proxy.core.IBeanProxy;
/**
* Interface to a Dimension bean proxy.
+ * <p>
+ * These are common for different windowing systems, e.g. AWT and SWT. So this here
+ * is common interface for them.
* Creation date: (4/7/00 3:46:39 PM)
* @author: Administrator
*/
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IExpression.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IExpression.java
index 97abdfb..bff0663 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IExpression.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IExpression.java
@@ -10,11 +10,13 @@
*******************************************************************************/
/*
* $RCSfile: IExpression.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
+import org.eclipse.jem.internal.proxy.initParser.tree.*;
import org.eclipse.jem.internal.proxy.initParser.tree.IExpressionConstants;
+import org.eclipse.jem.internal.proxy.initParser.tree.NoExpressionValueException;
/**
* This is an expression. It will be evaluated on the other side. The difference between an
@@ -35,7 +37,7 @@
* we build the expression.
* <p>
* To use, you call the IStandardBeanProxyFactory's createExpression method. An IExpression is
- * returned. From there you will start creating the contents of the expression. Any then you will
+ * returned. From there you will start creating the contents of the expression. And then you will
* finally either getExpressionValue() to get the final value of the expression, or use
* invokeExpression() to just execute the expression(s). If you use getExpressionValue(), there can
* only be one root expression. If you use invokeExpression there can be more than one root
@@ -44,9 +46,6 @@
* Since sequence is so important, it will be tested and if anything is done out of order an
* IllegalStateException will be thrown.
* <p>
- * Also, it is up to the implementation, but it may start executing ahead of completion, and so you
- * may get a ThrowableProxy from any of the calls during build up.
- * <p>
* Each time an expression is created, one argument passed in will be <code>forExpression</code> flag.
* This is a set of constants used as a clue for what expression this expression is being created.
* This is for a sanity check on the state. For example, when creating the array expression for an
@@ -55,7 +54,12 @@
* Without this flag, it would be easy to accidently create the wrong expression at the wrong time.
* Once such an error occurs, this IExpression will no longer be valid. IllegalStateException will be thrown
* for any type of access.
- *
+ * <p>
+ * It is guarenteed that the entire stack of commands will be sent without stopping except for IllegalStateException
+ * due to out of order expressions.
+ * <p>
+ * <b>Note:</b> This call is not meant to be instantiated by customers. It is the interface into the expression processing.
+ *
* @see org.eclipse.jem.internal.proxy.core.IStandardBeanProxyFactory#createExpression()
* @see java.lang.IllegalStateException
* @since 1.0.0
@@ -63,6 +67,14 @@
public interface IExpression extends IExpressionConstants {
/**
+ * Return the registry this expression is working against.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public ProxyFactoryRegistry getRegistry();
+
+ /**
* Invoke the expression(s). If there is more than one root expression, it will invoke them
* in the order created. If the expression stack is not complete, then <code>IllegalStateException</code>
* will be thrown.
@@ -76,6 +88,27 @@
public void invokeExpression() throws ThrowableProxy, NoExpressionValueException, IllegalStateException;
/**
+ * Return whether the expression is valid. It would be invalid if any of the create... calls had thrown an
+ * exception or if the expression has already been evaluated (invoked or getExpressionValue()).
+ *
+ * @return <code>true</code> if expression is valid, <code>false</code> if there had been some error, or if the expression has already been evaluated.
+ *
+ * @since 1.1.0
+ */
+ public boolean isValid();
+
+ /**
+ * Close the expression. This needs to be called if for some reason {@link IExpression#invokeExpression()} or {@link IExpression#getExpressionValue()}
+ * were not called. It is not an error to always call this after these calls. It will not have any problems with the expression already
+ * being closed. invoke and getvalue automatically call close for you. If you don't call close in case of an error, the resources
+ * for the expression will not be freed up.
+ *
+ *
+ * @since 1.1.0
+ */
+ public void close();
+
+ /**
* Invoke the root expression and return the value of the expression. If the expression stack
* is not complete, or if there is more than one root expression, then <code>IllegalStateException</code>
* will be thrown.
@@ -93,20 +126,20 @@
/**
* Create an Array Access (e.g. x[3]).
* This must be followed by create expressions for:
- * <code>ARRAYACCESS_ARRAY</code>
- * indexCount times an: <code>ARRAYACCESS_INDEX</code>
+ * <pre>
+ * <code>ARRAYACCESS_ARRAY</code>
+ * <code>ARRAYACCESS_INDEX</code> an indexCount times.
+ * </pre>
* <p>
* So the array access must be followed by 1+indexCount expressions.
*
* @param forExpression This is for what expression this expression is being created.
* @param indexCount The number of index expressions that will be created.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createArrayAccess(int forExpression, int indexCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createArrayAccess(ForExpression forExpression, int indexCount) throws IllegalStateException;
/**
* Create an Array Creation (e.g. <code>new int[3]</code> or <code>new int[3][]</code> or <code>new int[] {3, 4}</code>).
@@ -119,20 +152,19 @@
* <code>new int []</code> will have a count of 0.
* <p>
* This must be followed by create expressions for:
- * dimensionExpressionCount times an: <code>ARRAYCREATION_DIMENSION</code>
- * or an createArrayInitializer if dimension count is 0.
+ * <pre>
+ * <code>ARRAYCREATION_DIMENSION</code> a dimensionExpressionCount times,
+ * or an <code>createArrayInitializer()</code> if dimension count is 0.
+ * </pre>
*
* @param forExpression
* @param type This is the type. It must be fully-qualified and if an inner class, it must have the "$" format. It must also include the correct number of <code>[]</code> at the end.
* @param dimensionExpressionCount
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
- * @throws IllegalArgumentException
*
* @since 1.0.0
*/
- public void createArrayCreation(int forExpression, String type, int dimensionExpressionCount) throws ThrowableProxy, IllegalStateException, IllegalArgumentException, NoExpressionValueException;
+ public void createArrayCreation(ForExpression forExpression, String type, int dimensionExpressionCount) throws IllegalStateException;
/**
* Create an Array Creation (e.g. <code>new int[3]</code> or <code>new int[3][]</code> or <code>new int[] {3, 4}</code>).
@@ -151,13 +183,11 @@
* @param forExpression
* @param type This is the type.
* @param dimensionExpressionCount
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createArrayCreation(int forExpression, IBeanTypeProxy type, int dimensionExpressionCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createArrayCreation(ForExpression forExpression, IProxyBeanType type, int dimensionExpressionCount) throws IllegalStateException;
/**
* Create an array initializer. (e.g. <code>{2,3}</code>).
@@ -170,13 +200,11 @@
* but it does count as one of the expressionCounts.
*
* @param expressionCount Number of expressions, may be 0.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createArrayInitializer(int expressionCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createArrayInitializer(int expressionCount) throws IllegalStateException;
/**
* Create a cast expression (e.g. <code>(short)10</code> or <code>(java.lang.String) "asd"</code>)
@@ -186,13 +214,11 @@
*
* @param forExpression
* @param type This is the type. It must be fully-qualified and if an inner class, it must have the "$" format.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createCastExpression(int forExpression, String type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createCastExpression(ForExpression forExpression, String type) throws IllegalStateException;
/**
* Create a cast expression (e.g. <code>(short)10</code> or <code>(java.lang.String) "asd"</code>)
@@ -202,13 +228,11 @@
*
* @param forExpression
* @param type This is the type.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createCastExpression(int forExpression, IBeanTypeProxy type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createCastExpression(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException;
/**
* Create a new class instance expression (e.g. <code>new java.lang.Integer(5)</code>)
@@ -219,13 +243,11 @@
* @param forExpression
* @param type This is the type. It must be fully-qualified and if an inner class, it must have the "$" format.
* @param argumentCount
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createClassInstanceCreation(int forExpression, String type, int argumentCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createClassInstanceCreation(ForExpression forExpression, String type, int argumentCount) throws IllegalStateException;
/**
* Create a new class instance expression (e.g. <code>new java.lang.Integer(5)</code>)
@@ -236,13 +258,11 @@
* @param forExpression
* @param type This is the type.
* @param argumentCount
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createClassInstanceCreation(int forExpression, IBeanTypeProxy type, int argumentCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createClassInstanceCreation(ForExpression forExpression, IProxyBeanType type, int argumentCount) throws IllegalStateException;
/**
* Create a conditional expression (e.g. <code>x != 3 ? 4 : 5</code>)
@@ -253,13 +273,11 @@
* <code>CONDITIONAL_FALSE</code>
*
* @param forExpression
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createConditionalExpression(int forExpression) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createConditionalExpression(ForExpression forExpression) throws IllegalStateException;
/**
* Create a field access (e.g. <code>java.awt.Color.red</code>)
@@ -273,15 +291,53 @@
*
* @param forExpression
* @param fieldName The name of the field.
- * @param hasReceiver Has a receiver flag. Currently this must always be true.
- * @throws ThrowableProxy
+ * @param hasReceiver Has a receiver flag. Currently this must always be true. This is because can't tell what class to look into for the field without a receiver.
+ * @throws IllegalArgumentException
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @see IExpression#createTypeReceiver(String)
* @since 1.0.0
*/
- public void createFieldAccess(int forExpression, String fieldName, boolean hasReceiver) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createFieldAccess(ForExpression forExpression, String fieldName, boolean hasReceiver) throws IllegalArgumentException, IllegalStateException;
+
+ /**
+ * Create a field access (e.g. <code>java.awt.Color.red</code>)
+ * <p>
+ * Note: At this time we require a receiver for non-static access. In the future it may be possible to not have one, but
+ * for that we need a <code>this</code> object to know who the receiver implicitly is.
+ * The receiver may be a "type receiver" if it is a type, e.g. <code>java.awt.Color</code>.
+ * <p>
+ * This must be followed by createExpressions for:
+ * <pre>
+ * <code>FIELD_RECEIVER</code> if hasReceiver is <code>true</code>
+ * </pre>
+ *
+ * @param forExpression
+ * @param fieldProxy The field proxy for the field.
+ * @param hasReceiver Has a receiver flag.
+ * @throws IllegalStateException
+ *
+ * @see IExpression#createTypeReceiver(String)
+ * @since 1.0.0
+ */
+ public void createFieldAccess(ForExpression forExpression, IProxyField fieldProxy, boolean hasReceiver) throws IllegalStateException;
+
+ /**
+ * Create an if/else stmt. Since this is a statment, there is no ForExpression. ROOT_EXPRESSION must be the next expression type.
+ * <p<
+ * This must be followed by createExpressions for:
+ * <pre>
+ * <code>IF_CONDITION</code> The if test, must return boolean.
+ * <code>IF_TRUE</code> The if condition is true clause. The clause may be an expression, or a block.
+ * <code>IF_ELSE</code> if hasElseClause is <code>true</code>. The else clause. The clause may be an expression, or a block.
+ * </pre>
+ *
+ * @param hasElseClause
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public void createIfElse(boolean hasElseClause) throws IllegalStateException;
/**
* Create an infix expression (e.g. <code>3 + 4</code> or <code>3 + 4 + 5</code>).
@@ -290,22 +346,22 @@
* the expression can be done in one expression than requiring several, one for each operator.
* If they are different operators, then different expressions will be required.
* <p>
+ * <pre>
* This must be followed by createExpressions for:
* <code>INFIX_LEFT</code>
* <code>INFIX_RIGHT</code>
* extendedOperandCount times an: <code>INFIX_EXTENDED</code>
+ * </pre>
*
* @param forExpression
- * @param operator The operator. The values come from IExpressionConstants, the infix constants.
+ * @param operator The operator.
* @param extendedOperandCount The number of extended operands. May be zero.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @see org.eclipse.jem.internal.proxy.common.IExpressionConstants#IN_AND
* @since 1.0.0
*/
- public void createInfixExpression(int forExpression, int operator, int extendedOperandCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createInfixExpression(ForExpression forExpression, InfixOperator operator, int extendedOperandCount) throws IllegalStateException;
/**
* Create an instanceof expression (e.g. <code>x instanceof java.lang.String</code>
@@ -314,13 +370,11 @@
* <code>INSTANCEOF_VALUE</code>
* @param forExpression
* @param type This is the type. It must be fully-qualified and if an inner class, it must have the "$" format.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createInstanceofExpression(int forExpression, String type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createInstanceofExpression(ForExpression forExpression, String type) throws IllegalStateException;
/**
* Create an instanceof expression (e.g. <code>x instanceof java.lang.String</code>
@@ -329,16 +383,17 @@
* <code>INSTANCEOF_VALUE</code>
* @param forExpression
* @param type This is the type.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createInstanceofExpression(int forExpression, IBeanTypeProxy type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createInstanceofExpression(ForExpression forExpression, IProxyBeanType type) throws IllegalStateException;
/**
- * Create a method invocation expression (e.g. <code>java.lang.String.valueOf(10)</code>)
+ * Create a method invocation expression (e.g. <code>java.lang.String.valueOf(10)</code>).
+ * When using a string the method invoked will be the one most compatible with the arguments sent.
+ * This allows overloading a method to occur when coming in from a parse tree, since the parse tree
+ * doesn't know the exact method to use.
* <p>
* Note: At this time we require a receiver. In the future it may be possible to not have one, but
* for that we need a <code>this</code> object to know who the receiver implicitly is.
@@ -352,196 +407,195 @@
* @param name The name of the method
* @param hasReceiver Has a receiver flag. Currently this must always be true.
* @param argumentCount Count of number of arguments. May be zero.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
+ * @throws IllegalArgumentException
*
* @see IExpression#createTypeReceiver(String)
* @since 1.0.0
*/
- public void createMethodInvocation(int forExpression, String name, boolean hasReceiver, int argumentCount) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
-
+ public void createMethodInvocation(ForExpression forExpression, String name, boolean hasReceiver, int argumentCount) throws IllegalStateException, IllegalArgumentException;
+
+ /**
+ * Create a method invocation expression (e.g. <code>java.lang.String.valueOf(10)</code>)
+ * <p>
+ * Note: At this time we require a receiver. In the future it may be possible to not have one, but
+ * for that we need a <code>this</code> object to know who the receiver implicitly is.
+ * The receiver may be a "type receiver" if it is a type, e.g. <code>java.awt.Color</code>.
+ * <p>
+ * This must be followed by createExpression for:
+ * <code>METHOD_RECEIVER</code>
+ * argumentCounts times expressions for: <code>METHOD_ARGUMENT</code>
+ *
+ * @param forExpression
+ * @param methodProxy The proxy of the method
+ * @param hasReceiver Has a receiver flag. Currently this must always be true.
+ * @param argumentCount Count of number of arguments. May be zero.
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ *
+ * @see IExpression#createTypeReceiver(String)
+ * @since 1.0.0
+ */
+ public void createMethodInvocation(ForExpression forExpression, IProxyMethod methodProxy, boolean hasReceiver, int argumentCount) throws IllegalStateException, IllegalArgumentException;
+
/**
* Create a prefix expression (e.g. <code>!flag</code> or <code>-(3+4)</code>).
* If you are just trying to create a signed numeric literal, just use the createPrimitiveLiteral passing in a
* negative value. You don't need to use prefix expression for that.
* <p>
+ * <pre>
* This must be followed by createExpressions for:
* <code>PREFIX_OPERAND</code>
+ * </pre>
* @param forExpression
* @param operator The operator. The values come from IExpressionConstants, the prefix constants.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @see org.eclipse.jem.internal.proxy.common.IExpressionConstants#PRE_PLUS
* @since 1.0.0
*/
- public void createPrefixExpression(int forExpression, int operator) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrefixExpression(ForExpression forExpression, PrefixOperator operator) throws IllegalStateException;
/**
* Create a reference to <code>null</code>.
*
* @param forExpression
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createNull(int forExpression) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createNull(ForExpression forExpression) throws IllegalStateException;
/**
- * Create a type literal (e.g. <code>java.lang.String.class</code>).\
+ * Create a type literal (e.g. <code>java.lang.String.class</code>). This is used when the type is being used as value itself, not
+ * as a receiver for a field or method or constructor or instanceof. Like as an argument to a method.
* <p>
- * Note: If you want a type literal to a IBeanTypeProxy, just use createProxyExpression and pass in the
- * IBeanTypeProxy.
+ * Note: If you want a type literal to be an IProxyBeanType, just use {@link IExpression#createProxyExpression(ForExpression, IProxy)} and pass in the
+ * IProxyBeanType.
*
* @param forExpression
* @param type This is the type. It must be fully-qualified and if an inner class, it must have the "$" format.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createTypeLiteral(int forExpression, String type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createTypeLiteral(ForExpression forExpression, String type) throws IllegalStateException;
/**
* Create a type receiver. This is where a type is used as the receiver of a field access or a method invocation.
- * (e.g. <code>java.lang.String.valueOf(10)</code>).
+ * (e.g. <code>java.lang.String.valueOf(10)</code>). For this the "java.lang.String" IBeanTypeProxy is the type receiver.
* <p>
* This is unusual in that there is no forExpression. It isn't needed because these are only valid
* in certain situations (method or field receiver) and if used anywhere else it is an error.
*
* @param type This is the type. It must be fully-qualified and if an inner class, it must have the "$" format.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createTypeReceiver(String type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createTypeReceiver(String type) throws IllegalStateException;
/**
* Create a type receiver. This is where a type is used as the receiver of a field access or a method invocation.
- * (e.g. <code>java.lang.String.valueOf(10)</code>).
+ * (e.g. <code>java.lang.String.valueOf(10)</code>). For this the "java.lang.String" IProxyBeanType is the type receiver.
* <p>
* This is unusual in that there is no forExpression. It isn't needed because these are only valid
* in certain situations (method or field receiver) and if used anywhere else it is an error.
*
* @param type This is the type proxy.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createTypeReceiver(IBeanTypeProxy type) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createTypeReceiver(IProxyBeanType type) throws IllegalStateException;
/**
* Create a boolean primitive literal (e.g. <code>true</code>).
*
* @param forExpression
* @param value The boolean value for the literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, boolean value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, boolean value) throws IllegalStateException;
/**
* Create a character literal (e.g. <code>'a'</code> or <code>'\n'</code>)
*
* @param forExpression
* @param value The character value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, char value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, char value) throws IllegalStateException;
/**
* Create a byte literal (e.g. <code>(byte)10</code>)
*
* @param forExpression
* @param value The byte value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, byte value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, byte value) throws IllegalStateException;
/**
* Create a double literal (e.g. <code>10d</code>)
*
* @param forExpression
* @param value The double value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, double value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, double value) throws IllegalStateException;
/**
* Create a float literal (e.g. <code>10f</code>)
*
* @param forExpression
* @param value The float value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, float value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, float value) throws IllegalStateException;
/**
* Create a int literal (e.g. <code>100000</code>)
*
* @param forExpression
* @param value The int value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, int value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, int value) throws IllegalStateException;
/**
* Create a long literal (e.g. <code>10l</code>)
*
* @param forExpression
* @param value The long value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, long value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, long value) throws IllegalStateException;
/**
* Create a short literal (e.g. <code>(short)10</code>)
*
* @param forExpression
* @param value The short value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createPrimitiveLiteral(int forExpression, short value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createPrimitiveLiteral(ForExpression forExpression, short value) throws IllegalStateException;
/**
* Create a string literal (e.g. <code>"asdf"</code>). The value is the actual string, with escapes already
@@ -549,24 +603,332 @@
*
* @param forExpression
* @param value The string value for this literal.
- * @throws ThrowableProxy
* @throws IllegalStateException
- * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public void createStringLiteral(int forExpression, String value) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createStringLiteral(ForExpression forExpression, String value) throws IllegalStateException;
/**
* Create an expression that has an existing bean proxy as its value.
*
* @param forExpression This is for what expression this expression is being created.
- * @param proxy The proxy that should be used as a value.
+ * @param proxy The proxy that should be used as a value, either a bean proxy or an expression proxy.
+ * @throws IllegalStateException
+ *
+ * @since 1.0.0
+ */
+ public void createProxyExpression(ForExpression forExpression, IProxy proxy) throws IllegalStateException;
+
+ /**
+ * Create an assignment expression between a VariableReference and an expression. The left operand must be a variable reference (e.g. FieldAccess or
+ * ArrayAccess). The right operand may be any expression that results in a value.
+ * <p>
+ * <pre>
+ * This must be followed by createExpressions for:
+ * <code>ASSIGNMENT_LEFT</code>
+ * <code>ASSIGNMENT_RIGHT</code>
+ * </pre>
+ * @param forExpression
* @throws ThrowableProxy
* @throws IllegalStateException
* @throws NoExpressionValueException
*
- * @since 1.0.0
+ * @since 1.1.0
*/
- public void createProxyExpression(int forExpression, IBeanProxy proxy) throws ThrowableProxy, IllegalStateException, NoExpressionValueException;
+ public void createAssignmentExpression(ForExpression forExpression) throws IllegalStateException;
+
+ /**
+ * Create an assignment expression (e.g. x = 3+4) where x will be assigned to the ExpressionProxy.
+ * It may be used later on as a value in {@link IExpression#createExpressionProxyExpression(int, ExpressionProxy)}.
+ * Or if callbacks were added, the callbacks would be called to return the true IBeanProxy value of the expression proxy when the complete
+ * IExpression has been evaluated. The value of the assignment expression (e.g. x) will be passed on into the next expression.
+ * <p>
+ * <pre>
+ * This must be followed by createExpressions for:
+ * <code>ASSIGNMENT_RIGHT</code>
+ * </pre>
+ * <p>
+ * <b>Note:</b> It is guarenteed as part of the contract that expression proxies will be notified through the listeners of the final state in the
+ * order the expression proxies were created.
+ * @param forExpression This is for what expression this expression is being created.
+ * @return a proxy to the expression value.
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProxy createProxyAssignmentExpression(ForExpression forExpression) throws IllegalStateException;
+
+ /**
+ * Create a reassignment expression. This is like the original proxy assignment except that instead of returning a new proxy, it
+ * reassigns the new value to the existing proxy. This cannot be used on IBeanTypeExpressionProxy's. That is because
+ * they are controlled by the registry and severe errors would occur if they were reassigned.
+ * <p>
+ * <pre>
+ * This must be followed by createExpressions for:
+ * <code>ASSIGNMENT_RIGHT</code>
+ * </pre>
+ * <p>
+ * <b>Note:</b> Since we are not creating a new proxy, the notification on the callbacks will be in the original order of proxies. This
+ * does not change the notification position of this proxy.
+ *
+ * @param forExpression
+ * @param proxy
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException if the expression proxy is for a BeanType instead of just a standard expression proxy.
+ *
+ * @since 1.1.0
+ */
+ public void createProxyReassignmentExpression(ForExpression forExpression, ExpressionProxy proxy) throws IllegalStateException, IllegalArgumentException;
+
+ /**
+ * A simple method invocation. This is a helper to make it easier for a simple method invoke. It uses only the
+ * method proxy (not a string to look it up), it uses a IBeanProxy receiver (not a complicated expression), and the
+ * arguments are a mixture of IBeanProxies and ExpressionProxies. Also it can be called only when the next
+ * expression must be a RootExpression.
+ *
+ * @param method methodproxy of the method
+ * @param receiver the receiver proxy or <code>null</code> if a static method
+ * @param arguments array of arguments, where each element can only be either <code>null</code> for a null argument, <code>IProxy</code>. The array can be <code>null</code> if no arguments.
+ * @param wantResult <code>true</code> if you want an ExpressionProxy back, otherwise it will return <code>null</code>. For performance reasons, only use <code>true</code> if you really need the expression proxy.
+ * @return expression proxy if "wantResult" was true, else <code>null</code>.
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProxy createSimpleMethodInvoke(IProxyMethod method, IProxy receiver, IProxy[] arguments, boolean wantResult) throws IllegalStateException;
+
+ /**
+ * A simple field access. This is a helper to make it easier for a simple field access. It uses only the
+ * field proxy (not a string to look it up), and the bean proxy that is the receiver. Also it can be called only when the next
+ * expression must be a RootExpression. It doesn't allow complicated field access, such as <code>fielda.fieldb.fieldc</code>.
+ * Since this is a field access, it will always return an ExpressionProxy. It doesn't make sense to have a simple field access
+ * that doesn't return one.
+ *
+ * @param field field proxy of the field.
+ * @param receiver the receiver proxy. It may be <code>null</code> for static fields.
+ * @return expression proxy to the result of the access.
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProxy createSimpleFieldAccess(IProxyField field, IProxy receiver) throws IllegalStateException;
+
+ /**
+ * A simple field set. This is a helper to make it easier for a simple field access. It uses only the
+ * field proxy (not a string to look it up), and the bean proxy that is the receiver. Also it can be called only when the next
+ * expression must be a RootExpression. It doesn't allow complicated field access setting, such as <code>fielda.fieldb.fieldc = 3</code>.
+ *
+ * @param field field proxy of the field.
+ * @param receiver the receiver proxy. It may be <code>null</code> if this is a static field.
+ * @param value the value proxy to set it to or <code>null</code> if set to null value.
+ * @param wantResult <code>true</code> if you want an ExpressionProxy back, otherwise it will return <code>null</code>. For performance reasons, only use <code>true</code> if you really need the expression proxy.
+ * @return expression proxy if "wantResult" was true, else <code>null</code>.
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProxy createSimpleFieldSet(IProxyField field, IProxy receiver, IProxy value, boolean wantResult) throws IllegalStateException;
+
+ /**
+ * Begin a block. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * <p>
+ * Eventually {@link Expression#createBlockEnd()} must be called. You should use this pattern:
+ * <pre><code>
+ * exp.createBeginBlock();
+ * try {
+ * exp.create something else.
+ * ...
+ * } finally {
+ * exp.createEndBlock();
+ * }
+ * </code></pre>
+ *
+ * @return blocknumber for the block just opened. Can be used in {@link Expression#createBlockBreak(int)}.
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public int createBlockBegin() throws IllegalStateException;
+
+ /**
+ * Does a break for the specified block number. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * @param blockNumber
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public void createBlockBreak(int blockNumber) throws IllegalStateException;
+
+ /**
+ * End a block. It will always end the inner most block that currently is on the stack. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * @throws IllegalStateException
+ *
+ * @see Expression#createBlockBegin()
+ * @since 1.1.0
+ */
+ public void createBlockEnd() throws IllegalStateException;
+
+ /**
+ * Create a try/catch statement. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * There must be at least one catch or finally clause before try end or this is invalid.
+ * <p>
+ * This should be executed in the following way:
+ * <pre><code>
+ * exp.createTry();
+ * try {
+ * ... create other exceptions ...
+ * ... create catch/finally clauses as needed.
+ * } finally {
+ * if (exp.isValid())
+ * exp.createTryEnd();
+ * }
+ * </code></pre>
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public void createTry() throws IllegalStateException;
+
+
+ /**
+ * Create a catch clause for the inner most try statement. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * <p>
+ * Using this you can get just the exception as a proxy and/or execute some expressions as part of the catch clause.
+ * <p>
+ * This can be followed by RootExpressions, or another catch, or a finally, or a try end.
+ *
+ * @param exceptionType the type of the exception to catch on.
+ * @param wantExceptionReturned <code>true</code> if you want an expression proxy for the exception.
+ * @return the ExpressionProxy for the exception if <code>wantExceptionReturned</code> is <code>true</code>, <code>null</code> otherwise.
+ *
+ * @throws IllegalStateException
+ * @since 1.1.0
+ */
+ public ExpressionProxy createTryCatchClause(IProxyBeanType exceptionType, boolean wantExceptionReturned) throws IllegalStateException;;
+
+ /**
+ * Create a catch clause for the inner most try statement. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * <p>
+ * Using this you can get just the exception as a proxy and/or execute some expressions as part of the catch clause.
+ * <p>
+ * This can be followed by RootExpressions, or another catch, or a finally, or a try end.
+ *
+ * @param exceptionType the type of the exception to catch on.
+ * @param wantExceptionReturned <code>true</code> if you want an expression proxy for the exception.
+ * @return the ExpressionProxy for the exception if <code>wantExceptionReturned</code> is <code>true</code>, <code>null</code> otherwise.
+ *
+ * @throws IllegalStateException
+ * @since 1.1.0
+ */
+ public ExpressionProxy createTryCatchClause(String exceptionType, boolean wantExceptionReturned) throws IllegalStateException;;
+
+ /**
+ * Create a finally clause for the inner most try statement. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * There must be no more catch clauses for the try statement after this finally clause.
+ *
+ * @throws IllegalStateException
+ * @since 1.1.0
+ */
+ public void createTryFinallyClause() throws IllegalStateException;;
+
+ /**
+ * Create the end of the inner most try statement. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * There must be no more catch/finally clauses after this except if a new try statement is started.
+ *
+ * @throws IllegalStateException
+ * @since 1.1.0
+ */
+ public void createTryEnd() throws IllegalStateException;;
+
+ /**
+ * Create a throw. No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * The next expression is the exception to be thrown.
+ * <p>
+ * This must be followed by createExpression for:
+ * <code>THROW_OPERAND</code>
+ *
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public void createThrow() throws IllegalStateException;
+
+ /**
+ * Create a rethrow. This must be within a catch clause or there is an error.
+ * <p>
+ * This is a shortcut for:
+ * <pre><code>
+ * try {
+ * .. do something ..
+ * } catch (AnException e) {
+ * .. do something ..
+ * throw e;
+ * }
+ * </code></pre>
+ * @throws IllegalStateException
+ *
+ * @since 1.1.0
+ */
+ public void createRethrow() throws IllegalStateException;
+
+
+ /**
+ * Mark the expression stack so that if there are IllegalStateExceptions errors that would make the
+ * expression invalid, you can restore back to this mark point and the expression will now be valid
+ * again and at the state it was when mark was created. All marks must be ended, and at the same nesting
+ * level.
+ * <p>
+ * No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * <p>
+ * It must be used in conjunction with endMark. You must use <code>mark;try/finally{endMark;}</code> because
+ * the mark/endMark must match up.
+ * <pre><code>
+ * int mark = expression.mark();
+ * try {
+ * expression.create ...
+ * } catch (IllegalStateException e) {
+ * process the error.
+ * } finally {
+ * expression.endMark(mark); // After this, the expression will be valid again.
+ * }
+ * </code></pre>
+ * <p>
+ * However, the following code would be invalid nesting, and will throw an IllegalStateException on the createTryEnd. This is because
+ * we tried to end the Try statement within the mark. This is invalid because if we let it go through it would
+ * of popped the stack and when we got to the endMark the stack would of been popped past it and it could not
+ * be restored to the same state as it was at the time of the mark. The try would of already been ended.
+ * <pre><code>
+ * expression.createTry();
+ * int mark = expression.mark();
+ * try {
+ * expression.create ...
+ * expression.createTryEnd();
+ * } catch (IllegalStateException e) {
+ * process the error. The expression is now invalid.
+ * } finally {
+ * expression.endMark(mark); // After this, the expression will be valid again, if it had gone invalid.
+ * }
+ * </code></pre>
+ * <p>
+ * If not at RootExpression at time of mark() request, an IllegalStateException will be thrown.
+ * @return mark number, this number will be used in the cooresponding endMark.
+ * @throws IllegalStateException
+ *
+ * @see IExpression#endMark(int)
+ * @since 1.1.0
+ */
+ public int mark() throws IllegalStateException;
+
+ /**
+ * The end mark for a mark.
+ * <p>
+ * No need for a forExpression because it must currently be at ROOTEXPRESSION.
+ * @param markNumber
+ * @throws IllegalStateException
+ *
+ * @see IExpression#mark()
+ * @since 1.1.0
+ */
+ public void endMark(int markNumber) throws IllegalStateException;
}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IFieldProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IFieldProxy.java
index 48f0a88..d6e9967 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IFieldProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IFieldProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.core;
/*
* $RCSfile: IFieldProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -22,7 +22,7 @@
* Creation date: (1/17/00 12:17:52 PM)
* @author: Joe Winchester
*/
-public interface IFieldProxy extends IAccessibleObjectProxy {
+public interface IFieldProxy extends IAccessibleObjectProxy, IProxyField {
/**
* Return the type of the field.
*/
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxy.java
index c14a1a5..7fd5bb6 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxy.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: IMethodProxy.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
@@ -19,7 +19,7 @@
*
* @author: Joe Winchester
*/
-public interface IMethodProxy extends IAccessibleObjectProxy, IInvokable {
+public interface IMethodProxy extends IAccessibleObjectProxy, IInvokable, IProxyMethod {
/**
* Answer the class the method is defined in. Creation date: (12/3/99 11:37:12 AM)
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxyFactory.java
index 0e123c3..5d41541 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IMethodProxyFactory.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: IMethodProxyFactory.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
@@ -37,8 +37,32 @@
* @since 1.0.0
*/
IMethodProxy getMethodProxy(String className, String methodName, String[] parameterTypes);
+
+ /**
+ * Return an IProxyMethod for the specified name, arguments from the given class.
+ * @param expression
+ * @param className
+ * @param methodName
+ * @param parameterTypes
+ * @return
+ *
+ * @since 1.1.0
+ */
+ IProxyMethod getMethodProxy(IExpression expression, String className, String methodName, String[] parameterTypes);
/**
+ * Return an IProxyField for the specified name, arguments from the given class.
+ * @param expression
+ * @param className
+ * @param fieldName
+ * @return
+ *
+ * @since 1.1.0
+ */
+ IProxyField getFieldProxy(IExpression expression, String className, String fieldName);
+
+
+ /**
* Return an invokable for the specified name, arguments from the class. The method proxy is not retrieved. Instead the method will be looked up
* each time on the vm. Because of this these are suitable only for one-shot invokations. If it is to be invoked often, then a method proxy should
* be retrieved instead.
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IPointBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IPointBeanProxy.java
similarity index 80%
rename from plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IPointBeanProxy.java
rename to plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IPointBeanProxy.java
index 0344584..9b6c7c5 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IPointBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IPointBeanProxy.java
@@ -1,4 +1,4 @@
-package org.eclipse.jem.internal.proxy.awt;
+package org.eclipse.jem.internal.proxy.core;
/*******************************************************************************
* Copyright (c) 2001, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
@@ -11,13 +11,15 @@
*******************************************************************************/
/*
* $RCSfile: IPointBeanProxy.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:47 $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
*/
-import org.eclipse.jem.internal.proxy.core.IBeanProxy;
/**
* Interface to a Point bean proxy.
+ * <p>
+ * These are common for different windowing systems, e.g. AWT and SWT. So this here
+ * is common interface for them.
* Creation date: (4/7/00 3:46:39 PM)
* @author: Administrator
*/
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxy.java
new file mode 100644
index 0000000..be45338
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxy.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * $RCSfile: IProxy.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.core;
+
+
+/**
+ * A common interface for proxies. It is used by the expression processor to easily distinquish between
+ * a proxy and an Expression proxy.
+ * @since 1.1.0
+ */
+public interface IProxy {
+
+ /**
+ * Is this a bean proxy (including all of the subinterfaces of it, like IMethodProxy).
+ * @return <code>true</code> if this is a bean proxy.
+ *
+ * @since 1.1.0
+ */
+ public boolean isBeanProxy();
+
+ /**
+ * Is this an expression proxy.
+ * @return <code>true</code> if this is an expression proxy.
+ *
+ * @since 1.1.0
+ */
+ public boolean isExpressionProxy();
+}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyBeanType.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyBeanType.java
new file mode 100644
index 0000000..cecb136
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyBeanType.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 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: IProxyBeanType.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.core;
+
+
+/**
+ * This interface is for IBeanTypeProxy's and BeanTypeExpressionProxy's so that we can lazily
+ * get the beantype proxy and have the expression process it when needed.
+ *
+ * @since 1.1.0
+ */
+public interface IProxyBeanType extends IProxy {
+
+ /**
+ * Answer the name of the type we are proxying This is the fully qualified name. For arrays it will return the format: [Lclassname;
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public String getTypeName();
+
+ /**
+ * Get the IProxyMethod for the method from this beantype. It may be either a resolved method proxy (if already resolved) or
+ * it may be an ExpressionProxy if not yet resolved.
+ *
+ * @param expression
+ * @param methodName
+ * @param parameterTypes array of parameter types or <code>null</code> if no parameters.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameterTypes);
+
+ /**
+ * Get the IProxyMethod for the method from this beantype. It may be either a resolved method proxy (if already resolved) or
+ * it may be an ExpressionProxy if not yet resolved.
+ *
+ * @param expression
+ * @param methodName
+ * @param parameterTypes array of parameter types or <code>null</code> if no parameters.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes);
+
+ /**
+ * Get the IProxyyField for the field from this beantype. It may be either a resolved field proxy (if already resolved) or
+ * it may be an ExpressionProxy if not yet resolved.
+ *
+ * @param expression
+ * @param fieldName
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyField getFieldProxy(IExpression expression, String fieldName);
+}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyField.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyField.java
new file mode 100644
index 0000000..24ef953
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyField.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 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: IProxyField.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.core;
+
+
+/**
+ * This interface is for IFieldProxy's and FieldExpressionProxy's so that we can lazily
+ * get the field proxy and have the expression process it when needed.
+ * @since 1.1.0
+ */
+public interface IProxyField extends IProxy {
+
+}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyMethod.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyMethod.java
new file mode 100644
index 0000000..2268869
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IProxyMethod.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 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: IProxyMethod.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.core;
+
+
+/**
+ * This interface is for IMethodProxy's and MethodExpressionProxy's so that we can lazily
+ * get the method proxy and have the expression process it when needed.
+ *
+ * @since 1.1.0
+ */
+public interface IProxyMethod extends IProxy {
+
+}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IRectangleBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IRectangleBeanProxy.java
similarity index 85%
rename from plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IRectangleBeanProxy.java
rename to plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IRectangleBeanProxy.java
index 88cfd67..257ff06 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/awt/IRectangleBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IRectangleBeanProxy.java
@@ -1,4 +1,4 @@
-package org.eclipse.jem.internal.proxy.awt;
+package org.eclipse.jem.internal.proxy.core;
/*******************************************************************************
* Copyright (c) 2001, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
@@ -11,13 +11,15 @@
*******************************************************************************/
/*
* $RCSfile: IRectangleBeanProxy.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:47 $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
*/
-import org.eclipse.jem.internal.proxy.core.IBeanProxy;
/**
* Interface to a Rectangle bean proxy.
+ * <p>
+ * These are common for different windowing systems, e.g. AWT and SWT. So this here
+ * is common interface for them.
* Creation date: (4/7/00 3:46:39 PM)
* @author: Administrator
*/
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IStandardBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IStandardBeanTypeProxyFactory.java
index 377560a..c6d7ddb 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IStandardBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/IStandardBeanTypeProxyFactory.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: IStandardBeanTypeProxyFactory.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
import java.util.Set;
@@ -23,18 +23,36 @@
* @author: Richard Lee Kulp
*/
public interface IStandardBeanTypeProxyFactory extends IBeanProxyFactory {
+
/**
* Used by other registered bean type proxy factories to
* register their bean type proxies with the standard factory
* so that it will be cached there.
- *
- * The permanent flag indicates that beantype will never be released,
+ * <p><b>Note:</b> This is not meant to be called by customers. It is here for the usage
+ * of registry extensions.
+ * @param aBeanTypeProxy
+ * @param permanent indicates that beantype will never be released,
* not even if explicit request is made.
- * Creation date: (3/10/00 11:02:11 AM)
+ *
+ * @since 1.1.0
*/
void registerBeanTypeProxy(IBeanTypeProxy aBeanTypeProxy, boolean permanent);
/**
+ * Used by other registered bean type proxy factories to
+ * register their proxy bean type with the standard factory
+ * so that it will be cached there.
+ * <p><b>Note:</b> This is not meant to be called by customers. It is here for the usage
+ * of registry extensions.
+ * @param aBeanTypeProxy
+ * @param permanent indicates that beantype will never be released,
+ * not even if explicit request is made.
+ *
+ * @since 1.1.0
+ */
+void registerBeanTypeProxy(IProxyBeanType aBeanTypeProxy, boolean permanent);
+
+/**
* Return the beanType proxy for the given class name.
* It must be fully qualified. And for arrays it can handle
* either the jni type ([Ljava.lang.Object;) or the Java EMF Model
@@ -43,6 +61,17 @@
IBeanTypeProxy getBeanTypeProxy(String className);
/**
+ * Get the beantype proxy suitable for an expression.
+ *
+ * @param expression
+ * @param typeName
+ * @return
+ *
+ * @since 1.1.0
+ */
+IProxyBeanType getBeanTypeProxy(IExpression expression, String typeName);
+
+/**
* Return an Array type proxy for the given class name of
* the specified dimensions. This is a helper method. The
* same result can be gotton from getBeanTypeProxy.
@@ -67,6 +96,37 @@
IBeanTypeProxy getBeanTypeProxy(String componentClassName, int dimensions);
/**
+ * Return an Array type proxy for the given class name of
+ * the specified dimensions. This is a helper method. The
+ * same result can be gotton from getBeanTypeProxy.
+ * e.g.
+ * getBeanTypeProxy("java.lang.Object", 3)
+ * is the same as:
+ * getBeanTypeProxy("[[[Ljava.lang.Object;")
+ *
+ * They both result in a type of:
+ * Object [][][]
+ *
+ * or if using the JNI format (proxy format)
+ * getBeanTypeProxy("[Ljava.langObject;", 3)
+ * becomes
+ * Object [][][][]
+ *
+ * or if using the standard java format (as in actual code)
+ * getBeanTypeProxy("java.langObject[];", 3)
+ * becomes
+ * Object [][][][]
+ *
+ * @param expression
+ * @param componentClassName
+ * @param dimensions
+ * @return
+ *
+ * @since 1.1.0
+ */
+IProxyBeanType getBeanTypeProxy(IExpression expression, String componentClassName, int dimensions);
+
+/**
* Test if a specific bean type has been registered. Don't access and create
* if it isn't currently registered.
*/
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/JavaStandardBeanProxyConstants.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/JavaStandardBeanProxyConstants.java
index bb473b6..fb7b400 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/JavaStandardBeanProxyConstants.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/JavaStandardBeanProxyConstants.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: JavaStandardBeanProxyConstants.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -36,7 +36,7 @@
* @author: Administrator
*/
public final class JavaStandardBeanProxyConstants {
- public static final String REGISTRY_KEY = "STANDARDPROXYCONSTANTS:"; //$NON-NLS-1$
+ public static final Object REGISTRY_KEY = new Object();
final IBeanTypeProxy fCollectionType;
final IBeanTypeProxy fListType;
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ListenerList.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ListenerList.java
index 2d887a0..5511b35 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ListenerList.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ListenerList.java
@@ -10,13 +10,13 @@
*******************************************************************************/
/*
* $RCSfile: ListenerList.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
/**
* This class is used to maintain a list of listeners, and
- * is used in the implementations of several classes within JFace
+ * is used in the implementations of several classes within jem
* which allow you to register listeners of various kinds.
* It is a fairly lightweight object, occupying minimal space when
* no listeners are registered.
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/MapJNITypes.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/MapJNITypes.java
index 2d704a7..e1be81d 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/MapJNITypes.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/MapJNITypes.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: MapJNITypes.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
@@ -56,4 +56,17 @@
public static boolean isFormalTypePrimitive(String formalType) {
return MapTypes.MAP_TYPENAME_TO_SHORTSIG.get(formalType) != null;
}
+
+ /**
+ * Convert the formal type name, with the given number of dimensions,
+ * to an array JNI type.
+ * @param finalComponent final component name, should not be an array type.
+ * @param dimensions number of dimensions for the array.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static String getJNITypeName(String finalComponent, int dimensions) {
+ return MapTypes.getJNITypeName(finalComponent, dimensions);
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java
index 688cf72..df36db4 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyLaunchSupport.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: ProxyLaunchSupport.java,v $
- * $Revision: 1.21 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.22 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.core;
@@ -54,6 +54,15 @@
// If the property is trully not set, then there is no default and there are no configurations for it.
public static final String NOT_SET = "...not..set.."; //$NON-NLS-1$
+ public static final String EXPRESSION_TRACING = "/debug/traceexpressions"; // Trace IExpressions.
+
+ /**
+ * Timer threshold for indicating any expressions that took longer than this.
+ * If not set, then threshold will default to 100ms.
+ * It will only be used if traceexpressions is true.
+ */
+ public static final String EXPRESSION_TRACEING_TIMER_THRESHOLD = "/debug/traceexpressionstimethreshold";
+
/*
* Registry of launch key to LaunchInfo classes.
*/
@@ -619,6 +628,7 @@
*/
public static String ATTR_PRIVATE;
private static IUIRunner UI_RUNNER = null;
+
static {
ATTR_PRIVATE = null;
try {
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ThrowableProxy.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ThrowableProxy.java
index 5bb3d8f..38af2fa 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ThrowableProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ThrowableProxy.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: ThrowableProxy.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:53:46 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -29,6 +29,23 @@
super();
}
+ /**
+ * @param message
+ * @param cause
+ *
+ * @since 1.1.0
+ */
+ protected ThrowableProxy(String message, Throwable cause) {
+ super(message, cause);
+ }
+ /**
+ * @param cause
+ *
+ * @since 1.1.0
+ */
+ protected ThrowableProxy(Throwable cause) {
+ super(cause);
+ }
/**
* Constructs an <code>Exception</code> with the specified detail message.
*
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/messages.properties b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/messages.properties
index fb3e9f4..df25b76 100644
--- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/messages.properties
+++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/messages.properties
@@ -10,7 +10,7 @@
###############################################################################
#
# $Source: /cvsroot/webtools/jeetools.move/webtools.javaee.git/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/messages.properties,v $
-# $Revision: 1.7 $ $Date: 2005/02/15 22:53:46 $
+# $Revision: 1.8 $ $Date: 2005/05/11 19:01:12 $
#
@@ -38,9 +38,10 @@
ProxyWaitForBuild = Waiting for build to complete
Expression.InInvalidStateDueTo_EXC_ = IWAV0162E Expression is in invalid state due to "{0}"
Expression.InInvalidState_EXC_ = IWAV0163E Expression is in invalid state
-Expression.TypeSentInInvalidOrder_EXC_ = IWAV0164E Expression type sent in invalid order
+Expression.TypeSentInInvalidOrder_EXC_ = IWAV0164E Expression type sent in invalid order, received: {0}, expected {1}.
Expression.ArrayTypeNotAnArray_EXC_ = IWAV0165E ArrayType "{0}" is not an array.
-Expression.CannotHandleNoReceiveOnFieldAccess_EXC_ = IWAV0166E Currently cannot handle no receiver on field access.
-Expression.MethodsNeedReceiver_EXC_ = IWAV0167E Currently methods need receiver ({0})
+Expression.CannotHandleNoReceiveOnFieldAccess_EXC_ = IWAV0166E Access by field name ({0}) (not by proxy) requires a receiver.
+Expression.MethodsNeedReceiver_EXC_ = IWAV0167E Access by method name ({0}) (not by proxy) requires a receiver.
+Expression.InvalidMarkNesting = IWAV0168E Improper nesting of mark statements in Expression. Tried to pop or endMark to before current mark. Tried to go past Mark# {0}.
ProxyPlugin.CleanupDefaultProxyLaunchConfigurations = Clean up default proxy launch configurations.
ProxyLaunchSupport.RegistryCouldNotStartForSomeReason_WARN_ = IWAV0168W Registry could not be started for some reason.
diff --git a/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/ICallbackHandler.java b/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/ICallbackHandler.java
index 31dbc27..8a449ba 100644
--- a/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/ICallbackHandler.java
+++ b/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/ICallbackHandler.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.common;
/*
* $RCSfile: ICallbackHandler.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:54:34 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
/**
@@ -30,9 +30,9 @@
* client. Also you don't want to send big objects. It must
* be constants that don't need to be sent back for any reason
* since their identity will be lost in the transfer.
- *
+ * <p>
* This should be used if there are no parms (i.e. it is null).
- *
+ * <p>
* To send big objects, use the callback stream.
*
* @param callbackID
@@ -48,32 +48,43 @@
/**
* Callback to registered client.
- *
- * callbackID - The id of the callback. This will be given
- * to the callback when it is created, and it must pass
- * on to the handler. That way it is know which callback
- * to call on the client.
- * msgID - The id of the message for the callback. This is an
- * agreed upon id of the developers of the callback on both
- * sides.
- * parms - Null if no parms, or an array of objects to send to the client vm. They
+ * <p>
+ * The parms can be <code>null</code> if no parms, or it is an array of parms.
+ * The parms
* will be turned into proxies on the client vm. So the callback
* will recieve an array of proxies to the values in the parms.
* If any of the entries in the array is itself an array, a
* proxy to the array will be created and sent. The array itself
* will not be sent.
- *
+ * <p>
* If an array entry should go across as an array of proxies and
* not as one proxy to an array, then the entry needs to be an
- * instance of ICallbackHandler.TransmitableArray. This will flag
+ * instance of {@link ICallbackHandler.TransmitableArray transmitableArray}. This will flag
* that it should transmit the entire entry as proxies. This should
* be used sparingly, only if there isn't much data in the array and
* all of the array would be used on the client. That way transmitting
* the entire array will be faster than accessing individual components.
+ *
+ * @param callbackID The id of the callback. This will be given
+ * to the callback when it is created, and it must pass
+ * on to the handler. That way it is know which callback
+ * to call on the client.
+ * @param msgID The id of the message for the callback. This is an
+ * agreed upon id of the developers of the callback on both
+ * sides.
+ * @param parms Null if no parms, or an array of objects to send to the client vm. See the comments
+ * above for a complete description of the parameter.
*
+ * @see ICallbackHandler.TransmitableArray
*/
public Object callbackWithParms(int callbackID, int msgID, Object[] parms) throws CommandException;
+ /**
+ * Array wrapper that turns an array for parameters into a transmittable array.
+ *
+ * @see ICallbackHandler#callbackWithParms(int, int, Object[])
+ * @since 1.1.0
+ */
public static class TransmitableArray {
protected final Object[] fArray;
public TransmitableArray(Object[] array) {
diff --git a/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MapTypes.java b/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MapTypes.java
index 54951a8..b59e9d7 100644
--- a/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MapTypes.java
+++ b/plugins/org.eclipse.jem.proxy/proxyCommon/org/eclipse/jem/internal/proxy/common/MapTypes.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: MapTypes.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:54:34 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.common;
@@ -129,4 +129,31 @@
// If got here then just a name as is.
return jniName;
}
+
+ /**
+ * Convert the formal type name, with the given number of dimensions,
+ * to an array JNI type.
+ * @param finalComponent final component name, should not be an array type.
+ * @param dimensions number of dimensions for the array.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public static String getJNITypeName(String finalComponent, int dimensions) {
+ StringBuffer jni = new StringBuffer(finalComponent.length()+dimensions+2);
+ while (dimensions-- > 0) {
+ jni.append('[');
+ }
+
+ String shortSig = (String) MapTypes.MAP_TYPENAME_TO_SHORTSIG.get(finalComponent);
+ if (shortSig == null) {
+ jni.append('L');
+ jni.append(finalComponent);
+ jni.append(';');
+ } else {
+ jni.append(shortSig);
+ }
+
+ return jni.toString();
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/BeanProxyValueSender.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/BeanProxyValueSender.java
index 8aabf89..2631d13 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/BeanProxyValueSender.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/BeanProxyValueSender.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: BeanProxyValueSender.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -28,8 +28,8 @@
* @since 1.1.0
*/
public class BeanProxyValueSender implements Commands.ValueSender {
- private int index = 0;
- private Object[] array;
+ protected int index = 0;
+ protected Object[] array;
private Exception exception;
private final REMStandardBeanProxyFactory factory;
@@ -64,7 +64,7 @@
index = 0;
}
- public Object getArray() {
+ public Object[] getArray() {
return array;
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMBeanTypeProxyFactory.java
index cecf8c6..b81805d 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMBeanTypeProxyFactory.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: IREMBeanTypeProxyFactory.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -41,6 +41,28 @@
public IREMBeanTypeProxy getExtensionBeanTypeProxy(String typeName);
/**
+ * Return a bean type proxy for the class name.
+ * Return null if the extension factory doesn't handle this class.
+ * Don't register any proxies returned, they will automatically be registered.
+ * This should only return bean type proxies where the factory can determine
+ * everything it needs, such as supertype and classID.
+ * NOTE: This is implemented for the usage of the
+ * standard BeanType proxy factory. It should
+ * NOT be called by anyone else. They should
+ * go through the IStandardBeanTypeFactory
+ * instead. The standard bean type factory
+ * will call this method on the appropriate
+ * extension when it needs to.
+
+ * @param typeName
+ * @param expression
+ * @return
+ *
+ * @since 1.1.0
+ */
+public IProxyBeanType getExtensionBeanTypeProxy(String typeName, IExpression expression);
+
+/**
* Return a bean type proxy for the class id and class name.
* Return null if the extension factory doesn't handle this class.
* Don't register any proxies returned, they will automatically be registered.
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMConnection.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMConnection.java
index ce5528d..3dea82f 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMConnection.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMConnection.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: IREMConnection.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -93,13 +93,14 @@
/**
* Read array values as BeanProxies into valueSender.
- *
* @param returnValue
* @param valueSender
+ * @param allowFlag <code>true</code> to allow FLAG values, <code>false</code> if not allow flag values.
+ *
* @throws CommandException
*
* @since 1.1.0
*/
- public void readProxyArrayValues(Commands.ValueObject returnValue, Commands.ValueSender valueSender) throws CommandException;
+ public void readProxyArrayValues(Commands.ValueObject returnValue, Commands.ValueSender valueSender, boolean allowFlag) throws CommandException;
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMExpressionConnection.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMExpressionConnection.java
index 5051142..b38fae6 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMExpressionConnection.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/IREMExpressionConnection.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: IREMExpressionConnection.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -35,7 +35,7 @@
/**
* Start expression processing.
- * @param expressionID TODO
+ * @param expressionID
*
* @throws IOException
*
@@ -46,7 +46,7 @@
/**
* Push an expression command. This is the common portion of the
* subcommand. The actual data of the command will be separately done.
- * @param expressionID TODO
+ * @param expressionID
* @param subcommand The subcommand being sent. From IInternalExpressionConstants.
*
* @throws IOException
@@ -106,38 +106,55 @@
public void pushBoolean(boolean aBool) throws IOException;
/**
- * Pull the return value and put into the parameter value object. If an error
- * occurs, command exception is thrown. The value codes are either <code>ExpressionNoExpressionValueException</code> or
- * <code>ThrowableSent</code>
- * @param expressionID TODO
- * @param returnValue
+ * Get the final value. It must be called after processing the proxy id resolutions even for sync (so that we can get
+ * any thrown errors).
*
+ * @param result
* @throws CommandException
*
- * @since 1.0.0
+ * @since 1.1.0
*/
- public void pullValue(int expressionID, Commands.ValueObject returnValue) throws CommandException;
+ public void getFinalValue(Commands.ValueObject result) throws CommandException;
/**
- * Send the sync command and put the return value into the parameter value object. If an error
- * occurs, command exception is thrown. The value codes are either <code>ExpressionNoExpressionValueException</code> or
- * <code>ThrowableSent</code>
- * @param expressionID TODO
- * @param returnValue
+ * Send the pull value command, with the proxyids of intereset. If an error
+ * occurs, command exception is thrown.
+ * <p>
+ * After the pull value call, if no errors, the proxyids must be read, and then getFinalValue call must be sent.
+ * @param expressionID
+ * @param proxyids expression proxyids that request feedback or <code>null</code> if no proxy ids.
+ * @param sender sender to use to process the returned proxy ids, or <code>null</code> if expecting no proxy resolutions.
*
* @throws CommandException
*
* @since 1.0.0
*/
- public void sync(int expressionID, Commands.ValueObject returnValue) throws CommandException;
+ public void pullValue(int expressionID, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException;
+
+ /**
+ * Send the sync command, with the proxyids of intereset. If an error
+ * occurs, command exception is thrown.
+ * <p>
+ * After the sync call, if no errors, the returned proxyids must be processed and then the final endValue call must be sent.
+ *
+ * @param expressionID
+ * @param proxyids expression proxyids that request feedback or <code>null</code> if no proxy ids.
+ * @param sender sender to use to process the proxy id resolutions, or <code>null</code> if expecting no proxy ids.
+ *
+ * @throws CommandException
+ *
+ * @since 1.0.0
+ */
+ public void sync(int expressionID, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException;
/**
* Stop expression processing.
- * @param expressionID TODO
+ * @param expressionID
*
* @throws IOException
*
* @since 1.0.0
*/
public void stopExpressionProcessing(int expressionID) throws IOException;
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/LocalProxyLaunchDelegate.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/LocalProxyLaunchDelegate.java
index 579ce5b..9878d68 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/LocalProxyLaunchDelegate.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/LocalProxyLaunchDelegate.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
- * $RCSfile: LocalProxyLaunchDelegate.java,v $ $Revision: 1.21 $ $Date: 2005/02/15 22:56:10 $
+ * $RCSfile: LocalProxyLaunchDelegate.java,v $ $Revision: 1.22 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -25,11 +25,13 @@
import java.util.logging.Level;
import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.*;
import org.eclipse.debug.core.model.*;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.launching.*;
+import org.eclipse.jem.internal.proxy.common.remote.ExpressionCommands;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.remote.awt.REMRegisterAWT;
import org.eclipse.jem.util.TimerTests;
@@ -185,6 +187,21 @@
extraArgs+=4; // Number of extra args added for debug mode (if number changes below, this must change).
if(useNoverify)
extraArgs++; // An extra arg added for '-noverify' flag (if number changes below, this must change).
+
+ boolean useExpressionTracing = "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyLaunchSupport.EXPRESSION_TRACING));
+ long expressionTracingThreshold = -1;
+ if (useExpressionTracing) {
+ extraArgs++;
+ String thresholdString = Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyLaunchSupport.EXPRESSION_TRACEING_TIMER_THRESHOLD);
+ if (thresholdString != null) {
+ try {
+ expressionTracingThreshold = Long.valueOf(thresholdString).longValue();
+ extraArgs++;
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+
List javaLibPaths = controller.getFinalJavaLibraryPath();
int existingLibpaths = -1;
if (!javaLibPaths.isEmpty()) {
@@ -211,6 +228,12 @@
if(useNoverify)
cvmArgs[cvmArgsCount++] = "-noverify"; //$NON-NLS-1$
+
+ if (useExpressionTracing) {
+ cvmArgs[cvmArgsCount++] = "-D"+ExpressionCommands.EXPRESSIONTRACE+"=true";
+ if (expressionTracingThreshold != -1)
+ cvmArgs[cvmArgsCount++] = "-D"+ExpressionCommands.EXPRESSIONTRACE_TIMER_THRESHOLD+'='+String.valueOf(expressionTracingThreshold);
+ }
// If in debug mode, we need to find a port for it to use.
int dport = -1;
@@ -292,34 +315,77 @@
final String traceName = name;
IStreamsProxy fStreamsProxy = process.getStreamsProxy();
+ /**
+ * StreamListener. Should not be created if ProxyPlugin logger is not logging the requested level.
+ *
+ * @since 1.1.0
+ */
class StreamListener implements IStreamListener {
String tracePrefix;
Level level;
+ Job printJob; // Job to try to gather printing together.
+ Logger logger;
+ StringBuffer gatheredText = new StringBuffer(100);
+ {
+ logger = ProxyPlugin.getPlugin().getLogger();
+ printJob = new Job("") {
- public StreamListener(String type, Level level) {
- tracePrefix = traceName + ':' + type + '>';
+ protected IStatus run(IProgressMonitor monitor) {
+ monitor.beginTask("Print remote vm trace output", 1);
+ while(true) {
+ String output = null;
+ synchronized (gatheredText) {
+ if (gatheredText.length() <= tracePrefix.length())
+ break; // We've reached the end, no more to print.
+ output = gatheredText.toString();
+ gatheredText.setLength(tracePrefix.length()); // Reset the length to the prefix.
+ }
+ logger.log(output, level);
+ }
+ monitor.done();
+ return Status.OK_STATUS;
+ }
+ };
+ printJob.setPriority(Job.SHORT);
+ printJob.setSystem(true);
+ }
+
+ public StreamListener(String type, Level level, Logger logger) {
+ tracePrefix = traceName + ':' + type + '>' + System.getProperty("line.separator");
+ gatheredText.append(tracePrefix);
this.level = level;
+ this.logger = logger;
}
public void streamAppended(String newText, IStreamMonitor monitor) {
- Logger logger = ProxyPlugin.getPlugin().getLogger();
- if (logger.isLoggingLevel(level))
- logger.log(tracePrefix + newText, level);
+ synchronized(gatheredText) {
+ gatheredText.append(newText);
+ }
+ printJob.schedule(100L); // Wait tenth of second to gather as much as can together.
}
};
- // Always listen to System.err output.
- IStreamMonitor monitor = fStreamsProxy.getErrorStreamMonitor();
- if (monitor != null)
- monitor.addListener(new StreamListener("err", Level.WARNING)); //$NON-NLS-1$
+ Logger logger = ProxyPlugin.getPlugin().getLogger();
+ if (logger.isLoggingLevel(Level.WARNING)) {
+ // Always listen to System.err output if we are at least logging warnings.
+ IStreamMonitor monitor = fStreamsProxy.getErrorStreamMonitor();
+ if (monitor != null)
+ monitor.addListener(new StreamListener("err", Level.WARNING, logger)); //$NON-NLS-1$
+ }
// If debug trace is requested, then attach trace listener for System.out
- if ("true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyRemoteUtil.DEBUG_VM_TRACEOUT))) { //$NON-NLS-1$
- // Want to trace the output of the remote vm's.
-
- monitor = fStreamsProxy.getOutputStreamMonitor();
- if (monitor != null)
- monitor.addListener(new StreamListener("out", Level.INFO)); //$NON-NLS-1$
+ // Expression tracing requires debug trace too because it prints to sysout. However, it requesting expressionTracing, change logging level to INFO,
+ // we want them to show if this true. It is confusing to also have to change logging level in .options file.
+ if (useExpressionTracing)
+ if (!logger.isLoggingLevel(Level.INFO))
+ logger.setLevel(Level.INFO);
+ if (useExpressionTracing || "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyRemoteUtil.DEBUG_VM_TRACEOUT))) { //$NON-NLS-1$
+ // Want to trace the output of the remote vm's. And we are logging at least level info.
+ if (logger.isLoggingLevel(Level.INFO)) {
+ IStreamMonitor monitor = fStreamsProxy.getOutputStreamMonitor();
+ if (monitor != null)
+ monitor.addListener(new StreamListener("out", Level.INFO, logger)); //$NON-NLS-1$
+ }
}
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/ProxyRemoteUtil.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/ProxyRemoteUtil.java
index d5477b0..47ce3ff 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/ProxyRemoteUtil.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/ProxyRemoteUtil.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: ProxyRemoteUtil.java,v $
- * $Revision: 1.9 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.10 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -27,8 +27,8 @@
public static final String DEBUG_VM = "/remote/debug/debugvm", // Bring up debugger on remote vm's. //$NON-NLS-1$
IO_CONSOLE = "/remote/debug/ioconsole", // IO Through console (system in and out) for asking questions. //$NON-NLS-1$
DEBUG_VM_TRACEOUT = "/remote/debug/vmtraceout", // Trace the output from the remote vm's. //$NON-NLS-1$
- NO_TIMEOUTS = "/remote/debug/notimeouts"; // No socket timeouts when talking to remote vm. Turn this on when doing callback testing. Not needed otherwise. //$NON-NLS-1$
-
+ NO_TIMEOUTS = "/remote/debug/notimeouts"; // No socket timeouts when talking to remote vm. Turn this on when doing callback testing. Not needed otherwise. //$NON-NLS-1$
+
private static REMRegistryController pluginRegistryController;
/**
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanProxy.java
index 8ce2273..3469485 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMAbstractBeanProxy.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -119,4 +119,16 @@
value.setObjectID(isValid() ? getID().intValue() : Commands.VOID); // No longer exists, so send over null.
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanTypeProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanTypeProxy.java
index 02dbc20..dd803ea 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanTypeProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMAbstractBeanTypeProxy.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: REMAbstractBeanTypeProxy.java,v $
- * $Revision: 1.11 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.12 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -301,6 +301,15 @@
public IFieldProxy getFieldProxy(String fieldName) {
return ((REMStandardBeanTypeProxyFactory) fRegistry.getBeanTypeProxyFactory()).proxyConstants.getFieldProxy(this,fieldName);
}
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String fieldName) {
+ REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
+ return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getFieldProxy(expression, this, fieldName);
+ }
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IBeanTypeProxy#getConstructors()
@@ -357,6 +366,24 @@
public IMethodProxy getMethodProxy(String methodName, String[] argumentClassNames) {
return ((REMStandardBeanTypeProxyFactory) fRegistry.getBeanTypeProxyFactory()).proxyConstants.getMethodProxy(this,methodName,argumentClassNames);
}
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameterTypes) {
+ REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
+ return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes) {
+ REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
+ return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
+ }
/*
* (non-Javadoc)
@@ -656,4 +683,16 @@
}
}
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMArrayBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMArrayBeanProxy.java
index 13967a9..2d5cc55 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMArrayBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMArrayBeanProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMArrayBeanProxy.java,v $
- * $Revision: 1.6 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.7 $ $Date: 2005/05/11 19:01:12 $
*/
import java.lang.reflect.Array;
@@ -234,7 +234,7 @@
// However it will become IBeanProxy[]. That is because if ID's
// they must be proxies over here.
BeanProxyValueSender valueSender = new BeanProxyValueSender((REMStandardBeanProxyFactory) fFactory.getBeanProxyFactory(), returnValue);
- connection.readProxyArrayValues(returnValue, valueSender);
+ connection.readProxyArrayValues(returnValue, valueSender, false);
Exception e = valueSender.getException();
if (e != null) {
if (e instanceof ThrowableProxy)
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackRegistry.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackRegistry.java
index 8ca5224..487b3b2 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackRegistry.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackRegistry.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMCallbackRegistry.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:12 $
*/
import java.net.Socket;
@@ -19,6 +19,7 @@
import org.eclipse.jem.internal.proxy.common.remote.Commands;
import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
/**
* This registry will handle callbacks.
@@ -30,9 +31,9 @@
final String fNamePostfix;
List fThreads = Collections.synchronizedList(new LinkedList()); // List of active callback threads.
- HashMap fIdToCallback = new HashMap(5); // ID to Callback map.
- HashSet fRegisteredCallbackProxies = new HashSet(5); // Hold onto registered proxies so they aren't released as long as call back is registered.
-
+ Map fIdToCallback = new HashMap(5); // ID to Callback map.
+ Map fCallbackProxyToId = new HashMap(5); // Callback to ID map. This will also hold onto the callback proxies so that they don't get GC'd while the callback is registered.
+
IREMMethodProxy fInitializeCallback;
IREMBeanProxy fRemoteServer;
@@ -109,37 +110,80 @@
fThreads.clear();
fIdToCallback.clear();
- fRegisteredCallbackProxies.clear();
+ fCallbackProxyToId.clear();
fInitializeCallback = null;
fRemoteServer = null;
}
-
public ICallback getRegisteredCallback(int id) {
synchronized(fIdToCallback) {
return (ICallback) fIdToCallback.get(new Integer(id));
}
}
- /**
- * The public interface for registering callbacks
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ICallbackRegistry#registerCallback(org.eclipse.jem.internal.proxy.core.IBeanProxy, org.eclipse.jem.internal.proxy.core.ICallback)
*/
public void registerCallback(IBeanProxy callbackProxy, ICallback cb) {
synchronized(fIdToCallback) {
fIdToCallback.put(((IREMBeanProxy) callbackProxy).getID(), cb);
- fRegisteredCallbackProxies.add(callbackProxy);
+ fCallbackProxyToId.put(callbackProxy, ((IREMBeanProxy) callbackProxy).getID());
fInitializeCallback.invokeCatchThrowableExceptions(callbackProxy, new IBeanProxy[] {fRemoteServer, fFactory.getBeanProxyFactory().createBeanProxyWith(((IREMBeanProxy) callbackProxy).getID().intValue())});
}
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ICallbackRegistry#registerCallback(org.eclipse.jem.internal.proxy.core.IProxy, org.eclipse.jem.internal.proxy.core.ICallback, org.eclipse.jem.internal.proxy.core.IExpression)
+ */
+ public void registerCallback(IProxy callbackProxy, final ICallback cb, IExpression expression) {
+ final Integer id;
+ if (callbackProxy.isBeanProxy()) {
+ id = ((IREMBeanProxy) callbackProxy).getID();
+ synchronized(fIdToCallback) {
+ fIdToCallback.put(id, cb);
+ fCallbackProxyToId.put(callbackProxy, id);
+ }
+ } else {
+ id = new Integer(callbackProxy.hashCode());
+ synchronized (fIdToCallback) {
+ fIdToCallback.put(id, cb); // This is so that it is registered in case callback is invoked from remote vm during expression processing.
+ }
+ ((ExpressionProxy) callbackProxy).addProxyListener(new ExpressionProxy.ProxyListener() {
+ public void proxyResolved(ProxyEvent event) {
+ synchronized(fIdToCallback) {
+ fCallbackProxyToId.put(event.getProxy(), id);
+ }
+ }
+
+ public void proxyNotResolved(ProxyEvent event) {
+ // Failed, so remove registration completely.
+ synchronized (fIdToCallback) {
+ fIdToCallback.remove(id);
+ }
+ }
+
+ public void proxyVoid(ProxyEvent event) {
+ // Failed, so remove registration completely.
+ synchronized (fIdToCallback) {
+ fIdToCallback.remove(id);
+ }
+ }
+
+ });
+ }
+ expression.createSimpleMethodInvoke(fInitializeCallback, callbackProxy, new IProxy[] {fRemoteServer, fFactory.getBeanProxyFactory().createBeanProxyWith(id.intValue())}, false);
+ }
+
/**
* The public interface for deregistering callbacks.
*/
public void deregisterCallback(IBeanProxy callbackProxy) {
synchronized(fIdToCallback) {
- fIdToCallback.remove(((IREMBeanProxy) callbackProxy).getID());
- fRegisteredCallbackProxies.remove(callbackProxy); // Release it.
+ Integer id = (Integer) fCallbackProxyToId.remove(callbackProxy);
+ fIdToCallback.remove(id);
}
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackThread.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackThread.java
index dedd874..cbe2a4b 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackThread.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMCallbackThread.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMCallbackThread.java,v $
- * $Revision: 1.12 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.13 $ $Date: 2005/05/11 19:01:12 $
*/
import java.io.*;
@@ -36,8 +36,30 @@
final REMStandardBeanTypeProxyFactory fTypeFactory;
final REMProxyFactoryRegistry registry;
protected boolean shuttingDown;
+ protected boolean inTransaction; // Is this thread currently participating in a transaction, (i.e. reading/writing), if so then we can't use it for another transaction.
+ /**
+ * Is this callback thread currently participating in a transaction (reading/writing). If so then it can't be used for an
+ * independent new transaction.
+ *
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public boolean inTransaction() {
+ return inTransaction;
+ }
+
+ /**
+ * Set whether this callback thread is in a transaction or not.
+ * @param inTransaction
+ *
+ * @since 1.1.0
+ */
+ public void setIntransaction(boolean inTransaction) {
+ this.inTransaction = inTransaction;
+ }
// Kludge: Bug in Linux 1.3.xxx of JVM. Closing a socket while the socket is being read/accept will not interrupt the
// wait. Need to timeout to the socket read/accept before the socket close will be noticed. This has been fixed
@@ -127,6 +149,7 @@
// The register callback handler will know how to handle the parm,
// it will know if it is an array of proxies, or an object of some kind.
fFactory.startTransaction(); // Start a transaction.
+ setIntransaction(true); // Also tell ourselves that we are in a transaction.
boolean isProxies = true;
try {
Commands.readValue(in, valueObject);
@@ -135,7 +158,7 @@
// However it will become IBeanProxy[]. That is because if ID's
// they must be proxies over here.
valueSender.initialize(valueObject);
- Commands.readArray(in, valueObject.anInt, valueSender, valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
if (valueSender.getException() != null) {
close(); // Something wrong, close the thread so next time we get a new one.
}
@@ -146,6 +169,7 @@
parm = valueObject.getAsObject();
}
} finally {
+ setIntransaction(false);
fFactory.stopTransaction();
}
// Now perform the callback.
@@ -178,33 +202,30 @@
}
public Commands.ValueObject nextValue() {
- if (index < array.length) {
- Object retParm = array[index++];
- if (retParm != null)
- if (retParm instanceof IREMBeanProxy)
- ((IREMBeanProxy) retParm).renderBean(worker);
- else if (retParm instanceof TransmitableArray) {
- // It is another array, create a new
- // retriever.
- worker.setArrayIDS(
- new Retriever(((TransmitableArray) retParm).array),
- ((TransmitableArray) retParm).array.length,
- ((TransmitableArray) retParm).componentTypeID);
- } else {
- // It's an object. Need to get bean
- // type so that we can send it.
- IREMBeanProxy type =
- (IREMBeanProxy) fTypeFactory.getBeanTypeProxy(retParm.getClass().getName());
- if (type == null)
- throw new IllegalArgumentException();
- int classID = type.getID().intValue();
- worker.setAsObject(retParm, classID);
- }
- else
- worker.set();
- return worker;
- } else
- return null;
+ Object retParm = array[index++];
+ if (retParm != null)
+ if (retParm instanceof IREMBeanProxy)
+ ((IREMBeanProxy) retParm).renderBean(worker);
+ else if (retParm instanceof TransmitableArray) {
+ // It is another array, create a new
+ // retriever.
+ worker.setArrayIDS(
+ new Retriever(((TransmitableArray) retParm).array),
+ ((TransmitableArray) retParm).array.length,
+ ((TransmitableArray) retParm).componentTypeID);
+ } else {
+ // It's an object. Need to get bean
+ // type so that we can send it.
+ IREMBeanProxy type =
+ (IREMBeanProxy) fTypeFactory.getBeanTypeProxy(retParm.getClass().getName());
+ if (type == null)
+ throw new IllegalArgumentException();
+ int classID = type.getID().intValue();
+ worker.setAsObject(retParm, classID);
+ }
+ else
+ worker.set();
+ return worker;
}
};
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConnection.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConnection.java
index a37880e..f0b8756 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConnection.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConnection.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMConnection.java,v $
- * $Revision: 1.15 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.16 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -32,6 +32,7 @@
* It uses the property "proxyvm.bufsize" to determine the buffer size to use. If not specified, it uses the system default
*/
public class REMConnection implements IREMConnection, IREMExpressionConnection {
+
public final static String INVOKE_STEP = "Invoke";
public final static String INVOKE_METHOD_STEP = "Invoke Method";
protected Socket fSocket = null;
@@ -291,26 +292,41 @@
ExpressionCommands.sendBoolean(out, aBool);
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.remote.IREMExpressionConnection#pullValue(org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
- */
- public void pullValue(int expressionID, ValueObject returnValue) throws CommandException {
- if (isConnected())
- ExpressionCommands.sendPullValueCommand(expressionID, out, in, returnValue);
- }
+
/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.remote.IREMExpressionConnection#sync(org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
+ * @see org.eclipse.jem.internal.proxy.remote.IREMExpressionConnection#getFinalValue(org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
*/
- public void sync(int expressionID, ValueObject returnValue) throws CommandException {
+ public void getFinalValue(ValueObject result) throws CommandException {
if (isConnected())
- ExpressionCommands.sendSyncCommand(expressionID, out, in, returnValue);
+ Commands.readBackValue(in, result, Commands.NO_TYPE_CHECK);
}
-
- public void readProxyArrayValues(Commands.ValueObject returnValue, Commands.ValueSender valueSender) throws CommandException {
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.remote.IREMExpressionConnection#pullValue(int, org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
+ */
+ public void pullValue(int expressionID, ValueObject proxyids, ValueSender sender) throws CommandException {
if (isConnected())
- Commands.readArray(in, returnValue.anInt, valueSender, returnValue);
+ ExpressionCommands.sendPullValueCommand(expressionID, out, in, proxyids, sender);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.remote.IREMExpressionConnection#sync(int, org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
+ */
+ public void sync(int expressionID, ValueObject proxyids, ValueSender sender) throws CommandException {
+ if (isConnected())
+ ExpressionCommands.sendSyncCommand(expressionID, out, in, proxyids, sender);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.remote.IREMConnection#readProxyArrayValues(org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject, org.eclipse.jem.internal.proxy.common.remote.Commands.ValueSender, boolean)
+ */
+ public void readProxyArrayValues(Commands.ValueObject returnValue, Commands.ValueSender valueSender, boolean allowFlag) throws CommandException {
+ if (isConnected())
+ Commands.readArray(in, returnValue.anInt, valueSender, returnValue, allowFlag);
}
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstantBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstantBeanProxy.java
index 3444a37..5a04a28 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstantBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstantBeanProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMConstantBeanProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -85,4 +85,16 @@
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstructorProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstructorProxy.java
index 492bc5b..be4a841 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstructorProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMConstructorProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMConstructorProxy.java,v $
- * $Revision: 1.6 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.7 $ $Date: 2005/05/11 19:01:12 $
*/
import org.eclipse.core.runtime.IStatus;
@@ -78,4 +78,32 @@
return null;
}
}
+
+ private IBeanTypeProxy[] fParameterTypes;
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IConstructorProxy#getParameterTypes()
+ */
+ public synchronized IBeanTypeProxy[] getParameterTypes() {
+ if (fParameterTypes == null) {
+ IArrayBeanProxy parmTypes = (IArrayBeanProxy) REMStandardBeanProxyConstants.getConstants(fFactory)
+ .getConstructorParameterTypesMessage().invokeCatchThrowableExceptions(this);
+ if (parmTypes == null)
+ fParameterTypes = new IBeanTypeProxy[0]; // There was some error, only way null is returned
+ else {
+ int len = parmTypes.getLength();
+ fParameterTypes = new IBeanTypeProxy[len];
+ for (int i = 0; i < len; i++)
+ try {
+ fParameterTypes[i] = (IBeanTypeProxy) parmTypes.get(i);
+ } catch (ThrowableProxy e) {
+ }
+ fFactory.releaseProxy(parmTypes); // Don't need the array on the server anymore.
+ }
+ }
+
+ return fParameterTypes;
+ }
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMExpression.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMExpression.java
index f1a19ab..3c137b5 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMExpression.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMExpression.java
@@ -10,17 +10,21 @@
*******************************************************************************/
/*
* $RCSfile: REMExpression.java,v $
- * $Revision: 1.7 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.8 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
-import java.io.IOException;
+import java.io.*;
+import java.util.*;
+import java.util.Iterator;
+import java.util.List;
import java.util.logging.Level;
import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.remote.*;
+import org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject;
import org.eclipse.jem.internal.proxy.core.*;
-import org.eclipse.jem.internal.proxy.initParser.tree.IInternalExpressionConstants;
+import org.eclipse.jem.internal.proxy.initParser.tree.*;
/**
* The Remote proxy version of Expression.
@@ -29,9 +33,52 @@
*/
public class REMExpression extends Expression {
- protected IREMExpressionConnection connection;
+ private IREMExpressionConnection connection;
+ private boolean closed; // Are we closed.
- protected Commands.ValueObject workerValue = new Commands.ValueObject(); // A worker object so that we don't need to keep creating one and throwing it away.
+ protected Commands.ValueObject workerValue; // A worker object so that we don't need to keep creating one and throwing it away.
+
+ protected Map beanTypeCache; // Use to cache pending BeanTypes. Used in conjunction with REMStandardBeanTypeFactory.
+ protected Map methodsCache; // Use to cache pending expression method proxies. Used in conjunction with REMProxyConsants.
+ protected Map fieldsCache; // Use to cache pending expression field proxies. Used in conjunction with REMProxyConsants.
+
+ /*
+ * This is very special list. It tries to eliminate unneeded traffic. For example a mark immediately followed by an endmark does
+ * not need to be sent. Many expressions can look like: mark, endmark, endtransaction. This is a do nothing and we don't want
+ * to create a connection to just send this. So this list is used to queue up these and remove them too when found as not needed.
+ *
+ * However, this is very tricky because all pushToProxy transactions that actually do something MUST call the processPending() method
+ * first to make sure any pending transactions are submitted. Because once a real type transaction, such as assignment occurs, any
+ * pending transaction is a valid transaction, and no longer a do-nothing transaction.
+ *
+ * Each transaction type uses a subclass of PendingTransaction to be an entry on the list.
+ *
+ * The pendings currently supported are:
+ * mark/endmark
+ * try/catch/endtry
+ * block/endblock
+ *
+ * See each individual transaction type to see how it is handled.
+ */
+ protected List pendingTransactions;
+
+ /**
+ * PendingTransaction entry.
+ *
+ * @since 1.1.0
+ */
+ protected abstract static class PendingTransaction {
+
+ /**
+ * The transaction is now being pushed. The implementation should
+ * actually do the push.
+ *
+ * @param remExpression The REMExpression for this transaction.
+ *
+ * @since 1.1.0
+ */
+ public abstract void pushTransaction(REMExpression remExpression);
+ }
/**
* @param registry
@@ -40,17 +87,65 @@
*/
public REMExpression(REMProxyFactoryRegistry registry) {
super(registry);
- connection = (IREMExpressionConnection) registry.getFreeConnection();
- try {
- connection.startExpressionProcessing(this.hashCode());
- } catch (IOException e) {
- connection.close();
- ProxyPlugin.getPlugin().getLogger().log(e);
- throwIllegalStateException(IO_EXCEPTION_MSG);
- }
}
/**
+ * Return the expression id for this REMExpression. This id is used on the remote vm to
+ * identify who the request is for.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected int getREMExpressionID() {
+ return this.hashCode();
+ }
+ /**
+ * Get the pending transactions list.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected List getPendingTransactions() {
+ if (pendingTransactions == null)
+ pendingTransactions = new ArrayList();
+ return pendingTransactions;
+ }
+
+ // Use this flag when debugging to test if errors are due to improper pending processing.
+ // If true they will be treated as if not pending and will be executed immediately.
+ private static final boolean EXECUTE_PENDING_IMMEDIATELY = false;
+ protected void addPendingTransaction(PendingTransaction pending) {
+ if (!EXECUTE_PENDING_IMMEDIATELY)
+ getPendingTransactions().add(pending);
+ else
+ pending.pushTransaction(this);
+ }
+
+ /**
+ * @return Returns the connection.
+ *
+ * @since 1.1.0
+ */
+ protected IREMExpressionConnection getConnection() {
+ if (connection == null) {
+ connection = (IREMExpressionConnection) getREMRegistry().getFreeConnection();
+ // This will actually not be stopped until closeproxy. There could be a slight problem if the expression is never closed.
+ // But that shouldn't happen. This is to prevent any proxy that was released during the execution but was used by
+ // the expression from being released on the remote vm until after the expression is finished.
+ getREMBeanProxyFactory().startTransaction();
+ try {
+ connection.startExpressionProcessing(getREMExpressionID());
+ workerValue = new Commands.ValueObject();
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+ return connection;
+ }
+
+ /**
* General IOException occurred msg.
*/
protected static final String IO_EXCEPTION_MSG = ProxyRemoteMessages.getString("REMExpression.IOExceptionSeeLog_INFO_"); //$NON-NLS-1$
@@ -90,15 +185,76 @@
return (REMStandardBeanProxyFactory) beanProxyFactory;
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushToProxy(org.eclipse.jem.internal.proxy.core.IBeanProxy)
+ /**
+ * Process any pending transactions.
+ * <p>
+ * <b>Note: </b>It is required that all non-pending-participating transactions must
+ * call this method first to make sure pending transactions are sent. If this is
+ * not done, there will be errors in the expression.
+ *
+ *
+ * @since 1.1.0
*/
- protected void pushToProxy(IBeanProxy proxy) throws ThrowableProxy {
+ protected void processPendingTransactions() {
+ if (pendingTransactions != null && !pendingTransactions.isEmpty()) {
+ try {
+ for (int i = 0; i < pendingTransactions.size(); i++) {
+ ((PendingTransaction) pendingTransactions.get(i)).pushTransaction(this);
+ }
+ } finally {
+ pendingTransactions.clear();
+ }
+ }
+ }
+
+ /**
+ * Get the pending entry from top. If top is 1, then get top entry (i.e. last one added), 2 is next one.
+ * @param fromTop
+ * @return entry requested, or <code>null</code> if no such entry.
+ *
+ * @since 1.1.0
+ */
+ protected PendingTransaction getPendingEntryFromTop(int fromTop) {
+ if (pendingTransactions != null && pendingTransactions.size() >= fromTop) {
+ return (PendingTransaction) pendingTransactions.get(pendingTransactions.size()-fromTop);
+ } else
+ return null;
+ }
+
+ /**
+ * Pop up the top entry from the pending transactions queue.
+ * @param fromTop how many entries to pop from the pending transaction list.
+ *
+ *
+ * @since 1.1.0
+ */
+ protected void popPendingEntry(int fromTop) {
+ if (pendingTransactions != null)
+ if (pendingTransactions.size() > fromTop) {
+ while(fromTop-- >0)
+ pendingTransactions.remove(pendingTransactions.size()-1);
+ } else
+ pendingTransactions.clear();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushToProxy(org.eclipse.jem.internal.proxy.core.IProxy)
+ */
+ protected void pushToProxy(IProxy proxy) {
+ if (proxy == null || proxy.isBeanProxy())
+ pushToProxy((IBeanProxy) proxy);
+ else
+ pushToExpressionProxy((ExpressionProxy) proxy);
+ }
+
+ private void pushToProxy(IBeanProxy proxy) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push proxy command is:
// PushExpressionCommand(push to proxy) followed by:
// ValueObject containing the rendered proxy.
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.PUSH_TO_PROXY_EXPRESSION);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_TO_PROXY_EXPRESSION_VALUE);
if (proxy == null)
workerValue.set();
else
@@ -123,32 +279,130 @@
* @see org.eclipse.jem.internal.proxy.core.Expression#closeProxy()
*/
protected void closeProxy() {
- try {
+ if (connection != null && !closed) {
try {
- connection.stopExpressionProcessing(this.hashCode());
- } catch (IOException e) {
- connection.close();
- ProxyPlugin.getPlugin().getLogger().log(e, Level.INFO);
- // Not throwing an illegal state here because we don't care, other than logging and not
- // returning the connection to the registry that there was an error on close.
+ try {
+ if (connection.isConnected()) {
+ connection.stopExpressionProcessing(getREMExpressionID());
+ }
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e, Level.INFO);
+ // Not throwing an illegal state here because we don't care, other than logging and not
+ // returning the connection to the registry that there was an error on close.
+ } finally {
+ getREMBeanProxyFactory().stopTransaction(); // Resume proxy releases.
+ getREMRegistry().returnConnection(connection);
+ }
+ } finally {
+ closed = true;
}
- } finally {
- getREMRegistry().returnConnection(connection);
+ }
+ methodsCache = null;
+ fieldsCache = null;
+ beanTypeCache = null;
+ pendingTransactions = null;
+ }
+
+ private static final Object VOIDTYPE = new Object(); // A void type was sent in expression proxy resolution.
+ private static final Object NOTRESOLVED = new Object(); // A not resolved type was sent in expression proxy resolution.
+
+ /*
+ * Get the sender to use for pulling the expression proxy resolutions.
+ */
+ private BeanProxyValueSender getExpressionProxiesSender() {
+ return new BeanProxyValueSender(getREMBeanProxyFactory()) {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.remote.BeanProxyValueSender#sendValue(org.eclipse.jem.internal.proxy.common.remote.Commands.ValueObject)
+ */
+ public void sendValue(ValueObject value) {
+ if (value.getType() == Commands.FLAG) {
+ switch (value.anInt) {
+ case ExpressionCommands.EXPRESSIONPROXY_NOTRESOLVED:
+ array[index++] = NOTRESOLVED;
+ break;
+ case ExpressionCommands.EXPRESSIONPROXY_VOIDTYPE:
+ array[index++] = VOIDTYPE;
+ break;
+ default:
+ // Shouldn't happen.
+ break;
+ }
+ } else
+ super.sendValue(value);
+ }
+ };
+ }
+
+ /*
+ * Process the pulled expression proxy resolutions.
+ */
+ private void processpulledExpressionProxies(List expressionProxies, BeanProxyValueSender sender) {
+
+ // It is expected that each entry will coorespond to the next non-null expression proxy and will be the bean proxy or one of the special
+ // types.
+ int len = expressionProxies.size();
+ int j = 0;
+ Object[] resolveds = sender.getArray();
+ for (int i = 0; i < len; i++) {
+ ExpressionProxy ep = (ExpressionProxy) expressionProxies.get(i);
+ if (ep != null) {
+ Object resolved = resolveds[j++];
+ if (resolved == NOTRESOLVED)
+ fireProxyNotResolved(ep);
+ else if (resolved == VOIDTYPE)
+ fireProxyVoid(ep);
+ else
+ fireProxyResolved(ep, (IBeanProxy) resolved);
+ }
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pullProxyValue()
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pullProxyValue(int, java.util.List)
*/
- protected IBeanProxy pullProxyValue() throws ThrowableProxy, NoExpressionValueException {
+ protected IBeanProxy pullProxyValue(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException {
+ if (connection == null) {
+ markAllProxiesNotResolved(expressionProxies);
+ return null; // We haven't pushed any commands, so there is nothing to do. Don't create a connection for this.
+ }
+ // If there are any pending transactions at this point in time, there is no need to send them. They would be do nothings anyway.
+
+ boolean processedExpressionProxies = false;
+ IREMExpressionConnection connection = getConnection();
+ markInTransaction();
try {
- connection.pullValue(this.hashCode(), workerValue);
+ Commands.ValueObject proxyids = null;
+ BeanProxyValueSender sender = null;
+ if (proxycount > 0) {
+ proxyids = createExpressionProxiesValueObject(proxycount, expressionProxies);
+ sender = getExpressionProxiesSender();
+ }
+
+ connection.pullValue(getREMExpressionID(), proxyids, sender);
+ // If we got this far, then if there are proxies, we need to process these too.
+ if (proxycount > 0)
+ processpulledExpressionProxies(expressionProxies, sender);
+ processedExpressionProxies =true;
+ connection.getFinalValue(workerValue); // Get the returned value.
return getREMBeanProxyFactory().getBeanProxy(workerValue);
} catch (CommandErrorException e) {
- if (e.getErrorCode() == ExpressionCommands.ExpressionNoExpressionValueException) {
- throw new NoExpressionValueException((String) e.getErrorObject());
- }
try {
+ if (e.getErrorCode() == ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION) {
+ // Need to turn it into a Throwable.
+ ThrowableProxy t = null;
+ try {
+ getREMBeanProxyFactory().getBeanProxy(e.getValue()); // This will cause a throw to occur, but we don't want it going out, we want to capture it.
+ } catch (ThrowableProxy e1) {
+ t = e1;
+ }
+ throw new REMNoExpressionValueException(t);
+ }
getREMBeanProxyFactory().processErrorReturn(e);
} catch (CommandException e1) {
ProxyPlugin.getPlugin().getLogger().log(e);
@@ -163,23 +417,102 @@
connection.close();
throwIllegalStateException(COMMAND_EXCEPTION_MSG);
}
+ } finally {
+ markEndTransaction();
+ if (!processedExpressionProxies)
+ markAllProxiesNotResolved(expressionProxies); // We failed before we could process the expression proxies. So mark all as not resolved.
}
return null;
}
-
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushCastToProxy(java.lang.Object)
+
+ /**
+ * This is called by commands that write some data and will be reading data back immediately
+ * (i.e. pull value and invoke expression). If we are on a callback thread and have the
+ * used the connection from the callback thread, we need to tell the callback thread that
+ * it is in a transaction. This is needed because while reading data back there are
+ * sometimes calls back to the vm to get beantype data for new classes. This would
+ * normally be through a new connection so that it doesn't get stuck in the middle of the
+ * data being sent back. But when running on a callback the same connection is used. So it
+ * would stick data in the middle of the return stream of data. To prevent this we need
+ * to tell the callback thread that it is in a transaction during this call so that any
+ * such new connection requests will get a new connection.
+ * <p>
+ * markEndTransaction must be called in ALL cases, such use try/finally.
+ *
+ *
+ * @since 1.1.0
*/
- protected void pushCastToProxy(Object type) throws ThrowableProxy, NoExpressionValueException {
+ protected void markInTransaction() {
+ Thread thread = Thread.currentThread();
+ if (thread instanceof REMCallbackThread) {
+ // We are in a callback, and the callback connection is our connection, tell the callback that it is in transaction.
+ REMCallbackThread callbackThread = (REMCallbackThread) thread;
+ if (callbackThread.getConnection() == connection) {
+ callbackThread.setIntransaction(true);
+ }
+ }
+ }
+
+ /**
+ * Mark end of transaction.
+ *
+ * @see REMExpression#markInTransaction()
+ * @since 1.1.0
+ */
+ protected void markEndTransaction() {
+ Thread thread = Thread.currentThread();
+ if (thread instanceof REMCallbackThread) {
+ // We are in a callback, and the callback connection is our connection, tell the callback that it is in transaction.
+ REMCallbackThread callbackThread = (REMCallbackThread) thread;
+ if (callbackThread.getConnection() == connection) {
+ callbackThread.setIntransaction(false);
+ }
+ }
+ }
+
+ /**
+ * @param expressionProxies
+ *
+ * @since 1.1.0
+ */
+ private Commands.ValueObject createExpressionProxiesValueObject(int actualCount, List expressionProxies) {
+ class ExpressionProxyRetriever implements Commands.ValueRetrieve {
+ Iterator expressionProxiesItr;
+ Commands.ValueObject worker = new Commands.ValueObject();
+
+ public ExpressionProxyRetriever(List expressionProxies) {
+ this.expressionProxiesItr = expressionProxies.iterator();
+ }
+
+ public Commands.ValueObject nextValue() {
+ worker.set(-1);
+ while (expressionProxiesItr.hasNext()) {
+ Object parm = expressionProxiesItr.next();
+ if (parm != null) {
+ worker.set(((ExpressionProxy) parm).getProxyID());
+ break;
+ }
+ }
+ return worker;
+ }
+ };
+
+ workerValue.setArrayIDS(new ExpressionProxyRetriever(expressionProxies), actualCount, Commands.INT);
+ return workerValue;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushCastToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
+ */
+ protected void pushCastToProxy(IProxyBeanType type) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push cast to proxy command is:
// PushExpressionCommand(push cast to proxy) followed by:
- // ValueObject containing the rendered bean type proxy or the String representing the name of class.
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.CAST_EXPRESSION);
- if (type instanceof String)
- workerValue.set((String) type);
- else
- ((IREMBeanProxy) type).renderBean(workerValue);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.CAST_EXPRESSION_VALUE);
+ fillProxy(type, workerValue);
connection.pushValueObject(workerValue);
} catch (IOException e) {
connection.close();
@@ -196,19 +529,36 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushInstanceofToProxy(java.lang.Object)
+ /**
+ * Push the proxy bean type in the format depending on expression proxy or beantype proxy.
+ * @param type
+ * @throws IOException
+ *
+ * @since 1.1.0
*/
- protected void pushInstanceofToProxy(Object type) throws ThrowableProxy, NoExpressionValueException {
+ protected void fillProxy(IProxy type, Commands.ValueObject value) throws IOException {
+ // ValueObject containing the rendered bean type proxy if IBeanTypeProxy or int (for expression proxy id) if expression proxy.
+ if (type.isBeanProxy()) {
+ ((IREMBeanProxy) type).renderBean(value);
+ } else {
+ ExpressionProxy ep = (ExpressionProxy) type;
+ value.set(ep.getProxyID());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushInstanceofToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
+ */
+ protected void pushInstanceofToProxy(IProxyBeanType type) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push instanceof to proxy command is:
// PushExpressionCommand(push instanceof to proxy) followed by:
// ValueObject containing the rendered bean type proxy or the String representing the name of class.
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.INSTANCEOF_EXPRESSION);
- if (type instanceof String)
- workerValue.set((String) type);
- else
- ((IREMBeanProxy) type).renderBean(workerValue);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.INSTANCEOF_EXPRESSION_VALUE);
+ fillProxy(type, workerValue);
connection.pushValueObject(workerValue);
} catch (IOException e) {
connection.close();
@@ -225,18 +575,21 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushInfixToProxy(int, int)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushInfixToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InfixOperator, int)
*/
- protected void pushInfixToProxy(int operator, int operandType) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushInfixToProxy(InfixOperator operator, InternalInfixOperandType operandType) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push infix to proxy command is:
// PushExpressionCommand(push infix to proxy) followed by:
// byte: operator
// byte: operandType
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.INFIX_EXPRESSION);
- connection.pushByte((byte) operator);
- connection.pushByte((byte) operandType);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.INFIX_EXPRESSION_VALUE);
+ connection.pushByte((byte) operator.getValue());
+ connection.pushByte((byte) operandType.getValue());
} catch (IOException e) {
connection.close();
ProxyPlugin.getPlugin().getLogger().log(e);
@@ -245,16 +598,19 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushPrefixToProxy(int)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushPrefixToProxy(org.eclipse.jem.internal.proxy.initParser.tree.PrefixOperator)
*/
- protected void pushPrefixToProxy(int operator) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushPrefixToProxy(PrefixOperator operator) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push prefix to proxy command is:
// PushExpressionCommand(push prefix to proxy) followed by:
// byte: operator
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.PREFIX_EXPRESSION);
- connection.pushByte((byte) operator);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PREFIX_EXPRESSION_VALUE);
+ connection.pushByte((byte) operator.getValue());
} catch (IOException e) {
connection.close();
ProxyPlugin.getPlugin().getLogger().log(e);
@@ -264,40 +620,16 @@
}
/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushTypeLiteralToProxy(java.lang.String)
- */
- protected void pushTypeLiteralToProxy(String type) throws ThrowableProxy {
- try {
- // Format of push type literal to proxy command is:
- // PushExpressionCommand(push typeliteral to proxy) followed by:
- // ValueObject containing the String representing the name of class.
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.TYPELITERAL_EXPRESSION);
- workerValue.set((String) type);
- connection.pushValueObject(workerValue);
- } catch (IOException e) {
- connection.close();
- ProxyPlugin.getPlugin().getLogger().log(e);
- markInvalid(e.getLocalizedMessage());
- throwIllegalStateException(IO_EXCEPTION_MSG);
- } catch (CommandException e) {
- ProxyPlugin.getPlugin().getLogger().log(e);
- markInvalid(e.getLocalizedMessage());
- if (!e.isRecoverable()) {
- connection.close();
- throwIllegalStateException(COMMAND_EXCEPTION_MSG);
- }
- }
- }
-
- /* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayAccessToProxy(int)
*/
- protected void pushArrayAccessToProxy(int indexCount) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushArrayAccessToProxy(int indexCount) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push array access to proxy command is:
// PushExpressionCommand(push array acces to proxy) followed by:
// int: indexCount
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.ARRAY_ACCESS_EXPRESSION);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION_VALUE);
connection.pushInt(indexCount);
} catch (IOException e) {
connection.close();
@@ -307,20 +639,20 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayCreationToProxy(java.lang.Object, int)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayCreationToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType, int)
*/
- protected void pushArrayCreationToProxy(Object type, int dimensionCount) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushArrayCreationToProxy(IProxyBeanType type, int dimensionCount) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push array creation to proxy command is:
// PushExpressionCommand(push array creation to proxy) followed by:
- // ValueObject containing the rendered bean type proxy or the String representing the name of class.
+ // ValueObject containing the rendered bean type proxy or the expression proxy.
// int: dimension count
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.ARRAY_CREATION_EXPRESSION);
- if (type instanceof String)
- workerValue.set((String) type);
- else
- ((IREMBeanProxy) type).renderBean(workerValue);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ARRAY_CREATION_EXPRESSION_VALUE);
+ fillProxy(type, workerValue);
connection.pushValueObject(workerValue);
connection.pushInt(dimensionCount);
} catch (IOException e) {
@@ -338,21 +670,19 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayInitializerToProxy(java.lang.Object, int)
- */
- protected void pushArrayInitializerToProxy(Object type, int expressionCount) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushArrayInitializerToProxy(IProxyBeanType type, int stripCount, int expressionCount) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push array initializer to proxy command is:
// PushExpressionCommand(push array initializer to proxy) followed by:
- // ValueObject containing the rendered bean type proxy or the String representing the name of class.
+ // ValueObject containing the rendered bean type proxy or expression proxy.
+ // int: strip count
// int: expression count
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.ARRAY_INITIALIZER_EXPRESSION);
- if (type instanceof String)
- workerValue.set((String) type);
- else
- ((IREMBeanProxy) type).renderBean(workerValue);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION_VALUE);
+ fillProxy(type, workerValue);
connection.pushValueObject(workerValue);
+ connection.pushInt(stripCount);
connection.pushInt(expressionCount);
} catch (IOException e) {
connection.close();
@@ -369,20 +699,20 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushClassInstanceCreationToProxy(java.lang.Object, int)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushClassInstanceCreationToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType, int)
*/
- protected void pushClassInstanceCreationToProxy(Object type, int argumentCount) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushClassInstanceCreationToProxy(IProxyBeanType type, int argumentCount) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push class instance creation to proxy command is:
// PushExpressionCommand(push class instance creation to proxy) followed by:
- // ValueObject containing the rendered bean type proxy or the String representing the name of class.
+ // ValueObject containing the rendered bean type proxy or the expression proxy
// int: argument count
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.CLASS_INSTANCE_CREATION_EXPRESSION);
- if (type instanceof String)
- workerValue.set((String) type);
- else
- ((IREMBeanProxy) type).renderBean(workerValue);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION_VALUE);
+ fillProxy(type, workerValue);
connection.pushValueObject(workerValue);
connection.pushInt(argumentCount);
} catch (IOException e) {
@@ -400,19 +730,19 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushTypeReceiverToProxy(java.lang.Object)
- */
- protected void pushTypeReceiverToProxy(Object type) throws ThrowableProxy {
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTypeReceiverToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
+ */
+ protected void pushTypeReceiverToProxy(IProxyBeanType type) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push type receiver to proxy command is:
// PushExpressionCommand(push type receiver to proxy) followed by:
- // ValueObject containing the rendered bean type proxy or the String representing the name of class.
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.TYPERECEIVER_EXPRESSION);
- if (type instanceof String)
- workerValue.set((String) type);
- else
- ((IREMBeanProxy) type).renderBean(workerValue);
+ // ValueObject containing the rendered bean type proxy or the expression proxy.
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.TYPERECEIVER_EXPRESSION_VALUE);
+ fillProxy(type, workerValue);
connection.pushValueObject(workerValue);
} catch (IOException e) {
connection.close();
@@ -432,36 +762,56 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldAccessToProxy(java.lang.String, boolean)
*/
- protected void pushFieldAccessToProxy(String fieldName, boolean hasReceiver) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushFieldAccessToProxy(Object field, boolean hasReceiver) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push field access to proxy command is:
// PushExpressionCommand(push field access to proxy) followed by:
- // String: fieldName
+ // Commands.Value: fieldName or IProxyField
// boolean: hasReceiver
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.FIELD_ACCESS_EXPRESSION);
- connection.pushString(fieldName);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.FIELD_ACCESS_EXPRESSION_VALUE);
+ if (field instanceof String) {
+ workerValue.set((String) field);
+ } else {
+ fillProxy((IProxy) field, workerValue);
+ }
+ connection.pushValueObject(workerValue);
connection.pushBoolean(hasReceiver);
} catch (IOException e) {
connection.close();
ProxyPlugin.getPlugin().getLogger().log(e);
markInvalid(e.getLocalizedMessage());
throwIllegalStateException(IO_EXCEPTION_MSG);
+ } catch (CommandException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ if (!e.isRecoverable()) {
+ connection.close();
+ throwIllegalStateException(COMMAND_EXCEPTION_MSG);
+ }
}
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodInvocationToProxy(java.lang.String, boolean, int)
*/
- protected void pushMethodInvocationToProxy(String methodName, boolean hasReceiver, int argCount)
- throws ThrowableProxy, NoExpressionValueException {
+ protected void pushMethodInvocationToProxy(Object method, boolean hasReceiver, int argCount) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push method invocation to proxy command is:
// PushExpressionCommand(push method invocation to proxy) followed by:
- // String: methodName
+ // Commands.ValueObject: methodName or IMethodProxy
// boolean: hasReceiver
// int: argCount
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.METHOD_EXPRESSION);
- connection.pushString(methodName);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.METHOD_EXPRESSION_VALUE);
+ if (method instanceof String) {
+ workerValue.set((String) method);
+ } else {
+ fillProxy((IProxy) method, workerValue);
+ }
+ connection.pushValueObject(workerValue);
connection.pushBoolean(hasReceiver);
connection.pushInt(argCount);
} catch (IOException e) {
@@ -469,19 +819,28 @@
ProxyPlugin.getPlugin().getLogger().log(e);
markInvalid(e.getLocalizedMessage());
throwIllegalStateException(IO_EXCEPTION_MSG);
+ } catch (CommandException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ if (!e.isRecoverable()) {
+ connection.close();
+ throwIllegalStateException(COMMAND_EXCEPTION_MSG);
+ }
}
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.Expression#pushConditionalToProxy(int)
*/
- protected void pushConditionalToProxy(int expressionType) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushConditionalToProxy(InternalConditionalOperandType expressionType) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
try {
// Format of push conditional to proxy command is:
// PushExpressionCommand(push conditional to proxy) followed by:
// byte: expression type
- connection.pushExpressionCommand(this.hashCode(), (byte)IInternalExpressionConstants.CONDITIONAL_EXPRESSION);
- connection.pushByte((byte) expressionType);
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.CONDITIONAL_EXPRESSION_VALUE);
+ connection.pushByte((byte) expressionType.getValue());
} catch (IOException e) {
connection.close();
ProxyPlugin.getPlugin().getLogger().log(e);
@@ -490,18 +849,100 @@
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushInvoke()
+ /*
+ * A special one that takes the ThrowableProxy for no expression value and
+ * wrappers it prints its stack trace instead, but still makes it a subclass
+ * of NoExpressionValueException.
+ *
+ * @since 1.1.0
*/
- protected void pushInvoke() throws ThrowableProxy, NoExpressionValueException {
+ private static class REMNoExpressionValueException extends NoExpressionValueException {
+ public REMNoExpressionValueException(ThrowableProxy e) {
+ super(e);
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Throwable#getLocalizedMessage()
+ */
+ public String getLocalizedMessage() {
+ return ((ThrowableProxy) getCause()).getProxyLocalizedMessage();
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Throwable#getMessage()
+ */
+ public String getMessage() {
+ return ((ThrowableProxy) getCause()).getProxyMessage();
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Throwable#printStackTrace()
+ */
+ public void printStackTrace() {
+ getCause().printStackTrace();
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Throwable#printStackTrace(java.io.PrintStream)
+ */
+ public void printStackTrace(PrintStream s) {
+ getCause().printStackTrace(s);
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter)
+ */
+ public void printStackTrace(PrintWriter s) {
+ getCause().printStackTrace(s);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushInvoke(int, java.util.List)
+ */
+ protected void pushInvoke(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException {
+ if (connection == null) {
+ markAllProxiesNotResolved(expressionProxies);
+ return; // We haven't pushed any commands, so there is nothing to do. Don't create a connection for this.
+ }
+ // If at this point there are pending transactions, there is no need to send them because they would all be do-nothings.
+
+ boolean processedExpressionProxies = false;
+ IREMExpressionConnection connection = getConnection();
+ markInTransaction();
try {
- connection.sync(this.hashCode(), workerValue);
- getREMBeanProxyFactory().getBeanProxy(workerValue); // This processes the return. It will be either true or an error. If true we don't care and if error the catch will handle it.
- } catch (CommandErrorException e) {
- if (e.getErrorCode() == ExpressionCommands.ExpressionNoExpressionValueException) {
- throw new NoExpressionValueException((String) e.getErrorObject());
+ Commands.ValueObject proxyids = null;
+ BeanProxyValueSender sender = null;
+ if (proxycount > 0) {
+ proxyids = createExpressionProxiesValueObject(proxycount, expressionProxies);
+ sender = getExpressionProxiesSender();
}
+
+ connection.sync(getREMExpressionID(), proxyids, sender);
+
+ // If we got this far, then if there are proxies, we need to process these too.
+ if (proxycount > 0)
+ processpulledExpressionProxies(expressionProxies, sender);
+ processedExpressionProxies = true;
+ connection.getFinalValue(workerValue); // We don't care what it is, we just need to see if there is an error.
+ } catch (CommandErrorException e) {
try {
+ if (e.getErrorCode() == ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION) {
+ // Need to turn it into a Throwable.
+ ThrowableProxy t = null;
+ try {
+ getREMBeanProxyFactory().getBeanProxy(e.getValue()); // This will cause a throw to occur, but we don't want it going out, we want to capture it.
+ } catch (ThrowableProxy e1) {
+ t = e1;
+ }
+ throw new REMNoExpressionValueException(t);
+ }
getREMBeanProxyFactory().processErrorReturn(e);
} catch (CommandException e1) {
ProxyPlugin.getPlugin().getLogger().log(e);
@@ -516,7 +957,772 @@
connection.close();
throwIllegalStateException(COMMAND_EXCEPTION_MSG);
}
+ } finally {
+ markEndTransaction();
+ if (!processedExpressionProxies)
+ markAllProxiesNotResolved(expressionProxies); // We failed before we could process the expression proxies. So mark all as not resolved.
}
}
+ private static class REMBeanTypeExpressionProxy extends ExpressionProxy implements IBeanTypeExpressionProxy {
+
+ private String typeName;
+
+ /**
+ * @param proxyid
+ *
+ * @since 1.1.0
+ */
+ private REMBeanTypeExpressionProxy(int proxyid, Expression expression) {
+ super(proxyid, BEANTYPE_EXPRESSION_PROXY, expression);
+ }
+
+ public void setTypeName(String typeName) {
+ this.typeName = typeName;
+ }
+
+ public String getTypeName() {
+ return typeName;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy#toString()
+ */
+ public String toString() {
+ return super.toString()+" - "+getTypeName();
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameterTypes) {
+ REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
+ return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes) {
+ REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
+ return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String fieldName) {
+ REMProxyFactoryRegistry registry = (REMProxyFactoryRegistry) expression.getRegistry();
+ return ((REMMethodProxyFactory) registry.getMethodProxyFactory()).getFieldProxy(expression, this, fieldName);
+ }
+ }
+
+ private static class REMMethodExpressionProxy extends ExpressionProxy implements IProxyMethod {
+
+ /**
+ * @param proxyid
+ * @param proxyType
+ * @param expression
+ *
+ * @since 1.1.0
+ */
+ private REMMethodExpressionProxy(int proxyid, Expression expression) {
+ super(proxyid, METHOD_EXPRESSION_PROXY, expression);
+ }
+ }
+
+ private static class REMFieldExpressionProxy extends ExpressionProxy implements IProxyField {
+
+ /**
+ * @param proxyid
+ * @param proxyType
+ * @param expression
+ *
+ * @since 1.1.0
+ */
+ private REMFieldExpressionProxy(int proxyid, Expression expression) {
+ super(proxyid, FIELD_EXPRESSION_PROXY, expression);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#createExpressionProxy(int)
+ */
+ protected ExpressionProxy createExpressionProxy(int proxyType, int proxyID) {
+ switch (proxyType) {
+ case NORMAL_EXPRESSION_PROXY:
+ default:
+ return new ExpressionProxy(proxyID, NORMAL_EXPRESSION_PROXY, this);
+
+ case BEANTYPE_EXPRESSION_PROXY:
+ return new REMBeanTypeExpressionProxy(proxyID, this);
+
+ case METHOD_EXPRESSION_PROXY:
+ return new REMMethodExpressionProxy(proxyID, this);
+
+ case FIELD_EXPRESSION_PROXY:
+ return new REMFieldExpressionProxy(proxyID, this);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushAssignmentToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy)
+ */
+ protected void pushAssignmentToProxy(ExpressionProxy proxy) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push assignment to proxy command is:
+ // PushExpressionCommand(push assignment to proxy) followed by:
+ // int: proxy id
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ASSIGNMENT_PROXY_EXPRESSION_VALUE);
+ connection.pushInt(proxy.getProxyID());
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushAssignmentToProxy()
+ */
+ protected void pushAssignmentToProxy() {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of the push assignment command is:
+ // PushAssignmentCommand.
+ connection.pushExpressionCommand(getREMExpressionID(), (byte) InternalExpressionTypes.ASSIGNMENT_EXPRESSION_VALUE);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+
+ private void pushToExpressionProxy(ExpressionProxy proxy) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to expression proxy command is:
+ // PushExpressionCommand(push expression proxy to proxy) followed by:
+ // int: proxy id
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_TO_EXPRESSION_PROXY_EXPRESSION_VALUE);
+ connection.pushInt(proxy.getProxyID());
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+
+ }
+
+ private static class BlockBegin extends PendingTransaction {
+ public int blockNumber;
+
+ public BlockBegin(int blockNumber) {
+ this.blockNumber = blockNumber;
+ }
+
+ public void pushTransaction(REMExpression remExpression) {
+ IREMExpressionConnection connection = remExpression.getConnection();
+ try {
+ // Format of push to block begin proxy command is:
+ // PushExpressionCommand(push block begin proxy to proxy) followed by:
+ // int: block id
+ connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.BLOCK_BEGIN_EXPRESSION_VALUE);
+ connection.pushInt(blockNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockBeginToProxy(int)
+ */
+ protected void pushBlockBeginToProxy(int blockNumber) {
+ addPendingTransaction(new BlockBegin(blockNumber));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockEndToProxy(int)
+ */
+ protected void pushBlockEndToProxy(int blockNumber) {
+ // See if the top pending transactions is BreakBlock(blockNumber). If it is then the BreakBlock can be thrown away.
+ PendingTransaction topEntry = getPendingEntryFromTop(1);
+ if (topEntry instanceof BlockBreak && ((BlockBreak) topEntry).blockNumber == blockNumber) {
+ popPendingEntry(1);
+ topEntry = getPendingEntryFromTop(1);
+ }
+ // See if the top pending transaction is now BeginBlock(blockNumber). If it is, then this transaction and the block begin
+ // can be thrown away because they are an empty block.
+ if (topEntry instanceof BlockBegin && ((BlockBegin) topEntry).blockNumber == blockNumber) {
+ popPendingEntry(1);
+ return;
+ }
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to block end proxy command is:
+ // PushExpressionCommand(push block end proxy to proxy) followed by:
+ // int: block id
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.BLOCK_END_EXPRESSION_VALUE);
+ connection.pushInt(blockNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ private static class BlockBreak extends PendingTransaction {
+ public int blockNumber;
+
+ public BlockBreak(int blockNumber) {
+ this.blockNumber = blockNumber;
+ }
+
+ public void pushTransaction(REMExpression remExpression) {
+ IREMExpressionConnection connection = remExpression.getConnection();
+ try {
+ // Format of push to block break proxy command is:
+ // PushExpressionCommand(push block break proxy to proxy) followed by:
+ // int: block id
+ connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.BLOCK_BREAK_EXPRESSION_VALUE);
+ connection.pushInt(blockNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockBreakToProxy(int)
+ */
+ protected void pushBlockBreakToProxy(int blockNumber) {
+ // Even if there is no pending block begin for this block, we will pend the break.
+ // This is so that if the break occurred just before the block end, then it can be ignored.
+ addPendingTransaction(new BlockBreak(blockNumber));
+ }
+
+ private static class TryBegin extends PendingTransaction {
+
+ public final int tryNumber;
+
+ public TryBegin(int tryNumber) {
+ this.tryNumber = tryNumber;
+
+ }
+ public void pushTransaction(REMExpression remExpression) {
+ IREMExpressionConnection connection = remExpression.getConnection();
+ try {
+ // Format of push to try begin proxy command is:
+ // PushExpressionCommand(push try begin to proxy) followed by:
+ // int: try id
+ connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.TRY_BEGIN_EXPRESSION_VALUE);
+ connection.pushInt(tryNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryBeginToProxy(int)
+ */
+ protected void pushTryBeginToProxy(int tryNumber) {
+ addPendingTransaction(new TryBegin(tryNumber));
+ }
+
+ private static class TryCatch extends PendingTransaction {
+
+ public final int tryNumber;
+ private final IProxyBeanType exceptionType;
+ private final ExpressionProxy ep;
+
+ public TryCatch(int tryNumber, IProxyBeanType exceptionType, ExpressionProxy ep) {
+ this.tryNumber = tryNumber;
+ this.exceptionType = exceptionType;
+ this.ep = ep;
+ }
+
+ public void pushTransaction(REMExpression remExpression) {
+ IREMExpressionConnection connection = remExpression.getConnection();
+ try {
+ // Format of push to try begin proxy command is:
+ // PushExpressionCommand(push try begin to proxy) followed by:
+ // int: try id
+ // object: expression type (as beantype or as expression proxy)
+ // int: proxy id or (-1 if null).
+ connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.TRY_CATCH_EXPRESSION_VALUE);
+ connection.pushInt(tryNumber);
+ remExpression.fillProxy(exceptionType, remExpression.workerValue);
+ connection.pushValueObject(remExpression.workerValue);
+ if (ep != null)
+ connection.pushInt(ep.getProxyID());
+ else
+ connection.pushInt(-1);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
+ } catch (CommandException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ if (!e.isRecoverable()) {
+ connection.close();
+ remExpression.throwIllegalStateException(COMMAND_EXCEPTION_MSG);
+ }
+ }
+ }
+
+ }
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryCatchClauseToProxy(int, org.eclipse.jem.internal.proxy.core.IProxyBeanType, org.eclipse.jem.internal.proxy.core.ExpressionProxy)
+ */
+ protected void pushTryCatchClauseToProxy(int tryNumber, IProxyBeanType exceptionType, ExpressionProxy ep) {
+ addPendingTransaction(new TryCatch(tryNumber, exceptionType, ep));
+ }
+
+ private static class TryFinally extends PendingTransaction {
+
+ public final int tryNumber;
+
+ public TryFinally(int tryNumber) {
+ this.tryNumber = tryNumber;
+
+ }
+
+ public void pushTransaction(REMExpression remExpression) {
+ IREMExpressionConnection connection = remExpression.getConnection();
+ try {
+ // Format of push to try begin proxy command is:
+ // PushExpressionCommand(push try finally to proxy) followed by:
+ // int: try id
+ connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.TRY_FINALLY_EXPRESSION_VALUE);
+ connection.pushInt(tryNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryFinallyClauseToProxy(int)
+ */
+ protected void pushTryFinallyClauseToProxy(int tryNumber) {
+ addPendingTransaction(new TryFinally(tryNumber));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryEndToProxy(int)
+ */
+ protected void pushTryEndToProxy(int tryNumber) {
+ // This is a little tricky. We need to find if there is nothing but try/catch/finally for this tryNumber on the pending
+ // transactions up to the try begin, if there is nothing else, then we can throw the entire try away. That
+ // means there was no code at all in any of the try/catch/finally blocks.
+ int fromTop = 0;
+ while (true) {
+ PendingTransaction topEntry = getPendingEntryFromTop(++fromTop);
+ if (topEntry instanceof TryFinally) {
+ if (((TryFinally) topEntry).tryNumber != tryNumber)
+ break; // We met a finally that wasn't ours, so entire try group must be sent.
+ } else if (topEntry instanceof TryCatch) {
+ if (((TryCatch) topEntry).tryNumber != tryNumber)
+ break; // We met a catch that wasn't ours, so entire try group must be sent.
+ } else if (topEntry instanceof TryBegin) {
+ if (((TryBegin) topEntry).tryNumber == tryNumber) {
+ // We've met our try begin, and nothing but empty catch/finally in between, so the entire group can be thrown away
+ popPendingEntry(fromTop);
+ return;
+ } else
+ break; // We've hit a try begin that wasn't ours, so the entire try group must be sent.
+ } else
+ break; // We've hit something other than our try group, so process everything.
+ }
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to try begin proxy command is:
+ // PushExpressionCommand(push try end to proxy) followed by:
+ // int: try id
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.TRY_END_EXPRESSION_VALUE);
+ connection.pushInt(tryNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushThrowToProxy()
+ */
+ protected void pushThrowToProxy() {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to try begin proxy command is:
+ // PushExpressionCommand(push throw to proxy)
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.THROW_EXPRESSION_VALUE);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushRethrowToProxy(int)
+ */
+ protected void pushRethrowToProxy(int tryNumber) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to rethow proxy command is:
+ // PushExpressionCommand(push rethrow to proxy)
+ // int: try id
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.RETHROW_EXPRESSION_VALUE);
+ connection.pushInt(tryNumber);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBeanTypeToProxy(org.eclipse.jem.internal.proxy.core.IBeanTypeExpressionProxy)
+ */
+ protected void pushBeanTypeToProxy(IBeanTypeExpressionProxy proxy) {
+ // Push beantype to proxy is sent out of sequence without respect to where in expression we are,
+ // so no need to handle pending transactions at this point. They would not affect the result
+ // of this call.
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to beanType proxy command is:
+ // PushExpressionCommand(push bean type expression proxy)
+ // int: proxy id
+ // string: typename
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_BEANTYPE_EXPRESSIONPROXY_EXPRESSION_VALUE);
+ REMBeanTypeExpressionProxy ep = (REMBeanTypeExpressionProxy) proxy;
+ connection.pushInt(ep.getProxyID());
+ connection.pushString(ep.getTypeName());
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy, org.eclipse.jem.internal.proxy.core.IProxyBeanType, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ protected void pushMethodToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes) {
+ // Push method to proxy is sent out of sequence without respect to where in expression we are,
+ // so no need to handle pending transactions at this point. They would not affect the result
+ // of this call.
+
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to method proxy command is:
+ // PushExpressionCommand(push method type expression proxy)
+ // int: proxy id
+ // ValueObject: containing the rendered bean type proxy or the expression proxy for the declaring type
+ // string: method name
+ // int: number of parameter types
+ // ValueObject(s): containing the rendered bean type proxy or the expression proxy for the parameter types.
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_METHOD_EXPRESSIONPROXY_EXPRESSION_VALUE);
+ connection.pushInt(proxy.getProxyID());
+ fillProxy(declaringType, workerValue);
+ connection.pushValueObject(workerValue);
+ connection.pushString(methodName);
+ if (parameterTypes == null || parameterTypes.length == 0)
+ connection.pushInt(0);
+ else {
+ connection.pushInt(parameterTypes.length);
+ for (int i = 0; i < parameterTypes.length; i++) {
+ fillProxy(parameterTypes[i], workerValue);
+ connection.pushValueObject(workerValue);
+ }
+ }
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ } catch (CommandException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ if (!e.isRecoverable()) {
+ connection.close();
+ throwIllegalStateException(COMMAND_EXCEPTION_MSG);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy, org.eclipse.jem.internal.proxy.core.IProxyBeanType, java.lang.String)
+ */
+ protected void pushFieldToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String fieldName) {
+ // Push field to proxy is sent out of sequence without respect to where in expression we are,
+ // so no need to handle pending transactions at this point. They would not affect the result
+ // of this call.
+
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push to field proxy command is:
+ // PushExpressionCommand(push field type expression proxy)
+ // int: proxy id
+ // ValueObject: containing the rendered bean type proxy or the expression proxy for the declaring type
+ // string: field name
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.PUSH_FIELD_EXPRESSIONPROXY_EXPRESSION_VALUE);
+ connection.pushInt(proxy.getProxyID());
+ fillProxy(declaringType, workerValue);
+ connection.pushValueObject(workerValue);
+ connection.pushString(fieldName);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ } catch (CommandException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ if (!e.isRecoverable()) {
+ connection.close();
+ throwIllegalStateException(COMMAND_EXCEPTION_MSG);
+ }
+ }
+ }
+
+ /**
+ * Get the map of IProxyMethods for a beantype. Meant to be used only in conjunction with REMProxyConstants.
+ * It is here so the REMProxyConstants can store pending proxies per expression.
+ *
+ * @param beanType
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public Map getMethods(IProxyBeanType beanType) {
+ if (methodsCache == null)
+ methodsCache = new HashMap();
+ Map methods = (Map) methodsCache.get(beanType.getTypeName());
+ if(methods == null){
+ methods = new HashMap(20);
+ methodsCache.put(beanType.getTypeName(),methods);
+ }
+ return methods;
+ }
+
+ /**
+ * Get the map of IProxyFields for a beantype. Meant to be used only in conjunction with REMProxyConstants.
+ * It is here so the REMProxyConstants can store pending proxies per expression.
+ *
+ * @param beanType
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public Map getFields(IProxyBeanType beanType) {
+ if (fieldsCache == null)
+ fieldsCache = new HashMap();
+ Map fields = (Map) fieldsCache.get(beanType.getTypeName());
+ if(fields == null){
+ fields = new HashMap(20);
+ fieldsCache.put(beanType.getTypeName(),fields);
+ }
+ return fields;
+ }
+
+ /**
+ * Get the map of IProxyBeanTypes for a beantype name. Meant to be used only in conjunction with REMSgtandardBeanTypeFactory.
+ * It is here so the REMStandardBeanTypeFactory can store pending proxies per expression.
+ *
+ * @param beanType
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyBeanType getBeanType(String beanTypeName) {
+ if (beanTypeCache == null)
+ beanTypeCache = new HashMap();
+ return (IProxyBeanType) beanTypeCache.get(beanTypeName);
+ }
+
+ /**
+ * Add the beantype expression proxy to the map of bean type expression proxies. Used in conjunction with REMStandardBeanTypeFactory.
+ * It is here so the REMStandardBeanTypeFactory can store pending proxies per expression.
+ * @param beanTypeName
+ * @param beantype
+ *
+ * @since 1.1.0
+ */
+ public void addBeanType(String beanTypeName, IProxyBeanType beantype) {
+ beanTypeCache.put(beanTypeName, beantype);
+ }
+
+ /**
+ * Remove the beantype expression proxy from the map. This is called because there was a rollback due to an endmark.
+ * @param beanTypeName
+ *
+ * @since 1.1.0
+ */
+ public void removeBeanType(String beanTypeName) {
+ beanTypeCache.remove(beanTypeName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushIfTestToProxy()
+ */
+ protected void pushIfTestToProxy() {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push if test to proxy command is:
+ // PushExpressionCommand(push if test to proxy)
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.IF_TEST_EXPRESSION_VALUE);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushIfElseToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InternalIfElseOperandType)
+ */
+ protected void pushIfElseToProxy(InternalIfElseOperandType clauseType) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push conditional to proxy command is:
+ // PushExpressionCommand(push if/else clause to proxy) followed by:
+ // byte: clause type
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.IF_ELSE_EXPRESSION_VALUE);
+ connection.pushByte((byte) clauseType.getValue());
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushNewInstanceToProxy(java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType)
+ */
+ protected void pushNewInstanceToProxy(String initializationString, IProxyBeanType resultType) {
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push new instance from initstring to proxy command is:
+ // PushExpressionCommand(push new instance to proxy) followed by:
+ // string: init string
+ // ValueObject: containing the rendered bean type proxy or the expression proxy for the declaring type
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.NEW_INSTANCE_VALUE);
+ connection.pushString(initializationString);
+ fillProxy(resultType, workerValue);
+ connection.pushValueObject(workerValue);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ } catch (CommandException e) {
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ if (!e.isRecoverable()) {
+ connection.close();
+ throwIllegalStateException(COMMAND_EXCEPTION_MSG);
+ }
+ }
+ }
+
+ private static class Mark extends PendingTransaction {
+ public int markID;
+
+ public Mark(int markID) {
+ this.markID = markID;
+ }
+
+ public void pushTransaction(REMExpression remExpression) {
+ IREMExpressionConnection connection = remExpression.getConnection();
+ try {
+ // Format of push mark to proxy command is:
+ // PushExpressionCommand(push mark to proxy) followed by:
+ // int: markID
+ connection.pushExpressionCommand(remExpression.getREMExpressionID(), (byte)InternalExpressionTypes.MARK_VALUE);
+ connection.pushInt(markID);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ remExpression.markInvalid(e.getLocalizedMessage());
+ remExpression.throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
+
+ }
+
+ protected void pushMarkToProxy(int markID) {
+ addPendingTransaction(new Mark(markID));
+ }
+
+ protected void pushEndmarkToProxy(int markID, boolean restore) {
+ // See if the top pending transaction is now Mark(markID). If it is, then this transaction and the mark begin
+ // can be thrown away because they are an empty block.
+ PendingTransaction topEntry = getPendingEntryFromTop(1);
+ if (topEntry instanceof Mark && ((Mark) topEntry).markID == markID) {
+ popPendingEntry(1);
+ return;
+ }
+ processPendingTransactions();
+ IREMExpressionConnection connection = getConnection();
+ try {
+ // Format of push end mark to proxy command is:
+ // PushExpressionCommand(push end mark to proxy) followed by:
+ // int: markID
+ // boolean: restore
+ connection.pushExpressionCommand(getREMExpressionID(), (byte)InternalExpressionTypes.ENDMARK_VALUE);
+ connection.pushInt(markID);
+ connection.pushBoolean(restore);
+ } catch (IOException e) {
+ connection.close();
+ ProxyPlugin.getPlugin().getLogger().log(e);
+ markInvalid(e.getLocalizedMessage());
+ throwIllegalStateException(IO_EXCEPTION_MSG);
+ }
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInitErrorBeanTypeProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInitErrorBeanTypeProxy.java
index 6106117..ba76e0d 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInitErrorBeanTypeProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInitErrorBeanTypeProxy.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: REMInitErrorBeanTypeProxy.java,v $
- * $Revision: 1.7 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.8 $ $Date: 2005/05/11 19:01:12 $
*/package org.eclipse.jem.internal.proxy.remote;
import org.eclipse.jem.internal.proxy.core.*;
@@ -427,4 +427,41 @@
public IMethodProxy getCompatibleMethod(String methodName, IBeanTypeProxy[] argumentTypes) {
return null;
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameters) {
+ return null; // Since this guy is invalid, we can't return a method.
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String fieldName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInvokable.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInvokable.java
index 47c5af5..9f5945c 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInvokable.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMInvokable.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: REMInvokable.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -87,12 +87,9 @@
}
public Commands.ValueObject nextValue() {
- if (index < array.length) {
- Object parm = array[index++];
- ((IREMBeanTypeProxy) parm).renderBean(worker);
- return worker;
- } else
- return null;
+ Object parm = array[index++];
+ ((IREMBeanTypeProxy) parm).renderBean(worker);
+ return worker;
}
};
@@ -123,30 +120,27 @@
}
public Commands.ValueObject nextValue() {
- if (index < array.length) {
- Object parm = array[index++];
- if (parm != null)
- if (parm instanceof IREMBeanProxy)
- ((IREMBeanProxy) parm).renderBean(worker);
- else if (parm instanceof TransmitableArray) {
- // It is another array, create a new retriever.
- worker.setArrayIDS(
- new Retriever(((TransmitableArray) parm).array),
- ((TransmitableArray) parm).array.length,
- ((TransmitableArray) parm).componentTypeID);
- } else {
- // It's an object. Need to get bean type so that we can send it.
- IREMBeanProxy type = (IREMBeanProxy) typeFactory.getBeanTypeProxy(parm.getClass().getName());
- if (type == null)
- throw new IllegalArgumentException();
- int classID = type.getID().intValue();
- worker.setAsObject(parm, classID);
- }
- else
- worker.set();
- return worker;
- } else
- return null;
+ Object parm = array[index++];
+ if (parm != null)
+ if (parm instanceof IREMBeanProxy)
+ ((IREMBeanProxy) parm).renderBean(worker);
+ else if (parm instanceof TransmitableArray) {
+ // It is another array, create a new retriever.
+ worker.setArrayIDS(
+ new Retriever(((TransmitableArray) parm).array),
+ ((TransmitableArray) parm).array.length,
+ ((TransmitableArray) parm).componentTypeID);
+ } else {
+ // It's an object. Need to get bean type so that we can send it.
+ IREMBeanProxy type = (IREMBeanProxy) typeFactory.getBeanTypeProxy(parm.getClass().getName());
+ if (type == null)
+ throw new IllegalArgumentException();
+ int classID = type.getID().intValue();
+ worker.setAsObject(parm, classID);
+ }
+ else
+ worker.set();
+ return worker;
}
};
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java
index 5bbe882..f343a04 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMMethodProxy.java,v $
- * $Revision: 1.9 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.10 $ $Date: 2005/05/11 19:01:12 $
*/
import org.eclipse.core.runtime.IStatus;
@@ -140,30 +140,27 @@
}
public Commands.ValueObject nextValue() {
- if (index < array.length) {
- Object parm = array[index++];
- if (parm != null)
- if (parm instanceof IREMBeanProxy)
- ((IREMBeanProxy) parm).renderBean(worker);
- else if (parm instanceof TransmitableArray) {
- // It is another array, create a new retriever.
- worker.setArrayIDS(
- new Retriever(((TransmitableArray) parm).array),
- ((TransmitableArray) parm).array.length,
- ((TransmitableArray) parm).componentTypeID);
- } else {
- // It's an object. Need to get bean type so that we can send it.
- IREMBeanProxy type = (IREMBeanProxy) typeFactory.getBeanTypeProxy(parm.getClass().getName());
- if (type == null)
- throw new IllegalArgumentException();
- int classID = type.getID().intValue();
- worker.setAsObject(parm, classID);
- }
- else
- worker.set();
- return worker;
- } else
- return null;
+ Object parm = array[index++];
+ if (parm != null)
+ if (parm instanceof IREMBeanProxy)
+ ((IREMBeanProxy) parm).renderBean(worker);
+ else if (parm instanceof TransmitableArray) {
+ // It is another array, create a new retriever.
+ worker.setArrayIDS(
+ new Retriever(((TransmitableArray) parm).array),
+ ((TransmitableArray) parm).array.length,
+ ((TransmitableArray) parm).componentTypeID);
+ } else {
+ // It's an object. Need to get bean type so that we can send it.
+ IREMBeanProxy type = (IREMBeanProxy) typeFactory.getBeanTypeProxy(parm.getClass().getName());
+ if (type == null)
+ throw new IllegalArgumentException();
+ int classID = type.getID().intValue();
+ worker.setAsObject(parm, classID);
+ }
+ else
+ worker.set();
+ return worker;
}
};
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxyFactory.java
index c67d2e1..75bdc5f 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxyFactory.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: REMMethodProxyFactory.java,v $
- * $Revision: 1.8 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.9 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -72,8 +72,103 @@
IBeanTypeProxy clsProxy = typeFactory.getBeanTypeProxy(className);
if (clsProxy == null)
return null;
+ // This will redirect to the beantype, which will go through the method cache.
return clsProxy.getMethodProxy(methodName, parameterTypes);
}
+
+ /**
+ * A helper method to get the method proxy for the expression. This is used by registries and beantype proxies. It will go through
+ * the method cache to make sure we get only one.
+ *
+ * @param expression
+ * @param aBeanTypeProxy
+ * @param methodName
+ * @param parmTypes
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, IProxyBeanType aBeanTypeProxy, String methodName, IProxyBeanType[] parmTypes){
+ return ((REMStandardBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactory()).proxyConstants.getMethodProxy(expression, aBeanTypeProxy, methodName, parmTypes);
+ }
+
+ /**
+ * A helper method to get the field proxy for the expression. This is used by registries and beantype proxies. It will go through
+ * the method cache to make sure we get only one.
+ * @param expression
+ * @param aBeanTypeProxy
+ * @param fieldName
+ *
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyField getFieldProxy(IExpression expression, IProxyBeanType aBeanTypeProxy, String fieldName){
+ return ((REMStandardBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactory()).proxyConstants.getFieldProxy(expression, aBeanTypeProxy, fieldName);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IMethodProxyFactory#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String className, String fieldName) {
+ // We are getting the class resolved through the expression. Might as well because it probably will
+ // be needed again and this way when the expression is finished it will be resolved for later usage.
+ IStandardBeanTypeProxyFactory beanTypeProxyFactory = fFactoryRegistry.getBeanTypeProxyFactory();
+ IProxyBeanType beanType = beanTypeProxyFactory.getBeanTypeProxy(expression, className);
+ return beanType.getFieldProxy(expression, fieldName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IMethodProxyFactory#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String className, String methodName, String[] parameterTypes) {
+ // We are getting the class and parmtypes resolved through the expression. Might as well because they probably will
+ // be needed again and this way when the expression is finished they will be resolved for later usage.
+ IStandardBeanTypeProxyFactory beanTypeProxyFactory = fFactoryRegistry.getBeanTypeProxyFactory();
+ IProxyBeanType beanType = beanTypeProxyFactory.getBeanTypeProxy(expression, className);
+ IProxyBeanType[] parmTypes = getParameterTypes(expression, parameterTypes, beanTypeProxyFactory);
+ return beanType.getMethodProxy(expression, methodName, parmTypes);
+ }
+
+ /**
+ * Helper method for BeanTypes and proxy Beantypes. So they don't need to have common code to convert string to proxy bean type.
+ * @param expression
+ * @param classType
+ * @param methodName
+ * @param parameterTypes
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, IProxyBeanType classType, String methodName, String[] parameterTypes) {
+ // We are getting the class and parmtypes resolved through the expression. Might as well because they probably will
+ // be needed again and this way when the expression is finished they will be resolved for later usage.
+ IStandardBeanTypeProxyFactory beanTypeProxyFactory = fFactoryRegistry.getBeanTypeProxyFactory();
+ IProxyBeanType[] parmTypes = getParameterTypes(expression, parameterTypes, beanTypeProxyFactory);
+ return classType.getMethodProxy(expression, methodName, parmTypes);
+ }
+
+ /**
+ * @param expression
+ * @param parameterTypes
+ * @param beanTypeProxyFactory
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected IProxyBeanType[] getParameterTypes(IExpression expression, String[] parameterTypes, IStandardBeanTypeProxyFactory beanTypeProxyFactory) {
+ IProxyBeanType[] parmTypes;
+ if (parameterTypes == null || parameterTypes.length == 0)
+ parmTypes = null;
+ else {
+ parmTypes = new IProxyBeanType[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ parmTypes[i] = beanTypeProxyFactory.getBeanTypeProxy(expression, parameterTypes[i]);
+ }
+ }
+ return parmTypes;
+ }
/*
* (non-Javadoc)
@@ -118,6 +213,7 @@
/**
* Get the method id from the remote system and create the method proxy.
+ * This does not go through the method cache. It goes direct to the remote vm.
*
* NOTE: It is public ONLY so that IBeanTypeProxy implementations can call it. It must not be used by anyone else.
*/
@@ -155,6 +251,8 @@
/**
* Get the method id from the remote system and create the method proxy.
+ * <p>
+ * This does not go through the method cache. It goes direct to the remote vm.
*
* NOTE: It is public ONLY so that IBeanTypeProxy implementations can call it. It must not be used by anyone else.
*/
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyConstants.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyConstants.java
index d38961c..bff0693 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyConstants.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyConstants.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: REMProxyConstants.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.remote;
@@ -18,6 +18,7 @@
import java.util.Map.Entry;
import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
@@ -35,6 +36,12 @@
private Map invokablesCache = new HashMap(80);
private Map fieldsCache = new HashMap(80);
+ private REMProxyFactoryRegistry registry;
+
+ public REMProxyConstants(REMProxyFactoryRegistry registry) {
+ this.registry = registry;
+ }
+
/*
* Used as the key to the methodCache and invokablesCache when there are parms.
* It allows the parms to be either strings or IBeanTypeProxies without the
@@ -53,7 +60,7 @@
this.methodName = methodName;
}
- protected abstract boolean compareParms(IBeanTypeProxy[] parms);
+ protected abstract boolean compareParms(IProxyBeanType[] parms);
protected abstract boolean compareParms(String[] parms);
@@ -101,7 +108,7 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(org.eclipse.jem.internal.proxy.core.IBeanTypeProxy[])
*/
- protected boolean compareParms(IBeanTypeProxy[] parms) {
+ protected boolean compareParms(IProxyBeanType[] parms) {
if (parms.length != parmNames.length)
return false;
for (int i = 0; i < parms.length; i++) {
@@ -121,13 +128,21 @@
}
private static class MethodKeyProxyParms extends MethodKey {
- public IBeanTypeProxy[] parmTypes;
+ public IProxyBeanType[] parmTypes;
- public MethodKeyProxyParms(String methodName, IBeanTypeProxy[] parmTypes) {
+ public MethodKeyProxyParms(String methodName, IProxyBeanType[] parmTypes) {
super(methodName);
this.parmTypes = parmTypes;
}
+ public Object toMethodKeyStringParms() {
+ String[] parms = new String[parmTypes.length];
+ for (int i = 0; i < parmTypes.length; i++) {
+ parms[i] = parmTypes[i].getTypeName();
+ }
+ return new MethodKeyStringParms(methodName, parms);
+ }
+
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@@ -169,8 +184,14 @@
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(java.lang.String[])
*/
- protected boolean compareParms(IBeanTypeProxy[] parms) {
- return Arrays.equals(parms, parmTypes);
+ protected boolean compareParms(IProxyBeanType[] parms) {
+ if (parms.length != parmTypes.length)
+ return false;
+ for (int i = 0; i < parms.length; i++) {
+ if (!parmTypes[i].getTypeName().equals(parms[i].getTypeName()))
+ return false;
+ }
+ return true;
}
}
@@ -275,41 +296,53 @@
* @param parmTypes = array of qualified type names for the method arguments, null if no methods
*/
public IMethodProxy getMethodProxy(IBeanTypeProxy aBeanTypeProxy, String methodName, String[] parmTypes){
+ if (!registry.isValid())
+ return null;
- REMMETHODCOUNT++;
- // The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods
- Map methods = getMethods(aBeanTypeProxy);
-
- // The syntax of the key is methodName(parmType1,parmType2)
- Object key = null;
- if(parmTypes == null || parmTypes.length == 0){
- key = methodName;
- } else {
- key = new MethodKeyStringParms(methodName, parmTypes);
+ REMMETHODCOUNT++;
+ Map methods;
+ Object key;
+ synchronized (this) {
+ // The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods
+ methods = getMethods(aBeanTypeProxy);
+
+ // The syntax of the key is methodName(parmType1,parmType2)
+ if (parmTypes == null || parmTypes.length == 0) {
+ key = methodName;
+ } else {
+ key = new MethodKeyStringParms(methodName, parmTypes);
+ }
+
+ IMethodProxy result = (IMethodProxy) methods.get(key);
+ if (result != null)
+ return result;
}
- // Lookup the cache'd method proxy
- IMethodProxy result = (IMethodProxy) methods.get(key);
- // Do we have it, and is still valid (in case someone did a release on it).
- if(result != null && result.isValid()) return result;
-
UNIQUEMETHODCOUNT++;
// Get the method proxy and cache this before returning it
- REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) aBeanTypeProxy.getProxyFactoryRegistry().getMethodProxyFactory();
- result = proxyFactory.getMethodProxy((IREMBeanTypeProxy)aBeanTypeProxy,methodName,parmTypes);
- methods.put(key,result);
- return result;
-
+ // Get the method proxy and cache this before returning it
+ REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) registry.getMethodProxyFactory();
+ IMethodProxy result = proxyFactory.getMethodProxy((IREMBeanTypeProxy)aBeanTypeProxy,methodName,parmTypes);
+ synchronized (this) {
+ // Get it again to make sure it hasn't changed due to a race condition. We don't sync for the getMethodProxy because that goes to the remote vm and could deadlock.
+ IMethodProxy mValue = (IMethodProxy) methods.get(key);
+ if (mValue != null && mValue != result) {
+ registry.releaseProxy(result); // Don't need the result now, got it through a race condition.
+ return mValue; // We have a real value now.
+ }
+ methods.put(key, result);
+ }
+ return result;
}
/**
* @param aBeanTypeProxy
* @return Map of cache'd methods
*/
-private Map getMethods(IBeanTypeProxy aBeanTypeProxy) {
- Map methods = (Map) methodsCache.get(aBeanTypeProxy);
+private Map getMethods(IProxyBeanType aBeanTypeProxy) {
+ Map methods = (Map) methodsCache.get(aBeanTypeProxy.getTypeName());
if(methods == null){
methods = new HashMap(20);
- methodsCache.put(aBeanTypeProxy,methods);
+ methodsCache.put(aBeanTypeProxy.getTypeName(),methods);
}
return methods;
}
@@ -329,11 +362,11 @@
* @param aBeanTypeProxy
* @return Map of cache'd fields
*/
-private Map getFields(IBeanTypeProxy aBeanTypeProxy) {
- Map fields = (Map) fieldsCache.get(aBeanTypeProxy);
+private Map getFields(IProxyBeanType aBeanTypeProxy) {
+ Map fields = (Map) fieldsCache.get(aBeanTypeProxy.getTypeName());
if(fields == null){
fields = new HashMap(20);
- fieldsCache.put(aBeanTypeProxy,fields);
+ fieldsCache.put(aBeanTypeProxy.getTypeName(),fields);
}
return fields;
}
@@ -403,31 +436,124 @@
* @param parmTypes = array of qualified type names for the method arguments, null if no methods
*/
public IMethodProxy getMethodProxy(IBeanTypeProxy aBeanTypeProxy, String methodName, IBeanTypeProxy[] parmTypes){
+ if (!registry.isValid())
+ return null;
REMMETHODCOUNT++;
// The classCache map is keyed by the BeanTypeProxy and holds a further map of cache'd methods
- Map methods = getMethods(aBeanTypeProxy);
-
- Object key = null;
- if(parmTypes == null || parmTypes.length == 0){
- key = methodName;
- } else {
- key = new MethodKeyProxyParms(methodName, parmTypes);
- }
-
- // Lookup the cache'd method proxy
- IMethodProxy result = (IMethodProxy) methods.get(key);
- if(result != null) return result;
+ Map methods;
+ Object key;
+ synchronized (this) {
+ methods = getMethods(aBeanTypeProxy);
+
+ key = null;
+ if (parmTypes == null || parmTypes.length == 0) {
+ key = methodName;
+ } else {
+ key = new MethodKeyProxyParms(methodName, parmTypes);
+ }
+
+ IMethodProxy result = (IMethodProxy) methods.get(key);
+ if (result != null)
+ return result;
+ }
UNIQUEMETHODCOUNT++;
// Get the method proxy and cache this before returning it
// Get the method proxy and cache this before returning it
- REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) aBeanTypeProxy.getProxyFactoryRegistry().getMethodProxyFactory();
- result = proxyFactory.getMethodProxy((IREMBeanTypeProxy)aBeanTypeProxy,methodName,parmTypes);
- methods.put(key,result);
+ REMMethodProxyFactory proxyFactory = (REMMethodProxyFactory) registry.getMethodProxyFactory();
+ IMethodProxy result = proxyFactory.getMethodProxy((IREMBeanTypeProxy)aBeanTypeProxy,methodName,parmTypes);
+ synchronized (this) {
+ // Get it again to make sure it hasn't changed due to a race condition. We don't sync for the getMethodProxy because that goes to the remote vm and could deadlock.
+ IMethodProxy mValue = (IMethodProxy) methods.get(key);
+ if (mValue != null && mValue != result) {
+ registry.releaseProxy(result); // Don't need result now, got it already through a race condition.
+ return mValue; // We have a real value now.
+ }
+ methods.put(key, result);
+ }
+
return result;
}
+ /**
+ * Return the proxy method for the method through the expression.
+ * @param expression
+ * @param aBeanTypeProxy
+ * @param methodName
+ * @param parmTypes
+ * @return either the IMethodProxy if already resolved or an ExpressionProxy if not yet resolved.
+ *
+ * @since 1.1.0
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, IProxyBeanType aBeanTypeProxy, String methodName, IProxyBeanType[] parmTypes){
+ if (!registry.isValid())
+ return null;
+
+ REMMETHODCOUNT++;
+ Map methods;
+ Map epMethods;
+ Object key;
+ boolean isKey;
+ synchronized (this) {
+ // The classCache map is keyed by the BeanTypeProxy name and holds a further map of cache'd methods
+ methods = getMethods(aBeanTypeProxy);
+
+ if (parmTypes == null || parmTypes.length == 0) {
+ key = methodName;
+ isKey = false;
+ } else {
+ key = new MethodKeyProxyParms(methodName, parmTypes);
+ isKey = true;
+ }
+
+ IProxyMethod result = (IProxyMethod) methods.get(key);
+ if (result != null)
+ return result;
+
+ // See if stored in the expression.
+ epMethods = ((REMExpression) expression).getMethods(aBeanTypeProxy);
+ result = (IProxyMethod) epMethods.get(key);
+ if (result != null)
+ return result;
+ }
+
+ UNIQUEMETHODCOUNT++;
+ // Get the method expression proxy and cache this before returning it
+ IProxyMethod result = ((Expression) expression).createMethodExpressionProxy(aBeanTypeProxy,methodName,parmTypes);
+ epMethods.put(key, result);
+ final Object epKey = key;
+ final Map rMethods = methods;
+ final Map fepMethods = epMethods;
+ final boolean isKeyType = isKey;
+ ((ExpressionProxy) result).addProxyListener(new ExpressionProxy.ProxyAdapter() {
+ public void proxyResolved(ProxyEvent event) {
+ synchronized (REMProxyConstants.this) {
+ if (rMethods.containsKey(epKey))
+ return; // We already have a true method proxy in there. A race condition occurred.
+
+ // Now put this resolved guy into the methods.
+ // We don't want the key to contain expression proxies in the final map, so if it is a key type
+ // we will turn it into a string type key.
+ Object key;
+ if (isKeyType) {
+ key = ((MethodKeyProxyParms) epKey).toMethodKeyStringParms(); // So that we don't put a ket that contains expression proxy parm types into the main map.
+ } else
+ key = epKey;
+
+ rMethods.put(key, event.getProxy());
+ }
+ }
+
+ public void proxyNotResolved(ExpressionProxy.ProxyEvent event) {
+ synchronized (REMProxyConstants.this) {
+ fepMethods.remove(epKey);
+ }
+ }
+
+ });
+ return result;
+ }
/**
* @param proxy
@@ -474,21 +600,80 @@
* @return The field proxy that is cache'd for performance
*/
public IFieldProxy getFieldProxy(REMAbstractBeanTypeProxy aBeanTypeProxy, String fieldName) {
-
- REMFIELDCOUNT++;
- // The field map is keyed by the BeanTypeProxy and holds a further map of cache'd fields
- Map fields = getFields(aBeanTypeProxy);
+ if (!registry.isValid())
+ return null;
+
+ REMFIELDCOUNT++;
+ Map fields;
+ synchronized (this) {
+ // The field map is keyed by the BeanTypeProxy and holds a further map of cache'd fields
+ fields = getFields(aBeanTypeProxy);
- // Lookup the cache'd Field proxy
- IFieldProxy result = (IFieldProxy) fields.get(fieldName);
- if(result != null && result.isValid()) return result;
+ // Lookup the cache'd Field proxy
+ IFieldProxy result = (IFieldProxy) fields.get(fieldName);
+ if (result != null)
+ return result;
+ }
UNIQUEFIELDCOUNT++;
-
- result = (IFieldProxy) REMStandardBeanProxyConstants.getConstants(aBeanTypeProxy.getProxyFactoryRegistry()).getClassGetField().invokeCatchThrowableExceptions(
+ IFieldProxy result = (IFieldProxy) REMStandardBeanProxyConstants.getConstants(aBeanTypeProxy.getProxyFactoryRegistry()).getClassGetField().invokeCatchThrowableExceptions(
aBeanTypeProxy,
- aBeanTypeProxy.getProxyFactoryRegistry().getBeanProxyFactory().createBeanProxyWith(fieldName));
- fields.put(fieldName,result);
+ registry.getBeanProxyFactory().createBeanProxyWith(fieldName));
+ synchronized (this) {
+ IFieldProxy fValue = (IFieldProxy) fields.get(fieldName);
+ if (fValue != null) {
+ registry.releaseProxy(result); // Don't need it now. A race had put another one in.
+ return fValue;
+ }
+ fields.put(fieldName,result);
+ }
return result;
- }
+ }
+
+ public IProxyField getFieldProxy(IExpression expression, IProxyBeanType aBeanTypeProxy, final String fieldName){
+ if (!registry.isValid())
+ return null;
+
+ REMFIELDCOUNT++;
+ Map fields;
+ Map epFields;
+ synchronized (this) {
+ // The classCache map is keyed by the BeanTypeProxy name and holds a further map of cache'd methods
+ fields = getFields(aBeanTypeProxy);
+
+ IProxyField result = (IProxyField) fields.get(fieldName);
+ if (result != null)
+ return result;
+
+ // See if stored in the expression.
+ epFields = ((REMExpression) expression).getFields(aBeanTypeProxy);
+ result = (IProxyField) epFields.get(fieldName);
+ if (result != null)
+ return result;
+ }
+
+ UNIQUEFIELDCOUNT++;
+ // Get the field expression proxy and cache this before returning it
+ IProxyField result = ((REMExpression) expression).createFieldExpressionProxy(aBeanTypeProxy, fieldName);
+ epFields.put(fieldName, result);
+ final Map fpFields = fields;
+ final Map fepFields = epFields;
+ ((ExpressionProxy) result).addProxyListener(new ExpressionProxy.ProxyAdapter() {
+
+ public void proxyResolved(ProxyEvent event) {
+ synchronized (REMProxyConstants.this) {
+ if (fpFields.containsKey(fieldName))
+ return; // Already set to resolved value by someone else.
+ fpFields.put(fieldName, event.getProxy());
+ }
+ }
+ public void proxyNotResolved(ExpressionProxy.ProxyEvent event) {
+ synchronized (REMProxyConstants.this) {
+ fepFields.remove(fieldName);
+ }
+ }
+ });
+
+ return result;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyFactoryRegistry.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyFactoryRegistry.java
index e27b9cd..ff41049 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyFactoryRegistry.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMProxyFactoryRegistry.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMProxyFactoryRegistry.java,v $
- * $Revision: 1.16 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.17 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -122,7 +122,7 @@
waitRegistrationThread = new WaitForRegistrationThread();
waitRegistrationThread.start();
- // Now we will wait until the connection pool has been locked. The thread will
+ // Now we will wait until the registration callback has been done. The thread will
// signal us when that is done. This is so that we don't continue on and let
// a work connection be requested before we even got a chance to start waiting
// for the registration.
@@ -329,10 +329,12 @@
// The current thread is a call back thread, so just reuse the connection.
// But this thread could actually be trying to access another registry.
// So if this thread is for this registry, use it, if not for this registry, create a new connection.
- if (((REMCallbackThread) thread).registry == this) {
+ // But if for this registry AND is already in a transaction, we need a fresh connection.
+ REMCallbackThread callbackThread = (REMCallbackThread) thread;
+ if (callbackThread.registry == this && !callbackThread.inTransaction()) {
// This way any calls out to the remote vm will be on same thread as callback caller
// on remote vm because that thread is waiting on this connection for commands.
- IREMConnection c = ((REMCallbackThread) thread).getConnection();
+ IREMConnection c = (callbackThread).getConnection();
if (c.isConnected())
return c;
else
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyConstants.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyConstants.java
index 940c929..4d2df21 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyConstants.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyConstants.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMStandardBeanProxyConstants.java,v $
- * $Revision: 1.6 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.7 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -34,7 +34,7 @@
* @author: Administrator
*/
public final class REMStandardBeanProxyConstants {
- public static final String REGISTRY_KEY = "REMSTANDARDPROXYCONSTANTS:"; //$NON-NLS-1$
+ public static final Object REGISTRY_KEY = new Object();
private final ProxyFactoryRegistry fRegistry;
@@ -83,6 +83,7 @@
private IMethodProxy fFieldSet;
private IMethodProxy fConstructorNewInstance;
+ private IMethodProxy fConstructorParameterTypesMessage;
private IMethodProxy fArrayNewInstanceOneDimension;
private IMethodProxy fArrayNewInstanceMultiDimensions;
@@ -299,6 +300,12 @@
return fConstructorNewInstance;
}
+public IMethodProxy getConstructorParameterTypesMessage() {
+ if (fConstructorParameterTypesMessage == null)
+ fConstructorParameterTypesMessage = fRegistry.getMethodProxyFactory().getMethodProxy("java.lang.reflect.Constructor", "getParameterTypes", null); //$NON-NLS-1$ //$NON-NLS-2$
+ return fConstructorParameterTypesMessage;
+}
+
public IMethodProxy getArrayNewInstanceOneDimension() {
if (fArrayNewInstanceOneDimension == null)
fArrayNewInstanceOneDimension = fRegistry.getMethodProxyFactory().getMethodProxy("java.lang.reflect.Array", "newInstance", new String[] {"java.lang.Class", "int"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyFactory.java
index 9985128..3713eab 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanProxyFactory.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMStandardBeanProxyFactory.java,v $
- * $Revision: 1.10 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.11 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -191,13 +191,13 @@
// Synced in here so that we will remove it before some one else from a different thread may try
// to access it again.
if (id.intValue() != Commands.NOT_AN_ID) {
- ProxyRef ref = (ProxyRef) fIDToProxiesMap.remove(id);
+ ProxyRef ref = (ProxyRef) fIDToProxiesMap.get(id);
if (ref == null || ref.decrUseCnt() <= 0) {
// No usage, so do actual release.
+ fIDToProxiesMap.remove(id);
((IREMBeanProxy) proxy).release();
- releaseID(id.intValue());
if (ref != null)
- ref.clear(); // So the proxy will GC with out queuing up.
+ ref.enqueue(); // Queue it up so that on next release cycle it will go away.
}
} else {
((IREMBeanProxy) proxy).release();
@@ -734,6 +734,12 @@
}
}
+public boolean inTransaction() {
+ synchronized (fIDToProxiesMap) {
+ return transactionLockCount != 0;
+ }
+}
+
/**
* Stop Transaction: During the time between start/stop transaction,
* proxies will not be cleaned up. This prevents the case of a two step
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanTypeProxyFactory.java
index c02533a..2476bd5 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMStandardBeanTypeProxyFactory.java
@@ -9,573 +9,681 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jem.internal.proxy.remote;
+
/*
* $RCSfile: REMStandardBeanTypeProxyFactory.java,v $
- * $Revision: 1.9 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.10 $ $Date: 2005/05/11 19:01:12 $
*/
-
import java.text.MessageFormat;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.MapTypes;
import org.eclipse.jem.internal.proxy.common.remote.CommandErrorException;
import org.eclipse.jem.internal.proxy.common.remote.Commands;
/**
- * We are a beanTypeProxyFactory for creating REMBeanTypeProxy objects
- * Primitive types as well as common types like String are cached for speed
- * of lookup.
- * We are the standard one that the VCE uses.
- * Creation date: (12/3/99 2:32:48 PM)
+ * We are a beanTypeProxyFactory for creating REMBeanTypeProxy objects Primitive types as well as common types like String are cached for speed of
+ * lookup. We are the standard one that the VCE uses. Creation date: (12/3/99 2:32:48 PM)
+ *
* @author: Joe Winchester
*/
public final class REMStandardBeanTypeProxyFactory implements IStandardBeanTypeProxyFactory {
-
+
protected final REMProxyFactoryRegistry fFactoryRegistry;
+
protected REMStandardBeanProxyFactory fBeanFactory;
-
-
+
// Hashtable to cache proxies for classes so they are found on second and subsequent lookups
protected Map fBeanProxies = new HashMap(1000);
-
- // A Cache of bean type proxies that should not ever be released. These are the standard ones
+
+ // A Cache of bean type proxies that should not ever be released. These are the standard ones
// that we create here. They are never released because they wouldn't be correctly re-created
// if they were. Also they are standard ones with standard ID's that don't change so they
// don't need to be re-created later.
protected Set fPermanentProxies = new HashSet(30);
-
+
// Cache of requested but not found bean types. If not maintaining the list, this variable will be null.
// The values are strings (classnames in JNI format).
- protected Set fNotFoundTypes = null;
+ protected Set fNotFoundTypes = null;
// Cached copy of a few typical bean type proxies.
REMBeanTypeProxy objectClass;
- REMClassBeanTypeProxy classClass;
+
+ REMClassBeanTypeProxy classClass;
+
REMVoidBeanTypeProxy voidType;
+
REMBooleanTypeBeanTypeProxy booleanType;
+
REMBooleanClassBeanTypeProxy booleanClass;
+
REMIntegerTypeBeanTypeProxy intType;
+
REMIntegerClassBeanTypeProxy integerClass;
+
REMByteTypeBeanTypeProxy byteType;
- REMByteClassBeanTypeProxy byteClass;
- REMShortClassBeanTypeProxy shortClass;
+
+ REMByteClassBeanTypeProxy byteClass;
+
+ REMShortClassBeanTypeProxy shortClass;
+
REMShortTypeBeanTypeProxy shortType;
- REMLongClassBeanTypeProxy longClass;
- REMLongTypeBeanTypeProxy longType;
- REMDoubleClassBeanTypeProxy doubleClass;
- REMDoubleTypeBeanTypeProxy doubleType;
- REMFloatClassBeanTypeProxy floatClass;
- REMFloatTypeBeanTypeProxy floatType;
- REMBigDecimalBeanTypeProxy bigDecimalClass;
- REMBigIntegerBeanTypeProxy bigIntegerClass;
+
+ REMLongClassBeanTypeProxy longClass;
+
+ REMLongTypeBeanTypeProxy longType;
+
+ REMDoubleClassBeanTypeProxy doubleClass;
+
+ REMDoubleTypeBeanTypeProxy doubleType;
+
+ REMFloatClassBeanTypeProxy floatClass;
+
+ REMFloatTypeBeanTypeProxy floatType;
+
+ REMBigDecimalBeanTypeProxy bigDecimalClass;
+
+ REMBigIntegerBeanTypeProxy bigIntegerClass;
+
REMCharacterTypeBeanTypeProxy charType;
- REMCharacterClassBeanTypeProxy characterClass;
+
+ REMCharacterClassBeanTypeProxy characterClass;
+
REMStringBeanTypeProxy stringClass;
-
+
/**
* Available to all REM beantypes.
*/
public REMProxyConstants proxyConstants;
-/**
- * IDEBeanTypeProxyFactory constructor comment.
- */
-REMStandardBeanTypeProxyFactory(REMProxyFactoryRegistry aRegistry) {
- fFactoryRegistry = aRegistry;
- aRegistry.registerBeanTypeProxyFactory(this);
-
- proxyConstants = new REMProxyConstants();
+ /**
+ * IDEBeanTypeProxyFactory constructor comment.
+ */
+ REMStandardBeanTypeProxyFactory(REMProxyFactoryRegistry aRegistry) {
+ fFactoryRegistry = aRegistry;
+ aRegistry.registerBeanTypeProxyFactory(this);
- // Now initialize the cache.
- objectClass = new REMBeanTypeProxy(fFactoryRegistry, new Integer(Commands.OBJECT_CLASS), Object.class.getName(), null);
- classClass = new REMClassBeanTypeProxy(fFactoryRegistry, objectClass);
- voidType = new REMVoidBeanTypeProxy(fFactoryRegistry);
- booleanType = new REMBooleanTypeBeanTypeProxy(fFactoryRegistry);
- booleanClass = new REMBooleanClassBeanTypeProxy(fFactoryRegistry, objectClass);
- IBeanTypeProxy numberClass = objectClass.newBeanTypeForClass(new Integer(Commands.NUMBER_CLASS), Number.class.getName(), true);
- intType = new REMIntegerTypeBeanTypeProxy(fFactoryRegistry);
- integerClass = new REMIntegerClassBeanTypeProxy(fFactoryRegistry, numberClass);
- byteType = new REMByteTypeBeanTypeProxy(fFactoryRegistry);
- byteClass = new REMByteClassBeanTypeProxy(fFactoryRegistry, numberClass);
- shortType = new REMShortTypeBeanTypeProxy(fFactoryRegistry);
- shortClass = new REMShortClassBeanTypeProxy(fFactoryRegistry, numberClass);
- longType = new REMLongTypeBeanTypeProxy(fFactoryRegistry);
- longClass = new REMLongClassBeanTypeProxy(fFactoryRegistry, numberClass);
- doubleType = new REMDoubleTypeBeanTypeProxy(fFactoryRegistry);
- doubleClass = new REMDoubleClassBeanTypeProxy(fFactoryRegistry, numberClass);
- floatType = new REMFloatTypeBeanTypeProxy(fFactoryRegistry);
- floatClass = new REMFloatClassBeanTypeProxy(fFactoryRegistry, numberClass);
- bigDecimalClass = new REMBigDecimalBeanTypeProxy(fFactoryRegistry, numberClass);
- bigIntegerClass = new REMBigIntegerBeanTypeProxy(fFactoryRegistry, numberClass);
- charType = new REMCharacterTypeBeanTypeProxy(fFactoryRegistry);
- characterClass = new REMCharacterClassBeanTypeProxy(fFactoryRegistry, objectClass);
- stringClass = new REMStringBeanTypeProxy(fFactoryRegistry, objectClass);
- IBeanTypeProxy throwableClass = new REMThrowableBeanTypeProxy(fFactoryRegistry, new Integer(Commands.THROWABLE_CLASS), Throwable.class.getName(), objectClass);
- IBeanTypeProxy threadClass = objectClass.newBeanTypeForClass(new Integer(Commands.THREAD_CLASS), Thread.class.getName(), false);
+ proxyConstants = new REMProxyConstants(aRegistry);
- // Initialize the hashtable with the primitives, their lang equivalents, and also common classes like String
+ // Now initialize the cache.
+ objectClass = new REMBeanTypeProxy(fFactoryRegistry, new Integer(Commands.OBJECT_CLASS), Object.class.getName(), null);
+ classClass = new REMClassBeanTypeProxy(fFactoryRegistry, objectClass);
+ voidType = new REMVoidBeanTypeProxy(fFactoryRegistry);
+ booleanType = new REMBooleanTypeBeanTypeProxy(fFactoryRegistry);
+ booleanClass = new REMBooleanClassBeanTypeProxy(fFactoryRegistry, objectClass);
+ IBeanTypeProxy numberClass = objectClass.newBeanTypeForClass(new Integer(Commands.NUMBER_CLASS), Number.class.getName(), true);
+ intType = new REMIntegerTypeBeanTypeProxy(fFactoryRegistry);
+ integerClass = new REMIntegerClassBeanTypeProxy(fFactoryRegistry, numberClass);
+ byteType = new REMByteTypeBeanTypeProxy(fFactoryRegistry);
+ byteClass = new REMByteClassBeanTypeProxy(fFactoryRegistry, numberClass);
+ shortType = new REMShortTypeBeanTypeProxy(fFactoryRegistry);
+ shortClass = new REMShortClassBeanTypeProxy(fFactoryRegistry, numberClass);
+ longType = new REMLongTypeBeanTypeProxy(fFactoryRegistry);
+ longClass = new REMLongClassBeanTypeProxy(fFactoryRegistry, numberClass);
+ doubleType = new REMDoubleTypeBeanTypeProxy(fFactoryRegistry);
+ doubleClass = new REMDoubleClassBeanTypeProxy(fFactoryRegistry, numberClass);
+ floatType = new REMFloatTypeBeanTypeProxy(fFactoryRegistry);
+ floatClass = new REMFloatClassBeanTypeProxy(fFactoryRegistry, numberClass);
+ bigDecimalClass = new REMBigDecimalBeanTypeProxy(fFactoryRegistry, numberClass);
+ bigIntegerClass = new REMBigIntegerBeanTypeProxy(fFactoryRegistry, numberClass);
+ charType = new REMCharacterTypeBeanTypeProxy(fFactoryRegistry);
+ characterClass = new REMCharacterClassBeanTypeProxy(fFactoryRegistry, objectClass);
+ stringClass = new REMStringBeanTypeProxy(fFactoryRegistry, objectClass);
+ IBeanTypeProxy throwableClass = new REMThrowableBeanTypeProxy(fFactoryRegistry, new Integer(Commands.THROWABLE_CLASS), Throwable.class
+ .getName(), objectClass);
+ IBeanTypeProxy threadClass = objectClass.newBeanTypeForClass(new Integer(Commands.THREAD_CLASS), Thread.class.getName(), false);
- // Primitives
- fBeanProxies.put(voidType.getTypeName(), voidType);
- fBeanProxies.put(intType.getTypeName(), intType);
- fBeanProxies.put(booleanType.getTypeName(), booleanType);
- fBeanProxies.put(charType.getTypeName(), charType);
- fBeanProxies.put(byteType.getTypeName(), byteType);
- fBeanProxies.put(shortType.getTypeName(), shortType);
- fBeanProxies.put(longType.getTypeName(), longType);
- fBeanProxies.put(floatType.getTypeName(), floatType);
- fBeanProxies.put(doubleType.getTypeName(), doubleType);
+ // Initialize the hashtable with the primitives, their lang equivalents, and also common classes like String
- // java.lang primitive peers
- // Note that special classes are used for some of these which allow the IDE to get the
- // lang objects from the objects that are holding proxies
- fBeanProxies.put(integerClass.getTypeName(), integerClass);
- fBeanProxies.put(booleanClass.getTypeName(), booleanClass);
- fBeanProxies.put(characterClass.getTypeName(), characterClass);
- fBeanProxies.put(byteClass.getTypeName(), byteClass);
- fBeanProxies.put(shortClass.getTypeName(), shortClass);
- fBeanProxies.put(longClass.getTypeName(), longClass);
- fBeanProxies.put(floatClass.getTypeName(), floatClass);
- fBeanProxies.put(doubleClass.getTypeName(), doubleClass);
- fBeanProxies.put(bigDecimalClass.getTypeName(), bigDecimalClass);
- fBeanProxies.put(bigIntegerClass.getTypeName(), bigIntegerClass);
- fBeanProxies.put(stringClass.getTypeName(), stringClass);
- fBeanProxies.put(throwableClass.getTypeName(), throwableClass);
- fBeanProxies.put(objectClass.getTypeName(), objectClass);
- fBeanProxies.put(classClass.getTypeName(), classClass);
- fBeanProxies.put(numberClass.getTypeName(), numberClass);
- fBeanProxies.put(threadClass.getTypeName(), threadClass);
-
- // Mark these as permanent.
- fPermanentProxies.addAll(fBeanProxies.values());
-}
+ // Primitives
+ fBeanProxies.put(voidType.getTypeName(), voidType);
+ fBeanProxies.put(intType.getTypeName(), intType);
+ fBeanProxies.put(booleanType.getTypeName(), booleanType);
+ fBeanProxies.put(charType.getTypeName(), charType);
+ fBeanProxies.put(byteType.getTypeName(), byteType);
+ fBeanProxies.put(shortType.getTypeName(), shortType);
+ fBeanProxies.put(longType.getTypeName(), longType);
+ fBeanProxies.put(floatType.getTypeName(), floatType);
+ fBeanProxies.put(doubleType.getTypeName(), doubleType);
-/**
- * Initialize AFTER BeanProxyFactory has been created. This is REQUIRED!
- * NOTE: It is package protected so that only REMStandardBeanProxyFactory can call it when ready.
- */
-synchronized void initialize(REMStandardBeanProxyFactory proxyFactory) {
- fBeanFactory = proxyFactory;
- fBeanFactory.registerProxies(fBeanProxies.values());
-}
-
-
-/*
- * This is called when we know we don't have the class registered, so
- * we need to create the proxy. We have a connection passed in and will reuse it as necessary
- *
- * It is important that this be called only from within a transaction.
- */
-private synchronized IREMBeanTypeProxy createBeanTypeProxy(String typeName, IREMConnection connection) throws CommandException {
-
- // We don't have the beantype proxy, so create it.
- IREMBeanTypeProxy beanTypeProxy = null;
- Commands.GetClassReturn ret = null;
- try {
- ret = getClassReturn(connection, typeName);
- } catch (ThrowableProxy ep) {
- // Print out the trace and return proxy with init error.
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", ep)); //$NON-NLS-1$
- IREMBeanTypeProxy proxy = new REMInitErrorBeanTypeProxy(fFactoryRegistry, MessageFormat.format(ProxyRemoteMessages.getString("ExceptionErrorMsg_EXC_"), new Object[] {ep.getTypeProxy().getTypeName(), ep.getProxyLocalizedMessage()}), typeName); //$NON-NLS-1$
- registerBeanTypeProxy(proxy, false);
- return proxy;
- }
- if (ret == null) {
- if (fNotFoundTypes != null)
- fNotFoundTypes.add(typeName);
- return null; // The class doesn't even exist on the server.
+ // java.lang primitive peers
+ // Note that special classes are used for some of these which allow the IDE to get the
+ // lang objects from the objects that are holding proxies
+ fBeanProxies.put(integerClass.getTypeName(), integerClass);
+ fBeanProxies.put(booleanClass.getTypeName(), booleanClass);
+ fBeanProxies.put(characterClass.getTypeName(), characterClass);
+ fBeanProxies.put(byteClass.getTypeName(), byteClass);
+ fBeanProxies.put(shortClass.getTypeName(), shortClass);
+ fBeanProxies.put(longClass.getTypeName(), longClass);
+ fBeanProxies.put(floatClass.getTypeName(), floatClass);
+ fBeanProxies.put(doubleClass.getTypeName(), doubleClass);
+ fBeanProxies.put(bigDecimalClass.getTypeName(), bigDecimalClass);
+ fBeanProxies.put(bigIntegerClass.getTypeName(), bigIntegerClass);
+ fBeanProxies.put(stringClass.getTypeName(), stringClass);
+ fBeanProxies.put(throwableClass.getTypeName(), throwableClass);
+ fBeanProxies.put(objectClass.getTypeName(), objectClass);
+ fBeanProxies.put(classClass.getTypeName(), classClass);
+ fBeanProxies.put(numberClass.getTypeName(), numberClass);
+ fBeanProxies.put(threadClass.getTypeName(), threadClass);
+
+ // Mark these as permanent.
+ fPermanentProxies.addAll(fBeanProxies.values());
}
- if (typeName.charAt(0) != '[') {
- // It is not an array.
- IREMBeanTypeProxy superTypeProxy = null;
- if (!ret.isInterface && ret.superClassname.length() != 0) {
- // Get the beantype proxy of the superclass.
- superTypeProxy = getBeanTypeProxy(ret.superClassname, connection);
- }
-
- // First check with the factory for the package of the class.
- // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
- // the package ended and the class started. This check is here in case the
- // extension factory can handle this class but needs the id from the server to
- // create it.
- int packageIndex = typeName.lastIndexOf('.');
- if (packageIndex != -1) {
- String packageName = typeName.substring(0, packageIndex);
- IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
- if (packageFactory != null) {
- beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName, new Integer(ret.classID), superTypeProxy);
- if (beanTypeProxy != null) {
- registerBeanTypeProxy(beanTypeProxy, false);
- return beanTypeProxy;
- }
- }
- }
-
- if (ret.isInterface) {
- // Interface never have a super type, so we will create a specific type.
- beanTypeProxy = new REMInterfaceBeanTypeProxy(fFactoryRegistry, new Integer(ret.classID), typeName);
- } else {
- // Ask the supertype
- // to create a beantype proxy of the same beantype proxy class.
- // This is so that any subclasses will get the same beantype proxy class
- // for it if it is special.
- if (superTypeProxy != null)
- beanTypeProxy = superTypeProxy.newBeanTypeForClass(new Integer(ret.classID), typeName, ret.isAbstract);
- }
- } else
- beanTypeProxy = new REMArrayBeanTypeProxy(fFactoryRegistry, new Integer(ret.classID), typeName, objectClass);
-
- // Cache the instance so we can re-use it again
- if (beanTypeProxy != null)
- registerBeanTypeProxy(beanTypeProxy, false);
- return beanTypeProxy;
-}
-/**
- * Using the helper class to find a class by name, then create the proxy.
- */
-public IBeanTypeProxy getBeanTypeProxy(String typeName) {
- try {
- return getBeanTypeProxy(MapTypes.getJNIFormatName(typeName), (IREMConnection) null);
- } catch (CommandException e) {
- // Try once more (we won't have received recoverable exceptions here, they were already caught and handled)
+ /**
+ * Initialize AFTER BeanProxyFactory has been created. This is REQUIRED! NOTE: It is package protected so that only REMStandardBeanProxyFactory
+ * can call it when ready.
+ */
+ synchronized void initialize(REMStandardBeanProxyFactory proxyFactory) {
+ fBeanFactory = proxyFactory;
+ fBeanFactory.registerProxies(fBeanProxies.values());
+ }
+
+ /*
+ * This is called when we know we don't have the class registered, so we need to create the proxy. We have a connection passed in and will reuse
+ * it as necessary
+ *
+ * It is important that this be called only from within a transaction.
+ */
+ private synchronized IREMBeanTypeProxy createBeanTypeProxy(String typeName, IREMConnection connection) throws CommandException {
+
+ // We don't have the beantype proxy, so create it.
+ IREMBeanTypeProxy beanTypeProxy = null;
+ Commands.GetClassReturn ret = null;
try {
- return getBeanTypeProxy(typeName, (IREMConnection) null);
- } catch (CommandException eAgain) {
- // Failed again.
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
+ ret = getClassReturn(connection, typeName);
+ } catch (ThrowableProxy ep) {
+ // Print out the trace and return proxy with init error.
+ ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", ep)); //$NON-NLS-1$
+ IREMBeanTypeProxy proxy = new REMInitErrorBeanTypeProxy(fFactoryRegistry, MessageFormat.format(ProxyRemoteMessages
+ .getString("ExceptionErrorMsg_EXC_"), new Object[] { ep.getTypeProxy().getTypeName(), ep.getProxyLocalizedMessage()}), typeName); //$NON-NLS-1$
+ registerBeanTypeProxy(proxy, false);
+ return proxy;
}
- }
- return null;
-}
-
-/**
- * One that internally allows that we already have a connection to work with.
- * If the connection is null, then one will be created.
- *
- * It is important that if the connection is not null, then we are in a transaction.
- */
-private synchronized IREMBeanTypeProxy getBeanTypeProxy(String typeName, IREMConnection inConnect) throws CommandException {
+ if (ret == null) {
+ if (fNotFoundTypes != null)
+ fNotFoundTypes.add(typeName);
+ return null; // The class doesn't even exist on the server.
+ }
- // See whether we already have the proxy for the argument name
- IREMBeanTypeProxy beanTypeProxy = (IREMBeanTypeProxy) fBeanProxies.get(typeName);
- if (beanTypeProxy != null) {
- return beanTypeProxy;
- }
+ if (typeName.charAt(0) != '[') {
+ // It is not an array.
+ IREMBeanTypeProxy superTypeProxy = null;
+ if (!ret.isInterface && ret.superClassname.length() != 0) {
+ // Get the beantype proxy of the superclass.
+ superTypeProxy = getBeanTypeProxy(ret.superClassname, connection);
+ }
- // If not an array, then see if the package extension mechanism can find it.
- // Do this here so that if it is found in the package extension we won't necessarily create an
- // extra connection when not needed.
- if (typeName.charAt(0) != '[') {
- // It is not an array
- // First check with the factory for the package of the class.
- // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
- // the package ended and the class started.
- int packageIndex = typeName.lastIndexOf('.');
- if (packageIndex != -1) {
- String packageName = typeName.substring(0, packageIndex);
- IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
- if (packageFactory != null) {
- beanTypeProxy = (IREMBeanTypeProxy) packageFactory.getExtensionBeanTypeProxy(typeName);
- if (beanTypeProxy != null) {
- registerBeanTypeProxy(beanTypeProxy, false);
- return beanTypeProxy;
+ // First check with the factory for the package of the class.
+ // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
+ // the package ended and the class started. This check is here in case the
+ // extension factory can handle this class but needs the id from the server to
+ // create it.
+ int packageIndex = typeName.lastIndexOf('.');
+ if (packageIndex != -1) {
+ String packageName = typeName.substring(0, packageIndex);
+ IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
+ if (packageFactory != null) {
+ beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName, new Integer(ret.classID), superTypeProxy);
+ if (beanTypeProxy != null) {
+ registerBeanTypeProxy(beanTypeProxy, false);
+ return beanTypeProxy;
+ }
}
}
- }
- }
-
- IREMConnection connect = inConnect != null ? inConnect : fFactoryRegistry.getFreeConnection();
- if (inConnect == null)
- fBeanFactory.startTransaction(); // Start a transation.
- try {
- return createBeanTypeProxy(typeName, connect);
- } catch (CommandException e) {
- if (inConnect == null) {
- // Need to close the connection, not return it.
- fFactoryRegistry.closeConnection(connect);
- connect = null; // So that it won't be returned.
- }
- throw e; // Pass it on up
- } finally {
- if (inConnect == null)
- fBeanFactory.stopTransaction();
- if (inConnect == null && connect != null)
- fFactoryRegistry.returnConnection(connect);
- }
-}
-/*
- * It is important this be called only from within a transaction.
- */
-private Commands.GetClassReturn getClassReturn(IREMConnection connection, String className) throws CommandException, ThrowableProxy {
- try {
- return connection.getClass(className);
- } catch (CommandErrorException e) {
- fBeanFactory.processErrorReturn(e); // Let proxy factory handle the error return
- }
- return null;
-}
-
-/**
- * Return an Array type proxy for the given class name of
- * the specified dimensions. This is a helper method. The
- * same result can be gotton from getBeanTypeProxy.
- * e.g.
- * getBeanTypeProxy("java.lang.Object", 3)
- * is the same as:
- * getBeanTypeProxy("[[[Ljava.lang.Object;")
- *
- * They both result in a type of:
- * Object [][][]
- *
- * or
- * getBeanTypeProxy("[Ljava.langObject;", 3)
- * becomes
- * Object [][][][]
- */
-public IBeanTypeProxy getBeanTypeProxy(String componentClassName, int dimensions) {
- String jniComponentClassName = MapTypes.getJNIFormatName(componentClassName);
- String compType = jniComponentClassName;
- if (jniComponentClassName.charAt(0) != '[') {
- // We're not already an array, so create correct template.
- compType = (String) MapTypes.MAP_TYPENAME_TO_SHORTSIG.get(jniComponentClassName);
- if (compType == null) {
- // It is a class, and not a type.
- compType = "L"+jniComponentClassName+";"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
- // Now create it with the appropriate number of '[' in front.
- StringBuffer buffer = new StringBuffer(dimensions+compType.length());
- for (int i=0; i<dimensions; i++)
- buffer.append('[');
- buffer.append(compType);
- return getBeanTypeProxy(buffer.toString());
-}
-
-/**
- * Get the bean type proxy from a class id. This means that a new class id
- * was sent back from the server that we don't have yet. We need to go ask
- * the server for information on this type so that we can create it.
- *
- * NOTE: This is package protected so that only the standard bean proxy factory
- * can call it.
- *
- * It is important that this has been called within a transaction.
- */
-IREMBeanTypeProxy createBeanTypeProxy(Integer classID) {
- IREMConnection connect = fFactoryRegistry.getFreeConnection();
- try {
- return createBeanTypeProxy(classID, connect);
- } catch (CommandException e) {
- if (e.isRecoverable()) {
- // It is recoverable, print message, keep connection live and return it.
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
- } else {
- // Try again, close connection, get a new one.
- fFactoryRegistry.closeConnection(connect);
- connect = null;
- connect = fFactoryRegistry.getFreeConnection();
- try {
- return createBeanTypeProxy(classID, connect);
- } catch (CommandException eAgain) {
- // Failed again. Close connection, don't return it.
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
- fFactoryRegistry.closeConnection(connect);
- connect = null;
+ if (ret.isInterface) {
+ // Interface never have a super type, so we will create a specific type.
+ beanTypeProxy = new REMInterfaceBeanTypeProxy(fFactoryRegistry, new Integer(ret.classID), typeName);
+ } else {
+ // Ask the supertype
+ // to create a beantype proxy of the same beantype proxy class.
+ // This is so that any subclasses will get the same beantype proxy class
+ // for it if it is special.
+ if (superTypeProxy != null)
+ beanTypeProxy = superTypeProxy.newBeanTypeForClass(new Integer(ret.classID), typeName, ret.isAbstract);
}
- }
- } finally {
- if (connect != null)
- fFactoryRegistry.returnConnection(connect);
- }
- return null;
-}
+ } else
+ beanTypeProxy = new REMArrayBeanTypeProxy(fFactoryRegistry, new Integer(ret.classID), typeName, objectClass);
-/*
- * One that internally allows that we already have a connection to work with.
- * If the connection is null, then one will be created.
- *
- * It is important this be called only from within a transaction.
- */
-private synchronized IREMBeanTypeProxy createBeanTypeProxy(Integer classID, IREMConnection connect) throws CommandException {
- // We don't have the beantype proxy, so create it.
- IREMBeanTypeProxy beanTypeProxy = null;
-
- Commands.GetClassIDReturn ret = null;
- try {
- ret = getClassIDReturn(connect, classID);
- } catch (ThrowableProxy ep) {
- // Just print out the trace and return proxy not found.
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", ep)); //$NON-NLS-1$
- return null;
- }
-
- // If the signature is that of a class.
- if (ret.className.charAt(0) != '[') {
- // It is not an array.
- IREMBeanTypeProxy superTypeProxy = null;
- if (!ret.isInterface && ret.superClassname.length() != 0) {
- // Get the beantype proxy of the superclass.
- superTypeProxy = getBeanTypeProxy(ret.superClassname, connect);
- }
-
- // First check with the factory for the package of the class.
- // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
- // the package ended and the class started.
- int packageIndex = ret.className.lastIndexOf('.');
- if (packageIndex != -1) {
- String packageName = ret.className.substring(0, packageIndex);
- IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
- if (packageFactory != null) {
- beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(ret.className, classID, superTypeProxy);
- if (beanTypeProxy != null) {
- registerBeanTypeProxy(beanTypeProxy, false);
- return beanTypeProxy;
- }
- }
- }
-
- if (ret.isInterface) {
- // Interface never have a super type, so we will let the object class do it for us.
- beanTypeProxy = new REMInterfaceBeanTypeProxy(fFactoryRegistry, classID, ret.className);
- } else {
- // Ask the beantype proxy of the superclass
- // to create a beantype proxy of the same beantype proxy class.
- // This is so that any subclasses will get the same beantype proxy class
- // for it if it is special.
- if (superTypeProxy != null)
- beanTypeProxy = superTypeProxy.newBeanTypeForClass(classID, ret.className, ret.isAbstract);
- }
-
// Cache the instance so we can re-use it again
- if (beanTypeProxy != null)
+ if (beanTypeProxy != null)
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
- } else {
- // It is an array.
- beanTypeProxy = new REMArrayBeanTypeProxy(fFactoryRegistry, classID, ret.className, objectClass );
+ }
+
+ /**
+ * Using the helper class to find a class by name, then create the proxy.
+ */
+ public IBeanTypeProxy getBeanTypeProxy(String typeName) {
+ try {
+ return getBeanTypeProxy(MapTypes.getJNIFormatName(typeName), (IREMConnection) null);
+ } catch (CommandException e) {
+ // Try once more (we won't have received recoverable exceptions here, they were already caught and handled)
+ try {
+ return getBeanTypeProxy(typeName, (IREMConnection) null);
+ } catch (CommandException eAgain) {
+ // Failed again.
+ ProxyPlugin.getPlugin().getLogger().log(
+ new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IExpression,
+ * java.lang.String)
+ */
+ public synchronized IProxyBeanType getBeanTypeProxy(IExpression expression, String typeName) {
+ typeName = MapTypes.getJNIFormatName(typeName);
+ // See whether we already have the proxy for the argument name
+ IProxyBeanType beanTypeProxy = (IProxyBeanType) fBeanProxies.get(typeName);
+ if (beanTypeProxy != null)
+ return beanTypeProxy;
+
+ // Now see if an expression proxy cached.
+ beanTypeProxy = ((REMExpression) expression).getBeanType(typeName);
+ if (beanTypeProxy != null)
+ return beanTypeProxy;
+
+ // If not an array, then see if the package extension mechanism can find it.
+ // Do this here so that if it is found in the package extension we won't necessarily create an
+ // extra connection when not needed.
+ if (typeName.charAt(0) != '[') {
+ // It is not an array
+ // First check with the factory for the package of the class.
+ // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
+ // the package ended and the class started.
+ int packageIndex = typeName.lastIndexOf('.');
+ if (packageIndex != -1) {
+ String packageName = typeName.substring(0, packageIndex);
+ IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
+ if (packageFactory != null) {
+ beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName, expression);
+ if (beanTypeProxy != null) {
+ registerBeanTypeProxy(beanTypeProxy, false);
+ return beanTypeProxy;
+ }
+ }
+ }
+ }
+
+ // Need to create the expression proxy for it.
+ beanTypeProxy = ((Expression) expression).createBeanTypeExpressionProxy(typeName);
registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
- }
-}
-/*
- * It is important that this be called only from within a transaction.
- */
-private Commands.GetClassIDReturn getClassIDReturn(IREMConnection connection, Integer classID) throws CommandException, ThrowableProxy {
- try {
- return connection.getClassFromID(classID.intValue());
- } catch (CommandErrorException e) {
- fBeanFactory.processErrorReturn(e); // Let proxy factory handle the error return
}
- return null;
-}
+ /**
+ * One that internally allows that we already have a connection to work with. If the connection is null, then one will be created.
+ *
+ * It is important that if the connection is not null, then we are in a transaction.
+ */
+ private synchronized IREMBeanTypeProxy getBeanTypeProxy(String typeName, IREMConnection inConnect) throws CommandException {
+ // See whether we already have the proxy for the argument name
+ IProxyBeanType beanTypeProxy = (IProxyBeanType) fBeanProxies.get(typeName);
+ // See if there and resolved, if so, return it. If not resolved, that means we need it NOW
+ // so we must go for it. When finally resolved the original ExpressionProxy will be deregistered and
+ // the resolved beantypeproxy will be in its place.
+ if (beanTypeProxy != null && beanTypeProxy.isBeanProxy()) { return (IREMBeanTypeProxy) beanTypeProxy; }
-/**
- * registerBeanTypeProxy.
- * Register this bean type proxy on behalf of the
- * custom factory. This is so that during initializations,
- * the custom factory can cache specific bean type proxies
- * ahead of time.
- *
- * The permanent flag indicates whether this bean type should never be
- * released (i.e. not even explicitly released).
- */
-public synchronized void registerBeanTypeProxy(IBeanTypeProxy aBeanTypeProxy, boolean permanent) {
- fBeanProxies.put(aBeanTypeProxy.getTypeName(), aBeanTypeProxy);
- fBeanFactory.registerProxy((IREMBeanProxy) aBeanTypeProxy);
- if (permanent)
- fPermanentProxies.add(aBeanTypeProxy);
-}
+ // If not an array, then see if the package extension mechanism can find it.
+ // Do this here so that if it is found in the package extension we won't necessarily create an
+ // extra connection when not needed.
+ if (typeName.charAt(0) != '[') {
+ // It is not an array
+ // First check with the factory for the package of the class.
+ // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
+ // the package ended and the class started.
+ int packageIndex = typeName.lastIndexOf('.');
+ if (packageIndex != -1) {
+ String packageName = typeName.substring(0, packageIndex);
+ IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
+ if (packageFactory != null) {
+ beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName);
+ if (beanTypeProxy != null) {
+ registerBeanTypeProxy((IREMBeanTypeProxy) beanTypeProxy, false);
+ return (IREMBeanTypeProxy) beanTypeProxy;
+ }
+ }
+ }
+ }
-/**
- * A beantype proxy is asked to be released. We can only
- * release ones that were not in the permanent set that we
- * initialized with. Those in the permanent set can't be changed
- * so we can't release them.
- *
- * Answer whether it can be released from the server
- * too.
- *
- * NOTE: Package protected since only REMStandardBeanProxyFactory should call it.
- */
-boolean releaseProxy(IBeanTypeProxy proxy) {
-/** Currently we won't allow any bean type proxies to be released. We don't have a good
- * strategy for handling that there may be hard refs from subtypes. One thought is that
- * beanproxies table should store SoftReferences so that only when space is needed,
- * that any beantype that doesn't have a subtype (since subtypes hold a strong ref) or,
- * is in the permanent table (since that is hardref) could be GC'd. Then what would happen
- * is on releaseProxy we don't actually release, we change it to a WeakRef so that it would
- * definitely be released on a GC. These are complicated arch. and we're not sure if it
- * should be allowed or not. So for now, we don't allow them to be released.
- if (!fPermanentProxies.contains(proxy)) {
- // We can release it. It is not one of the permanent ones.
- synchronized(this) {
- fBeanProxies.remove(proxy.getTypeName());
- return true;
+ IREMConnection connect = inConnect != null ? inConnect : fFactoryRegistry.getFreeConnection();
+ if (inConnect == null)
+ fBeanFactory.startTransaction(); // Start a transation.
+ try {
+ return createBeanTypeProxy(typeName, connect);
+ } catch (CommandException e) {
+ if (inConnect == null) {
+ // Need to close the connection, not return it.
+ fFactoryRegistry.closeConnection(connect);
+ connect = null; // So that it won't be returned.
+ }
+ throw e; // Pass it on up
+ } finally {
+ if (inConnect == null)
+ fBeanFactory.stopTransaction();
+ if (inConnect == null && connect != null)
+ fFactoryRegistry.returnConnection(connect);
}
}
-*/
- return false;
-}
-/*
- * Terminate this factory. Since all of the proxies are registered in the
- * proxy factory, there is no need to release them here. There is no
- * need to clear out any fields since this factory will not be held onto
- * by anything and so it will be GC'd.
- */
-public void terminateFactory(boolean wait) {
-}
+ /*
+ * It is important this be called only from within a transaction.
+ */
+ private Commands.GetClassReturn getClassReturn(IREMConnection connection, String className) throws CommandException, ThrowableProxy {
+ try {
+ return connection.getClass(className);
+ } catch (CommandErrorException e) {
+ fBeanFactory.processErrorReturn(e); // Let proxy factory handle the error return
+ }
+ return null;
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeRegistered(String)
- */
-public synchronized boolean isBeanTypeRegistered(String className) {
- return fBeanProxies.containsKey(MapTypes.getJNIFormatName(className));
-}
+ /**
+ * Return an Array type proxy for the given class name of the specified dimensions. This is a helper method. The same result can be gotton from
+ * getBeanTypeProxy. e.g. getBeanTypeProxy("java.lang.Object", 3) is the same as: getBeanTypeProxy("[[[Ljava.lang.Object;")
+ *
+ * They both result in a type of: Object [][][]
+ *
+ * or getBeanTypeProxy("[Ljava.langObject;", 3) becomes Object [][][][]
+ */
+ public IBeanTypeProxy getBeanTypeProxy(String componentClassName, int dimensions) {
+ return getBeanTypeProxy(getArrayClassName(componentClassName, dimensions));
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registeredTypes()
- */
-public Set registeredTypes() {
- return fBeanProxies.keySet();
-}
+ /**
+ * @param componentClassName
+ * @param dimensions
+ * @return
+ *
+ * @since 1.1.0
+ */
+ private String getArrayClassName(String componentClassName, int dimensions) {
+ String jniComponentClassName = MapTypes.getJNIFormatName(componentClassName);
+ String compType = jniComponentClassName;
+ if (jniComponentClassName.charAt(0) != '[') {
+ // We're not already an array, so create correct template.
+ compType = (String) MapTypes.MAP_TYPENAME_TO_SHORTSIG.get(jniComponentClassName);
+ if (compType == null) {
+ // It is a class, and not a type.
+ compType = "L" + jniComponentClassName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeNotFound(String)
- */
-public synchronized boolean isBeanTypeNotFound(String className) {
- return fNotFoundTypes != null && fNotFoundTypes.contains(MapTypes.getJNIFormatName(className));
-}
+ // Now create it with the appropriate number of '[' in front.
+ StringBuffer buffer = new StringBuffer(dimensions + compType.length());
+ for (int i = 0; i < dimensions; i++)
+ buffer.append('[');
+ buffer.append(compType);
+ return buffer.toString();
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isMaintainNotFoundTypes()
- */
-public synchronized boolean isMaintainNotFoundTypes() {
- return fNotFoundTypes != null;
-}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IExpression,
+ * java.lang.String, int)
+ */
+ public IProxyBeanType getBeanTypeProxy(IExpression expression, String componentClassName, int dimensions) {
+ return getBeanTypeProxy(expression, getArrayClassName(componentClassName, dimensions));
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#setMaintainNotFoundTypes(boolean)
- */
-public synchronized void setMaintainNotFoundTypes(boolean maintain) {
- if (maintain) {
- if (fNotFoundTypes == null)
- fNotFoundTypes = new HashSet();
- } else
- fNotFoundTypes = null;
-}
+ /**
+ * Get the bean type proxy from a class id. This means that a new class id was sent back from the server that we don't have yet. We need to go ask
+ * the server for information on this type so that we can create it.
+ *
+ * NOTE: This is package protected so that only the standard bean proxy factory can call it.
+ *
+ * It is important that this has been called within a transaction.
+ */
+ IREMBeanTypeProxy createBeanTypeProxy(Integer classID) {
+ IREMConnection connect = fFactoryRegistry.getFreeConnection();
+ try {
+ return createBeanTypeProxy(classID, connect);
+ } catch (CommandException e) {
+ if (e.isRecoverable()) {
+ // It is recoverable, print message, keep connection live and return it.
+ ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
+ } else {
+ // Try again, close connection, get a new one.
+ fFactoryRegistry.closeConnection(connect);
+ connect = null;
+ connect = fFactoryRegistry.getFreeConnection();
+ try {
+ return createBeanTypeProxy(classID, connect);
+ } catch (CommandException eAgain) {
+ // Failed again. Close connection, don't return it.
+ ProxyPlugin.getPlugin().getLogger().log(
+ new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", eAgain)); //$NON-NLS-1$
+ fFactoryRegistry.closeConnection(connect);
+ connect = null;
+ }
+ }
+ } finally {
+ if (connect != null)
+ fFactoryRegistry.returnConnection(connect);
+ }
+ return null;
+ }
+
+ /*
+ * One that internally allows that we already have a connection to work with. If the connection is null, then one will be created.
+ *
+ * It is important this be called only from within a transaction.
+ */
+ private synchronized IREMBeanTypeProxy createBeanTypeProxy(Integer classID, IREMConnection connect) throws CommandException {
+ // We don't have the beantype proxy, so create it.
+ IREMBeanTypeProxy beanTypeProxy = null;
+
+ Commands.GetClassIDReturn ret = null;
+ try {
+ ret = getClassIDReturn(connect, classID);
+ } catch (ThrowableProxy ep) {
+ // Just print out the trace and return proxy not found.
+ ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", ep)); //$NON-NLS-1$
+ return null;
+ }
+
+ // If the signature is that of a class.
+ if (ret.className.charAt(0) != '[') {
+ // It is not an array.
+ IREMBeanTypeProxy superTypeProxy = null;
+ if (!ret.isInterface && ret.superClassname.length() != 0) {
+ // Get the beantype proxy of the superclass.
+ superTypeProxy = getBeanTypeProxy(ret.superClassname, connect);
+ }
+
+ // First check with the factory for the package of the class.
+ // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
+ // the package ended and the class started.
+ int packageIndex = ret.className.lastIndexOf('.');
+ if (packageIndex != -1) {
+ String packageName = ret.className.substring(0, packageIndex);
+ IREMBeanTypeProxyFactory packageFactory = (IREMBeanTypeProxyFactory) fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
+ if (packageFactory != null) {
+ beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(ret.className, classID, superTypeProxy);
+ if (beanTypeProxy != null) {
+ registerBeanTypeProxy(beanTypeProxy, false);
+ return beanTypeProxy;
+ }
+ }
+ }
+
+ if (ret.isInterface) {
+ // Interface never have a super type, so we will let the object class do it for us.
+ beanTypeProxy = new REMInterfaceBeanTypeProxy(fFactoryRegistry, classID, ret.className);
+ } else {
+ // Ask the beantype proxy of the superclass
+ // to create a beantype proxy of the same beantype proxy class.
+ // This is so that any subclasses will get the same beantype proxy class
+ // for it if it is special.
+ if (superTypeProxy != null)
+ beanTypeProxy = superTypeProxy.newBeanTypeForClass(classID, ret.className, ret.isAbstract);
+ }
+
+ // Cache the instance so we can re-use it again
+ if (beanTypeProxy != null)
+ registerBeanTypeProxy(beanTypeProxy, false);
+ return beanTypeProxy;
+ } else {
+ // It is an array.
+ beanTypeProxy = new REMArrayBeanTypeProxy(fFactoryRegistry, classID, ret.className, objectClass);
+ registerBeanTypeProxy(beanTypeProxy, false);
+ return beanTypeProxy;
+ }
+ }
+
+ /*
+ * It is important that this be called only from within a transaction.
+ */
+ private Commands.GetClassIDReturn getClassIDReturn(IREMConnection connection, Integer classID) throws CommandException, ThrowableProxy {
+ try {
+ return connection.getClassFromID(classID.intValue());
+ } catch (CommandErrorException e) {
+ fBeanFactory.processErrorReturn(e); // Let proxy factory handle the error return
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registerBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IBeanTypeProxy,
+ * boolean)
+ */
+ public synchronized void registerBeanTypeProxy(IBeanTypeProxy aBeanTypeProxy, boolean permanent) {
+ fBeanProxies.put(aBeanTypeProxy.getTypeName(), aBeanTypeProxy);
+ fBeanFactory.registerProxy((IREMBeanProxy) aBeanTypeProxy);
+ if (permanent)
+ fPermanentProxies.add(aBeanTypeProxy);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registerBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType,
+ * boolean)
+ */
+ public void registerBeanTypeProxy(IProxyBeanType aProxyBeanType, final boolean permanent) {
+ if (aProxyBeanType.isBeanProxy())
+ registerBeanTypeProxy((IBeanTypeProxy) aProxyBeanType, permanent); // A regular kind, do regular registration.
+ else {
+ ExpressionProxy beanExpressionProxy = ((ExpressionProxy) aProxyBeanType);
+ final String typeName = aProxyBeanType.getTypeName();
+ ((REMExpression) beanExpressionProxy.getExpression()).addBeanType(typeName, aProxyBeanType);
+ beanExpressionProxy.addProxyListener(new ExpressionProxy.ProxyAdapter() {
+
+ public void proxyResolved(ProxyEvent event) {
+ String typeName = ((IProxyBeanType) event.getSource()).getTypeName();
+ synchronized (REMStandardBeanTypeProxyFactory.this) {
+ if (!fBeanProxies.containsKey(typeName)) {
+ // It hasn't been resolved through some other means. So this is good. Actually this should never
+ // occur because upon resolution we've already registered the bean type proxy through the
+ // normal mechanisms. But to be safe, we'll do it here.
+ fBeanProxies.put(typeName, event.getProxy());
+ if (permanent)
+ fPermanentProxies.add(event.getProxy());
+ }
+ }
+ }
+
+ public void proxyNotResolved(ExpressionProxy.ProxyEvent event) {
+ ((REMExpression) ((ExpressionProxy) event.getSource()).getExpression()).removeBeanType(typeName);
+ }
+ });
+ }
+
+ }
+
+ /**
+ * A beantype proxy is asked to be released. We can only release ones that were not in the permanent set that we initialized with. Those in the
+ * permanent set can't be changed so we can't release them.
+ *
+ * Answer whether it can be released from the server too.
+ *
+ * NOTE: Package protected since only REMStandardBeanProxyFactory should call it.
+ */
+ boolean releaseProxy(IBeanTypeProxy proxy) {
+ /**
+ * Currently we won't allow any bean type proxies to be released. We don't have a good strategy for handling that there may be hard refs from
+ * subtypes. One thought is that beanproxies table should store SoftReferences so that only when space is needed, that any beantype that
+ * doesn't have a subtype (since subtypes hold a strong ref) or, is in the permanent table (since that is hardref) could be GC'd. Then what
+ * would happen is on releaseProxy we don't actually release, we change it to a WeakRef so that it would definitely be released on a GC. These
+ * are complicated arch. and we're not sure if it should be allowed or not. So for now, we don't allow them to be released. if
+ * (!fPermanentProxies.contains(proxy)) { // We can release it. It is not one of the permanent ones. synchronized(this) {
+ * fBeanProxies.remove(proxy.getTypeName()); return true; } }
+ */
+ return false;
+ }
+
+ /*
+ * Terminate this factory. Since all of the proxies are registered in the proxy factory, there is no need to release them here. There is no need
+ * to clear out any fields since this factory will not be held onto by anything and so it will be GC'd.
+ */
+ public void terminateFactory(boolean wait) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeRegistered(String)
+ */
+ public synchronized boolean isBeanTypeRegistered(String className) {
+ return fBeanProxies.containsKey(MapTypes.getJNIFormatName(className));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registeredTypes()
+ */
+ public Set registeredTypes() {
+ return fBeanProxies.keySet();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeNotFound(String)
+ */
+ public synchronized boolean isBeanTypeNotFound(String className) {
+ return fNotFoundTypes != null && fNotFoundTypes.contains(MapTypes.getJNIFormatName(className));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isMaintainNotFoundTypes()
+ */
+ public synchronized boolean isMaintainNotFoundTypes() {
+ return fNotFoundTypes != null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#setMaintainNotFoundTypes(boolean)
+ */
+ public synchronized void setMaintainNotFoundTypes(boolean maintain) {
+ if (maintain) {
+ if (fNotFoundTypes == null)
+ fNotFoundTypes = new HashSet();
+ } else
+ fNotFoundTypes = null;
+ }
}
-
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMThrowableBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMThrowableBeanProxy.java
index 7c1f4c7..dc1df12 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMThrowableBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMThrowableBeanProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.remote;
/*
* $RCSfile: REMThrowableBeanProxy.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -193,4 +193,16 @@
value.setObjectID(getID().intValue());
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMRegisterAWT.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMRegisterAWT.java
index e2a50c6..f32af80 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMRegisterAWT.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMRegisterAWT.java
@@ -11,9 +11,11 @@
*******************************************************************************/
/*
* $RCSfile: REMRegisterAWT.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
+import org.eclipse.jem.internal.proxy.core.IBeanTypeProxy;
+import org.eclipse.jem.internal.proxy.core.IMethodProxy;
import org.eclipse.jem.internal.proxy.remote.REMProxyFactoryRegistry;
/**
* This class is used to register the AWT factories. It is not
@@ -23,5 +25,14 @@
public static void registerAWT(REMProxyFactoryRegistry registry) {
new REMStandardAWTBeanTypeProxyFactory(registry);
new REMStandardAWTBeanProxyFactory(registry);
+
+ // If we are doing AWT, get the AWT event queue going. This is trying to be a time-saver
+ // by having it up right away.
+ IBeanTypeProxy starterBeanType = registry.getBeanTypeProxyFactory().getBeanTypeProxy("org.eclipse.jem.internal.proxy.vm.remote.AWTStarter");
+ if (starterBeanType != null) {
+ IMethodProxy starter = starterBeanType.getMethodProxy("startAWT");
+ if (starter != null)
+ starter.invokeCatchThrowableExceptions(null);
+ }
}
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMStandardAWTBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMStandardAWTBeanTypeProxyFactory.java
index d857878..263068d 100644
--- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMStandardAWTBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/awt/REMStandardAWTBeanTypeProxyFactory.java
@@ -1,4 +1,3 @@
-package org.eclipse.jem.internal.proxy.remote.awt;
/*******************************************************************************
* Copyright (c) 2001, 2003, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
@@ -11,56 +10,73 @@
*******************************************************************************/
/*
* $RCSfile: REMStandardAWTBeanTypeProxyFactory.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:56:10 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:12 $
*/
+package org.eclipse.jem.internal.proxy.remote.awt;
+
+import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.internal.proxy.core.IBeanTypeProxy;
import org.eclipse.jem.internal.proxy.remote.*;
+
/**
- * BeanType factory standard AWT bean types.
- * This is package protected because it shouldn't be
- * referenced outside the package. It should only be accessed through
- * the interface.
+ * BeanType factory standard AWT bean types. This is package protected because it shouldn't be referenced outside the package. It should only be
+ * accessed through the interface.
*/
class REMStandardAWTBeanTypeProxyFactory implements IREMBeanTypeProxyFactory {
static final String BEAN_TYPE_FACTORY_KEY = "java.awt"; //$NON-NLS-1$
-
+
protected final REMProxyFactoryRegistry fFactoryRegistry;
-
+
REMStandardAWTBeanTypeProxyFactory(REMProxyFactoryRegistry aRegistry) {
- fFactoryRegistry = aRegistry;
+ fFactoryRegistry = aRegistry;
fFactoryRegistry.registerBeanTypeProxyFactory(BEAN_TYPE_FACTORY_KEY, this);
}
-
- /**
- * We don't pre-cache any types. We need to have the
- * id from the server to create types.
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.remote.IREMBeanTypeProxyFactory#getExtensionBeanTypeProxy(java.lang.String)
*/
- public IREMBeanTypeProxy getExtensionBeanTypeProxy(String className){
+ public IREMBeanTypeProxy getExtensionBeanTypeProxy(String className) {
return null;
}
-
- /**
- * Create the correct beantype from the class and id passed in.
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.remote.IREMBeanTypeProxyFactory#getExtensionBeanTypeProxy(java.lang.String, java.lang.Integer,
+ * org.eclipse.jem.internal.proxy.core.IBeanTypeProxy)
*/
- public IREMBeanTypeProxy getExtensionBeanTypeProxy(String className, Integer classID, IBeanTypeProxy superType){
-
+ public IREMBeanTypeProxy getExtensionBeanTypeProxy(String className, Integer classID, IBeanTypeProxy superType) {
+
if ("java.awt.Dimension".equals(className)) //$NON-NLS-1$
return new REMDimensionBeanTypeProxy(fFactoryRegistry, classID, className, superType);
else if ("java.awt.Point".equals(className)) //$NON-NLS-1$
- return new REMPointBeanTypeProxy(fFactoryRegistry, classID, className, superType);
+ return new REMPointBeanTypeProxy(fFactoryRegistry, classID, className, superType);
else if ("java.awt.Rectangle".equals(className)) //$NON-NLS-1$
return new REMRectangleBeanTypeProxy(fFactoryRegistry, classID, className, superType);
- else
+ else
return null;
}
-
+
/*
- * Terminate this factory. Since it doesn't hold onto anything other than the registry,
- * and nothing will be holding onto this factory, nothing needs to be done. It will be GC'd.
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.remote.IREMBeanTypeProxyFactory#getExtensionBeanTypeProxy(java.lang.String,
+ * org.eclipse.jem.internal.proxy.core.IExpression)
+ */
+ public IProxyBeanType getExtensionBeanTypeProxy(String typeName, IExpression expression) {
+ return getExtensionBeanTypeProxy(typeName);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IBeanProxyFactory#terminateFactory(boolean)
*/
public void terminateFactory(boolean wait) {
- }
+ }
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanProxy.java
index 5307b78..6e8f886 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.ide;
/*
* $RCSfile: IDEBeanProxy.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
import org.eclipse.jem.internal.proxy.core.*;
@@ -70,6 +70,11 @@
}
return false;
}
+
+ public int hashCode() {
+ return 12345 + (getBean() != null ? getBean().hashCode() : 0);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.IBeanProxy#sameAs(org.eclipse.jem.internal.proxy.core.IBeanProxy)
*/
@@ -81,4 +86,16 @@
return false;
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanTypeProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanTypeProxy.java
index 7975efa..b17587b 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanTypeProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEBeanTypeProxy.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
- * $RCSfile: IDEBeanTypeProxy.java,v $ $Revision: 1.10 $ $Date: 2005/02/16 00:59:27 $
+ * $RCSfile: IDEBeanTypeProxy.java,v $ $Revision: 1.11 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.ide;
@@ -411,4 +411,37 @@
}
return ((IDEMethodProxyFactory) fProxyFactoryRegistry.getMethodProxyFactory()).getCompatibleMethod(fClass, methodName, argClasses);
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameterTypes) {
+ IProxyMethod method = ((IDEExpression) expression).getMethodExpressionProxy(this, methodName, parameterTypes);
+ if (method == null) {
+ // Need to go to the expression and create it.
+ method = ((Expression) expression).createMethodExpressionProxy(this, methodName, parameterTypes);
+ }
+ return method;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes) {
+ return ((IDEMethodProxyFactory) fProxyFactoryRegistry.getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String fieldName) {
+ IProxyField field = ((IDEExpression) expression).getFieldExpressionProxy(this, fieldName);
+ if (field == null) {
+ // Need to go to the expression and create it.
+ field = ((Expression) expression).createFieldExpressionProxy(this, fieldName);
+ }
+ return field;
+ }
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDECallbackRegistry.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDECallbackRegistry.java
index a4c0d4c..3dbeb33 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDECallbackRegistry.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDECallbackRegistry.java
@@ -11,10 +11,11 @@
package org.eclipse.jem.internal.proxy.ide;
/*
* $RCSfile: IDECallbackRegistry.java,v $
- * $Revision: 1.6 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.7 $ $Date: 2005/05/11 19:01:12 $
*/
import java.io.*;
+import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -22,6 +23,7 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
public class IDECallbackRegistry implements ICallbackRegistry {
@@ -31,10 +33,24 @@
Map fCallbackIDToCallback = new HashMap(25);
Map fBeanProxyToCallbackID = new HashMap(25);
Map fCallbackIDToStream = new HashMap(25);
+ private IProxyMethod initializeCallbackMethodProxy;
+ private IProxy vmServerProxy;
IDECallbackRegistry(IDEProxyFactoryRegistry aRegistry){
fProxyFactoryRegistry = aRegistry;
fVMServer = new IDEVMServer(this);
+
+ vmServerProxy = aRegistry.getBeanProxy(fVMServer.getClass(), fVMServer);
+
+ try {
+ Method initializeCallbackMethod = org.eclipse.jem.internal.proxy.common.ICallback.class.getMethod("initializeCallback", new Class[] {org.eclipse.jem.internal.proxy.common.IVMServer.class, Integer.TYPE});
+ initializeCallbackMethodProxy = (IProxyMethod) aRegistry.getBeanProxy(Method.class, initializeCallbackMethod);
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ }
+
}
/**
* Add a callback. aBeanProxy is running on the target VM and ICallback runs on our VM
@@ -55,6 +71,26 @@
}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ICallbackRegistry#registerCallback(org.eclipse.jem.internal.proxy.core.IProxy, org.eclipse.jem.internal.proxy.core.ICallback, org.eclipse.jem.internal.proxy.core.IExpression)
+ */
+public void registerCallback(IProxy callbackProxy, final ICallback cb, IExpression expression) {
+ final Integer callbackID = new Integer(++fNextCallbackID);
+ fCallbackIDToCallback.put(callbackID, cb);
+ if (callbackProxy.isBeanProxy()) {
+ fBeanProxyToCallbackID.put(callbackProxy, callbackID);
+ } else {
+ ((ExpressionProxy) callbackProxy).addProxyListener(new ExpressionProxy.ProxyAdapter() {
+ public void proxyResolved(ProxyEvent event) {
+ fBeanProxyToCallbackID.put(event.getProxy(), callbackID);
+ }
+ });
+ }
+ expression.createSimpleMethodInvoke(initializeCallbackMethodProxy, callbackProxy, new IProxy[] {vmServerProxy, fProxyFactoryRegistry.getBeanProxyFactory().createBeanProxyWith(callbackID.intValue())}, false);
+
+}
+
OutputStream requestStream(final int aCallbackID, final int aMsgID){
final PipedOutputStream result = new PipedOutputStream();
PipedInputStream tempStream = null;
@@ -106,8 +142,7 @@
public void deregisterCallback(IBeanProxy aBeanProxy){
// Remove the callback from both maps. The actual unregistering of the callback
// on the target VM is done separately by the object that added the event handler on the target VM
- Integer callbackID = (Integer) fBeanProxyToCallbackID.get(aBeanProxy);
- fBeanProxyToCallbackID.remove(aBeanProxy);
+ Integer callbackID = (Integer) fBeanProxyToCallbackID.remove(aBeanProxy);
fCallbackIDToCallback.remove(callbackID);
}
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEConstructorProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEConstructorProxy.java
index 99d386e..03fb443 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEConstructorProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEConstructorProxy.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.ide;
/*
* $RCSfile: IDEConstructorProxy.java,v $
- * $Revision: 1.7 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.8 $ $Date: 2005/05/11 19:01:12 $
*/
import java.lang.reflect.Constructor;
@@ -101,4 +101,19 @@
}
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IConstructorProxy#getParameterTypes()
+ */
+ public IBeanTypeProxy[] getParameterTypes() {
+ Class[] parmClasses = ((Constructor) getBean()).getParameterTypes();
+ IBeanTypeProxy[] parmTypes = new IBeanTypeProxy[parmClasses.length];
+ IDEStandardBeanTypeProxyFactory factory = (IDEStandardBeanTypeProxyFactory) fProxyFactoryRegistry.getBeanTypeProxyFactory();
+ for (int i = 0; i < parmClasses.length; i++) {
+ parmTypes[i] = factory.getBeanTypeProxy(parmClasses[i]);
+ }
+ return parmTypes;
+ }
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExpression.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExpression.java
index e560e99..7209df6 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExpression.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExpression.java
@@ -9,16 +9,18 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
- * $RCSfile: IDEExpression.java,v $ $Revision: 1.4 $ $Date: 2005/02/16 14:38:04 $
+ * $RCSfile: IDEExpression.java,v $ $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.ide;
-import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+
+import org.eclipse.core.runtime.Platform;
import org.eclipse.jem.internal.proxy.common.MethodHelper;
import org.eclipse.jem.internal.proxy.core.*;
-import org.eclipse.jem.internal.proxy.initParser.EvaluationException;
-import org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser;
+import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
+import org.eclipse.jem.internal.proxy.initParser.tree.*;
/**
* IDE expression processing.
@@ -28,8 +30,27 @@
public class IDEExpression extends Expression {
private final IDEStandardBeanTypeProxyFactory beantypefactory;
- protected final ExpressionProcesser eproc = new ExpressionProcesser();
+ protected final ExpressionProcesser eproc;
+ {
+ boolean useTracing = "true".equalsIgnoreCase(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyLaunchSupport.EXPRESSION_TRACING));
+ long threshold = Long.getLong(Platform.getDebugOption(ProxyPlugin.getPlugin().getBundle().getSymbolicName() + ProxyLaunchSupport.EXPRESSION_TRACEING_TIMER_THRESHOLD), -1L).longValue();
+ eproc = new ExpressionProcesser(useTracing, threshold);
+ }
+
+ private void processExpressionError() throws ThrowableProxy, NoExpressionValueException {
+ if (!eproc.noErrors())
+ if (eproc.isNoExpressionValue())
+ throw (NoExpressionValueException) eproc.getErrorThrowable();
+ else {
+ Throwable t = eproc.getErrorThrowable();
+ if (t instanceof ThrowableProxy)
+ throw (ThrowableProxy) t;
+ else
+ throw new IDEThrowableProxy(eproc.getErrorThrowable(), beantypefactory.getBeanTypeProxy(t.getClass()));
+ }
+ }
+
/**
* Create the IDEExpression
*
@@ -51,15 +72,16 @@
}
/*
- * (non-Javadoc)
- *
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushToProxy(org.eclipse.jem.internal.proxy.core.IBeanProxy)
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushToProxy(org.eclipse.jem.internal.proxy.core.IProxy)
*/
- protected void pushToProxy(IBeanProxy proxy) throws ThrowableProxy {
+ protected void pushToProxy(IProxy proxy) {
if (proxy == null)
eproc.pushExpression(null, MethodHelper.NULL_TYPE);
+ else if (proxy.isBeanProxy())
+ eproc.pushExpression(((IDEBeanProxy) proxy).getBean(), ((IDEBeanTypeProxy) ((IBeanProxy) proxy).getTypeProxy()).getTypeClass());
else
- eproc.pushExpression(((IDEBeanProxy) proxy).getBean(), ((IDEBeanTypeProxy) proxy.getTypeProxy()).getTypeClass());
+ eproc.pushExpressionProxy(((ExpressionProxy) proxy).getProxyID());
}
/*
@@ -68,69 +90,83 @@
* @see org.eclipse.jem.internal.proxy.core.Expression#closeProxy()
*/
protected void closeProxy() {
+ methodExpressionProxies = fieldExpressionProxies = null;
eproc.close();
}
/*
- * (non-Javadoc)
- *
- * @see org.eclipse.jem.internal.proxy.core.Expression#pullProxyValue()
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pullProxyValue(int, java.util.List)
*/
- protected IBeanProxy pullProxyValue() throws NoExpressionValueException {
+ protected IBeanProxy pullProxyValue(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException {
+ processExtensionProxies(proxycount, expressionProxies);
+ processExpressionError();
Object result[] = new Object[2];
eproc.pullValue(result);
- return getIDERegistry().getBeanProxy((Class) result[1], result[0]);
+ IBeanProxy resultProxy = getIDERegistry().getBeanProxy((Class) result[1], result[0]);
+ return resultProxy;
}
-
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushCastToProxy(java.lang.Object)
- */
- protected void pushCastToProxy(Object type) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushCast(getBeanTypeProxy(type).getTypeClass());
- } catch (ClassCastException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
+
+ private void processExtensionProxies(int proxycount, List expressionProxies) {
+ if (proxycount > 0) {
+ int len = expressionProxies.size();
+ Object[] proxyResolution = new Object[2];
+ for (int i = 0; i < len; i++) {
+ ExpressionProxy ep = (ExpressionProxy) expressionProxies.get(i);
+ if (ep != null) {
+ try {
+ eproc.pullExpressionProxyValue(ep.getProxyID(), proxyResolution);
+ if (proxyResolution[1] != Void.TYPE)
+ fireProxyResolved(ep, getIDERegistry().getBeanProxy((Class) proxyResolution[1], proxyResolution[0]));
+ else
+ fireProxyVoid(ep);
+ } catch (NoExpressionValueException e) {
+ fireProxyNotResolved(ep);
+ }
+ }
+ }
}
}
/*
- * (non-Javadoc)
- *
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushInstanceofToProxy(java.lang.Object)
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushCastToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
*/
- protected void pushInstanceofToProxy(Object type) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushCastToProxy(IProxyBeanType type) {
try {
- eproc.pushInstanceof(getBeanTypeProxy(type).getTypeClass());
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
+ eproc.pushCast(getIDEBeanTypeProxy(type).getTypeClass());
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
}
}
/*
- * (non-Javadoc)
- *
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushTypeLiteralToProxy(java.lang.String)
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushInstanceofToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
*/
- protected void pushTypeLiteralToProxy(String type) throws ThrowableProxy {
- eproc.pushExpression(getBeanTypeProxy(type).getTypeClass(), Class.class);
+ protected void pushInstanceofToProxy(IProxyBeanType type) {
+ try {
+ eproc.pushInstanceof(getIDEBeanTypeProxy(type).getTypeClass());
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ }
}
/**
* Get the BeanType proxy and test if valid. Throw ThrowableProxy if not valid.
*
- * @param type Must be either String or an IDEBeanTypeProxy. If String, it will look it up.
+ * @param type
* @return
* @throws ThrowableProxy
*
* @since 1.0.0
*/
- protected IDEBeanTypeProxy getBeanTypeProxy(Object type) throws ThrowableProxy {
- IDEBeanTypeProxy typeProxy = null;
- if (type instanceof String)
- typeProxy = (IDEBeanTypeProxy) registry.getBeanTypeProxyFactory().getBeanTypeProxy((String) type);
- else
+ protected IDEBeanTypeProxy getIDEBeanTypeProxy(IProxyBeanType type) throws ThrowableProxy {
+ IDEBeanTypeProxy typeProxy;
+ if (type.isExpressionProxy()) {
+ // It should already be resolved at this point.
+ typeProxy = ((IDEBeanTypeExpressionProxy) type).getBeanTypeProxy();
+ } else
typeProxy = (IDEBeanTypeProxy) type;
if (!typeProxy.isValid()) {
throw new IDEThrowableProxy(
@@ -140,147 +176,873 @@
return typeProxy;
}
- /*
- * (non-Javadoc)
+
+ /**
+ * Get the BeanType proxy and test if valid. Throw ThrowableProxy if not valid.
+ * @param type
+ * @return
+ * @throws ThrowableProxy
*
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushPrefixToProxy(int)
+ * @since 1.1.0
*/
- protected void pushPrefixToProxy(int operator) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushPrefix(operator);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- }
+ protected IDEBeanTypeProxy getIDEBeanTypeProxy(String type) throws ThrowableProxy {
+ return (IDEBeanTypeProxy) registry.getBeanTypeProxyFactory().getBeanTypeProxy(type);
}
/*
- * (non-Javadoc)
- *
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushInfixToProxy(int, int)
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushPrefixToProxy(org.eclipse.jem.internal.proxy.initParser.tree.PrefixOperator)
*/
- protected void pushInfixToProxy(int operator, int operandType) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushInfix(operator, operandType);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- }
+ protected void pushPrefixToProxy(PrefixOperator operator) {
+ eproc.pushPrefix(operator);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushInfixToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InfixOperator, org.eclipse.jem.internal.proxy.initParser.tree.InternalInfixOperandType)
+ */
+ protected void pushInfixToProxy(InfixOperator operator, InternalInfixOperandType operandType) {
+ eproc.pushInfix(operator, operandType);
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayAccessToProxy(int)
*/
- protected void pushArrayAccessToProxy(int indexCount) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushArrayAccess(indexCount);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- }
+ protected void pushArrayAccessToProxy(int indexCount) {
+ eproc.pushArrayAccess(indexCount);
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayCreationToProxy(java.lang.Object, int)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayCreationToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType, int)
*/
- protected void pushArrayCreationToProxy(Object type, int dimensionCount) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushArrayCreationToProxy(IProxyBeanType type, int dimensionCount) {
try {
- eproc.pushArrayCreation(getBeanTypeProxy(type).getTypeClass(), dimensionCount);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushArrayInitializerToProxy(java.lang.Object, int)
- */
- protected void pushArrayInitializerToProxy(Object type, int expressionCount) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushArrayInitializer(getBeanTypeProxy(type).getTypeClass(), expressionCount);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- }
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushClassInstanceCreationToProxy(java.lang.Object, int)
- */
- protected void pushClassInstanceCreationToProxy(Object type, int argumentCount) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushClassInstanceCreation(getBeanTypeProxy(type).getTypeClass(), argumentCount);
- } catch (InvocationTargetException e) {
- throw new IDEThrowableProxy(e.getTargetException(), getIDEBeanTypeFactory().getBeanTypeProxy(e.getTargetException().getClass()));
- } catch (NoExpressionValueException e) {
- throw e;
+ eproc.pushArrayCreation(getIDEBeanTypeProxy(type).getTypeClass(), dimensionCount);
} catch (ThrowableProxy e) {
- throw e;
- } catch (EvaluationException e) {
- throw new IDEThrowableProxy(e.getOriginalException(), getIDEBeanTypeFactory().getBeanTypeProxy(e.getOriginalException().getClass()));
- } catch (Exception e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
+ eproc.processException(e);
+ }
+ }
+
+ protected void pushArrayInitializerToProxy(IProxyBeanType type, int stripCount, int expressionCount) {
+ try {
+ eproc.pushArrayInitializer(getIDEBeanTypeProxy(type).getTypeClass(), stripCount, expressionCount);
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushClassInstanceCreationToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType, int)
+ */
+ protected void pushClassInstanceCreationToProxy(IProxyBeanType type, int argumentCount) {
+ try {
+ eproc.pushClassInstanceCreation(getIDEBeanTypeProxy(type).getTypeClass(), argumentCount);
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTypeReceiverToProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType)
+ */
+ protected void pushTypeReceiverToProxy(IProxyBeanType type) {
+ try {
+ Class c = getIDEBeanTypeProxy(type).getTypeClass();
+ eproc.pushExpression(c, c); // When as a receiver, the type is the same as the receiver.
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ } catch (RuntimeException e) {
+ eproc.processException(e);
}
}
/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pustTypeReceiverToProxy(java.lang.Object)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldAccessToProxy(java.lang.Object, boolean)
*/
- protected void pushTypeReceiverToProxy(Object type) throws ThrowableProxy {
- Class c = getBeanTypeProxy(type).getTypeClass();
- // The expressionType is used for receivers in field/method invocation to find the field/method. So we want the type to be type we have.
- // Also then the receiver to invoke against is the expression value, which is the type.
- eproc.pushExpression(c, c);
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldAccessToProxy(java.lang.String, boolean)
- */
- protected void pushFieldAccessToProxy(String fieldName, boolean hasReceiver) throws ThrowableProxy, NoExpressionValueException {
+ protected void pushFieldAccessToProxy(Object field, boolean hasReceiver) {
+ boolean isString = field instanceof String;
try {
- eproc.pushFieldAccess(fieldName, hasReceiver);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- } catch (NoExpressionValueException e) {
- throw e;
- } catch (NoSuchFieldException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- } catch (IllegalAccessException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
+ eproc.pushFieldAccess(isString ? field : getIDEFieldProxy((IProxyField) field).getBean(), isString, hasReceiver);
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
}
}
/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodInvocationToProxy(java.lang.String, boolean, int)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodInvocationToProxy(java.lang.Object, boolean, int)
*/
- protected void pushMethodInvocationToProxy(String methodName, boolean hasReceiver, int argCount)
- throws ThrowableProxy, NoExpressionValueException {
+ protected void pushMethodInvocationToProxy(Object method, boolean hasReceiver, int argCount) {
+ boolean isString = method instanceof String;
try {
- eproc.pushMethodInvocation(methodName, hasReceiver, argCount);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- } catch (NoExpressionValueException e) {
- throw e;
- } catch (EvaluationException e) {
- throw new IDEThrowableProxy(e.getOriginalException(), getIDEBeanTypeFactory().getBeanTypeProxy(e.getOriginalException().getClass()));
- } catch (IllegalAccessException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- } catch (InvocationTargetException e) {
- throw new IDEThrowableProxy(e.getTargetException(), getIDEBeanTypeFactory().getBeanTypeProxy(e.getTargetException().getClass()));
+ eproc.pushMethodInvocation(isString ? method : getIDEMethodProxy((IProxyMethod) method).getBean(), isString, hasReceiver, argCount);
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
}
}
- /* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.Expression#pushConditionalToProxy(int)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushConditionalToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InternalConditionalOperandType)
*/
- protected void pushConditionalToProxy(int expressionType) throws ThrowableProxy, NoExpressionValueException {
- try {
- eproc.pushConditional(expressionType);
- } catch (RuntimeException e) {
- throw new IDEThrowableProxy(e, getIDEBeanTypeFactory().getBeanTypeProxy(e.getClass()));
- }
+ protected void pushConditionalToProxy(InternalConditionalOperandType expressionType) {
+ eproc.pushConditional(expressionType);
}
/* (non-Javadoc)
* @see org.eclipse.jem.internal.proxy.core.Expression#pushInvoke()
*/
- protected void pushInvoke() {
- // In the IDE case do nothing. Nothing is pending.
+ protected void pushInvoke(int proxycount, List expressionProxies) throws ThrowableProxy, NoExpressionValueException {
+ // In the IDE case do nothing. Nothing is pending. But still need to handle proxy resolution.
+ processExtensionProxies(proxycount, expressionProxies);
+ processExpressionError();
+ }
+
+ /**
+ * This is used as both an ExpressionProxy (i.e. IDE side) and the Expressions expression proxy result on the other side.
+ * This makes it easier to just use same instance on both sides.
+ *
+ * @since 1.1.0
+ */
+ protected static class IDEExpressionProxy extends ExpressionProxy implements InternalExpressionProxy {
+
+ protected IDEExpressionProxy(int proxyid, int proxyType, Expression expression) {
+ super(proxyid, proxyType, expression);
+ }
+
+ private Object value;
+ private Class type;
+ private boolean set;
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy#dispose()
+ */
+ protected void dispose() {
+ super.dispose();
+ value = null;
+ type = null;
+ set = false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#getType()
+ */
+ public Class getType() {
+ return type;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#getValue()
+ */
+ public Object getValue() {
+ return value;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#setProxy(java.lang.Object, java.lang.Class)
+ */
+ public void setProxy(Object value, Class type) {
+ this.value = value;
+ this.type = type;
+ set = true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#isSet()
+ */
+ public boolean isSet() {
+ return set;
+ }
+ }
+
+ /**
+ * The Expression proxy for IDE BeanTypes.
+ *
+ * @since 1.1.0
+ */
+ protected static class IDEBeanTypeExpressionProxy extends IDEExpressionProxy implements IBeanTypeExpressionProxy {
+
+ private String typeName;
+ private IDEBeanTypeProxy resolvedProxy;
+
+ /**
+ * @param proxyid
+ *
+ * @since 1.1.0
+ */
+ public IDEBeanTypeExpressionProxy(int proxyid, Expression expression) {
+ super(proxyid, BEANTYPE_EXPRESSION_PROXY, expression);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IBeanTypeExpressionProxy#setTypeName(java.lang.String)
+ */
+ public void setTypeName(String typeName) {
+ this.typeName = typeName;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getTypeName()
+ */
+ public String getTypeName() {
+ return typeName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy#toString()
+ */
+ public String toString() {
+ return super.toString()+" - "+getTypeName();
+ }
+
+ /**
+ * Called by IDEExpression to resolve the beantype.
+ * @param beantypeProxy
+ *
+ * @since 1.1.0
+ */
+ void setProxy(IDEBeanTypeProxy beantypeProxy) {
+ this.resolvedProxy = beantypeProxy;
+ setProxy(resolvedProxy.getTypeClass(), Class.class);
+ }
+
+ /**
+ * Called by IDEExpression to get the resolved beantype proxy.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ IDEBeanTypeProxy getBeanTypeProxy() {
+ return resolvedProxy;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, IProxyBeanType[] parameterTypes) {
+ IProxyMethod method = ((IDEExpression) expression).getMethodExpressionProxy(this, methodName, parameterTypes);
+ if (method == null) {
+ // Need to go to the expression and create it.
+ method = ((Expression) expression).createMethodExpressionProxy(this, methodName, parameterTypes);
+ }
+ return method;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String methodName, String[] parameterTypes) {
+ return ((IDEMethodProxyFactory) expression.getRegistry().getMethodProxyFactory()).getMethodProxy(expression, this, methodName, parameterTypes);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxyBeanType#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String fieldName) {
+ IProxyField field = ((IDEExpression) expression).getFieldExpressionProxy(this, fieldName);
+ if (field == null) {
+ // Need to go to the expression and create it.
+ field = ((Expression) expression).createFieldExpressionProxy(this, fieldName);
+ }
+ return field;
+ }
+ }
+
+ /**
+ * The Expression proxy for IDE BeanTypes.
+ *
+ * @since 1.1.0
+ */
+ protected static class IDEMethodExpressionProxy extends IDEExpressionProxy implements IProxyMethod {
+
+ private String methodName;
+ private IDEMethodProxy resolvedProxy;
+ private ThrowableProxy errorThrowable;
+
+ /**
+ * @param proxyid
+ *
+ * @since 1.1.0
+ */
+ public IDEMethodExpressionProxy(int proxyid, Expression expression) {
+ super(proxyid, METHOD_EXPRESSION_PROXY, expression);
+ }
+
+ /**
+ * Set by IDEExpression with the method name.
+ * @param methodName
+ *
+ * @since 1.1.0
+ */
+ void setMethodName(String methodName) {
+ this.methodName = methodName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy#toString()
+ */
+ public String toString() {
+ return super.toString()+" - "+methodName;
+ }
+
+ /**
+ * Called by IDEExpression to resolve the beantype.
+ * @param methodProxy
+ *
+ * @since 1.1.0
+ */
+ void setProxy(IDEMethodProxy methodProxy) {
+ this.resolvedProxy = methodProxy;
+ setProxy(resolvedProxy.getBean(), Class.class);
+ }
+
+ /**
+ * Called by IDEExpression to say there was error in creating the proxy.
+ * @param errorThrowable
+ *
+ * @since 1.1.0
+ */
+ void setThrowable(ThrowableProxy errorThrowable) {
+ this.errorThrowable = errorThrowable;
+ }
+
+ /**
+ * Called by IDEExpression to get the resolved method proxy.
+ * @return
+ * @throws ThrowableProxy
+ *
+ * @since 1.1.0
+ */
+ IDEMethodProxy getMethodProxy() throws ThrowableProxy {
+ if (errorThrowable != null)
+ throw errorThrowable;
+ return resolvedProxy;
+ }
+ }
+
+ protected static class IDEFieldExpressionProxy extends IDEExpressionProxy implements IProxyField {
+
+ private String fieldName;
+ private IDEFieldProxy resolvedProxy;
+ private ThrowableProxy errorThrowable;
+
+ /**
+ * @param proxyid
+ *
+ * @since 1.1.0
+ */
+ public IDEFieldExpressionProxy(int proxyid, Expression expression) {
+ super(proxyid, FIELD_EXPRESSION_PROXY, expression);
+ }
+
+ /**
+ * Set by IDEExpression with the method name.
+ * @param fieldName
+ *
+ * @since 1.1.0
+ */
+ void setField(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.ExpressionProxy#toString()
+ */
+ public String toString() {
+ return super.toString()+" - "+fieldName;
+ }
+
+ /**
+ * Called by IDEExpression to resolve the beantype.
+ * @param fieldProxy
+ *
+ * @since 1.1.0
+ */
+ void setProxy(IDEFieldProxy fieldProxy) {
+ this.resolvedProxy = fieldProxy;
+ setProxy(resolvedProxy.getBean(), Class.class);
+ }
+
+ /**
+ * Called by IDEExpression to say there was error in creating the proxy.
+ * @param errorThrowable
+ *
+ * @since 1.1.0
+ */
+ void setThrowable(ThrowableProxy errorThrowable) {
+ this.errorThrowable = errorThrowable;
+ }
+
+ /**
+ * Called by IDEExpression to get the resolved field proxy.
+ * @return
+ * @throws ThrowableProxy
+ *
+ * @since 1.1.0
+ */
+ IDEFieldProxy getFieldProxy() throws ThrowableProxy {
+ if (errorThrowable != null)
+ throw errorThrowable;
+ return resolvedProxy;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#createExpressionProxy(int, int)
+ */
+ protected ExpressionProxy createExpressionProxy(int proxyType, int proxyID) {
+ switch (proxyType) {
+ case NORMAL_EXPRESSION_PROXY:
+ default:
+ return new IDEExpressionProxy(proxyID, NORMAL_EXPRESSION_PROXY, this);
+
+ case BEANTYPE_EXPRESSION_PROXY:
+ return new IDEBeanTypeExpressionProxy(proxyID, this);
+
+ case METHOD_EXPRESSION_PROXY:
+ return new IDEMethodExpressionProxy(proxyID, this);
+
+ case FIELD_EXPRESSION_PROXY:
+ return new IDEFieldExpressionProxy(proxyID, this);
+ }
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushAssignmentToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy)
+ */
+ protected void pushAssignmentToProxy(ExpressionProxy proxy) {
+ eproc.pushAssignment((InternalExpressionProxy) proxy);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushAssignmentToProxy()
+ */
+ protected void pushAssignmentToProxy() {
+ eproc.pushAssignment();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockBeginToProxy(int)
+ */
+ protected void pushBlockBeginToProxy(int blockNumber) {
+ eproc.pushBlockBegin(blockNumber);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockEndToProxy(int)
+ */
+ protected void pushBlockEndToProxy(int blockNumber) {
+ eproc.pushBlockEnd(blockNumber);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBlockBreakToProxy(int)
+ */
+ protected void pushBlockBreakToProxy(int blockNumber) {
+ eproc.pushBlockBreak(blockNumber);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryBeginToProxy(int)
+ */
+ protected void pushTryBeginToProxy(int tryNumber) {
+ eproc.pushTryBegin(tryNumber);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryCatchClauseToProxy(int, org.eclipse.jem.internal.proxy.core.IProxyBeanType, org.eclipse.jem.internal.proxy.core.ExpressionProxy)
+ */
+ protected void pushTryCatchClauseToProxy(int tryNumber, IProxyBeanType exceptionType, ExpressionProxy ep) {
+ try {
+ eproc.pushTryCatchClause(tryNumber, getIDEBeanTypeProxy(exceptionType).getTypeClass(), (InternalExpressionProxy) ep);
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryFinallyClauseToProxy(int)
+ */
+ protected void pushTryFinallyClauseToProxy(int tryNumber) {
+ eproc.pushTryFinallyClause(tryNumber);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushTryEndToProxy(int)
+ */
+ protected void pushTryEndToProxy(int tryNumber) {
+ eproc.pushTryEnd(tryNumber);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushThrowToProxy()
+ */
+ protected void pushThrowToProxy() {
+ eproc.pushThrowException();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushRethrowToProxy(int)
+ */
+ protected void pushRethrowToProxy(int tryNumber) {
+ eproc.pushTryRethrow(tryNumber);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushBeanTypeToProxy(org.eclipse.jem.internal.proxy.core.IBeanTypeExpressionProxy)
+ */
+ protected void pushBeanTypeToProxy(IBeanTypeExpressionProxy proxy) {
+ try {
+ IDEBeanTypeExpressionProxy ep = (IDEBeanTypeExpressionProxy) proxy;
+ IDEBeanTypeProxy typeProxy = getIDEBeanTypeProxy(proxy.getTypeName());
+ ep.setProxy(typeProxy);
+ eproc.allocateExpressionProxy(ep);
+ if (!typeProxy.isValid()) {
+ throw new IDEThrowableProxy(
+ new Exception(typeProxy.getInitializationError()),
+ getIDEBeanTypeFactory().getBeanTypeProxy(Exception.class));
+ }
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ }
+ }
+
+ /**
+ * Get the map of IProxyBeanTypes for a beantype name. Meant to be used only in conjunction with IDEStandardBeanTypeFactory.
+ * It is here so the IDDEStandardBeanTypeFactory can store pending proxies per expression.
+ *
+ * @param beanType
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyBeanType getBeanType(String beanTypeName) {
+ if (beanTypeCache == null)
+ beanTypeCache = new HashMap();
+ return (IProxyBeanType) beanTypeCache.get(beanTypeName);
+ }
+
+ /**
+ * Add the beantype expression proxy to the map of bean type expression proxies. Used in conjunction with IDEStandardBeanTypeFactory.
+ * It is here so the IDEStandardBeanTypeFactory can store pending proxies per expression.
+ * @param beanTypeName
+ * @param beantype
+ *
+ * @since 1.1.0
+ */
+ public void addBeanType(String beanTypeName, IProxyBeanType beantype) {
+ beanTypeCache.put(beanTypeName, beantype);
+ }
+
+ /**
+ * Remove the beantype expression proxy from the map. This is called because there was a rollback due to an endmark.
+ * @param beanTypeName
+ *
+ * @since 1.1.0
+ */
+ public void removeBeanType(String beanTypeName) {
+ beanTypeCache.remove(beanTypeName);
+ }
+
+ /**
+ * Keeping a local map of Method Expression Proxies so that we don't keep recreating them for each request from within this expression.
+ * The map will be: declaringTypeName->(Map) methodName or IDEMethodKey -> method expression proxy.
+ * @see IDEExpression#pushMethodToProxy(ExpressionProxy, IProxyBeanType, String, IProxyBeanType[]) for the actual implementation.
+ */
+ protected Map methodExpressionProxies;
+
+ /**
+ * Keeping a local map of Field Expression Proxies so that we don't keep recreating them for each request from within this expression.
+ * The map will be: declaringTypeName->(Map) fieldname -> field expression proxy.
+ * @see IDEExpression#pushFieldToProxy(ExpressionProxy, IProxyBeanType, String)
+ */
+ protected Map fieldExpressionProxies;
+
+ /**
+ * Keeping a local map of BeanType expression proxies so that we don't keep recreating them for each request from within this expression.
+ * The map will be: typename->beanTypeExpressionProxy
+ */
+ protected Map beanTypeCache; // Use to cache pending BeanTypes. Used in conjunction with IDEStandardBeanTypeFactory.
+
+ /*
+ * Used as the key to the methodCache when there are parms.
+ * It allows the parms to be either IProxyBeanType without the
+ * overhead of creating complicated strings.
+ *
+ * It will compare method name and each individual parm name without fluffing
+ * up a string and building it up.
+ *
+ * For no parm methods, just the name of the method as a string will be the key.
+ *
+ * @since 1.1.0
+ */
+ private static class MethodKey {
+ public String methodName;
+ public IProxyBeanType[] parmTypes;
+ public MethodKey(String methodName, IProxyBeanType[] parmTypes) {
+ this.methodName = methodName;
+ this.parmTypes = parmTypes;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ try {
+ return ((MethodKey) obj).compareParms(parmTypes);
+ } catch (ClassCastException e) {
+ return false;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#hashCode()
+ */
+ public int hashCode() {
+ int h = methodName.hashCode();;
+ for (int i = 0; i < parmTypes.length; i++) {
+ h += parmTypes[i].getTypeName().hashCode();
+ }
+ return h;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.remote.REMProxyConstants.MethodKey#compareParms(java.lang.String[])
+ */
+ protected boolean compareParms(IProxyBeanType[] parms) {
+ if (parms.length != parmTypes.length)
+ return false;
+ for (int i = 0; i < parms.length; i++) {
+ if (!parmTypes[i].getTypeName().equals(parms[i].getTypeName()))
+ return false;
+ }
+ return true;
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushMethodToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy, org.eclipse.jem.internal.proxy.core.IProxyBeanType, java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType[])
+ */
+ protected void pushMethodToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes) {
+ try {
+ final Map methods = getMethods(declaringType);
+ final Object key = getMethodKey(methodName, parameterTypes);
+ methods.put(key, proxy);
+ proxy.addProxyListener(new ExpressionProxy.ProxyAdapter() {
+
+ public void proxyNotResolved(ProxyEvent event) {
+ methods.remove(key); // Back it out. tis could happen due to endmark rollback.
+ }
+
+ });
+
+ IDEMethodExpressionProxy ep = (IDEMethodExpressionProxy) proxy;
+ ep.setMethodName(methodName);
+ // We resolve immediately. Any expression proxies should also be resolved at this point too.
+ Class declaringClass = getIDEBeanTypeProxy(declaringType).getTypeClass();
+ Class[] parameterClasses;
+ if (parameterTypes == null || parameterTypes.length == 0)
+ parameterClasses = null;
+ else {
+ parameterClasses = new Class[parameterTypes.length];
+ for (int i = 0; i < parameterClasses.length; i++) {
+ parameterClasses[i] = getIDEBeanTypeProxy(parameterTypes[i]).getTypeClass();
+ }
+ }
+ IDEMethodProxy methodProxy = ((IDEMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(declaringClass, methodName, parameterClasses);
+ if (methodProxy == null) {
+ String parms = "";
+ if (parameterTypes != null || parameterTypes.length > 0) {
+ StringBuffer st = new StringBuffer(100);
+ for (int i = 0; i < parameterClasses.length; i++) {
+ if (i > 0)
+ st.append(',');
+ st.append(parameterTypes[i].getTypeName());
+ }
+ parms = st.toString();
+ }
+ throw new IDEThrowableProxy(new NoSuchMethodException("No method: "+declaringType+'.'+methodName+"("+parms+')'),
+ getIDEBeanTypeFactory().getBeanTypeProxy(NoSuchMethodException.class));
+ }
+
+ ep.setProxy(methodProxy);
+ eproc.allocateExpressionProxy(ep);
+ } catch (ThrowableProxy e) {
+ ((IDEMethodExpressionProxy) proxy).setThrowable(e); // So we don't recreate throwable all of the time.
+ eproc.processException(e);
+ }
+ }
+
+ private Map getMethods(IProxyBeanType classtype) {
+ if (methodExpressionProxies == null)
+ methodExpressionProxies = new HashMap();
+ Map methods = (Map) methodExpressionProxies.get(classtype.getTypeName());
+ if (methods == null)
+ methodExpressionProxies.put(classtype.getTypeName(), methods = new HashMap());
+ return methods;
+ }
+
+ private Object getMethodKey(String methodName, IProxyBeanType[] parameterTypes) {
+ if (parameterTypes == null || parameterTypes.length == 0)
+ return methodName;
+ else
+ return new MethodKey(methodName, parameterTypes);
+ }
+
+ private Map getFields(IProxyBeanType classtype) {
+ if (fieldExpressionProxies == null)
+ fieldExpressionProxies = new HashMap();
+ Map fields = (Map) fieldExpressionProxies.get(classtype.getTypeName());
+ if (fields == null)
+ fieldExpressionProxies.put(classtype.getTypeName(), fields = new HashMap());
+ return fields;
+ }
+
+ /**
+ * This is used by IDEBeanTypes and IDEBeanTypeExpressionProxy to access any already created Method Expression Proxies.
+ *
+ * @param declaringType
+ * @param methodName
+ * @param parameterTypes
+ * @return IProxyMethod or <code>null</code> if not yet created.
+ *
+ * @since 1.1.0
+ */
+ IProxyMethod getMethodExpressionProxy(IProxyBeanType declaringType, String methodName, IProxyBeanType[] parameterTypes) {
+ Map methods = getMethods(declaringType);
+ Object key = getMethodKey(methodName, parameterTypes);
+ return (IProxyMethod) methods.get(key);
+ }
+
+ /**
+ * This is used by IDEBeanTypes and IDEBeanTypeExpressionProxy to access any already created Field Expression Proxies.
+ * @param declaringType
+ * @param fieldName
+ * @return
+ *
+ * @since 1.1.0
+ */
+ IProxyField getFieldExpressionProxy(IProxyBeanType declaringType, String fieldName) {
+ Map fields = getFields(declaringType);
+ return (IProxyField) fields.get(fieldName);
+ }
+
+ /**
+ * Get the IDEMethodProxy out of the already resolved Expression Proxy or IDEMethodProxy itself.
+ * @param method
+ * @return
+ * @throws ThrowableProxy
+ *
+ * @since 1.1.0
+ */
+ protected IDEMethodProxy getIDEMethodProxy(IProxyMethod method) throws ThrowableProxy {
+ IDEMethodProxy methodProxy;
+ if (method.isExpressionProxy()) {
+ // It should already be resolved at this point.
+ methodProxy = ((IDEMethodExpressionProxy) method).getMethodProxy();
+ } else
+ methodProxy = (IDEMethodProxy) method;
+ return methodProxy;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushFieldToProxy(org.eclipse.jem.internal.proxy.core.ExpressionProxy, org.eclipse.jem.internal.proxy.core.IProxyBeanType, java.lang.String)
+ */
+ protected void pushFieldToProxy(ExpressionProxy proxy, IProxyBeanType declaringType, final String fieldName) {
+
+ try {
+ final Map fields = getFields(declaringType);
+ fields.put(fieldName, proxy);
+ proxy.addProxyListener(new ExpressionProxy.ProxyAdapter(){
+ public void proxyNotResolved(ExpressionProxy.ProxyEvent event) {
+ fields.remove(fieldName); // this can happen due to an endmark. It could be one of the ones that are rolled back.
+ }
+ });
+
+
+ IDEFieldExpressionProxy ep = (IDEFieldExpressionProxy) proxy;
+ // We resolve immediately. Any expression proxies should also be resolved at this point too.
+ IDEFieldProxy fieldProxy = (IDEFieldProxy) getIDEBeanTypeProxy(declaringType).getFieldProxy(fieldName);
+ if (fieldProxy == null) {
+ throw new IDEThrowableProxy(new NoSuchFieldException("No field: "+declaringType+'.'+fieldName),
+ getIDEBeanTypeFactory().getBeanTypeProxy(NoSuchFieldException.class));
+ }
+
+ ep.setProxy(fieldProxy);
+ eproc.allocateExpressionProxy(ep);
+ } catch (ThrowableProxy e) {
+ ((IDEFieldExpressionProxy) proxy).setThrowable(e); // So we don't recreate throwable all of the time.
+ eproc.processException(e);
+ }
+
+ }
+
+ /**
+ * Get the IDEFieldProxy out of the already resolved Expression Proxy or IDEFieldProxy itself.
+ * @param field
+ * @return
+ * @throws ThrowableProxy
+ *
+ * @since 1.1.0
+ */
+ protected IDEFieldProxy getIDEFieldProxy(IProxyField field) throws ThrowableProxy {
+ IDEFieldProxy fieldProxy;
+ if (field.isExpressionProxy()) {
+ // It should already be resolved at this point.
+ fieldProxy = ((IDEFieldExpressionProxy) field).getFieldProxy();
+ } else
+ fieldProxy = (IDEFieldProxy) field;
+ return fieldProxy;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushIfTestToProxy()
+ */
+ protected void pushIfTestToProxy() {
+ eproc.pushIfElse();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushIfElseToProxy(org.eclipse.jem.internal.proxy.initParser.tree.InternalIfElseOperandType)
+ */
+ protected void pushIfElseToProxy(InternalIfElseOperandType clauseType) {
+ eproc.pushIfElse(clauseType);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.Expression#pushNewInstanceToProxy(java.lang.String, org.eclipse.jem.internal.proxy.core.IProxyBeanType)
+ */
+ protected void pushNewInstanceToProxy(String initializationString, IProxyBeanType resultType) {
+ try {
+ eproc.pushNewInstanceFromString(initializationString, getIDEBeanTypeProxy(resultType).getTypeClass(), getIDERegistry().fClassLoader);
+ } catch (ThrowableProxy e) {
+ eproc.processException(e);
+ }
+ }
+
+ protected void pushMarkToProxy(int markID) {
+ eproc.pushMark(markID);
+ }
+
+ protected void pushEndmarkToProxy(int markID, boolean restore) {
+ eproc.pushEndmark(markID, restore);
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExtensionBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExtensionBeanTypeProxyFactory.java
index 58bd344..c4a28ca 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExtensionBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEExtensionBeanTypeProxyFactory.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: IDEExtensionBeanTypeProxyFactory.java,v $
- * $Revision: 1.2 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.3 $ $Date: 2005/05/11 19:01:12 $
*/
import org.eclipse.jem.internal.proxy.core.*;
@@ -22,5 +22,7 @@
public IDEBeanTypeProxy getExtensionBeanTypeProxy(String typeName, IBeanTypeProxy superType);
+public IProxyBeanType getExtensionBeanTypeProxy(String typeName, IExpression expression);
+
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEMethodProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEMethodProxyFactory.java
index 93600ac..0ada52c 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEMethodProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEMethodProxyFactory.java
@@ -9,7 +9,7 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*
- * $RCSfile: IDEMethodProxyFactory.java,v $ $Revision: 1.9 $ $Date: 2005/02/15 22:57:26 $
+ * $RCSfile: IDEMethodProxyFactory.java,v $ $Revision: 1.10 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.ide;
@@ -134,6 +134,17 @@
return (IFieldProxy) fieldType.newBeanProxy(aField);
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IMethodProxyFactory#getFieldProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String)
+ */
+ public IProxyField getFieldProxy(IExpression expression, String className, String fieldName) {
+ // We are getting the class resolved through the expression. Might as well because it probably will
+ // be needed again and this way when the expression is finished they will be resolved for later usage.
+ IStandardBeanTypeProxyFactory beanTypeProxyFactory = fProxyFactoryRegistry.getBeanTypeProxyFactory();
+ IProxyBeanType beanType = beanTypeProxyFactory.getBeanTypeProxy(expression, className);
+ return beanType.getFieldProxy(expression, fieldName);
+ }
/**
* Return an instance of an IDEMethodProxy This is package protected because the only people who can use this are priveledge objects that have the
@@ -141,9 +152,9 @@
* method proxy you must use the interface methods on IMethodProxyFactory to do lookup by string or else on IBeanTypeProxy that has
* getMethod(String) as well
*/
- IMethodProxy getMethodProxy(Method aMethod) {
+ IDEMethodProxy getMethodProxy(Method aMethod) {
- return (IMethodProxy) methodType.newBeanProxy(aMethod);
+ return (IDEMethodProxy) methodType.newBeanProxy(aMethod);
}
@@ -156,6 +167,58 @@
return null;
}
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IMethodProxyFactory#getMethodProxy(org.eclipse.jem.internal.proxy.core.IExpression, java.lang.String, java.lang.String, java.lang.String[])
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, String className, String methodName, String[] parameterTypes) {
+ // We are getting the class and parmtypes resolved through the expression. Might as well because they probably will
+ // be needed again and this way when the expression is finished they will be resolved for later usage.
+ IStandardBeanTypeProxyFactory beanTypeProxyFactory = fProxyFactoryRegistry.getBeanTypeProxyFactory();
+ IProxyBeanType beanType = beanTypeProxyFactory.getBeanTypeProxy(expression, className);
+ IProxyBeanType[] parmTypes = getParameterTypes(expression, parameterTypes, beanTypeProxyFactory);
+ return beanType.getMethodProxy(expression, methodName, parmTypes);
+ }
+
+ /**
+ * Helper method for Beantypes and Proxy bean types to get the proxy.
+ * @param expression
+ * @param classType
+ * @param methodName
+ * @param parameterTypes
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public IProxyMethod getMethodProxy(IExpression expression, IProxyBeanType classType, String methodName, String[] parameterTypes) {
+ // We are getting the parmtypes resolved through the expression. Might as well because they probably will
+ // be needed again and this way when the expression is finished they will be resolved for later usage.
+ IStandardBeanTypeProxyFactory beanTypeProxyFactory = fProxyFactoryRegistry.getBeanTypeProxyFactory();
+ IProxyBeanType[] parmTypes = getParameterTypes(expression, parameterTypes, beanTypeProxyFactory);
+ return classType.getMethodProxy(expression, methodName, parmTypes);
+ }
+
+ /**
+ * @param expression
+ * @param parameterTypes
+ * @param beanTypeProxyFactory
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected IProxyBeanType[] getParameterTypes(IExpression expression, String[] parameterTypes, IStandardBeanTypeProxyFactory beanTypeProxyFactory) {
+ IProxyBeanType[] parmTypes;
+ if (parameterTypes == null || parameterTypes.length == 0)
+ parmTypes = null;
+ else {
+ parmTypes = new IProxyBeanType[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ parmTypes[i] = beanTypeProxyFactory.getBeanTypeProxy(expression, parameterTypes[i]);
+ }
+ }
+ return parmTypes;
+ }
public IMethodProxy getMethodProxy(Class cls, String methodName, String[] parameterTypes) {
try {
@@ -199,7 +262,7 @@
return null;
}
- IMethodProxy getMethodProxy(Class aClass, String methodName, Class[] args) {
+ IDEMethodProxy getMethodProxy(Class aClass, String methodName, Class[] args) {
try {
Method method = aClass.getMethod(methodName, args);
return getMethodProxy(method);
@@ -270,4 +333,5 @@
*/
public void terminateFactory(boolean wait) {
}
+
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEStandardBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEStandardBeanTypeProxyFactory.java
index 9e16478..018bf5e 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEStandardBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEStandardBeanTypeProxyFactory.java
@@ -1,17 +1,13 @@
-/*******************************************************************************
- * Copyright (c) 2001, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+/*****************************************************************************************************************************************************
+ * Copyright (c) 2001, 2004 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
+ * Contributors: IBM Corporation - initial API and implementation
+ ****************************************************************************************************************************************************/
package org.eclipse.jem.internal.proxy.ide;
+
/*
- * $RCSfile: IDEStandardBeanTypeProxyFactory.java,v $
- * $Revision: 1.8 $ $Date: 2005/02/15 22:57:26 $
+ * $RCSfile: IDEStandardBeanTypeProxyFactory.java,v $ $Revision: 1.9 $ $Date: 2005/05/11 19:01:12 $
*/
import java.lang.reflect.Array;
@@ -25,312 +21,441 @@
import org.eclipse.jem.internal.proxy.common.MapTypes;
import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.core.ExpressionProxy.ProxyEvent;
public class IDEStandardBeanTypeProxyFactory implements IStandardBeanTypeProxyFactory {
-
+
protected final IDEProxyFactoryRegistry fFactoryRegistry;
// Hashtable to cache proxies for classes so they are found on second and subsequent lookups
protected Map beanProxies;
-
+
public static Map MAP_SHORTSIG_TO_TYPE = new HashMap(8);
- public static Map MAP_TYPENAME_TO_SHORTSIG = new HashMap(8);
-
+
+ public static Map MAP_TYPENAME_TO_SHORTSIG = new HashMap(8);
+
static {
MAP_SHORTSIG_TO_TYPE.put("B", Byte.TYPE); //$NON-NLS-1$
MAP_SHORTSIG_TO_TYPE.put("C", Character.TYPE); //$NON-NLS-1$
- MAP_SHORTSIG_TO_TYPE.put("D", Double.TYPE); //$NON-NLS-1$
+ MAP_SHORTSIG_TO_TYPE.put("D", Double.TYPE); //$NON-NLS-1$
MAP_SHORTSIG_TO_TYPE.put("F", Float.TYPE); //$NON-NLS-1$
MAP_SHORTSIG_TO_TYPE.put("I", Integer.TYPE); //$NON-NLS-1$
MAP_SHORTSIG_TO_TYPE.put("J", Long.TYPE); //$NON-NLS-1$
MAP_SHORTSIG_TO_TYPE.put("S", Short.TYPE); //$NON-NLS-1$
MAP_SHORTSIG_TO_TYPE.put("Z", Boolean.TYPE); //$NON-NLS-1$
-
- MAP_TYPENAME_TO_SHORTSIG.put("byte","B"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("char","C"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("double","D"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("float","F"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("int","I"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("long","J"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("short","S"); //$NON-NLS-1$ //$NON-NLS-2$
- MAP_TYPENAME_TO_SHORTSIG.put("boolean","Z"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ MAP_TYPENAME_TO_SHORTSIG.put("byte", "B"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("char", "C"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("double", "D"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("float", "F"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("int", "I"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("long", "J"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("short", "S"); //$NON-NLS-1$ //$NON-NLS-2$
+ MAP_TYPENAME_TO_SHORTSIG.put("boolean", "Z"); //$NON-NLS-1$ //$NON-NLS-2$
}
-
+
// Cached copy of a few typical bean type proxies.
IDEBeanTypeProxy objectClass;
+
IDEBooleanTypeBeanTypeProxy booleanType;
+
IDEBooleanClassBeanTypeProxy booleanClass;
+
IDEIntegerTypeBeanTypeProxy intType;
+
IDEIntegerClassBeanTypeProxy integerClass;
+
IDEFloatTypeBeanTypeProxy floatType;
- IDEFloatClassBeanTypeProxy floatClass;
+
+ IDEFloatClassBeanTypeProxy floatClass;
+
IDELongTypeBeanTypeProxy longType;
+
IDELongClassBeanTypeProxy longClass;
+
IDEShortTypeBeanTypeProxy shortType;
+
IDEShortClassBeanTypeProxy shortClass;
+
IDEByteTypeBeanTypeProxy byteType;
- IDEByteClassBeanTypeProxy byteClass;
+
+ IDEByteClassBeanTypeProxy byteClass;
+
IDECharTypeBeanTypeProxy charType;
- IDECharacterClassBeanTypeProxy charClass;
+
+ IDECharacterClassBeanTypeProxy charClass;
+
IDEDoubleTypeBeanTypeProxy doubleType;
- IDEDoubleClassBeanTypeProxy doubleClass;
-
+
+ IDEDoubleClassBeanTypeProxy doubleClass;
+
IDEStringBeanTypeProxy stringClass;
+
IDEClassBeanTypeProxy classClass;
+
IDEBeanTypeProxy voidType;
-public IDEStandardBeanTypeProxyFactory(IDEProxyFactoryRegistry aRegistry) {
- fFactoryRegistry = aRegistry;
- aRegistry.registerBeanTypeProxyFactory(this);
+ public IDEStandardBeanTypeProxyFactory(IDEProxyFactoryRegistry aRegistry) {
+ fFactoryRegistry = aRegistry;
+ aRegistry.registerBeanTypeProxyFactory(this);
- // Now initialize the cache.
- objectClass = new IDEBeanTypeProxy(fFactoryRegistry,Object.class);
- booleanType = new IDEBooleanTypeBeanTypeProxy(fFactoryRegistry, Boolean.TYPE);
- booleanClass = new IDEBooleanClassBeanTypeProxy(fFactoryRegistry, Boolean.class);
- intType = new IDEIntegerTypeBeanTypeProxy(fFactoryRegistry, Integer.TYPE);
- integerClass = new IDEIntegerClassBeanTypeProxy(fFactoryRegistry, Integer.class);
- floatType = new IDEFloatTypeBeanTypeProxy(fFactoryRegistry,Float.TYPE);
- floatClass = new IDEFloatClassBeanTypeProxy(fFactoryRegistry,Float.class);
- longType = new IDELongTypeBeanTypeProxy(fFactoryRegistry,Long.TYPE);
- longClass = new IDELongClassBeanTypeProxy(fFactoryRegistry,Long.class);
- shortType = new IDEShortTypeBeanTypeProxy(fFactoryRegistry,Short.TYPE);
- shortClass = new IDEShortClassBeanTypeProxy(fFactoryRegistry,Short.class);
- byteType = new IDEByteTypeBeanTypeProxy(fFactoryRegistry,Byte.TYPE);
- byteClass = new IDEByteClassBeanTypeProxy(fFactoryRegistry,Byte.class);
- charType = new IDECharTypeBeanTypeProxy(fFactoryRegistry,Character.TYPE);
- charClass = new IDECharacterClassBeanTypeProxy(fFactoryRegistry,Character.class);
- doubleType = new IDEDoubleTypeBeanTypeProxy(fFactoryRegistry,Double.TYPE);
- doubleClass = new IDEDoubleClassBeanTypeProxy(fFactoryRegistry,Double.class);
- stringClass = new IDEStringBeanTypeProxy(fFactoryRegistry, String.class);
- classClass = new IDEClassBeanTypeProxy(fFactoryRegistry,java.lang.Class.class);
- voidType = new IDEBeanTypeProxy(fFactoryRegistry, Void.TYPE);
+ // Now initialize the cache.
+ objectClass = new IDEBeanTypeProxy(fFactoryRegistry, Object.class);
+ booleanType = new IDEBooleanTypeBeanTypeProxy(fFactoryRegistry, Boolean.TYPE);
+ booleanClass = new IDEBooleanClassBeanTypeProxy(fFactoryRegistry, Boolean.class);
+ intType = new IDEIntegerTypeBeanTypeProxy(fFactoryRegistry, Integer.TYPE);
+ integerClass = new IDEIntegerClassBeanTypeProxy(fFactoryRegistry, Integer.class);
+ floatType = new IDEFloatTypeBeanTypeProxy(fFactoryRegistry, Float.TYPE);
+ floatClass = new IDEFloatClassBeanTypeProxy(fFactoryRegistry, Float.class);
+ longType = new IDELongTypeBeanTypeProxy(fFactoryRegistry, Long.TYPE);
+ longClass = new IDELongClassBeanTypeProxy(fFactoryRegistry, Long.class);
+ shortType = new IDEShortTypeBeanTypeProxy(fFactoryRegistry, Short.TYPE);
+ shortClass = new IDEShortClassBeanTypeProxy(fFactoryRegistry, Short.class);
+ byteType = new IDEByteTypeBeanTypeProxy(fFactoryRegistry, Byte.TYPE);
+ byteClass = new IDEByteClassBeanTypeProxy(fFactoryRegistry, Byte.class);
+ charType = new IDECharTypeBeanTypeProxy(fFactoryRegistry, Character.TYPE);
+ charClass = new IDECharacterClassBeanTypeProxy(fFactoryRegistry, Character.class);
+ doubleType = new IDEDoubleTypeBeanTypeProxy(fFactoryRegistry, Double.TYPE);
+ doubleClass = new IDEDoubleClassBeanTypeProxy(fFactoryRegistry, Double.class);
+ stringClass = new IDEStringBeanTypeProxy(fFactoryRegistry, String.class);
+ classClass = new IDEClassBeanTypeProxy(fFactoryRegistry, java.lang.Class.class);
+ voidType = new IDEBeanTypeProxy(fFactoryRegistry, Void.TYPE);
- // Initialize the hashtable with the primitives, their lang equivalents, and also common classes like String
- beanProxies = new HashMap(20);
+ // Initialize the hashtable with the primitives, their lang equivalents, and also common classes like String
+ beanProxies = new HashMap(20);
- // Primitives
- beanProxies.put(intType.getTypeName(), intType);
- beanProxies.put(booleanType.getTypeName(), booleanType);
- beanProxies.put(charType.getTypeName(), charType);
- beanProxies.put(byteType.getTypeName(), byteType);
- beanProxies.put(shortType.getTypeName(), shortType);
- beanProxies.put(longType.getTypeName(), longType);
- beanProxies.put(floatType.getTypeName(), floatType);
- beanProxies.put(doubleType.getTypeName(), doubleType);
+ // Primitives
+ beanProxies.put(intType.getTypeName(), intType);
+ beanProxies.put(booleanType.getTypeName(), booleanType);
+ beanProxies.put(charType.getTypeName(), charType);
+ beanProxies.put(byteType.getTypeName(), byteType);
+ beanProxies.put(shortType.getTypeName(), shortType);
+ beanProxies.put(longType.getTypeName(), longType);
+ beanProxies.put(floatType.getTypeName(), floatType);
+ beanProxies.put(doubleType.getTypeName(), doubleType);
- // java.lang primitive peers
- // Note that special classes are used for some of these which allow the IDE to get the
- // lang objects from the objects that are holding proxies
- beanProxies.put(integerClass.getTypeName(), integerClass);
- beanProxies.put(booleanClass.getTypeName(), booleanClass);
- beanProxies.put(charClass.getTypeName(), charClass);
- beanProxies.put(byteClass.getTypeName(), byteClass);
- beanProxies.put(shortClass.getTypeName(), shortClass);
- beanProxies.put(longClass.getTypeName(), longClass);
- beanProxies.put(floatClass.getTypeName(), floatClass);
- beanProxies.put(doubleClass.getTypeName(), doubleClass);
- beanProxies.put(BigDecimal.class.getName(), new IDEBigDecimalBeanTypeProxy(fFactoryRegistry, BigDecimal.class));//$NON-NLS-1$
- beanProxies.put(BigInteger.class.getName(), new IDEBigIntegerBeanTypeProxy(fFactoryRegistry, BigInteger.class));//$NON-NLS-1$
- beanProxies.put(stringClass.getTypeName(), stringClass);
-
- beanProxies.put(classClass.getTypeName(), classClass);
- beanProxies.put(voidType.getTypeName(), voidType);
-}
-/**
- * We are an IDE proxy and know that the type is in the same VM as the IDE.
- * the IDEBeanTypeProxy object
- * NOTE This is package protected because the only person who can call it are priveledged classes
- * that are also creating things in an IDEProxy environment.
- * If anyone needs to make this method public they are doing the wrong thing as they should use the
- * public method getBeanTypeProxy(String) that is on the interface. The only other object that can
- * guarantee that they have the class for the argument are those that are part of the idevm package
- */
-IBeanTypeProxy getBeanTypeProxy(Class anIDEClass) {
- return getBeanTypeProxy(anIDEClass.getName());
+ // java.lang primitive peers
+ // Note that special classes are used for some of these which allow the IDE to get the
+ // lang objects from the objects that are holding proxies
+ beanProxies.put(integerClass.getTypeName(), integerClass);
+ beanProxies.put(booleanClass.getTypeName(), booleanClass);
+ beanProxies.put(charClass.getTypeName(), charClass);
+ beanProxies.put(byteClass.getTypeName(), byteClass);
+ beanProxies.put(shortClass.getTypeName(), shortClass);
+ beanProxies.put(longClass.getTypeName(), longClass);
+ beanProxies.put(floatClass.getTypeName(), floatClass);
+ beanProxies.put(doubleClass.getTypeName(), doubleClass);
+ beanProxies.put(BigDecimal.class.getName(), new IDEBigDecimalBeanTypeProxy(fFactoryRegistry, BigDecimal.class));//$NON-NLS-1$
+ beanProxies.put(BigInteger.class.getName(), new IDEBigIntegerBeanTypeProxy(fFactoryRegistry, BigInteger.class));//$NON-NLS-1$
+ beanProxies.put(stringClass.getTypeName(), stringClass);
-}
-/**
- * We are an IDE proxy and know that the type is in the same VM as the IDE.
- * the IDEBeanTypeProxy object
- */
-public synchronized IBeanTypeProxy getBeanTypeProxy(String typeName) {
- typeName = MapTypes.getJNIFormatName(typeName);
-
- // See whether we already have the proxy for the argument name
- IBeanTypeProxy beanTypeProxy = (IBeanTypeProxy) beanProxies.get(typeName);
- if (beanTypeProxy != null) {
- return beanTypeProxy;
+ beanProxies.put(classClass.getTypeName(), classClass);
+ beanProxies.put(voidType.getTypeName(), voidType);
}
-
- // If not an array, then see if the package extension mechanism can find it.
- // Do this here so that if it is found in the package extension we won't necessarily create an
- // extra connection when not needed.
- if (typeName.charAt(0) != '[') {
- // It is not an array
- // First check with the factory for the package of the class.
- // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
- // the package ended and the class started.
- int packageIndex = typeName.lastIndexOf('.');
- if (packageIndex != -1) {
- String packageName = typeName.substring(0, packageIndex);
- IDEExtensionBeanTypeProxyFactory packageFactory = (IDEExtensionBeanTypeProxyFactory)fFactoryRegistry.getBeanTypeProxyFactoryExtension(packageName);
- if (packageFactory != null) {
- beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName);
- if (beanTypeProxy != null) {
- registerBeanTypeProxy(beanTypeProxy, false);
- return beanTypeProxy;
+
+ /**
+ * We are an IDE proxy and know that the type is in the same VM as the IDE. the IDEBeanTypeProxy object NOTE This is package protected because the
+ * only person who can call it are priveledged classes that are also creating things in an IDEProxy environment. If anyone needs to make this
+ * method public they are doing the wrong thing as they should use the public method getBeanTypeProxy(String) that is on the interface. The only
+ * other object that can guarantee that they have the class for the argument are those that are part of the idevm package
+ */
+ IBeanTypeProxy getBeanTypeProxy(Class anIDEClass) {
+ return getBeanTypeProxy(anIDEClass.getName());
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(java.lang.String)
+ */
+ public synchronized IBeanTypeProxy getBeanTypeProxy(String typeName) {
+ typeName = MapTypes.getJNIFormatName(typeName);
+
+ // See whether we already have the proxy for the argument name
+ IProxyBeanType beanTypeProxy = (IProxyBeanType) beanProxies.get(typeName);
+ // See if there and resolved, if so, return it. If not resolved, that means we need it NOW
+ // so we must go for it. When finally resolved the original ExpressionProxy will be deregistered and
+ // the resolved beantypeproxy will be in its place.
+ if (beanTypeProxy != null && beanTypeProxy.isBeanProxy()) {
+ return (IBeanTypeProxy) beanTypeProxy;
+ }
+
+ // If not an array, then see if the package extension mechanism can find it.
+ // Do this here so that if it is found in the package extension we won't necessarily create an
+ // extra connection when not needed.
+ if (typeName.charAt(0) != '[') {
+ // It is not an array
+ // First check with the factory for the package of the class.
+ // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
+ // the package ended and the class started.
+ int packageIndex = typeName.lastIndexOf('.');
+ if (packageIndex != -1) {
+ String packageName = typeName.substring(0, packageIndex);
+ IDEExtensionBeanTypeProxyFactory packageFactory = (IDEExtensionBeanTypeProxyFactory) fFactoryRegistry
+ .getBeanTypeProxyFactoryExtension(packageName);
+ if (packageFactory != null) {
+ beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName);
+ if (beanTypeProxy != null) {
+ registerBeanTypeProxy((IBeanTypeProxy) beanTypeProxy, false);
+ return (IBeanTypeProxy) beanTypeProxy;
+ }
+ }
+ }
+ // There was not a registered factory that dealt with the class. Load it using the factory
+ // registry which has the plugin's class loader
+ try {
+ Class ideClass = fFactoryRegistry.loadClass(typeName);
+ IDEBeanTypeProxy superTypeProxy = null;
+ if (ideClass.getSuperclass() != null) {
+ // Get the beantype proxy of the superclass.
+ superTypeProxy = (IDEBeanTypeProxy) getBeanTypeProxy(ideClass.getSuperclass());
+ }
+
+ // Ask the supertype
+ // to create a beantype proxy of the same beantype proxy class.
+ // This is so that any subclasses will get the same beantype proxy class
+ // for it if it is special.
+ if (superTypeProxy != null)
+ beanTypeProxy = superTypeProxy.newBeanTypeForClass(ideClass);
+
+ if (beanTypeProxy == null)
+ beanTypeProxy = new IDEBeanTypeProxy(fFactoryRegistry, ideClass);
+ } catch (ClassNotFoundException e) {
+ ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.INFO, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e));
+ String msg = MessageFormat.format("{0}({1})", new Object[] { e.getClass(), e.getMessage()}); //$NON-NLS-1$
+ beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg);
+ } catch (ExceptionInInitializerError e) {
+ ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e));
+ String msg = MessageFormat.format("{0}({1})", new Object[] { e.getClass(), e.getMessage()}); //$NON-NLS-1$
+ beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg);
+ } catch (LinkageError e) {
+ ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e));
+ String msg = MessageFormat.format("{0}({1})", new Object[] { e.getClass(), e.getMessage()}); //$NON-NLS-1$
+ beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg);
+ }
+
+ // Cache the instance so we can re-use it again
+ beanProxies.put(typeName, beanTypeProxy);
+ return (IBeanTypeProxy) beanTypeProxy;
+ } else {
+ // need to create a array of this many dimensions so that we can get the appropriate class for it.
+ int dims = typeName.lastIndexOf('[') + 1;
+ Class finalComponentType = null;
+ if (typeName.charAt(dims) == 'L') {
+ // It is a class.
+ // Strip off up to the 'L', and the trailing ';'. That is the class name.
+ IDEBeanTypeProxy finalType = (IDEBeanTypeProxy) getBeanTypeProxy(typeName.substring(dims + 1, typeName.length() - 1));
+ if (finalType != null)
+ finalComponentType = finalType.fClass;
+ } else {
+ // It is a type. Need to map it.
+ finalComponentType = (Class) IDEStandardBeanTypeProxyFactory.MAP_SHORTSIG_TO_TYPE.get(typeName.substring(dims, dims + 1));
+ }
+
+ if (finalComponentType != null) {
+ Object dummyArray = Array.newInstance(finalComponentType, new int[dims]);
+ beanTypeProxy = new IDEArrayBeanTypeProxy(fFactoryRegistry, typeName, dummyArray.getClass());
+ beanProxies.put(typeName, beanTypeProxy);
+ }
+ return (IBeanTypeProxy) beanTypeProxy;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IExpression,
+ * java.lang.String)
+ */
+ public synchronized IProxyBeanType getBeanTypeProxy(IExpression expression, String typeName) {
+ typeName = MapTypes.getJNIFormatName(typeName);
+
+ // See whether we already have the proxy for the argument name
+ IProxyBeanType beanTypeProxy = (IProxyBeanType) beanProxies.get(typeName);
+ if (beanTypeProxy != null) { return beanTypeProxy; }
+
+ // Now see if an expression proxy cached.
+ beanTypeProxy = ((IDEExpression) expression).getBeanType(typeName);
+ if (beanTypeProxy != null)
+ return beanTypeProxy;
+
+
+ // If not an array, then see if the package extension mechanism can find it.
+ // Do this here so that if it is found in the package extension we won't necessarily create an
+ // extra connection when not needed.
+ if (typeName.charAt(0) != '[') {
+ // It is not an array
+ // First check with the factory for the package of the class.
+ // Inner classes have to use the dollar notation since if they didn't we couldn't tell where
+ // the package ended and the class started.
+ int packageIndex = typeName.lastIndexOf('.');
+ if (packageIndex != -1) {
+ String packageName = typeName.substring(0, packageIndex);
+ IDEExtensionBeanTypeProxyFactory packageFactory = (IDEExtensionBeanTypeProxyFactory) fFactoryRegistry
+ .getBeanTypeProxyFactoryExtension(packageName);
+ if (packageFactory != null) {
+ beanTypeProxy = packageFactory.getExtensionBeanTypeProxy(typeName, expression);
+ if (beanTypeProxy != null) {
+ registerBeanTypeProxy(beanTypeProxy, false);
+ return beanTypeProxy;
+ }
}
}
}
- // There was not a registered factory that dealt with the class. Load it using the factory
- // registry which has the plugin's class loader
- try {
- Class ideClass = fFactoryRegistry.loadClass(typeName);
- IDEBeanTypeProxy superTypeProxy = null;
- if (ideClass.getSuperclass() != null) {
- // Get the beantype proxy of the superclass.
- superTypeProxy = (IDEBeanTypeProxy) getBeanTypeProxy(ideClass.getSuperclass());
- }
-
- // Ask the supertype
- // to create a beantype proxy of the same beantype proxy class.
- // This is so that any subclasses will get the same beantype proxy class
- // for it if it is special.
- if (superTypeProxy != null)
- beanTypeProxy = superTypeProxy.newBeanTypeForClass(ideClass);
-
- if (beanTypeProxy == null)
- beanTypeProxy = new IDEBeanTypeProxy(fFactoryRegistry, ideClass);
- } catch (ClassNotFoundException e) {
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.INFO, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e));
- String msg = MessageFormat.format("{0}({1})", new Object[] {e.getClass(), e.getMessage()}); //$NON-NLS-1$
- beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg);
- } catch (ExceptionInInitializerError e) {
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e));
- String msg = MessageFormat.format("{0}({1})", new Object[] {e.getClass(), e.getMessage()}); //$NON-NLS-1$
- beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg);
- } catch (LinkageError e) {
- ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e));
- String msg = MessageFormat.format("{0}({1})", new Object[] {e.getClass(), e.getMessage()}); //$NON-NLS-1$
- beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg);
- }
- // Cache the instance so we can re-use it again
- beanProxies.put(typeName, beanTypeProxy);
+ // There was not a registered factory that dealt with the class. So create the expression proxy.
+ beanTypeProxy = ((Expression) expression).createBeanTypeExpressionProxy(typeName);
+ registerBeanTypeProxy(beanTypeProxy, false);
return beanTypeProxy;
- } else {
- // need to create a array of this many dimensions so that we can get the appropriate class for it.
- int dims = typeName.lastIndexOf('[')+1;
- Class finalComponentType = null;
- if (typeName.charAt(dims) == 'L') {
- // It is a class.
- // Strip off up to the 'L', and the trailing ';'. That is the class name.
- IDEBeanTypeProxy finalType = (IDEBeanTypeProxy) getBeanTypeProxy(typeName.substring(dims+1, typeName.length()-1));
- if (finalType != null)
- finalComponentType = finalType.fClass;
- } else {
- // It is a type. Need to map it.
- finalComponentType = (Class) IDEStandardBeanTypeProxyFactory.MAP_SHORTSIG_TO_TYPE.get(typeName.substring(dims, dims+1));
- }
-
- if (finalComponentType != null) {
- Object dummyArray = Array.newInstance(finalComponentType, new int[dims]);
- beanTypeProxy = new IDEArrayBeanTypeProxy(fFactoryRegistry, typeName, dummyArray.getClass());
- beanProxies.put(typeName,beanTypeProxy);
- }
- return beanTypeProxy;
+
}
-}
-/**
- * Return an Array type proxy for the given class name of
- * the specified dimensions. This is a helper method. The
- * same result can be gotton from getBeanTypeProxy.
- * e.g.
- * getBeanTypeProxy("java.lang.Object", 3)
- * is the same as:
- * getBeanTypeProxy("[[[Ljava.lang.Object;")
- *
- * They both result in a type of:
- * Object [][][]
- *
- * or
- * getBeanTypeProxy("[Ljava.langObject;", 3)
- * becomes
- * Object [][][][]
- */
-public IBeanTypeProxy getBeanTypeProxy(String componentClassName, int dimensions) {
- String jniComponentTypeName = MapTypes.getJNIFormatName(componentClassName);
- String compType = jniComponentTypeName;
- if (jniComponentTypeName.charAt(0) != '[') {
- // We're not already an array, so create correct template.
- compType = (String) MAP_TYPENAME_TO_SHORTSIG.get(componentClassName);
- if (compType == null) {
- // It is a class, and not a type.
- compType = "L"+jniComponentTypeName+";"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(java.lang.String, int)
+ */
+ public IBeanTypeProxy getBeanTypeProxy(String componentClassName, int dimensions) {
+ return getBeanTypeProxy(getArrayClassname(componentClassName, dimensions));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#getBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IExpression,
+ * java.lang.String, int)
+ */
+ public IProxyBeanType getBeanTypeProxy(IExpression expression, String componentClassName, int dimensions) {
+ return getBeanTypeProxy(expression, getArrayClassname(componentClassName, dimensions));
+ }
+
+ /**
+ * @param componentClassName
+ * @param dimensions
+ * @return
+ *
+ * @since 1.1.0
+ */
+ protected String getArrayClassname(String componentClassName, int dimensions) {
+ String jniComponentTypeName = MapTypes.getJNIFormatName(componentClassName);
+ String compType = jniComponentTypeName;
+ if (jniComponentTypeName.charAt(0) != '[') {
+ // We're not already an array, so create correct template.
+ compType = (String) MAP_TYPENAME_TO_SHORTSIG.get(componentClassName);
+ if (compType == null) {
+ // It is a class, and not a type.
+ compType = "L" + jniComponentTypeName + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
}
- }
- // Now create it with the appropriate number of '[' in front.
- StringBuffer buffer = new StringBuffer(dimensions+compType.length());
- for (int i=0; i<dimensions; i++)
- buffer.append('[');
- buffer.append(compType);
- return getBeanTypeProxy(buffer.toString());
-}
+ // Now create it with the appropriate number of '[' in front.
+ StringBuffer buffer = new StringBuffer(dimensions + compType.length());
+ for (int i = 0; i < dimensions; i++)
+ buffer.append('[');
+ buffer.append(compType);
+ return buffer.toString();
+ }
-/*
- * (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IBeanProxyFactory#terminateFactory(boolean)
- */
-public void terminateFactory(boolean wait){
-}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IBeanProxyFactory#terminateFactory(boolean)
+ */
+ public void terminateFactory(boolean wait) {
+ }
-/**
- * registerBeanTypeProxy.
- * Register this bean type proxy on behalf of the
- * custom factory. This is so that during initializations,
- * the custom factory can cache specific bean type proxies
- * ahead of time.
- */
-public synchronized void registerBeanTypeProxy(IBeanTypeProxy aBeanTypeProxy,boolean permanent){
- beanProxies.put(aBeanTypeProxy.getTypeName(), aBeanTypeProxy);
-}
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeRegistered(String)
- */
-public synchronized boolean isBeanTypeRegistered(String className) {
- return beanProxies.containsKey(MapTypes.getJNIFormatName(className));
-}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registerBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IBeanTypeProxy,
+ * boolean)
+ */
+ public synchronized void registerBeanTypeProxy(IBeanTypeProxy aBeanTypeProxy, boolean permanent) {
+ beanProxies.put(aBeanTypeProxy.getTypeName(), aBeanTypeProxy);
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registeredTypes()
- */
-public Set registeredTypes() {
- return beanProxies.keySet();
-}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registerBeanTypeProxy(org.eclipse.jem.internal.proxy.core.IProxyBeanType,
+ * boolean)
+ */
+ public void registerBeanTypeProxy(IProxyBeanType aProxyBeanType, boolean permanent) {
+ if (aProxyBeanType.isBeanProxy())
+ registerBeanTypeProxy((IBeanTypeProxy) aProxyBeanType, permanent); // A regular kind, do regular registration.
+ else {
+ ExpressionProxy beanExpressionProxy = ((ExpressionProxy) aProxyBeanType);
+ final String typeName = aProxyBeanType.getTypeName();
+ ((IDEExpression) beanExpressionProxy.getExpression()).addBeanType(typeName, aProxyBeanType);
+ beanExpressionProxy.addProxyListener(new ExpressionProxy.ProxyAdapter() {
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeNotFound(String)
- */
-public boolean isBeanTypeNotFound(String className) {
- // Do nothing. No need for it in IDE system because there will always be a proxy, even when not found.
- // In that case an IDEInitErrorBeanTypeProxy will be created.
- return false;
-}
+ public void proxyResolved(ProxyEvent event) {
+ String typeName = ((IProxyBeanType) event.getSource()).getTypeName();
+ synchronized (IDEStandardBeanTypeProxyFactory.this) {
+ if (!beanProxies.containsKey(typeName)) {
+ // It hasn't been resolved through some other means. So this is good. Actually this should never
+ // occur because upon resolution we've already registered the bean type proxy through the
+ // normal mechanisms. But to be safe, we'll do it here.
+ beanProxies.put(typeName, event.getProxy());
+ }
+ }
+ }
+
+ public void proxyNotResolved(ExpressionProxy.ProxyEvent event) {
+ ((IDEExpression) ((ExpressionProxy) event.getSource()).getExpression()).removeBeanType(typeName);
+ }
+ });
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isMaintainNotFoundTypes()
- */
-public boolean isMaintainNotFoundTypes() {
- // Do nothing. No need for it in IDE system because there will always be a proxy, even when not found.
- // In that case an IDEInitErrorBeanTypeProxy will be created.
- return false;
-}
+ }
-/* (non-Javadoc)
- * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#setMaintainNotFoundTypes(boolean)
- */
-public void setMaintainNotFoundTypes(boolean maintain) {
- // Do nothing. No need for it in IDE system because there will always be a proxy, even when not found.
- // In that case an IDEInitErrorBeanTypeProxy will be created.
-}
-}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeRegistered(String)
+ */
+ public synchronized boolean isBeanTypeRegistered(String className) {
+ return beanProxies.containsKey(MapTypes.getJNIFormatName(className));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#registeredTypes()
+ */
+ public Set registeredTypes() {
+ return beanProxies.keySet();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isBeanTypeNotFound(String)
+ */
+ public boolean isBeanTypeNotFound(String className) {
+ // Do nothing. No need for it in IDE system because there will always be a proxy, even when not found.
+ // In that case an IDEInitErrorBeanTypeProxy will be created.
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#isMaintainNotFoundTypes()
+ */
+ public boolean isMaintainNotFoundTypes() {
+ // Do nothing. No need for it in IDE system because there will always be a proxy, even when not found.
+ // In that case an IDEInitErrorBeanTypeProxy will be created.
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.core.IStandardBeanTypeProxyFactory#setMaintainNotFoundTypes(boolean)
+ */
+ public void setMaintainNotFoundTypes(boolean maintain) {
+ // Do nothing. No need for it in IDE system because there will always be a proxy, even when not found.
+ // In that case an IDEInitErrorBeanTypeProxy will be created.
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEThrowableProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEThrowableProxy.java
index 7e4a1da..f1ccaa1 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEThrowableProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEThrowableProxy.java
@@ -11,18 +11,17 @@
package org.eclipse.jem.internal.proxy.ide;
/*
* $RCSfile: IDEThrowableProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
import org.eclipse.jem.internal.proxy.core.*;
public class IDEThrowableProxy extends ThrowableProxy implements IIDEBeanProxy {
- protected Throwable fExc;
protected IBeanTypeProxy fBeanTypeProxy;
protected IDEThrowableProxy(Throwable exc, IBeanTypeProxy aBeanTypeProxy) {
- fExc = exc;
+ super(exc);
fBeanTypeProxy = aBeanTypeProxy;
}
@@ -30,7 +29,7 @@
if (super.equals(obj))
return true;
if (obj instanceof IIDEBeanProxy) {
- return fExc.equals(((IIDEBeanProxy) obj).getBean());
+ return getCause().equals(((IIDEBeanProxy) obj).getBean());
}
return false;
}
@@ -42,24 +41,24 @@
if (this == aBeanProxy)
return true;
if (aBeanProxy instanceof IIDEBeanProxy)
- return fExc == ((IIDEBeanProxy) aBeanProxy).getBean();
+ return getCause() == ((IIDEBeanProxy) aBeanProxy).getBean();
return false;
}
public String getProxyLocalizedMessage() {
- return fExc.getLocalizedMessage();
+ return getCause().getLocalizedMessage();
}
public String getProxyMessage() {
- return fExc.getMessage();
+ return getCause().getMessage();
}
public void printProxyStackTrace(java.io.PrintWriter writer) {
- fExc.printStackTrace(writer);
+ getCause().printStackTrace(writer);
}
public void printProxyStackTrace(java.io.PrintStream stream) {
- fExc.printStackTrace(stream);
+ getCause().printStackTrace(stream);
}
public void printProxyStackTrace() {
- fExc.printStackTrace();
+ getCause().printStackTrace();
}
public IBeanTypeProxy getTypeProxy() {
return fBeanTypeProxy;
@@ -68,7 +67,7 @@
return fBeanTypeProxy.getProxyFactoryRegistry();
}
public String toBeanString() {
- return fExc.toString();
+ return getCause().toString();
}
public boolean isValid() {
return true;
@@ -77,7 +76,19 @@
* Return the exception which is the live bean
*/
public Object getBean() {
- return fExc;
+ return getCause();
}
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isBeanProxy()
+ */
+ public final boolean isBeanProxy() {
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IProxy#isExpressionProxy()
+ */
+ public final boolean isExpressionProxy() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEDimensionBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEDimensionBeanProxy.java
index 67d9327..8d039a8 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEDimensionBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEDimensionBeanProxy.java
@@ -11,14 +11,16 @@
package org.eclipse.jem.internal.proxy.ide.awt;
/*
* $RCSfile: IDEDimensionBeanProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
-import org.eclipse.jem.internal.proxy.core.*;
-import org.eclipse.jem.internal.proxy.ide.*;
-import org.eclipse.jem.internal.proxy.awt.*;
import java.awt.Dimension;
+import org.eclipse.jem.internal.proxy.core.IBeanTypeProxy;
+import org.eclipse.jem.internal.proxy.core.IDimensionBeanProxy;
+import org.eclipse.jem.internal.proxy.ide.IDEObjectBeanProxy;
+import org.eclipse.jem.internal.proxy.ide.IDEProxyFactoryRegistry;
+
public class IDEDimensionBeanProxy extends IDEObjectBeanProxy implements IDimensionBeanProxy {
protected Dimension fDimension;
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEPointBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEPointBeanProxy.java
index 61ba3f9..149ad21 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEPointBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEPointBeanProxy.java
@@ -11,14 +11,16 @@
package org.eclipse.jem.internal.proxy.ide.awt;
/*
* $RCSfile: IDEPointBeanProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
-import org.eclipse.jem.internal.proxy.core.*;
-import org.eclipse.jem.internal.proxy.ide.*;
-import org.eclipse.jem.internal.proxy.awt.*;
import java.awt.Point;
+import org.eclipse.jem.internal.proxy.core.IBeanTypeProxy;
+import org.eclipse.jem.internal.proxy.core.IPointBeanProxy;
+import org.eclipse.jem.internal.proxy.ide.IDEObjectBeanProxy;
+import org.eclipse.jem.internal.proxy.ide.IDEProxyFactoryRegistry;
+
public class IDEPointBeanProxy extends IDEObjectBeanProxy implements IPointBeanProxy {
protected Point fPoint;
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDERectangleBeanProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDERectangleBeanProxy.java
index 3a4fa41..b566391 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDERectangleBeanProxy.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDERectangleBeanProxy.java
@@ -11,14 +11,15 @@
package org.eclipse.jem.internal.proxy.ide.awt;
/*
* $RCSfile: IDERectangleBeanProxy.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
-import org.eclipse.jem.internal.proxy.core.*;
-import org.eclipse.jem.internal.proxy.ide.*;
-import org.eclipse.jem.internal.proxy.awt.*;
import java.awt.Rectangle;
+import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.ide.IDEObjectBeanProxy;
+import org.eclipse.jem.internal.proxy.ide.IDEProxyFactoryRegistry;
+
public class IDERectangleBeanProxy extends IDEObjectBeanProxy implements IRectangleBeanProxy {
protected Rectangle fRectangle;
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEStandardAWTBeanTypeProxyFactory.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEStandardAWTBeanTypeProxyFactory.java
index 35ef089..53707b9 100644
--- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEStandardAWTBeanTypeProxyFactory.java
+++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/awt/IDEStandardAWTBeanTypeProxyFactory.java
@@ -1,4 +1,3 @@
-package org.eclipse.jem.internal.proxy.ide.awt;
/*******************************************************************************
* Copyright (c) 2001, 2003, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
@@ -11,56 +10,76 @@
*******************************************************************************/
/*
* $RCSfile: IDEStandardAWTBeanTypeProxyFactory.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:57:26 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:12 $
*/
+package org.eclipse.jem.internal.proxy.ide.awt;
-import org.eclipse.jem.internal.proxy.ide.*;
import org.eclipse.jem.internal.proxy.core.*;
+import org.eclipse.jem.internal.proxy.ide.*;
+
/**
- * BeanType factory standard AWT bean types.
- * This is package protected because it shouldn't be
- * referenced outside the package. It should only be accessed through
- * the interface.
+ * BeanType factory standard AWT bean types. This is package protected because it shouldn't be referenced outside the package. It should only be
+ * accessed through the interface.
*/
class IDEStandardAWTBeanTypeProxyFactory implements IDEExtensionBeanTypeProxyFactory {
static final String BEAN_TYPE_FACTORY_KEY = "java.awt"; //$NON-NLS-1$
-
+
protected final IDEProxyFactoryRegistry fFactoryRegistry;
+
protected final IDEDimensionBeanTypeProxy dimensionType;
+
protected final IDEPointBeanTypeProxy pointType;
+
protected final IDERectangleBeanTypeProxy rectangleType;
-
-IDEStandardAWTBeanTypeProxyFactory(IDEProxyFactoryRegistry aRegistry) {
- fFactoryRegistry = aRegistry;
- fFactoryRegistry.registerBeanTypeProxyFactory(BEAN_TYPE_FACTORY_KEY, this);
- dimensionType = new IDEDimensionBeanTypeProxy(fFactoryRegistry);
- pointType = new IDEPointBeanTypeProxy(fFactoryRegistry);
- rectangleType = new IDERectangleBeanTypeProxy(fFactoryRegistry);
-}
-/**
- * Create the correct beantype from the class and id passed in.
- */
-public IDEBeanTypeProxy getExtensionBeanTypeProxy(String className){
-
- if ("java.awt.Dimension".equals(className)) //$NON-NLS-1$
- return dimensionType;
- else if ("java.awt.Point".equals(className)) //$NON-NLS-1$
- return pointType;
- else if ("java.awt.Rectangle".equals(className)) //$NON-NLS-1$
- return rectangleType;
- else
- return null;
-}
-/**
- * Create the correct beantype from the class and id passed in.
- */
-public IDEBeanTypeProxy getExtensionBeanTypeProxy(String className, IBeanTypeProxy beanTypeProxy){
+ IDEStandardAWTBeanTypeProxyFactory(IDEProxyFactoryRegistry aRegistry) {
+ fFactoryRegistry = aRegistry;
+ fFactoryRegistry.registerBeanTypeProxyFactory(BEAN_TYPE_FACTORY_KEY, this);
+ dimensionType = new IDEDimensionBeanTypeProxy(fFactoryRegistry);
+ pointType = new IDEPointBeanTypeProxy(fFactoryRegistry);
+ rectangleType = new IDERectangleBeanTypeProxy(fFactoryRegistry);
+ }
- return getExtensionBeanTypeProxy(className);
-}
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.ide.IDEExtensionBeanTypeProxyFactory#getExtensionBeanTypeProxy(java.lang.String)
+ */
+ public IDEBeanTypeProxy getExtensionBeanTypeProxy(String className) {
-public void terminateFactory(boolean wait){
-}
-}
+ if ("java.awt.Dimension".equals(className)) //$NON-NLS-1$
+ return dimensionType;
+ else if ("java.awt.Point".equals(className)) //$NON-NLS-1$
+ return pointType;
+ else if ("java.awt.Rectangle".equals(className)) //$NON-NLS-1$
+ return rectangleType;
+ else
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.ide.IDEExtensionBeanTypeProxyFactory#getExtensionBeanTypeProxy(java.lang.String, org.eclipse.jem.internal.proxy.core.IBeanTypeProxy)
+ */
+ public IDEBeanTypeProxy getExtensionBeanTypeProxy(String className, IBeanTypeProxy beanTypeProxy) {
+
+ return getExtensionBeanTypeProxy(className);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jem.internal.proxy.ide.IDEExtensionBeanTypeProxyFactory#getExtensionBeanTypeProxy(java.lang.String,
+ * org.eclipse.jem.internal.proxy.core.IExpression)
+ */
+ public IProxyBeanType getExtensionBeanTypeProxy(String typeName, IExpression expression) {
+ return getExtensionBeanTypeProxy(typeName);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.core.IBeanProxyFactory#terminateFactory(boolean)
+ */
+ public void terminateFactory(boolean wait) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/CommandErrorException.java b/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/CommandErrorException.java
index 14e21c5..c3042e7 100644
--- a/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/CommandErrorException.java
+++ b/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/CommandErrorException.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.common.remote;
/*
* $RCSfile: CommandErrorException.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:56:39 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:12 $
*/
import org.eclipse.jem.internal.proxy.common.CommandException;
@@ -32,7 +32,7 @@
}
public CommandErrorException(String msg, int errorCode, Commands.ValueObject errorData, Object errorObject) {
- super(msg, errorData);
+ super(msg, errorData.clone());
fErrorObject = errorObject;
fErrorCode = errorCode;
}
diff --git a/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/Commands.java b/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/Commands.java
index 8038136..ed834c3 100644
--- a/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/Commands.java
+++ b/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/Commands.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.common.remote;
/*
* $RCSfile: Commands.java,v $
- * $Revision: 1.12 $ $Date: 2005/02/15 22:56:39 $
+ * $Revision: 1.13 $ $Date: 2005/05/11 19:01:12 $
*/
import java.io.*;
@@ -149,9 +149,10 @@
OBJECT_ID = 50, // Object identity key - writeInt
NEW_OBJECT_ID = 51, // New Object identity (this is a new object that didn't exist before)
THROW = 52, // An exception occured. The value is a throwable, it is of the same format as NEW_OBJECT_ID.
- ARRAY_IDS = 53; // An array of values, where there are at least one ID in the array. If there were no
+ ARRAY_IDS = 53, // An array of values, where there are at least one ID in the array. If there were no
// ID's (i.e. all just values), then use OBJECT type intead and have it written as
// writeObject.
+ FLAG = 54; // The value is a flag int. If this is allowed on a read, the anInt field will contain the flag value.
@@ -355,6 +356,11 @@
* sent, then the primitive field will be set instead, though the type
* will still be the Object type (i.e. if type = L_BYTE, the aByte will
* have the value in it).
+ *
+ * Note: Also flags can be send back. The type will be FLAG and the anInt field will be the
+ * flag value. This is used to indicate special things that aren't values. Most useful in
+ * arrays where one of the entries is not a value. This can only be used if readValue
+ * is passed a flag indicating flags are valid, otherwise it will be treated as not valie.
*/
public static class ValueObject implements Cloneable {
public byte type; // Same as the types above
@@ -424,6 +430,16 @@
}
/**
+ * Get the type as one of the valid Commands.Types. VOID, BYTE, L_BYTE, etc.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
* Special getter to get the type as an Object, this is used by invoke for example.
*/
public Object getAsObject() {
@@ -509,6 +525,12 @@
type = VOID;
anObject = null;
}
+
+ public void setFlag(int flag) {
+ type = FLAG;
+ anInt = flag;
+ }
+
public void set(byte value) {
type = BYTE;
aByte = value;
@@ -681,9 +703,34 @@
public static final Object SOME_UNEXPECTED_EXCEPTION = "SOME_UNEXPECTED_EXCEPTION"; // There was some kind of exception that wasn't expected. The data will be the exception. //$NON-NLS-1$
public static final Object TOO_MANY_BYTES = "TOO_MANY_BYTES"; // Too many bytes were sent on a writeBytes. It was //$NON-NLS-1$
// more than could be read into the buffer. The data will be the size sent.
-
-
- public static void readValue(DataInputStream is, ValueObject value) throws CommandException {
+
+ /**
+ * Read a value from the stream into the value object. It will not allow values of type FLAG.
+ *
+ * @param is
+ * @param value
+ * @param allowFlag
+ * @return the value object sent in. This allows <code>value = Commands.readValue(is, new Commands.ValueObject());</code>
+ * @throws CommandException
+ *
+ *
+ * @since 1.0.0
+ */
+ public static ValueObject readValue(DataInputStream is, ValueObject value) throws CommandException {
+ readValue(is, value, false);
+ return value;
+ }
+
+ /**
+ * Read a value from the stream into the value object. It will allow values of type FLAG if allowFlag is true.
+ * @param is
+ * @param value
+ * @param allowFlag <code>true</code> if values of type flag are allow.
+ * @throws CommandException
+ *
+ * @since 1.1.0
+ */
+ public static void readValue(DataInputStream is, ValueObject value, boolean allowFlag) throws CommandException {
try {
value.anObject = null;
value.type = is.readByte();
@@ -748,6 +795,12 @@
break;
case VOID:
break;
+ case FLAG:
+ if (allowFlag) {
+ value.anInt = is.readInt();
+ break;
+ }
+ // Flags not allowed, so drop into default.
default:
throw new UnexpectedCommandException(UNKNOWN_READ_TYPE, false, new Byte(value.type));
}
@@ -764,28 +817,48 @@
* Special interface used to read back arrays. It will be called when
*/
public static interface ValueSender {
- // This is called for each entry from the array. It is assumed that the ValueSender has
- // the array that is being built.
+ /**
+ * This is called for each entry from the array. It is assumed that the ValueSender has
+ * the array that is being built.
+ * @param value
+ *
+ * @since 1.1.0
+ */
public void sendValue(ValueObject value);
-
- // This is called when an ARRAY_IDS is found within the reading of the array (i.e. nested arrays)
- // It is asking for a new ValueSender to use while this nested array. The arrayValue contains
- // the valueobject for the array header (i.e. the class id of the array and the number of elements).
- // It is the responsibility of the ValueSender to store this array in the array that is being built.
+
+ /**
+ * This is called when an ARRAY_IDS is found within the reading of the array (i.e. nested arrays)
+ * It is asking for a new ValueSender to use while this nested array. The arrayValue contains
+ * the valueobject for the array header (i.e. the class id of the array and the number of elements).
+ * It is the responsibility of the ValueSender to store this array in the array that is being built.
+ * @param arrayValue
+ * @return
+ *
+ * @since 1.1.0
+ */
public ValueSender nestedArray(ValueObject arrayValue);
+ /**
+ * Called to initialize the sender with the given array header. This is not always called, each usage
+ * knows whether it can be called or not. For example the implementation of nestedArray may not need to call initialize.
+ * @param arrayHeader
+ *
+ * @since 1.1.0
+ */
+ public void initialize(ValueObject arrayHeader);
+
}
/*
* NOTE: It is important that on the IDE side that this is called within a transaction.
* If not, there could be some corruption if proxy cleanup occurs in the middle.
*/
- public static void readArray(DataInputStream is, int arraySize, ValueSender valueSender, ValueObject value) throws CommandException {
+ public static void readArray(DataInputStream is, int arraySize, ValueSender valueSender, ValueObject value, boolean allowFlag) throws CommandException {
// Anything exception other than a CommandException, we will try to flush the input so that
// it can continue with the next command and not close the connection.
RuntimeException exception = null;
for (int i=0; i<arraySize; i++) {
- readValue(is, value);
+ readValue(is, value, allowFlag);
if (exception == null)
try {
if (value.type != ARRAY_IDS)
@@ -805,9 +878,11 @@
public ValueSender nestedArray(ValueObject arrayValue) {
return this;
}
+ public void initialize(ValueObject arrayHeader) {
+ }
};
}
- readArray(is, value.anInt, nestedSender, value);
+ readArray(is, value.anInt, nestedSender, value, allowFlag);
if (exception != null)
throw exception; // An exception ocurred in new sender request.
}
@@ -820,19 +895,31 @@
throw exception;
}
-
+
/**
* Special interface to handle writing the ARRAY_IDS type.
* An instance of this object will be in the valueObject sent to writeValue when the type of the value
* is ARRAY_IDS. Then write value will know to call this interface to write out the values.
+ *
+ * @since 1.1.0
*/
public static interface ValueRetrieve {
- // This interface is used to retreive the next value object so that it can be written to the output stream.
- // Return null when there are no more.
+ /**
+ * Returns the next value object to send. It will be called the number of times that the size of
+ * the array was set to be send.
+ * @return The value object to send.
+ * @throws EOFException
+ *
+ * @since 1.1.0
+ */
public ValueObject nextValue() throws EOFException;
}
-
+
public static void writeValue(DataOutputStream os, ValueObject value, boolean asValueCommand) throws CommandException {
+ writeValue(os, value, asValueCommand, asValueCommand ? true : false);
+ }
+
+ public static void writeValue(DataOutputStream os, ValueObject value, boolean asValueCommand, boolean flush) throws CommandException {
try {
if (asValueCommand)
os.writeByte(VALUE);
@@ -907,23 +994,27 @@
// We are writing out an array with ID's in it. The fields of the vale object will be:
// classID: The class id of the component type of the array.
// anObject: Contains the ValueRetriever to get the next value.
- os.writeByte(value.type);
+ os.writeByte(ARRAY_IDS);
os.writeInt(value.classID);
- os.writeInt(value.anInt);
+ os.writeInt(value.anInt); // The size of the array.
// Now comes the kludgy part, writing the values.
ValueRetrieve retriever = (ValueRetrieve) value.anObject;
- ValueObject nextEntry = null;
- while ((nextEntry = retriever.nextValue()) != null)
- writeValue(os, nextEntry, false);
+ int len = value.anInt;
+ while (len-- > 0)
+ writeValue(os, retriever.nextValue(), false);
break;
case VOID:
os.writeByte(value.type);
break;
+ case FLAG:
+ os.writeByte(FLAG);
+ os.writeInt(value.anInt);
+ break;
default:
os.writeByte(VOID);
throw new UnexpectedCommandException(UNKNOWN_WRITE_TYPE, true, value);
}
- if (asValueCommand)
+ if (flush)
os.flush();
} catch (CommandException e) {
// rethrow this exception since we want these to go on out.
diff --git a/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/ExpressionCommands.java b/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/ExpressionCommands.java
index a91ebdb..204c35c 100644
--- a/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/ExpressionCommands.java
+++ b/plugins/org.eclipse.jem.proxy/remoteCommon/org/eclipse/jem/internal/proxy/common/remote/ExpressionCommands.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: ExpressionCommands.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:56:39 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.common.remote;
@@ -34,10 +34,18 @@
END_EXPRESSION_TREE_PROCESSING = 2,
SYNC_REQUEST = 3,
PULL_VALUE_REQUEST = 4;
-
+
// These are the expression specific error codes (it can also send back general ones. See SYNC_REQUEST docs lower down).
public static final int
- ExpressionNoExpressionValueException = Commands.MAX_ERROR_CODE+1; // No expression value occurred.
+ EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION = Commands.MAX_ERROR_CODE+1; // No expression value occurred.
+
+ // These are the flag values sent in proxy resolution when doesn't resolve to proxy.
+ public static final int
+ EXPRESSIONPROXY_VOIDTYPE = 0, // Expression proxy resolves to void type.
+ EXPRESSIONPROXY_NOTRESOLVED = 1; // Expression proxy not resolved.
+
+ public static final String EXPRESSIONTRACE = "proxyvm.expressionTrace"; // The system property for turning on expression tracing.
+ public static final String EXPRESSIONTRACE_TIMER_THRESHOLD = "proxyvm.expressionTraceTimerThreshold"; // The system property for timer threshold.
/*
* The format of the commands are:
@@ -63,7 +71,7 @@
* IDE will wait for it to complete and read back the value. It will send back:
* 1: VALUE command with boolean true as the value.
* 2: ERROR command with code of ExpressionClassNotFound, with value of String with message from exception.
- * 3: ERROR command with code of ExpressionNoExpressionValueException, with value of String with message from exception.
+ * 3: ERROR command with code of EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION, with value of String with message from exception.
* 4: THROWABLE command with the actual exception that occurred.
*
*
@@ -80,7 +88,7 @@
/**
* Send the start expression processing command.
- * @param expressionID TODO
+ * @param expressionID
* @param os
*
* @throws IOException
@@ -95,7 +103,7 @@
/**
* Send the end expression processing command.
- * @param expressionID TODO
+ * @param expressionID
* @param os
*
* @throws IOException
@@ -111,7 +119,7 @@
/**
* Send an expression subcommand.
- * @param expressionID TODO
+ * @param expressionID
* @param os
* @param subcommand
*
@@ -162,7 +170,7 @@
* @since 1.0.0
*/
public static void sendString(DataOutputStream os, String aString) throws IOException {
- os.writeUTF(aString);
+ Commands.sendStringData(os, aString);
}
/**
@@ -179,26 +187,32 @@
}
/**
- * Send the pull value command. Return either the value or an error (NoValueExpressionException or a Throwable)>
- * @param expressionID TODO
+ * Send the pull value command. After processing the proxies, caller should call getFinalValue() to get the value.
+ * @param expressionID
* @param os
* @param is
- * @param valueReturn
+ * @param proxyids if not <code>null</code>, then this is the list of expression proxy ids that need to be returned as rendered.
+ * @param sender sender used to process the resolved proxy ids, or <code>null</code> if no proxy ids.
* @throws CommandException
*
* @since 1.0.0
*/
- public static void sendPullValueCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject valueReturn) throws CommandException {
+ public static void sendPullValueCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException {
try {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(PULL_VALUE_REQUEST);
+ sendProxyIDs(os, proxyids);
os.flush();
- Commands.readBackValue(is, valueReturn, Commands.NO_TYPE_CHECK);
+ if (proxyids != null) {
+ Commands.readBackValue(is, proxyids, Commands.ARRAY_IDS); // Read the array header.
+ sender.initialize(proxyids);
+ Commands.readArray(is, proxyids.anInt, sender, proxyids, true); // Read the array.
+ }
} catch (CommandException e) {
// rethrow this exception since we want these to go on out.
throw e;
- } catch (Exception e) {
+ } catch (IOException e) {
// Wrapper this one.
throw new UnexpectedExceptionCommandException(false, e);
}
@@ -206,24 +220,30 @@
/**
* Send a sync command. This does a synchronize with the remote expression processor. It makes sure that the
- * stream is caught and doesn't return until everything on the stream has been processed. It will then return a
- * value. The value should <code>true</code> if everything is OK, it could be an error return,
- * @param expressionID TODO
+ * stream is caught and doesn't return until everything on the stream has been processed. Should then call
+ * getFinalValue() to verify the expression is valid.
+ * @param expressionID
* @param os
* @param is
- * @param returnValue
+ * @param proxyids if not <code>null</code>, then this is the list of expression proxy ids that need to be returned as rendered.
+ * @param sender the sender used for reading back the proxyid resolutions, or <code>null</code> if no proxy ids.
*
* @throws CommandException
*
* @since 1.0.0
*/
- public static void sendSyncCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject returnValue) throws CommandException {
+ public static void sendSyncCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException {
try {
os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
os.writeInt(expressionID);
os.writeByte(SYNC_REQUEST);
+ sendProxyIDs(os, proxyids);
os.flush();
- Commands.readBackValue(is, returnValue, Commands.NO_TYPE_CHECK);
+ if (proxyids != null) {
+ Commands.readBackValue(is, proxyids, Commands.ARRAY_IDS); // Read the array header.
+ sender.initialize(proxyids);
+ Commands.readArray(is, proxyids.anInt, sender, proxyids, true); // Read the array.
+ }
} catch (CommandException e) {
// rethrow this exception since we want these to go on out.
throw e;
@@ -233,6 +253,23 @@
}
}
+ /**
+ * Send the proxyids (if not null) as part of a command. Used by sync and pullValue.
+ * @param os
+ * @param proxyids <code>null</code> if not requesting proxy ids.
+ * @throws IOException
+ * @throws CommandException
+ *
+ * @since 1.1.0
+ */
+ private static void sendProxyIDs(DataOutputStream os, Commands.ValueObject proxyids) throws IOException, CommandException {
+ if (proxyids != null) {
+ os.writeBoolean(true); // Indicates proxy ids being sent.
+ Commands.writeValue(os, proxyids, false, false);
+ } else
+ os.writeBoolean(false); // No proxyids being sent.
+ }
+
private ExpressionCommands() {
// Never intended to be instantiated.
}
diff --git a/plugins/org.eclipse.jem.proxy/schema/contributors.exsd b/plugins/org.eclipse.jem.proxy/schema/contributors.exsd
index cface6b..972d3fb 100644
--- a/plugins/org.eclipse.jem.proxy/schema/contributors.exsd
+++ b/plugins/org.eclipse.jem.proxy/schema/contributors.exsd
@@ -106,7 +106,7 @@
<contributor
class="com.example.ContributorImplementation"
container="MY_CONTAINER">
- <contributor>
+ </contributor>
</extension>
</pre>
</p>
diff --git a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/AWTStarter.java b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/AWTStarter.java
new file mode 100644
index 0000000..761f48e
--- /dev/null
+++ b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/AWTStarter.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 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: AWTStarter.java,v $
+ * $Revision: 1.1 $ $Date: 2005/05/11 19:01:12 $
+ */
+package org.eclipse.jem.internal.proxy.vm.remote;
+
+import java.awt.Toolkit;
+
+
+/**
+ * This class is used to do start the AWT eventqueue ahead of time to try to parallel process it.
+ * @since 1.1.0
+ */
+public class AWTStarter {
+
+ public static void startAWT() {
+ Thread t = new Thread() {
+ public void run() {
+ Thread.yield(); // So as not to possibly hold up the guy doing the starting.
+ Toolkit.getDefaultToolkit();
+ }
+ };
+ t.start();
+ }
+}
diff --git a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/CallbackHandler.java b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/CallbackHandler.java
index 3568630..73d50b7 100644
--- a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/CallbackHandler.java
+++ b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/CallbackHandler.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.vm.remote;
/*
* $RCSfile: CallbackHandler.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:57:54 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
import java.net.Socket;
@@ -106,24 +106,21 @@
}
public Commands.ValueObject nextValue() {
- if (index < array.length) {
- Object parm = array[index++];
- if (parm != null) {
- if (parm instanceof ICallbackHandler.TransmitableArray) {
- // It is another array, create a new retriever.
- worker.setArrayIDS(new Retriever(((ICallbackHandler.TransmitableArray) parm).getArray()), ((ICallbackHandler.TransmitableArray) parm).getArray().length, Commands.OBJECT_CLASS);
- } else {
- // They may add some new ID's and if there is an error, they
- // won't get released, but that is a slight chance we will have
- // to take because we don't know which ones were new and which
- // ones weren't.
- fillInValue(parm, NOT_A_PRIMITIVE, worker);
- }
- } else
- worker.set();
- return worker;
+ Object parm = array[index++];
+ if (parm != null) {
+ if (parm instanceof ICallbackHandler.TransmitableArray) {
+ // It is another array, create a new retriever.
+ worker.setArrayIDS(new Retriever(((ICallbackHandler.TransmitableArray) parm).getArray()), ((ICallbackHandler.TransmitableArray) parm).getArray().length, Commands.OBJECT_CLASS);
+ } else {
+ // They may add some new ID's and if there is an error, they
+ // won't get released, but that is a slight chance we will have
+ // to take because we don't know which ones were new and which
+ // ones weren't.
+ fillInValue(parm, NOT_A_PRIMITIVE, worker);
+ }
} else
- return null;
+ worker.set();
+ return worker;
}
};
diff --git a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java
index 33123f5..bc2b08d 100644
--- a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java
+++ b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ConnectionHandler.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.proxy.vm.remote;
/*
* $RCSfile: ConnectionHandler.java,v $
- * $Revision: 1.10 $ $Date: 2005/02/15 22:57:54 $
+ * $Revision: 1.11 $ $Date: 2005/05/11 19:01:12 $
*/
@@ -24,6 +24,7 @@
import org.eclipse.jem.internal.proxy.common.CommandException;
import org.eclipse.jem.internal.proxy.common.remote.*;
import org.eclipse.jem.internal.proxy.initParser.*;
+import org.eclipse.jem.internal.proxy.initParser.tree.NoExpressionValueException;
/**
* This handles one connection.
@@ -304,7 +305,7 @@
if (valueObject.type == Commands.ARRAY_IDS) {
// It is an array containing IDs, as it normally would be.
valueSender.initialize(valueObject);
- Commands.readArray(in, valueObject.anInt, valueSender, valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
parms = (Object[]) valueSender.getArray();
} else {
// It is all objects or null, so it should be an Object[] or null. If not, then this is an error.
@@ -365,7 +366,7 @@
if (valueObject.type == Commands.ARRAY_IDS) {
// It is an array containing IDs, as it normally would be.
valueSender.initialize(valueObject);
- Commands.readArray(in, valueObject.anInt, valueSender, valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
parmTypes = (Class[]) valueSender.getArray();
} else {
// It null, so it should be an null. If not, then this is an error.
@@ -380,7 +381,7 @@
if (valueObject.type == Commands.ARRAY_IDS) {
// It is an array containing IDs, as it normally would be.
valueSender.initialize(valueObject);
- Commands.readArray(in, valueObject.anInt, valueSender, valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
parms = (Object[]) valueSender.getArray();
} else {
// It is all objects or null, so it should be an Object[] or null. If not, then this is an error.
@@ -454,7 +455,7 @@
if (valueObject.type == Commands.ARRAY_IDS) {
// It is an array containing IDs, as it normally would be.
valueSender.initialize(valueObject);
- Commands.readArray(in, valueObject.anInt, valueSender, valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
result = (Object[]) valueSender.getArray();
} else {
result = getInvokableObject(valueObject);
@@ -488,7 +489,12 @@
break;
case Commands.EXPRESSION_TREE_COMMAND:
- processExpressionCommand(valueObject);
+ try {
+ processExpressionCommand(valueObject, valueSender);
+ } finally {
+ valueObject.set();
+ valueSender.clear();
+ }
break;
default:
@@ -563,16 +569,13 @@
}
public Commands.ValueObject nextValue() {
- if (index < length) {
- fillInValue(Array.get(array, index++), componentType, worker);
- return worker;
- } else
- return null;
+ fillInValue(Array.get(array, index++), componentType, worker);
+ return worker;
}
};
- private void processExpressionCommand(Commands.ValueObject valueObject) throws IOException, CommandException {
+ private void processExpressionCommand(Commands.ValueObject valueObject, InvokableValueSender valueSender) throws IOException, CommandException {
Integer expressionID = new Integer(in.readInt());
byte cmdType = in.readByte();
ExpressionProcesserController exp = null;
@@ -586,41 +589,51 @@
exp.process(in);
break;
case ExpressionCommands.SYNC_REQUEST:
+ boolean haveProxies = in.readBoolean(); // See if we expression proxy ids that need to be resolved
+ if (haveProxies) {
+ Commands.readValue(in, valueObject);
+ valueSender.initialize(valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
+ }
+
exp = (ExpressionProcesserController) expressionProcessors.get(expressionID);
+ if (haveProxies)
+ sendExpressionProxyResolutions(valueObject, (int[]) valueSender.getArray(), exp);
if (exp.noErrors()) {
valueObject.set(true); // Mark that all is good.
- try {
- Commands.writeValue(out, valueObject, true);
- } finally {
- valueObject.set();
- }
+ Commands.writeValue(out, valueObject, true, true);
} else {
processExpressionError(exp, valueObject);
}
break;
case ExpressionCommands.PULL_VALUE_REQUEST:
- exp = (ExpressionProcesserController) expressionProcessors.get(expressionID);
- if (exp.noErrors()) {
- Object[] pulledValue = exp.pullValue();
- if (pulledValue != null) {
- // No errors during pulling either.
- try {
- if (((Class) pulledValue[1]).isPrimitive()) {
- int returnTypeID = server.getIdentityID((Class) pulledValue[1]);
- // Need to tell sendObject the correct primitive type.
- sendObject(pulledValue[0], returnTypeID, valueObject, out, true);
-
- } else {
- sendObject(pulledValue[0], NOT_A_PRIMITIVE, valueObject, out, true); // Just send the object back. sendObject knows how to iterpret the type
- }
- break; // We sent good return, so leave.
- } finally {
- valueObject.set();
- pulledValue = null;
- }
- }
+ haveProxies = in.readBoolean(); // See if we expression proxy ids that need to be resolved
+ if (haveProxies) {
+ Commands.readValue(in, valueObject);
+ valueSender.initialize(valueObject);
+ Commands.readArray(in, valueObject.anInt, valueSender, valueObject, false);
}
- processExpressionError(exp, valueObject);
+
+ exp = (ExpressionProcesserController) expressionProcessors.get(expressionID);
+ if (haveProxies)
+ sendExpressionProxyResolutions(valueObject, (int[]) valueSender.getArray(), exp);
+ if (exp.noErrors()) {
+ try {
+ Object[] pulledValue = exp.pullValue();
+ // Send back the command code for pull value. Don't flush. We will flush when all done.
+ if (((Class) pulledValue[1]).isPrimitive()) {
+ int returnTypeID = server.getIdentityID((Class) pulledValue[1]);
+ // Need to tell sendObject the correct primitive type.
+ sendObject(pulledValue[0], returnTypeID, valueObject, out, true, true);
+
+ } else {
+ sendObject(pulledValue[0], NOT_A_PRIMITIVE, valueObject, out, true, true); // Just send the object back. sendObject knows how to iterpret the type
+ }
+ } catch (NoExpressionValueException e) {
+ sendNoValueErrorCommand(exp, valueObject);
+ }
+ } else
+ processExpressionError(exp, valueObject);
break;
case ExpressionCommands.END_EXPRESSION_TREE_PROCESSING:
exp = (ExpressionProcesserController) expressionProcessors.remove(expressionID);
@@ -629,24 +642,60 @@
}
}
- private void processExpressionError(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException {
- try {
- int code = exp.getErrorCode();
- if (code != 0) {
- // We have an error code to send back.
- String emsg = exp.getErrorMsg();
- if (emsg != null)
- valueObject.set(emsg);
- else
- valueObject.set();
- Commands.sendErrorCommand(out, code, valueObject);
- } else {
- // It must be an exception.
- sendException(exp.getErrorThrowable(), valueObject, out);
+ /*
+ * @param is
+ * @param exp
+ *
+ * @since 1.1.0
+ */
+ private void sendExpressionProxyResolutions(Commands.ValueObject valueObject, final int[] proxyIDs, final ExpressionProcesserController exp) throws CommandException {
+ class ExpressionProxyRetriever implements Commands.ValueRetrieve {
+ int index = 0;
+ Object[] proxyResolution = new Object[2];
+ Commands.ValueObject worker = new Commands.ValueObject();
+
+ public Commands.ValueObject nextValue() {
+ int proxyID = proxyIDs[index++];
+ if (exp.pullExpressionProxyValue(proxyID, proxyResolution)) {
+ if (proxyResolution[1] != Void.TYPE) {
+ if (((Class) proxyResolution[1]).isPrimitive()) {
+ int returnTypeID = server.getIdentityID((Class) proxyResolution[1]);
+ // Need to tell worker the correct primitive type.
+ fillInValue(proxyResolution[0], returnTypeID, worker);
+ } else {
+ fillInValue(proxyResolution[0], NOT_A_PRIMITIVE, worker);
+ }
+ } else
+ worker.setFlag(ExpressionCommands.EXPRESSIONPROXY_VOIDTYPE); // It was resolved, but to not set due to void type of expression.
+ } else
+ worker.setFlag(ExpressionCommands.EXPRESSIONPROXY_NOTRESOLVED); // It wasn't resolved.
+
+ return worker;
}
- } finally {
- valueObject.set();
- }
+ };
+
+ valueObject.setArrayIDS(new ExpressionProxyRetriever(), proxyIDs.length, Commands.OBJECT_CLASS);
+ Commands.writeValue(out, valueObject, true, false); // Write it back as a value command.
+
+ }
+
+ private void processExpressionError(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException {
+ if (exp.isNoExpressionValue()) {
+ sendNoValueErrorCommand(exp, valueObject);
+ } else
+ sendException(exp.getErrorThrowable(), valueObject, out);
+ }
+
+ /*
+ * @param exp
+ * @param valueObject
+ * @throws CommandException
+ *
+ * @since 1.1.0
+ */
+ private void sendNoValueErrorCommand(ExpressionProcesserController exp, Commands.ValueObject valueObject) throws CommandException {
+ setExceptionIntoValue(exp.getErrorThrowable(), valueObject);
+ Commands.sendErrorCommand(out, ExpressionCommands.EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION, valueObject);
}
protected static final int NOT_A_PRIMITIVE = Commands.NOT_AN_ID;
@@ -765,11 +814,14 @@
return added;
}
-public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand) throws CommandException {
+public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand) throws CommandException {
+ sendObject(object, primitiveTypeID, valueObject, out, writeAsCommand, writeAsCommand);
+}
+public void sendObject(Object object, int primitiveTypeID, Commands.ValueObject valueObject, DataOutputStream out, boolean writeAsCommand, boolean flush) throws CommandException {
int added = fillInValue(object, primitiveTypeID, valueObject);
boolean sent = false;
try {
- Commands.writeValue(out, valueObject, writeAsCommand); // Write it back as a value command.
+ Commands.writeValue(out, valueObject, writeAsCommand, flush); // Write it back as a value command.
sent = true;
} finally {
if (!sent) {
diff --git a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ExpressionProcesserController.java b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ExpressionProcesserController.java
index 347b804..de89505 100644
--- a/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ExpressionProcesserController.java
+++ b/plugins/org.eclipse.jem.proxy/vm_remotevm/org/eclipse/jem/internal/proxy/vm/remote/ExpressionProcesserController.java
@@ -10,25 +10,21 @@
*******************************************************************************/
/*
* $RCSfile: ExpressionProcesserController.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:57:54 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:12 $
*/
package org.eclipse.jem.internal.proxy.vm.remote;
import java.io.DataInputStream;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jem.internal.proxy.common.*;
-import org.eclipse.jem.internal.proxy.common.CommandException;
-import org.eclipse.jem.internal.proxy.common.MapTypes;
import org.eclipse.jem.internal.proxy.common.remote.Commands;
import org.eclipse.jem.internal.proxy.common.remote.ExpressionCommands;
-import org.eclipse.jem.internal.proxy.initParser.EvaluationException;
-import org.eclipse.jem.internal.proxy.initParser.tree.ExpressionProcesser;
-import org.eclipse.jem.internal.proxy.initParser.tree.IInternalExpressionConstants;
-import org.eclipse.jem.internal.proxy.initParser.tree.IExpressionConstants.NoExpressionValueException;
+import org.eclipse.jem.internal.proxy.initParser.tree.*;
/**
@@ -54,6 +50,7 @@
*/
public class ExpressionProcesserController {
+
protected final RemoteVMServerThread server;
protected final ConnectionHandler connHandler;
protected final ExpressionProcesser exp;
@@ -61,24 +58,13 @@
private ClassLoader classLoader;
/**
- * An error has occurred. At this point all subcommands will simply make sure they flush the input stream
- * correctly, but they do not process it.
- *
- * @since 1.0.0
- */
- protected boolean errorOccurred = false;
-
- private String novalueMsg = null; // If NoExpressionValueException then this is the msg.
- private Throwable exception = null; // Was there another kind of exception that was caught.
-
- /**
* Create with a default expression processer.
* @param server
*
* @since 1.0.0
*/
public ExpressionProcesserController(RemoteVMServerThread server, ConnectionHandler connHandler) {
- this(server, connHandler, new ExpressionProcesser());
+ this(server, connHandler, new ExpressionProcesser(Boolean.getBoolean(ExpressionCommands.EXPRESSIONTRACE), Long.getLong(ExpressionCommands.EXPRESSIONTRACE_TIMER_THRESHOLD, -1L).longValue()));
}
/**
@@ -152,6 +138,8 @@
*/
public void process(DataInputStream in) throws CommandException, IOException {
// In the following subcommand processing, we always read the entire subcommand from the stream.
+ // This is so that any errors during processing will not mess up the stream with unread data.
+ //
// Then we check if an error has occurred in the past. If it has, we simply break. This is because
// once an error occurred we don't want to continue wasting time evaluating, however we need to make
// sure that the stream is read completely so that we don't have a corrupted input stream. That way
@@ -159,11 +147,9 @@
byte subcommand = in.readByte();
try {
switch (subcommand) {
- case IInternalExpressionConstants.PUSH_TO_PROXY_EXPRESSION :
+ case InternalExpressionTypes.PUSH_TO_PROXY_EXPRESSION_VALUE:
// Getting a proxy push. The value is sent as valueObject, so use that to read it in.
Commands.readValue(in, workerValue);
- if (errorOccurred)
- break;
Object value = connHandler.getInvokableObject(workerValue);
if (value == null)
exp.pushExpression(null, MethodHelper.NULL_TYPE);
@@ -173,364 +159,495 @@
exp.pushExpression(value, value.getClass());
break;
- case IInternalExpressionConstants.CAST_EXPRESSION :
+ case InternalExpressionTypes.CAST_EXPRESSION_VALUE:
// Get a cast request. The type is sent as valueObject.
Commands.readValue(in, workerValue);
- if (errorOccurred)
- break;
- value = connHandler.getInvokableObject(workerValue);
try {
- if (value instanceof String)
- value = loadClass((String) value);
- exp.pushCast((Class) value);
- } catch (NoExpressionValueException e) {
- processException(e);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushCast(classValue);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
} catch (ClassNotFoundException e) {
- processException(e);
- }
+ // Do nothing, already processed.
+ }
break;
- case IInternalExpressionConstants.INSTANCEOF_EXPRESSION :
+ case InternalExpressionTypes.INSTANCEOF_EXPRESSION_VALUE:
// Get a instanceof request. The type is sent as valueObject.
Commands.readValue(in, workerValue);
- if (errorOccurred)
- break;
- value = connHandler.getInvokableObject(workerValue);
try {
- if (value instanceof String)
- value = loadClass((String) value);
- exp.pushInstanceof((Class) value);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushInstanceof(classValue);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
} catch (ClassNotFoundException e) {
- processException(e);
- } catch (NoExpressionValueException e) {
- processException(e);
- }
+ // Do nothing, already processed.
+ }
break;
- case IInternalExpressionConstants.INFIX_EXPRESSION :
+ case InternalExpressionTypes.INFIX_EXPRESSION_VALUE:
// Get an infix request. The operator and operand type are sent as bytes.
byte infix_operator = in.readByte();
byte infix_operandType = in.readByte();
- if (errorOccurred)
- break;
- try {
- exp.pushInfix(infix_operator, infix_operandType);
- } catch (NoExpressionValueException e1) {
- processException(e1);
- }
+ exp.pushInfix(InfixOperator.get(infix_operator), InternalInfixOperandType.get(infix_operandType));
break;
- case IInternalExpressionConstants.PREFIX_EXPRESSION :
+ case InternalExpressionTypes.PREFIX_EXPRESSION_VALUE:
// Get a prefix request. The operator is sent as byte.
byte prefix_operandType = in.readByte();
- if (errorOccurred)
- break;
- try {
- exp.pushPrefix(prefix_operandType);
- } catch (NoExpressionValueException e2) {
- processException(e2);
- }
+ exp.pushPrefix(PrefixOperator.get(prefix_operandType));
break;
- case IInternalExpressionConstants.TYPELITERAL_EXPRESSION :
- // Get a type literal request. The type string is sent as valueObject.
- Commands.readValue(in, workerValue);
- if (errorOccurred)
- break;
- value = connHandler.getInvokableObject(workerValue);
- try {
- value = loadClass((String) value);
- exp.pushExpression((Class) value, Class.class);
- } catch (ClassNotFoundException e) {
- processException(e);
- }
- break;
-
- case IInternalExpressionConstants.ARRAY_ACCESS_EXPRESSION :
+ case InternalExpressionTypes.ARRAY_ACCESS_EXPRESSION_VALUE:
// Get an array access request. The index cound is sent as int.
int arrayAccess_Indexcount = in.readInt();
- if (errorOccurred)
- break;
- try {
- exp.pushArrayAccess(arrayAccess_Indexcount);
- } catch (NoExpressionValueException e3) {
- processException(e3);
- }
+ exp.pushArrayAccess(arrayAccess_Indexcount);
break;
- case IInternalExpressionConstants.ARRAY_CREATION_EXPRESSION :
+ case InternalExpressionTypes.ARRAY_CREATION_EXPRESSION_VALUE:
// Get an array creation request. The type is sent as valueObject, followed by int dimension count.
Commands.readValue(in, workerValue);
int arrayCreation_dimCount = in.readInt();
- if (errorOccurred)
- break;
- value = connHandler.getInvokableObject(workerValue);
try {
- if (value instanceof String)
- value = loadClass((String) value);
- exp.pushArrayCreation((Class) value, arrayCreation_dimCount);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushArrayCreation(classValue, arrayCreation_dimCount);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
} catch (ClassNotFoundException e) {
- processException(e);
- } catch (NoExpressionValueException e) {
- processException(e);
- }
+ // Do nothing, already processed.
+ }
+
break;
- case IInternalExpressionConstants.ARRAY_INITIALIZER_EXPRESSION :
+ case InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION_VALUE:
// Get an array initializer request. The type is sent as valueObject, followed by int expression count.
Commands.readValue(in, workerValue);
+ int stripCount = in.readInt();
int arrayInitializer_expressionCount = in.readInt();
- if (errorOccurred)
- break;
- value = connHandler.getInvokableObject(workerValue);
try {
- if (value instanceof String)
- value = loadClass((String) value);
- exp.pushArrayInitializer((Class) value, arrayInitializer_expressionCount);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushArrayInitializer(classValue, stripCount, arrayInitializer_expressionCount);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
} catch (ClassNotFoundException e) {
- processException(e);
- } catch (NoExpressionValueException e) {
- processException(e);
+ // Do nothing, already processed.
}
break;
- case IInternalExpressionConstants.CLASS_INSTANCE_CREATION_EXPRESSION :
+ case InternalExpressionTypes.CLASS_INSTANCE_CREATION_EXPRESSION_VALUE:
// Get a class instance creation request. The type is sent as valueObject, followed by int argument count.
Commands.readValue(in, workerValue);
int newInstance_argCount = in.readInt();
- if (errorOccurred)
- return;
- value = connHandler.getInvokableObject(workerValue);
try {
- if (value instanceof String)
- value = loadClass((String) value);
- exp.pushClassInstanceCreation((Class) value, newInstance_argCount);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushClassInstanceCreation(classValue, newInstance_argCount);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
} catch (ClassNotFoundException e) {
- processException(e);
- } catch (EvaluationException e) {
- processException(e);
- } catch (NoExpressionValueException e) {
- processException(e);
- } catch (InstantiationException e) {
- processException(e);
- } catch (IllegalAccessException e) {
- processException(e);
- } catch (InvocationTargetException e) {
- processException(e);
- } catch (LinkageError e) {
- processError(e);
+ // Do nothing, already processed.
}
break;
- case IInternalExpressionConstants.TYPERECEIVER_EXPRESSION :
+ case InternalExpressionTypes.TYPERECEIVER_EXPRESSION_VALUE:
// Get a type receiver request. The type is sent as valueObject.
Commands.readValue(in, workerValue);
- if (errorOccurred)
- break;
- value = connHandler.getInvokableObject(workerValue);
try {
- if (value instanceof String)
- value = loadClass((String) value);
- exp.pushExpression(value, (Class) value);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushExpression(classValue, classValue);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
} catch (ClassNotFoundException e) {
- processException(e);
+ // Do nothing, already processed.
}
break;
- case IInternalExpressionConstants.FIELD_ACCESS_EXPRESSION :
- // Get a field access request. The field name sent as string, followed by hasReceiver as boolean.
- String fieldAccess_name = in.readUTF();
- boolean fieldAccess_receiver = in.readBoolean();
- if (errorOccurred)
- break;
+ case InternalExpressionTypes.FIELD_ACCESS_EXPRESSION_VALUE:
+ // Get a field access request. Command.ValueObject, followed by hasReceiver as boolean.
+ Commands.readValue(in, workerValue);
+ boolean has_fieldAccess_receiver = in.readBoolean();
try {
- exp.pushFieldAccess(fieldAccess_name, fieldAccess_receiver);
- } catch (NoExpressionValueException e4) {
- processException(e4);
- } catch (NoSuchFieldException e4) {
- processException(e4);
- } catch (IllegalAccessException e4) {
- processException(e4);
+ Object fieldAccess = getFieldValue(workerValue);
+ exp.pushFieldAccess(fieldAccess, workerValue.getType() == Commands.STRING, has_fieldAccess_receiver);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ } catch (NoSuchFieldException e1) {
+ // Do nothing, already processed.
}
break;
- case IInternalExpressionConstants.METHOD_EXPRESSION :
- // Get a method invocation request. The method name sent as string, followed by hasReceiver as boolean, and argCount as int.
- String method_name = in.readUTF();
- boolean method_receiver = in.readBoolean();
+ case InternalExpressionTypes.METHOD_EXPRESSION_VALUE:
+ // Get a method invocation request. Sent as Commands.ValueObject, followed by hasReceiver as boolean., and argCount as int.
+ Commands.readValue(in, workerValue);
+ boolean has_method_receiver = in.readBoolean();
int method_argCount = in.readInt();
- if (errorOccurred)
- break;
try {
- exp.pushMethodInvocation(method_name, method_receiver, method_argCount);
- } catch (EvaluationException e5) {
- processException(e5);
- } catch (NoExpressionValueException e5) {
- processException(e5);
- } catch (IllegalAccessException e5) {
- processException(e5);
- } catch (InvocationTargetException e5) {
- processException(e5);
- }
+ Object method = getMethodValue(workerValue);
+ exp.pushMethodInvocation(method, workerValue.getType() == Commands.STRING, has_method_receiver, method_argCount);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ } catch (NoSuchMethodException e) {
+ // Do nothing, already processed.
+ }
break;
- case IInternalExpressionConstants.CONDITIONAL_EXPRESSION :
+ case InternalExpressionTypes.CONDITIONAL_EXPRESSION_VALUE:
// Get a conditional expression request. The expression type (ie. condition/true/false) is sent as a byte
- byte conditional_type = in.readByte();
- if (errorOccurred)
- break;
+ exp.pushConditional(InternalConditionalOperandType.get(in.readByte()));
+ break;
+
+ case InternalExpressionTypes.ASSIGNMENT_PROXY_EXPRESSION_VALUE:
+ // Get an assignment expression request. The proxy id is sent as an int.
+ int proxyid = in.readInt();
+ exp.pushAssignment(new RemoteExpressionProxy(proxyid));
+ break;
+
+ case InternalExpressionTypes.ASSIGNMENT_EXPRESSION_VALUE:
+ // Get an assignment expression request. Nothing else to read from stream.
+ exp.pushAssignment();
+ break;
+
+ case InternalExpressionTypes.PUSH_TO_EXPRESSION_PROXY_EXPRESSION_VALUE:
+ // Get a push expression proxy expression. The proxy id is sent as an int.
+ exp.pushExpressionProxy(in.readInt());
+ break;
+
+ case InternalExpressionTypes.BLOCK_BEGIN_EXPRESSION_VALUE:
+ // Get a begin block proxy expression. The block id is sent as an int.
+ exp.pushBlockBegin(in.readInt());
+ break;
+
+ case InternalExpressionTypes.BLOCK_BREAK_EXPRESSION_VALUE:
+ // Get a break block proxy expression. The block id is sent as an int.
+ exp.pushBlockBreak(in.readInt());
+ break;
+
+ case InternalExpressionTypes.BLOCK_END_EXPRESSION_VALUE:
+ // Get a end block proxy expression. The block id is sent as an int.
+ exp.pushBlockEnd(in.readInt());
+ break;
+
+ case InternalExpressionTypes.TRY_BEGIN_EXPRESSION_VALUE:
+ // Get a try begin proxy expression. The try id is sent as an int.
+ exp.pushTryBegin(in.readInt());
+ break;
+
+ case InternalExpressionTypes.TRY_CATCH_EXPRESSION_VALUE:
+ int tryNumber = in.readInt();
+ Commands.readValue(in, workerValue);
+ proxyid = in.readInt();
try {
- exp.pushConditional(conditional_type);
- } catch (NoExpressionValueException e6) {
- processException(e6);
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushTryCatchClause(tryNumber, classValue, proxyid != -1 ? new RemoteExpressionProxy(proxyid) : null);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ } catch (ClassNotFoundException e) {
+ // Do nothing, already processed.
+ }
+ break;
+
+ case InternalExpressionTypes.TRY_FINALLY_EXPRESSION_VALUE:
+ // Get a try finally proxy expression. The try id is sent as an int.
+ exp.pushTryFinallyClause(in.readInt());
+ break;
+
+ case InternalExpressionTypes.TRY_END_EXPRESSION_VALUE:
+ // Get a try end proxy expression. The try id is sent as an int.
+ exp.pushTryEnd(in.readInt());
+ break;
+
+ case InternalExpressionTypes.THROW_EXPRESSION_VALUE:
+ exp.pushThrowException();
+ break;
+
+ case InternalExpressionTypes.RETHROW_EXPRESSION_VALUE:
+ // Get a rethrow proxy expression. The try id is sent as an int.
+ exp.pushTryRethrow(in.readInt());
+ break;
+
+ case InternalExpressionTypes.PUSH_BEANTYPE_EXPRESSIONPROXY_EXPRESSION_VALUE:
+ // Get the beantype expression proxy and resolve it.
+ proxyid = in.readInt();
+ String typeName = Commands.readStringData(in);
+ try {
+ Class classValue = loadClass(typeName);
+ RemoteExpressionProxy rep = new RemoteExpressionProxy(proxyid);
+ rep.setProxy(classValue, Class.class);
+ exp.allocateExpressionProxy(rep);
+ } catch (ClassNotFoundException e) {
+ exp.processException(e);
+ } catch (LinkageError e) {
+ exp.processException(e);
}
break;
+
+ case InternalExpressionTypes.PUSH_METHOD_EXPRESSIONPROXY_EXPRESSION_VALUE:
+ // Get the Method expression proxy and resolve it.
+ // Comes over as:
+ // int for proxy id for the method
+ // beanTypeValue for declaring class (either beantype or expression proxy)
+ // string for method name
+ // int for arg count
+ // beanTypeValue(s) for arg types (as many as arg count).
+ proxyid = in.readInt();
+ Commands.ValueObject decClassValue = Commands.readValue(in, new Commands.ValueObject());
+ String methodName = Commands.readStringData(in);
+ int argCount = in.readInt();
+ Commands.ValueObject[] args = null;
+ if (argCount > 0) {
+ args = new Commands.ValueObject[argCount];
+ for (int i = 0; i < argCount; i++) {
+ args[i] = Commands.readValue(in, new Commands.ValueObject());
+ }
+ }
+ try {
+ Class decClass = getBeanTypeValue(decClassValue);
+ Class[] argClasses = null;
+ if (argCount>0) {
+ argClasses = new Class[argCount];
+ for (int i = 0; i < argCount; i++) {
+ argClasses[i] = getBeanTypeValue(args[i]);
+ }
+ }
+ // Now get the method itself.
+ Method m = decClass.getMethod(methodName, argClasses);
+ RemoteExpressionProxy rep = new RemoteExpressionProxy(proxyid);
+ rep.setProxy(m, Method.class);
+ exp.allocateExpressionProxy(rep);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ } catch (ClassNotFoundException e) {
+ // Do nothing, already processed.
+ } catch (NoSuchMethodException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ }
+ break;
+
+ case InternalExpressionTypes.PUSH_FIELD_EXPRESSIONPROXY_EXPRESSION_VALUE:
+ // Get the Filed expression proxy and resolve it.
+ // Comes over as:
+ // int for proxy id for the field
+ // beanTypeValue for declaring class (either beantype or expression proxy)
+ // string for field name
+ proxyid = in.readInt();
+ decClassValue = Commands.readValue(in, new Commands.ValueObject());
+ String fieldName = Commands.readStringData(in);
+ try {
+ Class decClass = getBeanTypeValue(decClassValue);
+ // Now get the field itself.
+ Field f = decClass.getField(fieldName);
+ RemoteExpressionProxy rep = new RemoteExpressionProxy(proxyid);
+ rep.setProxy(f, Method.class);
+ exp.allocateExpressionProxy(rep);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ } catch (ClassNotFoundException e) {
+ // Do nothing, already processed.
+ } catch (NoSuchFieldException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ }
+ break;
+
+ case InternalExpressionTypes.IF_TEST_EXPRESSION_VALUE:
+ // Get a if test expression request.
+ exp.pushIfElse();
+ break;
+
+ case InternalExpressionTypes.IF_ELSE_EXPRESSION_VALUE:
+ // Get a if/else expression clause request. The clause type (ie. true/false) is sent as a byte
+ exp.pushIfElse(InternalIfElseOperandType.get(in.readByte()));
+ break;
+
+ case InternalExpressionTypes.NEW_INSTANCE_VALUE:
+ // Get a new instance from string.
+ String initString = Commands.readStringData(in);
+ workerValue = Commands.readValue(in, new Commands.ValueObject());
+ try {
+ Class classValue = getBeanTypeValue(workerValue);
+ exp.pushNewInstanceFromString(initString, classValue, classLoader);
+ } catch (ClassCastException e) {
+ exp.processException(e); // Let the processor know we have a stopping error.
+ } catch (ClassNotFoundException e) {
+ // Do nothing, already processed.
+ }
+ break;
+
+ case InternalExpressionTypes.MARK_VALUE:
+ // Do a mark.
+ int markID = in.readInt();
+ exp.pushMark(markID);
+ break;
+
+ case InternalExpressionTypes.ENDMARK_VALUE:
+ // Do an end mark.
+ markID = in.readInt();
+ boolean restore = in.readBoolean();
+ exp.pushEndmark(markID, restore);
+ break;
}
} catch (RuntimeException e) {
- processException(e);
+ exp.processException(e);
}
workerValue.set(); // Clear it out so nothing being held onto.
}
-
/**
- * Pull the value. If an error occurred during this, then <code>null</code> is returned, and
- * caller should do normal error processing.
+ * Get the beantype (class) out of the value object sent in. It can handle the beantype sent or
+ * as an expression proxy to a beantype expression proxy.
*
- * @return r[0] is the value, r[1] is the type of the value. <code>null</code> if there was an error.
+ * @param value
+ * @return
+ * @throws ClassCastException means either not a type sent in, or proxy was not a type.
+ * @throws ClassNotFoundException the expression proxy did not resolve. In that case it has already been processed by the expression processor.
*
- * @since 1.0.0
+ * @since 1.1.0
*/
- public Object[] pullValue() {
- Object[] result = new Object[2];
- try {
- exp.pullValue(result);
- return result;
- } catch (NoExpressionValueException e) {
- processException(e);
+ protected Class getBeanTypeValue(Commands.ValueObject value) throws ClassCastException, ClassNotFoundException {
+ Object beantype = connHandler.getInvokableObject(value);
+ // It is either a type directly or is an expression proxy.
+ if (value.type == Commands.INT) {
+ // It is an expression proxy request.
+ Object[] expvalue = new Object[2];
+ if (exp.getExpressionProxyValue(((Integer) beantype).intValue(), expvalue)) {
+ beantype = expvalue[0];
+ } else
+ throw new ClassNotFoundException();
}
- return null;
+ return (Class) beantype;
}
-
+
/**
- * Process all other exceptions then the NoExpressionValueException, InvocationTargetException, and EvaluationException. This is
- * for exceptions that are not related to the input stream and shouldn't
- * cause the input stream to be closed.
+ * Get the method out of the value object sent in. It can handle the method sent or
+ * as an expression proxy to a method expression proxy.
+ * @param value
+ * @return method if a method or string if a string or get the method if an expression proxy.
+ * @throws NoSuchMethodException the expression proxy did not resolve. In that case it has already been processed by the expression processor.
+ * @throws ClassCastException means either not a method sent in, or proxy was not a method.
*
- * @param e
- *
- * @since 1.0.0
+ * @since 1.1.0
*/
- protected final void processException(Exception e) {
- // Process all other exceptions.
- errorOccurred = true;
- exception = e;
- }
-
- /**
- * Process certain errors. Should not be called for general errors. Should be called for specific java.lang.Errors that
- * are not related to the input stream and shouldn't cause the input stream to be closed.
- *
- * @param e
- *
- * @since 1.0.2
- */
- protected final void processError(Error e) {
- // Process specific errors
- errorOccurred = true;
- exception = e;
- }
-
- /**
- * Process InvocationTargetException to retrieve the actual target.
- * @param e
- *
- * @since 1.0.0
- */
- protected final void processException(InvocationTargetException e) {
- errorOccurred = true;
- exception = e.getTargetException();
- }
-
- /**
- * Process EvaluationException to retrieve the actual target.
- * @param e
- *
- * @since 1.0.0
- */
- protected final void processException(EvaluationException e) {
- errorOccurred = true;
- exception = e.getOriginalException();
+ protected Object getMethodValue(Commands.ValueObject value) throws NoSuchMethodException, ClassCastException {
+ Object method = connHandler.getInvokableObject(value);
+ // It is either a method directly or is an expression proxy.
+ if (value.type == Commands.INT) {
+ // It is an expression proxy request.
+ Object[] expvalue = new Object[2];
+ if (exp.getExpressionProxyValue(((Integer) method).intValue(), expvalue)) {
+ method = expvalue[0];
+ } else
+ throw new NoSuchMethodException();
+ }
+ return method;
}
/**
- * Special case for NoExpressionValueException caught.
- * @param e
+ * Get the field out of the value object sent in. It can handle the field sent or
+ * as an expression proxy to a field expression proxy.
+ * @param value
+ * @return field if a field or string if a string or get the field if an expression proxy.
+ * @throws NoSuchFieldException the expression proxy did not resolve. In that case it has already been processed by the expression processor.
+ * @throws ClassCastException means either not a field sent in, or proxy was not a field.
*
- * @since 1.0.0
+ * @since 1.1.0
*/
- protected final void processException(NoExpressionValueException e) {
- errorOccurred = true;
- novalueMsg = e.getLocalizedMessage();
- if (novalueMsg == null)
- novalueMsg = ""; // It was null, so just default of empty string so we know it had occurred.
+ protected Object getFieldValue(Commands.ValueObject value) throws NoSuchFieldException, ClassCastException {
+ Object field = connHandler.getInvokableObject(value);
+ // It is either a field directly or is an expression proxy.
+ if (value.type == Commands.INT) {
+ // It is an expression proxy request.
+ Object[] expvalue = new Object[2];
+ if (exp.getExpressionProxyValue(((Integer) field).intValue(), expvalue)) {
+ field = expvalue[0];
+ } else
+ throw new NoSuchFieldException();
+ }
+ return field;
+ }
+
+ /**
+ * Pull the Expression Proxy value into the result object.
+ * @param proxyID
+ * @param result
+ * @return <code>true</code> if value could be returned, <code>false</code> if it was no expression value assigned.
+ *
+ * @since 1.1.0
+ */
+ public boolean pullExpressionProxyValue(int proxyID, Object[] result) {
+ try {
+ exp.pullExpressionProxyValue(proxyID, result);
+ return true;
+ } catch (NoExpressionValueException e) {
+ }
+ return false;
}
+
+ private static class RemoteExpressionProxy implements InternalExpressionProxy {
+
+
+ private final int proxyID;
+ private Object value;
+ private Class type;
+ private boolean set;
+
+ public RemoteExpressionProxy(int proxyID) {
+ this.proxyID = proxyID;
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#getProxyID()
+ */
+ public int getProxyID() {
+ return proxyID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#getType()
+ */
+ public Class getType() {
+ return type;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#getValue()
+ */
+ public Object getValue() {
+ return value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#isSet()
+ */
+ public boolean isSet() {
+ return set;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.internal.proxy.initParser.tree.InternalExpressionProxy#setProxy(java.lang.Object, java.lang.Class)
+ */
+ public void setProxy(Object value, Class type) {
+ this.value = value;
+ this.type = type;
+ set = true;
+ }
+ }
+
/**
- * Return whether there are any errors.
+ * Pull the value.
*
- * @return <code>true</code> if no errors.
+ * @return r[0] is the value, r[1] is the type of the value.
+ * @throws NoExpressionValueException
*
* @since 1.0.0
*/
- public boolean noErrors() {
- return !errorOccurred;
+ public Object[] pullValue() throws NoExpressionValueException {
+ Object[] result = new Object[2];
+ exp.pullValue(result);
+ return result;
}
-
- /**
- * Return the error code from ExpressionCommands if non-exception error occurred.
- * Return zero if no error.
- *
- * @return Zero if no error code to return, else error code from ExpressionCommands.
- *
- * @see org.eclipse.jem.internal.proxy.common.remote.ExpressionCommands#ExpressionNoExpressionValueException
- *
- * @since 1.0.0
- */
- public int getErrorCode() {
- if (novalueMsg != null)
- return ExpressionCommands.ExpressionNoExpressionValueException;
- else
- return 0;
- }
-
- /**
- * Return the error message, should only be called if <code>getErrorCode()</code> returned non-zero.
- *
- * @return The error message if any. <code>null</code> otherwise.
- *
- * @since 1.0.0
- */
- public String getErrorMsg() {
- if (novalueMsg != null && novalueMsg.length() > 0)
- return novalueMsg;
- else
- return null;
- }
-
- /**
- * Return the throwable if a Throwable was caught.
- *
- * @return The throwable, or <code>null</code> if not set.
- *
- * @since 1.0.0
- */
- public Throwable getErrorThrowable() {
- return exception;
- }
-
+
/**
* Close out things.
*
@@ -539,5 +656,35 @@
public void close() {
exp.close();
}
+
+ /**
+ * Get the throwable error.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public Throwable getErrorThrowable() {
+ return exp.getErrorThrowable();
+ }
+
+ /**
+ * Return whether there were no errors or not.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public boolean noErrors() {
+ return exp.noErrors();
+ }
+
+ /**
+ * Return whether there is a no expression value exception or not.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public boolean isNoExpressionValue() {
+ return exp.isNoExpressionValue();
+ }
}
diff --git a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JDOMSearchHelper.java b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JDOMSearchHelper.java
index 5946a98..75175de 100644
--- a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JDOMSearchHelper.java
+++ b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JDOMSearchHelper.java
@@ -11,7 +11,7 @@
*******************************************************************************/
/*
* $RCSfile: JDOMSearchHelper.java,v $
- * $Revision: 1.3 $ $Date: 2005/03/15 23:21:02 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:23 $
*/
import java.io.File;
@@ -347,10 +347,7 @@
public static IType findType(String packageName, String qualifiedTypeName, IJavaProject javaProject) {
try {
if (javaProject != null) {
- String typeName = qualifiedTypeName;
- if (qualifiedTypeName.indexOf('$') != -1)
- typeName = qualifiedTypeName.replace('$', '.');
- return javaProject.findType(packageName, typeName);
+ return javaProject.findType(packageName, qualifiedTypeName.replace('$', '.'));
}
} catch (JavaModelException jme) {
System.out.println(ResourceHandler.getString("Error_Looking_Up_Type_ERROR_", (new Object[] { packageName + "." + qualifiedTypeName, jme.getMessage()}))); //$NON-NLS-1$ = "Error looking up type: "
diff --git a/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/FeatureValueProvider.java b/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/FeatureValueProvider.java
index d647525..f1e40f4 100644
--- a/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/FeatureValueProvider.java
+++ b/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/FeatureValueProvider.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.instantiation.base;
/*
* $RCSfile: FeatureValueProvider.java,v $
- * $Revision: 1.3 $ $Date: 2005/02/15 22:36:09 $
+ * $Revision: 1.4 $ $Date: 2005/05/11 19:01:16 $
*/
import org.eclipse.emf.ecore.EStructuralFeature;
@@ -35,17 +35,17 @@
*
* @param feature
* @param value
- *
+ * @return <code>null</code> to continue to next setting, or a value to stop visiting and return that value be the real exception.
* @since 1.1.0
*/
- void isSet(EStructuralFeature feature, Object value);
+ Object isSet(EStructuralFeature feature, Object value);
}
/**
* Visit the set features.
* @param aVisitor
- *
+ * @param <code>null</code> if all settings visited, or the value returned from the visit (isSet) that returned a non-nullSe.
* @since 1.1.0
*/
- void visitSetFeatures(Visitor aVisitor);
+ Object visitSetFeatures(Visitor aVisitor);
}
diff --git a/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/JavaObjectInstance.java b/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/JavaObjectInstance.java
index bb6cada..002d477 100644
--- a/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/JavaObjectInstance.java
+++ b/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/JavaObjectInstance.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.instantiation.base;
/*
* $RCSfile: JavaObjectInstance.java,v $
- * $Revision: 1.13 $ $Date: 2005/02/15 22:36:09 $
+ * $Revision: 1.14 $ $Date: 2005/05/11 19:01:16 $
*/
import java.util.List;
@@ -44,7 +44,8 @@
* Visit the argument with all of the set features in an optimized fashion
*/
private final static Object NIL = EStructuralFeatureImpl.InternalSettingDelegateSingle.NIL;
- public void visitSetFeatures(Visitor aVisitor) {
+ public Object visitSetFeatures(Visitor aVisitor) {
+ Object result = null;
if (eHasSettings()) {
JavaObjectInstancePropertiesHolder settings = (JavaObjectInstancePropertiesHolder) eProperties();
@@ -57,11 +58,13 @@
// <null> is handled by the placeholder NIL. A setting of true null means not set. A setting of NIL means set to null.
if (propertyValue == NIL)
propertyValue = null;
- aVisitor.isSet((EStructuralFeature) allFeatures.get(i), propertyValue);
+ if ((result = aVisitor.isSet((EStructuralFeature) allFeatures.get(i), propertyValue)) != null)
+ break;
}
}
}
- }
+ }
+ return result;
}
public boolean isSetAllocation() {
diff --git a/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/ParseTreeAllocationInstantiationVisitor.java b/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/ParseTreeAllocationInstantiationVisitor.java
index 0f7ce5b..dcaecc7 100644
--- a/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/ParseTreeAllocationInstantiationVisitor.java
+++ b/plugins/org.eclipse.jem/javainst/org/eclipse/jem/internal/instantiation/base/ParseTreeAllocationInstantiationVisitor.java
@@ -10,17 +10,15 @@
*******************************************************************************/
/*
* $RCSfile: ParseTreeAllocationInstantiationVisitor.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:36:09 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:16 $
*/
package org.eclipse.jem.internal.instantiation.base;
import java.util.List;
import org.eclipse.jem.internal.instantiation.*;
-import org.eclipse.jem.internal.instantiation.ParseVisitor;
import org.eclipse.jem.internal.proxy.core.*;
-import org.eclipse.jem.internal.proxy.initParser.tree.IExpressionConstants;
-import org.eclipse.jem.internal.proxy.initParser.tree.IExpressionConstants.NoExpressionValueException;
+import org.eclipse.jem.internal.proxy.initParser.tree.*;
/**
* This is the standard parse visitor for instantiating a bean proxy from a java parse tree allocation.
@@ -29,12 +27,7 @@
* @since 1.0.0
*/
public class ParseTreeAllocationInstantiationVisitor extends ParseVisitor {
-
- /**
- * Registry for processing the expressions against.
- */
- private ProxyFactoryRegistry registry;
-
+
/**
* The expression that is being created and evaluated.
*/
@@ -45,7 +38,7 @@
* visitation to the next expression. It will set this to what that expression should be using. This
* is necessary because the next expression doesn't know what it should be.
*/
- private int nextExpression = IExpression.ROOTEXPRESSION;
+ private ForExpression nextExpression = ForExpression.ROOTEXPRESSION;
/**
* An exception occurred during processing. It is a RuntimeException because
@@ -67,28 +60,28 @@
}
}
- static final int[] INFIXTOPROXY;
+ static final InfixOperator[] INFIXTOPROXY;
static {
- INFIXTOPROXY = new int[PTInfixOperator.VALUES.size()];
- INFIXTOPROXY[PTInfixOperator.AND] = IExpressionConstants.IN_AND;
- INFIXTOPROXY[PTInfixOperator.CONDITIONAL_AND] = IExpressionConstants.IN_CONDITIONAL_AND;
- INFIXTOPROXY[PTInfixOperator.CONDITIONAL_OR] = IExpressionConstants.IN_CONDITIONAL_OR;
- INFIXTOPROXY[PTInfixOperator.DIVIDE] = IExpressionConstants.IN_DIVIDE;
- INFIXTOPROXY[PTInfixOperator.EQUALS] = IExpressionConstants.IN_EQUALS;
- INFIXTOPROXY[PTInfixOperator.GREATER] = IExpressionConstants.IN_GREATER;
- INFIXTOPROXY[PTInfixOperator.GREATER_EQUALS] = IExpressionConstants.IN_GREATER_EQUALS;
- INFIXTOPROXY[PTInfixOperator.LEFT_SHIFT] = IExpressionConstants.IN_LEFT_SHIFT;
- INFIXTOPROXY[PTInfixOperator.LESS] = IExpressionConstants.IN_LESS;
- INFIXTOPROXY[PTInfixOperator.LESS_EQUALS] = IExpressionConstants.IN_LESS_EQUALS;
- INFIXTOPROXY[PTInfixOperator.MINUS] = IExpressionConstants.IN_MINUS;
- INFIXTOPROXY[PTInfixOperator.NOT_EQUALS] = IExpressionConstants.IN_NOT_EQUALS;
- INFIXTOPROXY[PTInfixOperator.OR] = IExpressionConstants.IN_OR;
- INFIXTOPROXY[PTInfixOperator.PLUS] = IExpressionConstants.IN_PLUS;
- INFIXTOPROXY[PTInfixOperator.REMAINDER] = IExpressionConstants.IN_REMAINDER;
- INFIXTOPROXY[PTInfixOperator.RIGHT_SHIFT_SIGNED] = IExpressionConstants.IN_RIGHT_SHIFT_SIGNED;
- INFIXTOPROXY[PTInfixOperator.RIGHT_SHIFT_UNSIGNED] = IExpressionConstants.IN_RIGHT_SHIFT_UNSIGNED;
- INFIXTOPROXY[PTInfixOperator.TIMES] = IExpressionConstants.IN_TIMES;
- INFIXTOPROXY[PTInfixOperator.XOR] = IExpressionConstants.IN_XOR;
+ INFIXTOPROXY = new InfixOperator[PTInfixOperator.VALUES.size()];
+ INFIXTOPROXY[PTInfixOperator.AND] = InfixOperator.IN_AND;
+ INFIXTOPROXY[PTInfixOperator.CONDITIONAL_AND] = InfixOperator.IN_CONDITIONAL_AND;
+ INFIXTOPROXY[PTInfixOperator.CONDITIONAL_OR] = InfixOperator.IN_CONDITIONAL_OR;
+ INFIXTOPROXY[PTInfixOperator.DIVIDE] = InfixOperator.IN_DIVIDE;
+ INFIXTOPROXY[PTInfixOperator.EQUALS] = InfixOperator.IN_EQUALS;
+ INFIXTOPROXY[PTInfixOperator.GREATER] = InfixOperator.IN_GREATER;
+ INFIXTOPROXY[PTInfixOperator.GREATER_EQUALS] = InfixOperator.IN_GREATER_EQUALS;
+ INFIXTOPROXY[PTInfixOperator.LEFT_SHIFT] = InfixOperator.IN_LEFT_SHIFT;
+ INFIXTOPROXY[PTInfixOperator.LESS] = InfixOperator.IN_LESS;
+ INFIXTOPROXY[PTInfixOperator.LESS_EQUALS] = InfixOperator.IN_LESS_EQUALS;
+ INFIXTOPROXY[PTInfixOperator.MINUS] = InfixOperator.IN_MINUS;
+ INFIXTOPROXY[PTInfixOperator.NOT_EQUALS] = InfixOperator.IN_NOT_EQUALS;
+ INFIXTOPROXY[PTInfixOperator.OR] = InfixOperator.IN_OR;
+ INFIXTOPROXY[PTInfixOperator.PLUS] = InfixOperator.IN_PLUS;
+ INFIXTOPROXY[PTInfixOperator.REMAINDER] = InfixOperator.IN_REMAINDER;
+ INFIXTOPROXY[PTInfixOperator.RIGHT_SHIFT_SIGNED] = InfixOperator.IN_RIGHT_SHIFT_SIGNED;
+ INFIXTOPROXY[PTInfixOperator.RIGHT_SHIFT_UNSIGNED] = InfixOperator.IN_RIGHT_SHIFT_UNSIGNED;
+ INFIXTOPROXY[PTInfixOperator.TIMES] = InfixOperator.IN_TIMES;
+ INFIXTOPROXY[PTInfixOperator.XOR] = InfixOperator.IN_XOR;
}
/**
@@ -99,17 +92,17 @@
*
* @since 1.0.0
*/
- public static int convertPTInfixOperatorToProxyInfixOperator(PTInfixOperator operator) {
+ public static InfixOperator convertPTInfixOperatorToProxyInfixOperator(PTInfixOperator operator) {
return INFIXTOPROXY[operator.getValue()];
}
- static final int[] PREFIXTOPROXY;
+ static final PrefixOperator[] PREFIXTOPROXY;
static {
- PREFIXTOPROXY = new int[PTPrefixOperator.VALUES.size()];
- PREFIXTOPROXY[PTPrefixOperator.COMPLEMENT] = IExpressionConstants.PRE_COMPLEMENT;
- PREFIXTOPROXY[PTPrefixOperator.MINUS] = IExpressionConstants.PRE_MINUS;
- PREFIXTOPROXY[PTPrefixOperator.NOT] = IExpressionConstants.PRE_NOT;
- PREFIXTOPROXY[PTPrefixOperator.PLUS] = IExpressionConstants.PRE_PLUS;
+ PREFIXTOPROXY = new PrefixOperator[PTPrefixOperator.VALUES.size()];
+ PREFIXTOPROXY[PTPrefixOperator.COMPLEMENT] = PrefixOperator.PRE_COMPLEMENT;
+ PREFIXTOPROXY[PTPrefixOperator.MINUS] = PrefixOperator.PRE_MINUS;
+ PREFIXTOPROXY[PTPrefixOperator.NOT] = PrefixOperator.PRE_NOT;
+ PREFIXTOPROXY[PTPrefixOperator.PLUS] = PrefixOperator.PRE_PLUS;
}
/**
@@ -120,7 +113,7 @@
*
* @since 1.0.0
*/
- public static int convertPTPrefixOperatorToProxyPrefixOperator(PTPrefixOperator operator) {
+ public static PrefixOperator convertPTPrefixOperatorToProxyPrefixOperator(PTPrefixOperator operator) {
return PREFIXTOPROXY[operator.getValue()];
}
@@ -142,7 +135,7 @@
* @since 1.0.0
*/
protected final ProxyFactoryRegistry getRegistry() {
- return registry;
+ return expression.getRegistry();
}
/**
@@ -157,7 +150,7 @@
}
/**
- * Get the beanproxy for the given expression and registry.
+ * Get the beanproxy for the given expression and registry. It will evaluate immediately.
*
* @param expression
* @param registry
@@ -170,18 +163,17 @@
* @since 1.0.0
*/
public IBeanProxy getBeanProxy(PTExpression expression, ProxyFactoryRegistry registry) throws IllegalStateException, IllegalArgumentException, ThrowableProxy, NoExpressionValueException, ProcessingException {
- this.registry = registry;
this.expression = registry.getBeanProxyFactory().createExpression();
- setNextExpression(IExpression.ROOTEXPRESSION);
+ setNextExpression(ForExpression.ROOTEXPRESSION);
try {
expression.accept(this);
} catch (ProcessingException e) {
// Handle the most common that make sense to be know distinctly and throw them instead of ProcessingException.
Throwable t = e.getCause();
- if (t instanceof ThrowableProxy)
- throw (ThrowableProxy) t;
- else if (t instanceof NoExpressionValueException)
+ if (t instanceof NoExpressionValueException)
throw (NoExpressionValueException) t;
+ else if (t instanceof IllegalStateException)
+ throw (IllegalStateException) t;
else
throw e;
}
@@ -190,6 +182,35 @@
}
/**
+ * Using the given expression processor allocate the proxy. It will not evaluate immediately, but just push onto the expression.
+ * @param expression
+ * @param expressionProcessor
+ * @return the ExpressionProxy for the allocation.
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws ProcessingException
+ *
+ * @since 1.1.0
+ */
+ public ExpressionProxy getProxy(PTExpression expression, IExpression expressionProcessor) throws IllegalStateException, IllegalArgumentException, ProcessingException {
+ this.expression = expressionProcessor;
+ try {
+ ExpressionProxy proxy = expressionProcessor.createProxyAssignmentExpression(ForExpression.ROOTEXPRESSION);
+ setNextExpression(ForExpression.ASSIGNMENT_RIGHT);
+ expression.accept(this);
+ return proxy;
+ } catch (ProcessingException e) {
+ // Handle the most common that make sense to be know distinctly and throw them instead of ProcessingException.
+ Throwable t = e.getCause();
+ if (t instanceof IllegalStateException)
+ throw (IllegalStateException) t;
+ else
+ throw e;
+ }
+ }
+
+
+ /**
* Set the next expression type. (i.e. the <code>forExpression</code> field of most of the create expression methods.
*
* @param nextExpression
@@ -197,7 +218,7 @@
* @see IExpression#createInfixExpression(int, int, int)
* @since 1.0.0
*/
- protected final void setNextExpression(int nextExpression) {
+ protected final void setNextExpression(ForExpression nextExpression) {
this.nextExpression = nextExpression;
}
@@ -209,7 +230,7 @@
* @see IExpression#createInfixExpression(int, int, int)
* @since 1.0.0
*/
- protected final int getNextExpression() {
+ protected final ForExpression getNextExpression() {
return nextExpression;
}
@@ -217,20 +238,14 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTArrayAccess)
*/
public boolean visit(PTArrayAccess node) {
- try {
- getExpression().createArrayAccess(getNextExpression(), node.getIndexes().size());
- setNextExpression(IExpression.ARRAYACCESS_ARRAY);
- node.getArray().accept(this);
- List idx = node.getIndexes();
- int s = idx.size();
- for (int i = 0; i < s; i++) {
- setNextExpression(IExpression.ARRAYACCESS_INDEX);
- ((PTExpression) idx.get(i)).accept(this);
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ getExpression().createArrayAccess(getNextExpression(), node.getIndexes().size());
+ setNextExpression(ForExpression.ARRAYACCESS_ARRAY);
+ node.getArray().accept(this);
+ List idx = node.getIndexes();
+ int s = idx.size();
+ for (int i = 0; i < s; i++) {
+ setNextExpression(ForExpression.ARRAYACCESS_INDEX);
+ ((PTExpression) idx.get(i)).accept(this);
}
return false;
}
@@ -239,22 +254,16 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTArrayCreation)
*/
public boolean visit(PTArrayCreation node) {
- try {
- getExpression().createArrayCreation(getNextExpression(), node.getType(), node.getDimensions().size());
- if (node.getDimensions().isEmpty()) {
- node.getInitializer().accept(this); // Array initializer doesn't require a next expression.
- } else {
- List dims = node.getDimensions();
- int s = dims.size();
- for (int i = 0; i < s; i++) {
- setNextExpression(IExpression.ARRAYCREATION_DIMENSION);
- ((PTExpression) dims.get(i)).accept(this);
- }
+ getExpression().createArrayCreation(getNextExpression(), node.getType(), node.getDimensions().size());
+ if (node.getDimensions().isEmpty()) {
+ node.getInitializer().accept(this); // Array initializer doesn't require a next expression.
+ } else {
+ List dims = node.getDimensions();
+ int s = dims.size();
+ for (int i = 0; i < s; i++) {
+ setNextExpression(ForExpression.ARRAYCREATION_DIMENSION);
+ ((PTExpression) dims.get(i)).accept(this);
}
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
}
return false;
}
@@ -263,18 +272,12 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTArrayInitializer)
*/
public boolean visit(PTArrayInitializer node) {
- try {
- getExpression().createArrayInitializer(node.getExpressions().size());
- List exps = node.getExpressions();
- int s = exps.size();
- for (int i = 0; i < s; i++) {
- setNextExpression(IExpression.ARRAYINITIALIZER_EXPRESSION);
- ((PTExpression) exps.get(i)).accept(this);
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ getExpression().createArrayInitializer(node.getExpressions().size());
+ List exps = node.getExpressions();
+ int s = exps.size();
+ for (int i = 0; i < s; i++) {
+ setNextExpression(ForExpression.ARRAYINITIALIZER_EXPRESSION);
+ ((PTExpression) exps.get(i)).accept(this);
}
return false;
}
@@ -283,13 +286,7 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTBooleanLiteral)
*/
public boolean visit(PTBooleanLiteral node) {
- try {
- getExpression().createPrimitiveLiteral(getNextExpression(), node.isBooleanValue());
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createPrimitiveLiteral(getNextExpression(), node.isBooleanValue());
return false;
}
@@ -297,15 +294,9 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTCastExpression)
*/
public boolean visit(PTCastExpression node) {
- try {
- getExpression().createCastExpression(getNextExpression(), node.getType());
- setNextExpression(IExpression.CAST_EXPRESSION);
- node.getExpression().accept(this);
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createCastExpression(getNextExpression(), node.getType());
+ setNextExpression(ForExpression.CAST_EXPRESSION);
+ node.getExpression().accept(this);
return false;
}
@@ -313,13 +304,7 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTCharacterLiteral)
*/
public boolean visit(PTCharacterLiteral node) {
- try {
- getExpression().createPrimitiveLiteral(getNextExpression(), node.getCharValue());
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createPrimitiveLiteral(getNextExpression(), node.getCharValue());
return false;
}
@@ -327,18 +312,12 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTClassInstanceCreation)
*/
public boolean visit(PTClassInstanceCreation node) {
- try {
- getExpression().createClassInstanceCreation(getNextExpression(), node.getType(), node.getArguments().size());
- List args = node.getArguments();
- int s = args.size();
- for (int i = 0; i < s; i++) {
- setNextExpression(IExpression.CLASSINSTANCECREATION_ARGUMENT);
- ((PTExpression) args.get(i)).accept(this);
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ getExpression().createClassInstanceCreation(getNextExpression(), node.getType(), node.getArguments().size());
+ List args = node.getArguments();
+ int s = args.size();
+ for (int i = 0; i < s; i++) {
+ setNextExpression(ForExpression.CLASSINSTANCECREATION_ARGUMENT);
+ ((PTExpression) args.get(i)).accept(this);
}
return false;
}
@@ -347,19 +326,13 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTConditionalExpression)
*/
public boolean visit(PTConditionalExpression node) {
- try {
- getExpression().createConditionalExpression(getNextExpression());
- setNextExpression(IExpression.CONDITIONAL_CONDITION);
- node.getCondition().accept(this);
- setNextExpression(IExpression.CONDITIONAL_TRUE);
- node.getTrue().accept(this);
- setNextExpression(IExpression.CONDITIONAL_FALSE);
- node.getFalse().accept(this);
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createConditionalExpression(getNextExpression());
+ setNextExpression(ForExpression.CONDITIONAL_CONDITION);
+ node.getCondition().accept(this);
+ setNextExpression(ForExpression.CONDITIONAL_TRUE);
+ node.getTrue().accept(this);
+ setNextExpression(ForExpression.CONDITIONAL_FALSE);
+ node.getFalse().accept(this);
return false;
}
@@ -367,16 +340,10 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTFieldAccess)
*/
public boolean visit(PTFieldAccess node) {
- try {
- getExpression().createFieldAccess(getNextExpression(), node.getField(), node.getReceiver() != null);
- if (node.getReceiver() != null) {
- setNextExpression(IExpression.FIELD_RECEIVER);
- node.getReceiver().accept(this);
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ getExpression().createFieldAccess(getNextExpression(), node.getField(), node.getReceiver() != null);
+ if (node.getReceiver() != null) {
+ setNextExpression(ForExpression.FIELD_RECEIVER);
+ node.getReceiver().accept(this);
}
return false;
}
@@ -385,22 +352,16 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTInfixExpression)
*/
public boolean visit(PTInfixExpression node) {
- try {
- getExpression().createInfixExpression(getNextExpression(), convertPTInfixOperatorToProxyInfixOperator(node.getOperator()), node.getExtendedOperands().size());
- setNextExpression(IExpression.INFIX_LEFT);
- node.getLeftOperand().accept(this);
- setNextExpression(IExpression.INFIX_RIGHT);
- node.getRightOperand().accept(this);
- List extended = node.getExtendedOperands();
- int s = extended.size();
- for (int i = 0; i < s; i++) {
- setNextExpression(IExpression.INFIX_EXTENDED);
- ((PTExpression) extended.get(i)).accept(this);
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ getExpression().createInfixExpression(getNextExpression(), convertPTInfixOperatorToProxyInfixOperator(node.getOperator()), node.getExtendedOperands().size());
+ setNextExpression(ForExpression.INFIX_LEFT);
+ node.getLeftOperand().accept(this);
+ setNextExpression(ForExpression.INFIX_RIGHT);
+ node.getRightOperand().accept(this);
+ List extended = node.getExtendedOperands();
+ int s = extended.size();
+ for (int i = 0; i < s; i++) {
+ setNextExpression(ForExpression.INFIX_EXTENDED);
+ ((PTExpression) extended.get(i)).accept(this);
}
return false;
}
@@ -409,15 +370,9 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTInstanceof)
*/
public boolean visit(PTInstanceof node) {
- try {
- getExpression().createInstanceofExpression(getNextExpression(), node.getType());
- setNextExpression(IExpression.INSTANCEOF_VALUE);
- node.getOperand().accept(this);
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createInstanceofExpression(getNextExpression(), node.getType());
+ setNextExpression(ForExpression.INSTANCEOF_VALUE);
+ node.getOperand().accept(this);
return false;
}
@@ -432,22 +387,16 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTMethodInvocation)
*/
public boolean visit(PTMethodInvocation node) {
- try {
- getExpression().createMethodInvocation(getNextExpression(), node.getName(), node.getReceiver() != null, node.getArguments().size());
- if (node.getReceiver() != null) {
- setNextExpression(IExpression.METHOD_RECEIVER);
- node.getReceiver().accept(this);
- }
- List args = node.getArguments();
- int s = args.size();
- for (int i = 0; i < s; i++) {
- setNextExpression(IExpression.METHOD_ARGUMENT);
- ((PTExpression) args.get(i)).accept(this);
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ getExpression().createMethodInvocation(getNextExpression(), node.getName(), node.getReceiver() != null, node.getArguments().size());
+ if (node.getReceiver() != null) {
+ setNextExpression(ForExpression.METHOD_RECEIVER);
+ node.getReceiver().accept(this);
+ }
+ List args = node.getArguments();
+ int s = args.size();
+ for (int i = 0; i < s; i++) {
+ setNextExpression(ForExpression.METHOD_ARGUMENT);
+ ((PTExpression) args.get(i)).accept(this);
}
return false;
}
@@ -456,14 +405,8 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTName)
*/
public boolean visit(PTName node) {
- try {
- // This is special in the PTName can only be used as a type receiver at this time.
- getExpression().createTypeReceiver(node.getName());
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ // This is special in the PTName can only be used as a type receiver at this time.
+ getExpression().createTypeReceiver(node.getName());
return false;
}
@@ -471,14 +414,8 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTNullLiteral)
*/
public boolean visit(PTNullLiteral node) {
- try {
- // This is special in the PTName can only be used as a type receiver at this time.
- getExpression().createNull(getNextExpression());
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ // This is special in the PTName can only be used as a type receiver at this time.
+ getExpression().createNull(getNextExpression());
return false;
}
@@ -486,31 +423,25 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTNumberLiteral)
*/
public boolean visit(PTNumberLiteral node) {
- try {
- // It is assumed the tokens are trimmed.
- String lit = node.getToken();
- char lastChar = lit.charAt(lit.length()-1);
- if (lastChar == 'l' || lastChar == 'L' ) {
- // It is definitely a long.
- // Using decode so that things like 0x3 will be parsed. parseLong won't recognize those.
- getExpression().createPrimitiveLiteral(getNextExpression(), Long.decode(lit.substring(0, lit.length()-1)).longValue());
- } else if (lastChar == 'F' || lastChar == 'f') {
- // It is definitely a float.
- getExpression().createPrimitiveLiteral(getNextExpression(), Float.parseFloat(lit.substring(0, lit.length()-1)));
- } else if (lastChar == 'D' || lastChar == 'd') {
- // It is definitely a double.
- getExpression().createPrimitiveLiteral(getNextExpression(), Double.parseDouble(lit.substring(0, lit.length()-1)));
- } else if (lit.indexOf('.') != -1 || lit.indexOf('e') != -1 || lit.indexOf('E') != -1) {
- // It is definitely a double. (has a period or an exponent, but does not have an 'f' on the end is always a double).
- getExpression().createPrimitiveLiteral(getNextExpression(), Double.parseDouble(lit.substring(0, lit.length())));
- } else {
- // Using decode so that things like 0x3 will be parsed. parseInt won't recognize those.
- getExpression().createPrimitiveLiteral(getNextExpression(), Integer.decode(lit).intValue());
- }
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
+ // It is assumed the tokens are trimmed.
+ String lit = node.getToken();
+ char lastChar = lit.charAt(lit.length()-1);
+ if (lastChar == 'l' || lastChar == 'L' ) {
+ // It is definitely a long.
+ // Using decode so that things like 0x3 will be parsed. parseLong won't recognize those.
+ getExpression().createPrimitiveLiteral(getNextExpression(), Long.decode(lit.substring(0, lit.length()-1)).longValue());
+ } else if (lastChar == 'F' || lastChar == 'f') {
+ // It is definitely a float.
+ getExpression().createPrimitiveLiteral(getNextExpression(), Float.parseFloat(lit.substring(0, lit.length()-1)));
+ } else if (lastChar == 'D' || lastChar == 'd') {
+ // It is definitely a double.
+ getExpression().createPrimitiveLiteral(getNextExpression(), Double.parseDouble(lit.substring(0, lit.length()-1)));
+ } else if (lit.indexOf('.') != -1 || lit.indexOf('e') != -1 || lit.indexOf('E') != -1) {
+ // It is definitely a double. (has a period or an exponent, but does not have an 'f' on the end is always a double).
+ getExpression().createPrimitiveLiteral(getNextExpression(), Double.parseDouble(lit.substring(0, lit.length())));
+ } else {
+ // Using decode so that things like 0x3 will be parsed. parseInt won't recognize those.
+ getExpression().createPrimitiveLiteral(getNextExpression(), Integer.decode(lit).intValue());
}
return false;
}
@@ -527,15 +458,9 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTPrefixExpression)
*/
public boolean visit(PTPrefixExpression node) {
- try {
- getExpression().createPrefixExpression(getNextExpression(), convertPTPrefixOperatorToProxyPrefixOperator(node.getOperator()));
- setNextExpression(IExpression.PREFIX_OPERAND);
- node.getExpression().accept(this);
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createPrefixExpression(getNextExpression(), convertPTPrefixOperatorToProxyPrefixOperator(node.getOperator()));
+ setNextExpression(ForExpression.PREFIX_OPERAND);
+ node.getExpression().accept(this);
return false;
}
@@ -543,13 +468,7 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTStringLiteral)
*/
public boolean visit(PTStringLiteral node) {
- try {
- getExpression().createProxyExpression(getNextExpression(), getRegistry().getBeanProxyFactory().createBeanProxyWith(node.getLiteralValue()));
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createProxyExpression(getNextExpression(), getRegistry().getBeanProxyFactory().createBeanProxyWith(node.getLiteralValue()));
return false;
}
@@ -564,13 +483,7 @@
* @see org.eclipse.jem.internal.instantiation.ParseVisitor#visit(org.eclipse.jem.internal.instantiation.PTTypeLiteral)
*/
public boolean visit(PTTypeLiteral node) {
- try {
- getExpression().createTypeLiteral(getNextExpression(), node.getType());
- } catch (ThrowableProxy e) {
- throw new ProcessingException(e);
- } catch (NoExpressionValueException e) {
- throw new ProcessingException(e);
- }
+ getExpression().createTypeLiteral(getNextExpression(), node.getType());
return false;
}
diff --git a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaReflectionKey.java b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaReflectionKey.java
index cb05c13..3ef0435 100644
--- a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaReflectionKey.java
+++ b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaReflectionKey.java
@@ -11,13 +11,12 @@
package org.eclipse.jem.internal.java.adapters;
/*
* $RCSfile: JavaReflectionKey.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:37:02 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:16 $
*/
import java.util.*;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.jem.java.*;
@@ -51,50 +50,10 @@
static { initializePrimitivesCollection(); }
- protected XMIResource resource; //FB
+ protected JavaXMIFactoryImpl.JavaXMIResource resource; //FB
protected List extensions;
-//FB /**
-//FB * JavaReflectionKey constructor comment.
-//FB */
-//FB public JavaReflectionKey() {
-//FB super();
-//FB }
-//FB /**
-//FB * Method JavaReflectionKey.
-//FB * @param extensions
-//FB */
-//FB public JavaReflectionKey(List extensions) {
-//FB super();
-//FB setExtensions(extensions);
-//FB }
-
-//FB /**
-//FB * Method JavaReflectionKey.
-//FB * @param extensions
-//FB * @param extent
-//FB */
-//FB public JavaReflectionKey(List extensions, Extent extent) {
-//FB this(extent);
-//FB setExtensions(extensions);
-//FB }
-
-//FB /**
-//FB * JavaReflectionKey constructor comment.
-//FB * @param e com.ibm.etools.emf.ref.Extent
-//FB */
-//FB public JavaReflectionKey(com.ibm.etools.emf.ref.Extent e) {
-//FB super(e);
-//FB }
-//FB /**
-//FB * Set the extensions to use. Typically only called by JavaXMIFactoryImpl.
-//FB */
-//FB public void setExtensions(List extensions) {
-//FB this.extensions = extensions;
-//FB }
-
-//FB ADDED
-public JavaReflectionKey(List extensions, XMIResource resource) {
+public JavaReflectionKey(List extensions, JavaXMIFactoryImpl.JavaXMIResource resource) {
this.extensions = extensions;
this.resource = resource;
}
@@ -389,7 +348,7 @@
* The Key must be an ID for it to be found.
*/
public Object primGet(String key) {
- return resource.getIDToEObjectMap().get(key);
+ return resource.primGetEObject(key);
}
protected EPackage getPackage() {
//FB return (EPackage) super.get(JavaPackage.PACKAGE_ID);
diff --git a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaXMIFactoryImpl.java b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaXMIFactoryImpl.java
index 7896eab..622c04a 100644
--- a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaXMIFactoryImpl.java
+++ b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/internal/java/adapters/JavaXMIFactoryImpl.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.internal.java.adapters;
/*
* $RCSfile: JavaXMIFactoryImpl.java,v $
- * $Revision: 1.5 $ $Date: 2005/02/15 22:37:02 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 19:01:16 $
*/
import java.io.IOException;
import java.util.*;
@@ -110,6 +110,20 @@
}
return result;
}
+
+ /**
+ * Used by JavaReflectionKey to look directly into ID table to bypass an infinite loop. It will
+ * call here because it may not of first been found, but then added, so now is found.
+ *
+ * @param uriFragment
+ * @return
+ *
+ * @since 1.1.0
+ */
+ EObject primGetEObject(String uriFragment) {
+ return super.getEObject(uriFragment);
+ }
+
/* (non-Javadoc)
* @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#useIDAttributes()
*/
diff --git a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/JavaHelpers.java b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/JavaHelpers.java
index 998120f..b3cc8c1 100644
--- a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/JavaHelpers.java
+++ b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/JavaHelpers.java
@@ -12,7 +12,7 @@
/*
* $RCSfile: JavaHelpers.java,v $
- * $Revision: 1.4 $ $Date: 2005/02/15 22:37:02 $
+ * $Revision: 1.5 $ $Date: 2005/05/11 19:01:16 $
*/
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
@@ -39,6 +39,17 @@
static final String PRIM_INTEGER_NAME = "int";
static final String PRIM_LONG_NAME = "long";
static final String PRIM_SHORT_NAME = "short";
+
+ static final int PRIM_NOT_ID = 0;
+ static final int PRIM_BOOLEAN_ID = 1;
+ static final int PRIM_CHARACTER_ID = 2;
+ static final int PRIM_BYTE_ID = 3;
+ static final int PRIM_DOUBLE_ID = 4;
+ static final int PRIM_FLOAT_ID = 5;
+ static final int PRIM_INTEGER_ID = 6;
+ static final int PRIM_LONG_ID = 7;
+ static final int PRIM_SHORT_ID = 8;
+
/**
* Get the qualified name (with using '.' for inner classes). Will return the name if primitive too (e.g. "boolean")
* Note: This should of been get the simple name and not the qualifed name, but it is too late and has been established
@@ -56,7 +67,24 @@
* @since 1.0.0
*/
public String getSimpleName();
+
+ /**
+ * Get the primitive type that this helper wrappers or is (e.g. "java.lang.Integer" and "int" types return "int" type). If not a primitive
+ * or a wrapper for a primitive, then return null.
+ * @return
+ *
+ * @since 1.0.0
+ */
public JavaDataType getPrimitive();
+
+ /**
+ * Get the primitive id that this helper wrappers or is (e.g. "java.lang.Integer" and "int" will return {@link JavaHelpers#PRIM_INTEGER_ID}). If
+ * not a wrapper for a primitive then return {@link JavaHelpers#PRIM_NOT_ID}.
+ * @return
+ *
+ * @since 1.1.0
+ */
+ public int getPrimitiveID();
/**
* To be used by people that need to get the qualified name. This would use '.' for inner classes
* and include the package name.
diff --git a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java
index ce1219f..faba2ad 100644
--- a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java
+++ b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java
@@ -10,7 +10,7 @@
*******************************************************************************/
/*
* $RCSfile: JavaClassImpl.java,v $
- * $Revision: 1.14 $ $Date: 2005/04/14 19:05:33 $
+ * $Revision: 1.15 $ $Date: 2005/05/11 19:01:16 $
*/
package org.eclipse.jem.java.impl;
@@ -619,6 +619,31 @@
}
return null;
}
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.java.JavaHelpers#getPrimitiveID()
+ */
+ public int getPrimitiveID() {
+ String myName = getQualifiedName();
+ if (myName.equals(INTEGER_NAME))
+ return PRIM_INTEGER_ID;
+ if (myName.equals(BOOLEAN_NAME))
+ return PRIM_BOOLEAN_ID;
+ if (myName.equals(BYTE_NAME))
+ return PRIM_BYTE_ID;
+ if (myName.equals(SHORT_NAME))
+ return PRIM_SHORT_ID;
+ if (myName.equals(LONG_NAME))
+ return PRIM_LONG_ID;
+ if (myName.equals(FLOAT_NAME))
+ return PRIM_FLOAT_ID;
+ if (myName.equals(DOUBLE_NAME))
+ return PRIM_DOUBLE_ID;
+ if (myName.equals(CHARACTER_NAME))
+ return PRIM_CHARACTER_ID;
+ return PRIM_NOT_ID;
+ }
/**
* Return the primitive name for this type if one exists.
diff --git a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaDataTypeImpl.java b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaDataTypeImpl.java
index dd79ff5..a6912a6 100644
--- a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaDataTypeImpl.java
+++ b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaDataTypeImpl.java
@@ -11,7 +11,7 @@
package org.eclipse.jem.java.impl;
/*
* $RCSfile: JavaDataTypeImpl.java,v $
- * $Revision: 1.7 $ $Date: 2005/04/14 19:05:33 $
+ * $Revision: 1.8 $ $Date: 2005/05/11 19:01:16 $
*/
import java.util.Collection;
@@ -42,9 +42,13 @@
static final String FLOAT_ZERO = "0.0f";
static final String CHAR_ZERO = "'0'";
static final String ZERO = "0";
+
+ private int primitive_type = PRIM_NOT_ID;
+
protected JavaDataTypeImpl() {
super();
}
+
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
@@ -59,13 +63,13 @@
*/
public String getDefaultValueString() {
String typeName = getJavaName();
- if (typeName.equals(Boolean.TYPE.getName()))
+ if (typeName.equals(PRIM_BOOLEAN_NAME))
return FALSE;
- if (typeName.equals(Double.TYPE.getName()))
+ if (typeName.equals(PRIM_DOUBLE_NAME))
return DOUBLE_ZERO;
- if (typeName.equals(Float.TYPE.getName()))
+ if (typeName.equals(PRIM_FLOAT_NAME))
return FLOAT_ZERO;
- if (typeName.equals(Character.TYPE.getName()))
+ if (typeName.equals(PRIM_CHARACTER_NAME))
return CHAR_ZERO;
return ZERO;
}
@@ -76,6 +80,33 @@
return this;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jem.java.JavaHelpers#getPrimitiveID()
+ */
+ public int getPrimitiveID() {
+ if (primitive_type == PRIM_NOT_ID) {
+ String name = getName();
+ if (name.equals(PRIM_BOOLEAN_NAME))
+ primitive_type = PRIM_BOOLEAN_ID;
+ if (name.equals(PRIM_CHARACTER_NAME))
+ primitive_type = PRIM_CHARACTER_ID;
+ if (name.equals(PRIM_BYTE_NAME))
+ primitive_type = PRIM_BYTE_ID;
+ if (name.equals(PRIM_SHORT_NAME))
+ primitive_type = PRIM_SHORT_ID;
+ if (name.equals(PRIM_INTEGER_NAME))
+ primitive_type = PRIM_INTEGER_ID;
+ if (name.equals(PRIM_LONG_NAME))
+ primitive_type = PRIM_LONG_ID;
+ if (name.equals(PRIM_FLOAT_NAME))
+ primitive_type = PRIM_FLOAT_ID;
+ if (name.equals(PRIM_DOUBLE_NAME))
+ primitive_type = PRIM_DOUBLE_ID;
+ }
+ return primitive_type;
+ }
+
public String getSimpleName() {
return getName();
}
@@ -93,24 +124,26 @@
* getWrapper method comment.
*/
protected String getWrapperQualifiedName() {
- String myName = getJavaName();
- if (myName.equals(PRIM_INTEGER_NAME))
- return INTEGER_NAME;
- if(myName.equals(PRIM_CHARACTER_NAME))
- return CHARACTER_NAME;
- if(myName.equals(PRIM_BOOLEAN_NAME))
- return BOOLEAN_NAME;
- if(myName.equals(PRIM_BYTE_NAME))
- return BYTE_NAME;
- if(myName.equals(PRIM_SHORT_NAME))
- return SHORT_NAME;
- if(myName.equals(PRIM_LONG_NAME))
- return LONG_NAME;
- if(myName.equals(PRIM_FLOAT_NAME))
- return FLOAT_NAME;
- if(myName.equals(PRIM_DOUBLE_NAME))
- return DOUBLE_NAME;
- return null;
+ switch (getPrimitiveID()) {
+ case PRIM_INTEGER_ID:
+ return INTEGER_NAME;
+ case PRIM_CHARACTER_ID:
+ return CHARACTER_NAME;
+ case PRIM_BOOLEAN_ID:
+ return BOOLEAN_NAME;
+ case PRIM_BYTE_ID:
+ return BYTE_NAME;
+ case PRIM_SHORT_ID:
+ return SHORT_NAME;
+ case PRIM_LONG_ID:
+ return LONG_NAME;
+ case PRIM_FLOAT_ID:
+ return FLOAT_NAME;
+ case PRIM_DOUBLE_ID:
+ return DOUBLE_NAME;
+ default:
+ return null;
+ }
}
/*
* JavaHelpers.isArray() - array types are always JavaClasses, even if their component type is