Not found classes, methods, fields were causing out of sequence exceptions in the expressions. This caused the error handling to believe the error was on the wrong beans. This would cause a confusing error to the user and could cause other parts of the model to not instantiate that should be able to.
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 e712f82..4c967c8 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,7 +10,7 @@ *******************************************************************************/ /* * $RCSfile: ExpressionProcesser.java,v $ - * $Revision: 1.17 $ $Date: 2005/07/11 19:40:00 $ + * $Revision: 1.18 $ $Date: 2005/07/20 19:27:25 $ */ package org.eclipse.jem.internal.proxy.initParser.tree; @@ -713,6 +713,20 @@ } } + /** + * Get the expression proxy value, or the NoExpressionValueException if not resolved. This + * is useful for callers that need to handle the proxy itself for failed calls. + * + * @param proxyid + * @param value + * @throws NoExpressionValueException + * + * @since 1.1.0 + */ + public void getExpressionProxy(int proxyid, Object[] value) throws NoExpressionValueException { + getExpressionProxyValue(proxyid, value, true, 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 @@ -742,7 +756,7 @@ } else { if (doTrace) printTrace("Return Proxy #" + proxyid + ": Not resolved", false); //$NON-NLS-1$ //$NON-NLS-2$ - NoExpressionValueException e = new NoExpressionValueException(InitparserTreeMessages.getString("ExpressionProcesser.GetExpressionProxyValue.ExpressionProxyNotSet_EXC_")); //$NON-NLS-1$ + NoExpressionValueException e = new NoExpressionValueException(InitparserTreeMessages.getString("ExpressionProcesser.GetExpressionProxyValue.ExpressionProxyNotSet_EXC_"), proxy); //$NON-NLS-1$ if (pull) throw e; else
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 index b054401..41e6a77 100644 --- 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
@@ -10,7 +10,7 @@ *******************************************************************************/ /* * $RCSfile: NoExpressionValueException.java,v $ - * $Revision: 1.2 $ $Date: 2005/06/16 17:46:14 $ + * $Revision: 1.3 $ $Date: 2005/07/20 19:27:25 $ */ package org.eclipse.jem.internal.proxy.initParser.tree; @@ -31,6 +31,8 @@ * @since 1.1.0 */ private static final long serialVersionUID = -7953101867782417964L; + + private InternalExpressionProxy proxy; /** * Construct with no arguments. @@ -53,6 +55,33 @@ * @since 1.0.0 */ public NoExpressionValueException(String message) { - super(message); + this(message, null); + } + + /** + * Construct with a message and a proxy. This is only used from {@link ExpressionProcesser#getExpressionProxyValue(int, Object[])} when + * the proxy existed but it was not set. + * + * @param message + * @param proxy + * + * @since 1.1.0 + */ + public NoExpressionValueException(String message, InternalExpressionProxy proxy) { + super (message); + this.proxy = proxy; + } + + /** + * Get the proxy if there is one. It will be a proxy if {@link ExpressionProcesser#getExpressionProxyValue(int, Object[])} + * was for an existing proxy but that proxy was not set. Otherwise it will be null. This is here for callers to + * put special info in the proxy for the not set condition and report better info. + * + * @return the proxy (if not set) or <code>null</code> if no proxy available. + * + * @since 1.1.0 + */ + public InternalExpressionProxy getProxy() { + return proxy; } } \ No newline at end of file
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 736d2fc..e38128d 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,7 +9,7 @@ * IBM Corporation - initial API and implementation *******************************************************************************/ /* - * $RCSfile: IDEExpression.java,v $ $Revision: 1.10 $ $Date: 2005/06/22 21:05:17 $ + * $RCSfile: IDEExpression.java,v $ $Revision: 1.11 $ $Date: 2005/07/20 19:27:25 $ */ package org.eclipse.jem.internal.proxy.ide; @@ -718,9 +718,16 @@ ep.setProxy(typeProxy); eproc.allocateExpressionProxy(ep); if (!typeProxy.isValid()) { - throw new IDEThrowableProxy( - new Exception(typeProxy.getInitializationError()), - getIDEBeanTypeFactory().getBeanTypeProxy(Exception.class)); + Throwable cause = ((IDEInitErrorBeanTypeProxy) typeProxy).getCause(); + if (cause == null) + throw new IDEThrowableProxy( + new Exception(typeProxy.getInitializationError()), + getIDEBeanTypeFactory().getBeanTypeProxy(Exception.class)); + else + throw new IDEThrowableProxy( + cause, + getIDEBeanTypeFactory().getBeanTypeProxy(cause.getClass())); + } } catch (ThrowableProxy e) { eproc.processException(e); @@ -876,7 +883,7 @@ IDEMethodProxy methodProxy = ((IDEMethodProxyFactory) registry.getMethodProxyFactory()).getMethodProxy(declaringClass, methodName, parameterClasses); if (methodProxy == null) { String parms = ""; //$NON-NLS-1$ - if (parameterTypes != null || parameterTypes.length > 0) { + if (parameterTypes != null && parameterTypes.length > 0) { StringBuffer st = new StringBuffer(100); for (int i = 0; i < parameterClasses.length; i++) { if (i > 0)
diff --git a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEInitErrorBeanTypeProxy.java b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEInitErrorBeanTypeProxy.java index 3b04ea9..4c5e3f1 100644 --- a/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEInitErrorBeanTypeProxy.java +++ b/plugins/org.eclipse.jem.proxy/proxyide/org/eclipse/jem/internal/proxy/ide/IDEInitErrorBeanTypeProxy.java
@@ -12,7 +12,7 @@ /* * $RCSfile: IDEInitErrorBeanTypeProxy.java,v $ - * $Revision: 1.5 $ $Date: 2005/02/15 22:57:26 $ + * $Revision: 1.6 $ $Date: 2005/07/20 19:27:25 $ */ import org.eclipse.jem.internal.proxy.core.*; @@ -28,14 +28,26 @@ protected String classname; protected String initializationError; + + protected Throwable cause; - protected IDEInitErrorBeanTypeProxy(IDEProxyFactoryRegistry registry, String classname, String initializationError) { + protected IDEInitErrorBeanTypeProxy(IDEProxyFactoryRegistry registry, String classname, String initializationError, Throwable cause) { super(registry, null); this.classname = classname; this.initializationError = initializationError; + this.cause = cause; } /** + * Get the throwable (cause) that made this bean type bad. + * @return the Throwable that was the cause, or null if not caused by an throwable. + * + * @since 1.1.0 + */ + public Throwable getCause() { + return cause; + } + /** * @see org.eclipse.jem.internal.proxy.core.IBeanTypeProxy#getConstructorProxy(String[]) */ public IConstructorProxy getConstructorProxy(String[] argumentClassNames) {
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 ad885de..3604e3e 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
@@ -7,7 +7,7 @@ package org.eclipse.jem.internal.proxy.ide; /* - * $RCSfile: IDEStandardBeanTypeProxyFactory.java,v $ $Revision: 1.10 $ $Date: 2005/05/18 23:11:26 $ + * $RCSfile: IDEStandardBeanTypeProxyFactory.java,v $ $Revision: 1.11 $ $Date: 2005/07/20 19:27:25 $ */ import java.lang.reflect.Array; @@ -224,15 +224,15 @@ } catch (ClassNotFoundException e) { ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.INFO, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$ String msg = MessageFormat.format("{0}({1})", new Object[] { e.getClass(), e.getMessage()}); //$NON-NLS-1$ - beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg); + beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg, e); } catch (ExceptionInInitializerError e) { ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$ String msg = MessageFormat.format("{0}({1})", new Object[] { e.getClass(), e.getMessage()}); //$NON-NLS-1$ - beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg); + beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg, e.getCause()); } catch (LinkageError e) { ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$ String msg = MessageFormat.format("{0}({1})", new Object[] { e.getClass(), e.getMessage()}); //$NON-NLS-1$ - beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg); + beanTypeProxy = new IDEInitErrorBeanTypeProxy(fFactoryRegistry, typeName, msg, e); } // Cache the instance so we can re-use it again
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 a50ea79..19720ba 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,7 +10,7 @@ *******************************************************************************/ /* * $RCSfile: ExpressionProcesserController.java,v $ - * $Revision: 1.10 $ $Date: 2005/06/22 21:05:17 $ + * $Revision: 1.11 $ $Date: 2005/07/20 19:27:25 $ */ package org.eclipse.jem.internal.proxy.vm.remote; @@ -177,11 +177,9 @@ try { 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) { - // Do nothing, already processed. - } + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. + } break; case InternalExpressionTypes.INSTANCEOF_EXPRESSION_VALUE: @@ -190,11 +188,9 @@ try { 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) { - // Do nothing, already processed. - } + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. + } break; case InternalExpressionTypes.INFIX_EXPRESSION_VALUE: @@ -223,12 +219,9 @@ try { 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) { - // Do nothing, already processed. - } - + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. + } break; case InternalExpressionTypes.ARRAY_INITIALIZER_EXPRESSION_VALUE: @@ -239,10 +232,8 @@ try { 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) { - // Do nothing, already processed. + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. } break; @@ -253,10 +244,8 @@ try { 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) { - // Do nothing, already processed. + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. } break; @@ -266,10 +255,8 @@ try { 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) { - // Do nothing, already processed. + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. } break; @@ -282,8 +269,8 @@ 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. + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. } break; @@ -295,11 +282,9 @@ try { 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. - } + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. + } break; case InternalExpressionTypes.CONDITIONAL_EXPRESSION_VALUE: @@ -320,7 +305,19 @@ 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()); + // First test if a possible FailedExpressionProxy because we could of been pushing + // a failed reflection proxy. + proxyid = in.readInt(); + try { + exp.getExpressionProxy(proxyid, new Object[] {null, null}); + } catch (NoExpressionValueException e1) { + if (e1.getProxy() != null) { + FailedRemoteExpressionProxy failure = (FailedRemoteExpressionProxy) e1.getProxy(); + exp.processException((Throwable) failure.getValue()); + break; // Don't go on, we processed it. A standard no expression value should be passed on and let following code handle it. + } + } + exp.pushExpressionProxy(proxyid); break; case InternalExpressionTypes.BLOCK_BEGIN_EXPRESSION_VALUE: @@ -350,11 +347,9 @@ try { 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. - } + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. + } break; case InternalExpressionTypes.TRY_FINALLY_EXPRESSION_VALUE: @@ -386,9 +381,13 @@ rep.setProxy(classValue, Class.class); exp.allocateExpressionProxy(rep); } catch (ClassNotFoundException e) { - exp.processException(e); + FailedRemoteExpressionProxy rep = new FailedRemoteExpressionProxy(proxyid); + rep.setProxy(e, e.getClass()); + exp.allocateExpressionProxy(rep); } catch (LinkageError e) { - exp.processException(e); + FailedRemoteExpressionProxy rep = new FailedRemoteExpressionProxy(proxyid); + rep.setProxy(e, e.getClass()); + exp.allocateExpressionProxy(rep); } break; @@ -427,10 +426,10 @@ 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 (FailedProxyException e) { + FailedRemoteExpressionProxy rep = new FailedRemoteExpressionProxy(proxyid); + rep.setProxy(e.getCause(), e.getCause().getClass()); + exp.allocateExpressionProxy(rep); } catch (NoSuchMethodException e) { // The default trace doesn't show what method was being searched for, so recreate with that. StringBuffer s = new StringBuffer(); @@ -448,7 +447,9 @@ s.append(')'); NoSuchMethodException ne = new NoSuchMethodException(s.toString()); ne.setStackTrace(e.getStackTrace()); - exp.processException(ne); // Let the processor know we have a stopping error. + FailedRemoteExpressionProxy rep = new FailedRemoteExpressionProxy(proxyid); + rep.setProxy(ne, ne.getClass()); + exp.allocateExpressionProxy(rep); } break; @@ -468,12 +469,14 @@ 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 (FailedProxyException e) { + FailedRemoteExpressionProxy rep = new FailedRemoteExpressionProxy(proxyid); + rep.setProxy(e.getCause(), e.getCause().getClass()); + exp.allocateExpressionProxy(rep); } catch (NoSuchFieldException e) { - exp.processException(e); // Let the processor know we have a stopping error. + FailedRemoteExpressionProxy rep = new FailedRemoteExpressionProxy(proxyid); + rep.setProxy(e, e.getClass()); + exp.allocateExpressionProxy(rep); } break; @@ -494,10 +497,8 @@ 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. + } catch (FailedProxyException e) { + exp.processException(e.getCause()); // Let the processor know we have a stopping error. } break; @@ -534,26 +535,55 @@ } /** + * This is an exception that is thrown from the getBeanType, field, method (reflect type stuff) + * that wrappers the real throwable that occurred during the previous reflection. This is + * because reflection is done out of sequence with the use of the reflect value. So we need + * to store the reflection exception in this exception and then store this exception in + * a {@link FailedRemoteExpressionProxy}. This will then be picked up when trying to be + * used and it will get the true exception out of the {@link Throwable#getCause()}. + * + * @since 1.1.0 + */ + private static class FailedProxyException extends Exception { + /** + * Comment for <code>serialVersionUID</code> + * + * @since 1.1.0 + */ + private static final long serialVersionUID = 2872325672166348923L; + + public FailedProxyException(Throwable realThrowable) { + super(realThrowable); + } + } + + /** * 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. * * @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. + * @throws FailedProxyException Wrappers the real throwable that caused the bean type to not be found. * * @since 1.1.0 */ - protected Class getBeanTypeValue(Commands.ValueObject value) throws ClassCastException, ClassNotFoundException { + protected Class getBeanTypeValue(Commands.ValueObject value) throws FailedProxyException { 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)) { + try { + exp.getExpressionProxy(((Integer) beantype).intValue(), expvalue); beantype = expvalue[0]; - } else - throw new ClassNotFoundException(); + } catch (NoExpressionValueException e) { + // See if there is a failed proxy. + if (e.getProxy() != null) { + FailedRemoteExpressionProxy failure = (FailedRemoteExpressionProxy) e.getProxy(); + throw new FailedProxyException((Throwable) failure.getValue()); + } else + throw new FailedProxyException(new ClassNotFoundException()); // This shouldn't of occurred. + } } return (Class) beantype; } @@ -563,21 +593,27 @@ * 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. + * @throws FailedProxyException Wrappers the real Throwable that caused the method to not be found. * * @since 1.1.0 */ - protected Object getMethodValue(Commands.ValueObject value) throws NoSuchMethodException, ClassCastException { + protected Object getMethodValue(Commands.ValueObject value) throws FailedProxyException { 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)) { + try { + exp.getExpressionProxy(((Integer) method).intValue(), expvalue); method = expvalue[0]; - } else - throw new NoSuchMethodException(); + } catch (NoExpressionValueException e) { + // See if there is a failed proxy. + if (e.getProxy() != null) { + FailedRemoteExpressionProxy failure = (FailedRemoteExpressionProxy) e.getProxy(); + throw new FailedProxyException((Throwable) failure.getValue()); + } else + throw new FailedProxyException(new NoSuchMethodException()); // This shouldn't of occurred. + } } return method; } @@ -587,21 +623,28 @@ * 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. + * @throws FailedProxyException Wrappers the real throwable that caused the field to not be found. * * @since 1.1.0 */ - protected Object getFieldValue(Commands.ValueObject value) throws NoSuchFieldException, ClassCastException { + protected Object getFieldValue(Commands.ValueObject value) throws FailedProxyException { 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)) { + try { + exp.getExpressionProxy(((Integer) field).intValue(), expvalue); field = expvalue[0]; - } else - throw new NoSuchFieldException(); + } catch (NoExpressionValueException e) { + // See if there is a failed proxy. + if (e.getProxy() != null) { + FailedRemoteExpressionProxy failure = (FailedRemoteExpressionProxy) e.getProxy(); + throw new FailedProxyException((Throwable) failure.getValue()); + } else + throw new FailedProxyException(new NoSuchFieldException()); // This shouldn't of occurred. + + } } return field; } @@ -672,6 +715,41 @@ this.type = type; set = true; } + + public boolean isFailedExpression() { + return false; + } + } + + /** + * Used for the java.lang.reflect things (class, field, method) to indicate + * why they aren't found. + * <p> + * The exception will be placed into value, BUT this should never be sent + * back to the caller. It is intended only as a place-holder for subsequent + * usage. Use the {@link RemoteExpressionProxy#isFailedExpression()} method + * to determine if it is a failed one. + * <p> + * This is used because the reflect calls are done out of sequence from where + * they are used and so if there was an error, the error is reported in the + * wrong place. + * + * @since 1.1.0 + */ + private static class FailedRemoteExpressionProxy extends RemoteExpressionProxy { + + public FailedRemoteExpressionProxy(int proxyID) { + super(proxyID); + } + + public boolean isFailedExpression() { + return true; + } + + public boolean isSet() { + return false; // This should never be considered to be set. It is holder of info only. + } + }