Creates an IREE Status in Java matching the C implementation, and passes status codes through jni

PiperOrigin-RevId: 314373937
diff --git a/bindings/java/com/google/iree/Context.java b/bindings/java/com/google/iree/Context.java
index 7162945..3e221bd 100644
--- a/bindings/java/com/google/iree/Context.java
+++ b/bindings/java/com/google/iree/Context.java
@@ -18,9 +18,13 @@
 
 /** An isolated execution context. */
 final class Context {
-  public Context(Instance instance) {
+  public Context(Instance instance) throws Exception {
     nativeAddress = nativeNew();
-    nativeCreate(instance.getNativeAddress());
+    Status status = Status.fromCode(nativeCreate(instance.getNativeAddress()));
+
+    if (!status.isOk()) {
+      throw status.toException("Could not create Context");
+    }
   }
 
   public int getId() {
@@ -35,7 +39,7 @@
 
   private native long nativeNew();
 
-  private native void nativeCreate(long instanceAddress);
+  private native int nativeCreate(long instanceAddress);
 
   private native void nativeFree();
 
diff --git a/bindings/java/com/google/iree/Instance.java b/bindings/java/com/google/iree/Instance.java
index f3f0709..75dda80 100644
--- a/bindings/java/com/google/iree/Instance.java
+++ b/bindings/java/com/google/iree/Instance.java
@@ -30,13 +30,17 @@
     loaded = true;
   }
 
-  public Instance() {
+  public Instance() throws Exception {
     if (!loaded) {
       throw new IllegalStateException("Native library is not loaded");
     }
 
     nativeAddress = nativeNew();
-    nativeCreate();
+    Status status = Status.fromCode(nativeCreate());
+
+    if (!status.isOk()) {
+      throw status.toException("Could not create Instance");
+    }
   }
 
   public long getNativeAddress() {
@@ -53,7 +57,7 @@
 
   private native long nativeNew();
 
-  private native void nativeCreate();
+  private native int nativeCreate();
 
   private native void nativeFree();
 }
diff --git a/bindings/java/com/google/iree/Status.java b/bindings/java/com/google/iree/Status.java
new file mode 100644
index 0000000..ea14058
--- /dev/null
+++ b/bindings/java/com/google/iree/Status.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed 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 com.google.iree;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.TimeoutException;
+
+/** Well-known status codes matching iree_status_code_t values. */
+public enum Status {
+  OK,
+  CANCELLED,
+  UNKNOWN,
+  INVALID_ARGUMENT,
+  DEADLINE_EXCEEDED,
+  NOT_FOUND,
+  ALREADY_EXISTS,
+  PERMISSION_DENIED,
+  UNAUTHENTICATED,
+  RESOURCE_EXHAUSTED,
+  FAILED_PRECONDITION,
+  ABORTED,
+  OUT_OF_RANGE,
+  UNIMPLEMENTED,
+  INTERNAL,
+  UNAVAILABLE,
+  DATA_LOSS;
+
+  public boolean isOk() {
+    return this == Status.OK;
+  }
+
+  public Exception toException(String message) {
+    String messageWithStatus = this + ": " + message;
+    switch(this) {
+      case CANCELLED:
+        return new CancellationException(messageWithStatus);
+      case UNKNOWN:
+        return new RuntimeException(messageWithStatus);
+      case INVALID_ARGUMENT:
+        return new IllegalArgumentException(messageWithStatus);
+      case DEADLINE_EXCEEDED:
+        return new TimeoutException(messageWithStatus);
+      case NOT_FOUND:
+        return new RuntimeException(messageWithStatus);
+      case ALREADY_EXISTS:
+        return new IllegalStateException(messageWithStatus);
+      case PERMISSION_DENIED:
+        return new IllegalAccessException(messageWithStatus);
+      case RESOURCE_EXHAUSTED:
+        return new RuntimeException(messageWithStatus);
+      case FAILED_PRECONDITION:
+        return new IllegalStateException(messageWithStatus);
+      case ABORTED:
+        return new InterruptedException(messageWithStatus);
+      case OUT_OF_RANGE:
+        return new IndexOutOfBoundsException(messageWithStatus);
+      case UNIMPLEMENTED:
+        return new UnsupportedOperationException(messageWithStatus);
+      case INTERNAL:
+        return new RuntimeException(messageWithStatus);
+      case UNAVAILABLE:
+        return new IllegalStateException(messageWithStatus);
+      case DATA_LOSS:
+        return new RuntimeException(messageWithStatus);
+      case UNAUTHENTICATED:
+        return new IllegalStateException(messageWithStatus);
+      default:
+        return new RuntimeException(messageWithStatus);
+    }
+  }
+
+  public static Status fromCode(int code) {
+    return Status.values()[code];
+  }
+}
diff --git a/bindings/java/com/google/iree/native/context_jni.cc b/bindings/java/com/google/iree/native/context_jni.cc
index 733c0d3..55c8099 100644
--- a/bindings/java/com/google/iree/native/context_jni.cc
+++ b/bindings/java/com/google/iree/native/context_jni.cc
@@ -50,18 +50,14 @@
   delete context;
 }
 
-JNI_FUNC void JNI_PREFIX(nativeCreate)(JNIEnv* env, jobject thiz,
+JNI_FUNC jint JNI_PREFIX(nativeCreate)(JNIEnv* env, jobject thiz,
                                        jlong instanceAddress) {
   ContextWrapper* context = GetContextWrapper(env, thiz);
   CHECK_NE(context, nullptr);
 
   auto instance = (InstanceWrapper*)instanceAddress;
   auto status = context->Create(*instance);
-
-  // TODO(jennik): Propogate this status through to java side.
-  if (!status.ok()) {
-    LOG(FATAL) << status.message();
-  }
+  return (jint)status.code();
 }
 
 JNI_FUNC jint JNI_PREFIX(nativeGetId)(JNIEnv* env, jobject thiz) {
diff --git a/bindings/java/com/google/iree/native/instance_jni.cc b/bindings/java/com/google/iree/native/instance_jni.cc
index b00d69c..61c6498 100644
--- a/bindings/java/com/google/iree/native/instance_jni.cc
+++ b/bindings/java/com/google/iree/native/instance_jni.cc
@@ -48,14 +48,10 @@
   delete instance;
 }
 
-JNI_FUNC void JNI_PREFIX(nativeCreate)(JNIEnv* env, jobject thiz) {
+JNI_FUNC jint JNI_PREFIX(nativeCreate)(JNIEnv* env, jobject thiz) {
   InstanceWrapper* instance = GetInstanceWrapper(env, thiz);
   CHECK_NE(instance, nullptr);
 
   auto status = instance->Create();
-
-  // TODO(jennik): Propogate this status through to java side.
-  if (!status.ok()) {
-    LOG(FATAL) << status.message();
-  }
+  return (jint)status.code();
 }
diff --git a/bindings/javatests/com/google/iree/ContextTest.java b/bindings/javatests/com/google/iree/ContextTest.java
index aca5c2b..39099c5 100644
--- a/bindings/javatests/com/google/iree/ContextTest.java
+++ b/bindings/javatests/com/google/iree/ContextTest.java
@@ -27,17 +27,16 @@
 @RunWith(AndroidJUnit4.class)
 public final class ContextTest {
   @Test
-  public void create_throwsExceptionWithoutNativeLib() {
+  public void create_throwsExceptionWithoutNativeLib() throws Exception {
     try {
       new Instance();
       fail();
-    } catch (IllegalStateException e) {
-      // Expected exception.
+    } catch (IllegalStateException expected) {
     }
   }
 
   @Test
-  public void create_createsContextWithId() {
+  public void create_createsContextWithId() throws Exception {
     Instance.loadNativeLibrary();
     Instance instance = new Instance();
     Context context = new Context(instance);