[NO ISSUE][HYR] Exception map utility method, fix getBootClassPath() on java >= 9

Change-Id: Ic4cb7a6c3c3636578ba02584cebdba55e6da9995
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10363
Reviewed-by: Michael Blow <mblow@apache.org>
Reviewed-by: Till Westmann <tillw@apache.org>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/hyracks-fullstack/hyracks/hyracks-api/pom.xml b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
index 90fb5ed..2c50ee4 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-api/pom.xml
@@ -94,5 +94,9 @@
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ExceptionUtils.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ExceptionUtils.java
index 9067dce..d748ed8 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ExceptionUtils.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/ExceptionUtils.java
@@ -21,9 +21,14 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
 
 import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.util.ThrowingFunction;
+
+import com.google.common.util.concurrent.UncheckedExecutionException;
 
 /**
  * @author yingyib
@@ -133,4 +138,24 @@
     public static boolean causedByInterrupt(Throwable th) {
         return getRootCause(th) instanceof InterruptedException;
     }
+
+    /**
+     * Convenience utility method to provide a form of {@link Map#computeIfAbsent(Object, Function)} which allows
+     * throwable mapping functions.  Any exceptions thrown by the mapping function is propagated as an instance of
+     * {@link HyracksDataException}
+     */
+    public static <K, V> V computeIfAbsent(Map<K, V> map, K key, ThrowingFunction<K, V> function)
+            throws HyracksDataException {
+        try {
+            return map.computeIfAbsent(key, k -> {
+                try {
+                    return function.process(k);
+                } catch (Exception e) {
+                    throw new UncheckedExecutionException(e);
+                }
+            });
+        } catch (UncheckedExecutionException e) {
+            throw HyracksDataException.create(e.getCause());
+        }
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/MXHelper.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/MXHelper.java
index 247c001..c238b50 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/MXHelper.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/MXHelper.java
@@ -108,9 +108,8 @@
 
     public static String getBootClassPath() {
         try {
-            return runtimeMXBean.getBootClassPath();
+            return runtimeMXBean.isBootClassPathSupported() ? runtimeMXBean.getBootClassPath() : null;
         } catch (UnsupportedOperationException e) {
-            // boot classpath is not supported in Java 9 and later
             LOGGER.debug("ignoring exception calling RuntimeMXBean.getBootClassPath; returning null", e);
             return null;
         }