/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.test.dunit; import org.apache.geode.GemFireException; /** * This exception is thrown when an exception occurs during a remote method invocation. This * {@link RuntimeException} wraps the actual exception. It allows distributed unit tests to verify * that an exception was thrown in a different VM. * * <PRE> * VM vm0 = host0.getVM(0); * try { * vm.invoke(() -> this.getUnknownObject()); * * } catch (RMIException ex) { * assertIndexDetailsEquals(ex.getCause() instanceof ObjectException); * } * </PRE> * * Note that special steps are taken so that the stack trace of the cause exception reflects the * call stack on the remote machine. The stack trace of the exception returned by * {@link #getCause()} may not be available. * * see hydra.RemoteTestModuleIF * */ @SuppressWarnings("serial") public class RMIException extends GemFireException { /** * SHADOWED FIELD that holds the cause exception (as opposed to the HokeyException */ private Throwable cause; /** The name of the method being invoked */ private String methodName; /** * The name of the class (or class of the object type) whose method was being invoked */ private String className; /** The type of exception that was thrown in the remote VM */ private String exceptionClassName; /** Stack trace for the exception that was thrown in the remote VM */ private String stackTrace; /** The VM in which the method was executing */ private VM vm; //////////////////////// Constructors //////////////////////// /** * Creates a new <code>RMIException</code> that was caused by a given <code>Throwable</code> while * invoking a given method. */ public RMIException(VM vm, String className, String methodName, Throwable cause) { super("While invoking " + className + "." + methodName + " in " + vm, cause); this.cause = cause; this.className = className; this.methodName = methodName; this.vm = vm; } /** * Creates a new <code>RMIException</code> to indicate that an exception of a given type was * thrown while invoking a given method. * * @param vm The VM in which the method was executing * @param className The name of the class whose method was being invoked remotely * @param methodName The name of the method that was being invoked remotely * @param cause The type of exception that was thrown in the remote VM * @param stackTrace The stack trace of the exception from the remote VM */ public RMIException(VM vm, String className, String methodName, Throwable cause, String stackTrace) { super("While invoking " + className + "." + methodName + " in " + vm, new HokeyException(cause, stackTrace)); this.vm = vm; this.cause = cause; this.className = className; this.methodName = methodName; // this.exceptionClassName = exceptionClassName; assignment has no effect this.stackTrace = stackTrace; } /** * Returns the class name of the exception that was thrown in a remote method invocation. */ public String getExceptionClassName() { return this.exceptionClassName; } // /** // * Returns the stack trace for the exception that was thrown in a // * remote method invocation. // */ // public String getStackTrace() { // return this.stackTrace; // } /** * Returns the cause of this exception. Note that this is not necessarily the exception that gets * printed out with the stack trace. */ public Throwable getCause() { return this.cause; } /** * Returns the VM in which the remote method was invoked */ public VM getVM() { return this.vm; } ////////////////////// Inner Classes ////////////////////// /** * A hokey exception class that makes it looks like we have a real cause exception. */ private static class HokeyException extends Throwable { private String stackTrace; private String toString; HokeyException(Throwable cause, String stackTrace) { this.toString = cause.toString(); this.stackTrace = stackTrace; } public void printStackTrace(java.io.PrintWriter pw) { pw.print(this.stackTrace); pw.flush(); } public String toString() { return this.toString; } } }