This is an automated email from the ASF dual-hosted git repository.

sai_boorlagadda pushed a commit to branch feature/GEODE-5787-dunit-internal
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 27548dcf3b2a080670120128d0150f12dc651b1e
Author: Sai Boorlagadda <sboorlaga...@pivotal.io>
AuthorDate: Tue Oct 2 11:44:28 2018 -0700

    GEODE-5787: move MethExecutor into dunit
---
 .../main/java/org/apache/geode/test/dunit/VM.java  |   3 +-
 .../geode/test/dunit/standalone/DUnitLauncher.java |   2 +-
 .../geode/test/dunit/standalone/MethExecutor.java  | 363 +++++++++++++++++++++
 .../test/dunit/standalone/MethExecutorResult.java  | 174 ++++++++++
 .../geode/test/dunit/standalone/RemoteDUnitVM.java |   2 -
 .../test/dunit/standalone/RemoteDUnitVMIF.java     |   2 -
 6 files changed, 539 insertions(+), 7 deletions(-)

diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java
index 32643ec..74f618a 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/VM.java
@@ -24,10 +24,9 @@ import java.rmi.RemoteException;
 import java.util.List;
 import java.util.concurrent.Callable;
 
-import hydra.MethExecutorResult;
-
 import org.apache.geode.internal.process.ProcessUtils;
 import org.apache.geode.test.dunit.standalone.BounceResult;
+import org.apache.geode.test.dunit.standalone.MethExecutorResult;
 import org.apache.geode.test.dunit.standalone.RemoteDUnitVMIF;
 import org.apache.geode.test.dunit.standalone.StandAloneDUnitEnv;
 import org.apache.geode.test.dunit.standalone.VersionManager;
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java
index 8f82f9b..d427896 100644
--- 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/DUnitLauncher.java
@@ -48,7 +48,7 @@ import java.util.Properties;
 
 import batterytest.greplogs.ExpectedStrings;
 import batterytest.greplogs.LogConsumer;
-import hydra.MethExecutorResult;
+import org.apache.geode.test.dunit.standalone.MethExecutorResult;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.LoggerContext;
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/MethExecutor.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/MethExecutor.java
new file mode 100644
index 0000000..7913739
--- /dev/null
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/MethExecutor.java
@@ -0,0 +1,363 @@
+/*
+ * 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.standalone;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+import org.apache.geode.SystemFailure;
+
+/**
+ *
+ * A class specialized for executing (via reflection) the receiver/selector 
pairs found in
+ * TestTasks.
+ *
+ */
+public class MethExecutor {
+
+  // @todo lises add static args method
+
+  /**
+   * Helper method that searches a class (and its superclasses) for a method 
with the given name and
+   * parameter types.
+   *
+   * @throws NoSuchMethodException If the method cannot be found
+   */
+  public static Method getMethod(Class c, String methodName, Class[] 
paramTypes)
+      throws NoSuchMethodException {
+
+    ArrayList matchingMethods = new ArrayList();
+    for (Class q = c; q != null; q = q.getSuperclass()) {
+      Method[] methods = q.getDeclaredMethods();
+      NEXT_METHOD: for (int i = 0; i < methods.length; i++) {
+        Method m = methods[i];
+        if (!m.getName().equals(methodName)) {
+          continue;
+        }
+
+        Class[] argTypes = m.getParameterTypes();
+        if (argTypes.length != paramTypes.length) {
+          continue;
+        }
+
+        for (int j = 0; j < argTypes.length; j++) {
+          if (paramTypes[j] == null) {
+            if (argTypes[j].isPrimitive()) {
+              // this parameter is not ok, the parameter is a primative and 
the value is null
+              continue NEXT_METHOD;
+            } else {
+              // this parameter is ok, the argument is an object and the value 
is null
+              continue;
+            }
+          }
+          if (!argTypes[j].isAssignableFrom(paramTypes[j])) {
+            Class argType = argTypes[j];
+            Class paramType = paramTypes[j];
+
+            if (argType.isPrimitive()) {
+              if ((argType.equals(boolean.class) && 
paramType.equals(Boolean.class))
+                  || (argType.equals(short.class) && 
paramType.equals(Short.class))
+                  || (argType.equals(int.class) && 
paramType.equals(Integer.class))
+                  || (argType.equals(long.class) && 
paramType.equals(Long.class))
+                  || (argType.equals(float.class) && 
paramType.equals(Float.class))
+                  || (argType.equals(double.class) && 
paramType.equals(Double.class))
+                  || (argType.equals(char.class) && 
paramType.equals(Character.class))
+                  || (argType.equals(byte.class) && 
paramType.equals(Byte.class)) || false) {
+
+                // This parameter is okay, try the next arg
+                continue;
+              }
+            }
+            continue NEXT_METHOD;
+          }
+        }
+
+        matchingMethods.add(m);
+      }
+
+      // We want to check to make sure there aren't two
+      // ambiguous methods on the same class. But a subclass
+      // can still override a method on a super class, so we'll stop
+      // if we found a method on the subclass.
+      if (matchingMethods.size() > 0) {
+        break;
+      }
+    }
+
+    if (matchingMethods.isEmpty()) {
+      StringBuffer sb = new StringBuffer();
+      sb.append("Could not find method ");
+      sb.append(methodName);
+      sb.append(" with ");
+      sb.append(paramTypes.length);
+      sb.append(" parameters [");
+      for (int i = 0; i < paramTypes.length; i++) {
+        String name = paramTypes[i] == null ? null : paramTypes[i].getName();
+        sb.append(name);
+        if (i < paramTypes.length - 1) {
+          sb.append(", ");
+        }
+      }
+      sb.append("] in class ");
+      sb.append(c.getName());
+      throw new NoSuchMethodException(sb.toString());
+    }
+    if (matchingMethods.size() > 1) {
+      StringBuffer sb = new StringBuffer();
+      sb.append("Method is ambiguous ");
+      sb.append(methodName);
+      sb.append(" with ");
+      sb.append(paramTypes.length);
+      sb.append(" parameters [");
+      for (int i = 0; i < paramTypes.length; i++) {
+        String name = paramTypes[i] == null ? null : paramTypes[i].getName();
+        sb.append(name);
+        if (i < paramTypes.length - 1) {
+          sb.append(", ");
+        }
+      }
+      sb.append("] in class ");
+      sb.append(c.getName());
+      sb.append(" methods=" + matchingMethods);
+      throw new NoSuchMethodException(sb.toString());
+    } else
+      return (Method) matchingMethods.get(0);
+  }
+
+  /**
+   *
+   * Send the message "selector" to the class named "receiver". Return the 
result, including stack
+   * trace (if any).
+   *
+   */
+  public static MethExecutorResult execute(String receiver, String selector) {
+    return execute(receiver, selector, null);
+  }
+
+  /**
+   * Executes the given static method on the given class with the given 
arguments.
+   */
+  public static MethExecutorResult execute(String receiver, String selector, 
Object[] args) {
+    try {
+      // get the class
+      Class receiverClass = Class.forName(receiver);
+
+      // invoke the method
+      Object res = null;
+      try {
+        Class[] paramTypes;
+        if (args == null) {
+          paramTypes = new Class[0];
+
+        } else {
+          paramTypes = new Class[args.length];
+          for (int i = 0; i < args.length; i++) {
+            if (args[i] == null) {
+              paramTypes[i] = null;
+
+            } else {
+              paramTypes[i] = args[i].getClass();
+            }
+          }
+        }
+
+        Method theMethod = getMethod(receiverClass, selector, paramTypes);
+        theMethod.setAccessible(true);
+        res = theMethod.invoke(receiverClass, args);
+        return new MethExecutorResult(res);
+
+      } catch (InvocationTargetException invTargEx) {
+        Throwable targEx = invTargEx.getTargetException();
+        if (targEx == null) {
+          return new MethExecutorResult(res);
+
+        } else {
+          return new MethExecutorResult(targEx);
+        }
+      }
+
+    } catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    } catch (Throwable t) {
+      // String s = "While trying to invoke " + receiver + "." +
+      // selector;
+      // t = new HydraConfigException(s, t);
+      return new MethExecutorResult(t);
+    }
+  }
+
+  /**
+   *
+   * Send the message "selector" to the object "target". Return the result, 
including stack trace
+   * (if any).
+   *
+   */
+  public static MethExecutorResult executeObject(Object target, String 
selector) {
+    return executeObject(target, selector, null);
+  }
+
+  /**
+   * Executes the given instance method on the given object with the given 
arguments.
+   */
+  public static MethExecutorResult executeObject(Object target, String 
selector, Object[] args) {
+    try {
+      // get the class
+      Class receiverClass = target.getClass();
+
+      // invoke the method
+      Object res = null;
+      try {
+        Class[] paramTypes;
+        if (args == null) {
+          paramTypes = new Class[0];
+
+        } else {
+          paramTypes = new Class[args.length];
+          for (int i = 0; i < args.length; i++) {
+            if (args[i] == null) {
+              paramTypes[i] = Object.class;
+
+            } else {
+              paramTypes[i] = args[i].getClass();
+            }
+          }
+        }
+
+        Method theMethod = getMethod(receiverClass, selector, paramTypes);
+        theMethod.setAccessible(true);
+        res = theMethod.invoke(target, args);
+        return new MethExecutorResult(res);
+
+      } catch (InvocationTargetException invTargEx) {
+        Throwable targEx = invTargEx.getTargetException();
+        if (targEx == null) {
+          return new MethExecutorResult(res);
+
+        } else {
+          return new MethExecutorResult(targEx);
+        }
+      }
+
+    } catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    } catch (Throwable t) {
+      return new MethExecutorResult(t);
+    }
+  }
+
+  /**
+   *
+   * Send the message "selector" to an instance of the class named "receiver". 
Return the result,
+   * including stack trace (if any).
+   *
+   */
+  public static MethExecutorResult executeInstance(String receiver, String 
selector) {
+
+    try {
+      // get the class
+      Class receiverClass = Class.forName(receiver);
+      Object target = receiverClass.newInstance();
+
+      // invoke the method
+      Object res = null;
+      try {
+        Method theMethod = getMethod(receiverClass, selector, new Class[0]);
+        res = theMethod.invoke(target, new Object[0]);
+        return new MethExecutorResult(res);
+
+      } catch (InvocationTargetException invTargEx) {
+        Throwable targEx = invTargEx.getTargetException();
+        if (targEx == null) {
+          return new MethExecutorResult(res);
+        } else {
+          return new MethExecutorResult(targEx);
+        }
+      }
+
+    } catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    } catch (Throwable t) {
+      return new MethExecutorResult(t);
+    }
+  }
+
+  /**
+   *
+   * Send the message "selector" to an instance of the class named "receiver". 
Return the result,
+   * including stack trace (if any).
+   *
+   */
+  public static MethExecutorResult executeInstance(String receiver, String 
selector, Class[] types,
+      Object[] args) {
+
+    try {
+      // get the class
+      Class receiverClass = Class.forName(receiver);
+      Constructor init = receiverClass.getDeclaredConstructor(new Class[0]);
+      init.setAccessible(true);
+      Object target = init.newInstance(new Object[0]);
+
+      // invoke the method
+      Object res = null;
+      try {
+        Method theMethod = getMethod(receiverClass, selector, types);
+        res = theMethod.invoke(target, args);
+        return new MethExecutorResult(res);
+
+      } catch (InvocationTargetException invTargEx) {
+        Throwable targEx = invTargEx.getTargetException();
+        if (targEx == null) {
+          return new MethExecutorResult(res);
+
+        } else {
+          return new MethExecutorResult(targEx);
+        }
+      }
+
+    } catch (VirtualMachineError e) {
+      SystemFailure.initiateFailure(e);
+      throw e;
+    } catch (Throwable t) {
+      return new MethExecutorResult(t);
+    }
+  }
+
+  /**
+   *
+   * A small program for testing this class.
+   *
+   */
+  public static String testMethod1() {
+    return "The result is: " + System.currentTimeMillis();
+  }
+
+  public static String testMethod2() {
+    throw new ArrayIndexOutOfBoundsException("frip");
+  }
+
+  public static void main(String[] args) {
+    MethExecutorResult result = null;
+    result = MethExecutor.execute("hydra.MethExecutor", "testMethod1");
+    System.out.println(result.toString());
+    result = MethExecutor.execute("hydra.MethExecutor", "testMethod2");
+    System.out.println(result.toString());
+  }
+}
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/MethExecutorResult.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/MethExecutorResult.java
new file mode 100644
index 0000000..b1a2061
--- /dev/null
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/MethExecutorResult.java
@@ -0,0 +1,174 @@
+/*
+ * 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.standalone;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+
+/**
+ *
+ * The result of a MethExecutor execute method.
+ *
+ */
+public class MethExecutorResult implements Serializable {
+
+  /**
+   * A "result" object that indicates that an exception occurred while 
invoking the method
+   */
+  public static final Serializable EXCEPTION_OCCURRED = new Serializable() {
+    public boolean equals(Object o) {
+      // Allows instances to be compared across VMs
+      return o != null && this.getClass().equals(o.getClass());
+    }
+
+    public String toString() {
+      return "EXCEPTION_OCCURRED";
+    }
+  };
+
+  /**
+   * A "exception" object that indicates that an exception could not be 
serialized.
+   */
+  public static final Throwable NONSERIALIZABLE_EXCEPTION = new Throwable() {
+    public boolean equals(Object o) {
+      // Allows instances to be compared across VMs
+      return o != null && this.getClass().equals(o.getClass());
+    }
+
+    public String toString() {
+      return "NONSERIALIZABLE_EXCEPTION";
+    }
+  };
+
+
+  //////////////////// Instance Methods ///////////////////////////
+
+  /** The result of execution (may be an exception or error type) */
+  private Object result;
+
+  /** The exception that resulted from invoking the method */
+  private Throwable exception;
+
+  /** Type of the exception (if applicable) */
+  private String exceptionClassName;
+
+  /** Message of the exception (if applicable) */
+  private String exceptionMessage;
+
+  /** Stack trace information (if applicable) */
+  private String stackTrace;
+
+  public MethExecutorResult() {
+    this.result = null;
+  }
+
+  public MethExecutorResult(Object result) {
+    this.result = result;
+  }
+
+  /**
+   * This constructor is invoked when invoking a method resulted in an 
exception being thrown. The
+   * "result" is set to {@link #EXCEPTION_OCCURRED}. If the exception could 
not be serialized,
+   * {@link #getException()} will return IOException with the exception stack 
as the message.
+   */
+  public MethExecutorResult(Throwable thr) {
+    this.result = EXCEPTION_OCCURRED;
+    this.exceptionClassName = thr.getClass().getName();
+    this.exceptionMessage = thr.getMessage();
+
+    StringWriter sw = new StringWriter();
+
+    thr.printStackTrace(new PrintWriter(sw, true));
+    this.stackTrace = sw.toString();
+
+    try {
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      ObjectOutputStream oos = new ObjectOutputStream(baos);
+      oos.writeObject(thr);
+      this.exception = thr;
+
+    } catch (IOException ex) {
+      sw = new StringWriter();
+      ex.printStackTrace(new PrintWriter(sw, true));
+      this.exception = new IOException(sw.toString());
+    }
+  }
+
+  public String toString() {
+    StringBuffer s = new StringBuffer();
+    s.append(this.getResult());
+    s.append("\n");
+    if (this.getStackTrace() != null) {
+      s.append(this.getStackTrace());
+    }
+    return s.toString();
+  }
+
+  /**
+   * Returns the result of the method call. If an exception was thrown during 
the method call,
+   * {@link #EXCEPTION_OCCURRED} is returned.
+   *
+   * @see #exceptionOccurred()
+   */
+  public Object getResult() {
+    return this.result;
+  }
+
+  /**
+   * Returns the name of the exception class of the exception that was thrown 
while invoking a
+   * method. If no exception was thrown, <code>null</code> is returned.
+   */
+  public String getExceptionClassName() {
+    return this.exceptionClassName;
+  }
+
+  /**
+   * Returns the message of the exception that was thrown while invoking a 
method. If no exception
+   * was thrown, <code>null</code> is returned.
+   */
+  public String getExceptionMessage() {
+    return this.exceptionMessage;
+  }
+
+  /**
+   * Returns the stack trace of the exception that was thrown while invoking a 
method. If no
+   * exception was thrown, <code>null</code> is returned.
+   */
+  public String getStackTrace() {
+    return this.stackTrace;
+  }
+
+  /**
+   * Returns the exception that was thrown while invoking a method. If the 
exception could not be
+   * serialized, then {@link #NONSERIALIZABLE_EXCEPTION} is returned. If no 
exception was thrown,
+   * <code>null</code> is returned.
+   */
+  public Throwable getException() {
+    return this.exception;
+  }
+
+  /**
+   * Returns whether or not an exception occurred while invoking the method
+   */
+  public boolean exceptionOccurred() {
+    return EXCEPTION_OCCURRED.equals(this.result);
+  }
+
+}
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVM.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVM.java
index d02ce74..382ea04 100644
--- 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVM.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVM.java
@@ -18,8 +18,6 @@ import java.rmi.RemoteException;
 import java.rmi.server.UnicastRemoteObject;
 import java.util.concurrent.TimeUnit;
 
-import hydra.MethExecutor;
-import hydra.MethExecutorResult;
 import org.apache.logging.log4j.Logger;
 
 import org.apache.geode.internal.logging.LogService;
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVMIF.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVMIF.java
index 9db6b06..b8400e7 100644
--- 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVMIF.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/RemoteDUnitVMIF.java
@@ -17,8 +17,6 @@ package org.apache.geode.test.dunit.standalone;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
 
-import hydra.MethExecutorResult;
-
 public interface RemoteDUnitVMIF extends Remote {
 
   MethExecutorResult executeMethodOnObject(Object target, String methodName) 
throws RemoteException;

Reply via email to