Provide base methods for Abstract stub

Default implementation returns status UNIMPLEMENTED. This allows adding
new methods to services without breaking existing code.
diff --git a/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp
index 81e452d..0aadd18 100644
--- a/compiler/src/java_plugin/cpp/java_generator.cpp
+++ b/compiler/src/java_plugin/cpp/java_generator.cpp
@@ -155,6 +155,7 @@
 
   if (flavor == ProtoFlavor::NANO) {
     p->Print(
+        *vars,
         "private static final class NanoFactory<T extends com.google.protobuf.nano.MessageNano>\n"
         "    implements io.grpc.protobuf.nano.MessageNanoFactory<T> {\n"
         "  private final int id;\n"
@@ -163,7 +164,7 @@
         "    this.id = id;\n"
         "  }\n"
         "\n"
-        "  @Override\n"
+        "  @$Override$\n"
         "  public T newInstance() {\n"
         "    Object o;\n"
         "    switch (id) {\n");
@@ -204,7 +205,8 @@
   BLOCKING_SERVER_INTERFACE = 3,
   ASYNC_CLIENT_IMPL = 4,
   BLOCKING_CLIENT_IMPL = 5,
-  FUTURE_CLIENT_IMPL = 6
+  FUTURE_CLIENT_IMPL = 6,
+  ABSTRACT = 7,
 };
 
 enum CallType {
@@ -219,9 +221,14 @@
     map<string, string>* vars,
     Printer* p, StubType type, bool generate_nano) {
   (*vars)["service_name"] = service->name();
+  (*vars)["abstract_name"] = "Abstract" + service->name();
   string interface_name = service->name();
   string impl_name = service->name();
+  bool abstract = false;
   switch (type) {
+    case ABSTRACT:
+      abstract = true;
+      break;
     case ASYNC_INTERFACE:
     case ASYNC_CLIENT_IMPL:
       impl_name += "Stub";
@@ -242,9 +249,10 @@
     default:
       GRPC_CODEGEN_FAIL << "Cannot determine class name for StubType: " << type;
   }
-  bool impl;
   CallType call_type;
+  bool impl = false;
   switch (type) {
+    case ABSTRACT:
     case ASYNC_INTERFACE:
       call_type = ASYNC_CALL;
       impl = false;
@@ -277,7 +285,12 @@
   (*vars)["impl_name"] = impl_name;
 
   // Class head
-  if (!impl) {
+  if (abstract) {
+    p->Print(
+        *vars,
+        "public static abstract class $abstract_name$ implements $service_name$, "
+        "$BindableService$ {\n");
+  } else if (!impl) {
     p->Print(
         *vars,
         "public static interface $interface_name$ {\n");
@@ -343,7 +356,7 @@
 
     // Method signature
     p->Print("\n");
-    if (impl) {
+    if (impl || abstract) {
       p->Print(
           *vars,
           "@$Override$\n");
@@ -395,10 +408,34 @@
             "    $input_type$ request)");
         break;
     }
-    if (impl) {
-      // Method body for client impls
-      p->Print(" {\n");
-      p->Indent();
+
+    if (!(abstract || impl)) {
+      // Interface method - there will be no body, close method.
+      p->Print(";\n");
+      continue;
+    }
+
+    // Method body for abstract stub & client impls.
+    p->Print(" {\n");
+    p->Indent();
+
+    if (abstract) {
+      switch (call_type) {
+        // NB: Skipping validation of service methods. If something is wrong, we wouldn't get to
+        // this point as compiler would return errors when generating service interface.
+        case ASYNC_CALL:
+          if (client_streaming) {
+            p->Print(
+                *vars,
+                "return asyncUnimplementedStreamingCall($method_field_name$, responseObserver);\n");
+          } else {
+            p->Print(
+                *vars,
+                "asyncUnimplementedUnaryCall($method_field_name$, responseObserver);\n");
+          }
+          break;
+      }
+    } else if (impl) {
       switch (call_type) {
         case BLOCKING_CALL:
           GRPC_CODEGEN_CHECK(!client_streaming)
@@ -451,12 +488,24 @@
               "    getChannel().newCall($method_field_name$, getCallOptions()), request);\n");
           break;
       }
-      p->Outdent();
-      p->Print("}\n");
-    } else {
-      p->Print(";\n");
     }
+    p->Outdent();
+    p->Print("}\n");
   }
+
+  if (abstract) {
+    p->Print("\n");
+    p->Print(*vars,
+             "@$Override$ public $ServerServiceDefinition$ bindService() {\n"
+             );
+    p->Indent();
+    p->Print(*vars,
+             "return $service_class_name$.bindService(this);\n"
+             );
+    p->Outdent();
+    p->Print("}\n");
+  }
+
   p->Outdent();
   p->Print("}\n\n");
 }
@@ -642,27 +691,6 @@
   p->Print("}\n");
 }
 
-static void PrintAbstractServiceClass(const ServiceDescriptor* service,
-                                   map<string, string>* vars,
-                                   Printer* p) {
-  p->Print(
-      *vars,
-      "public static abstract class Abstract$service_name$"
-      " implements $service_name$, $BindableService$ {\n");
-  p->Indent();
-  p->Print(*vars,
-           "@Override public $ServerServiceDefinition$ bindService() {\n"
-           );
-  p->Indent();
-  p->Print(*vars,
-           "return $service_class_name$.bindService(this);\n"
-           );
-  p->Outdent();
-  p->Print("}\n");
-  p->Outdent();
-  p->Print("}\n\n");
-}
-
 static void PrintService(const ServiceDescriptor* service,
                          map<string, string>* vars,
                          Printer* p,
@@ -720,12 +748,12 @@
 
   bool generate_nano = flavor == ProtoFlavor::NANO;
   PrintStub(service, vars, p, ASYNC_INTERFACE, generate_nano);
+  PrintStub(service, vars, p, ABSTRACT, generate_nano);
   PrintStub(service, vars, p, BLOCKING_CLIENT_INTERFACE, generate_nano);
   PrintStub(service, vars, p, FUTURE_CLIENT_INTERFACE, generate_nano);
   PrintStub(service, vars, p, ASYNC_CLIENT_IMPL, generate_nano);
   PrintStub(service, vars, p, BLOCKING_CLIENT_IMPL, generate_nano);
   PrintStub(service, vars, p, FUTURE_CLIENT_IMPL, generate_nano);
-  PrintAbstractServiceClass(service, vars, p);
   PrintMethodHandlerClass(service, vars, p, generate_nano);
   PrintBindServiceMethod(service, vars, p, generate_nano);
   p->Outdent();
@@ -757,7 +785,11 @@
       "import static "
       "io.grpc.stub.ServerCalls.asyncClientStreamingCall;\n"
       "import static "
-      "io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\n\n");
+      "io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\n"
+      "import static "
+      "io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n"
+      "import static "
+      "io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;\n\n");
   if (generate_nano) {
     p->Print("import java.io.IOException;\n\n");
   }
diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt
index b029819..cd82a81 100644
--- a/compiler/src/test/golden/TestService.java.txt
+++ b/compiler/src/test/golden/TestService.java.txt
@@ -12,6 +12,8 @@
 import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
 import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
 import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
 
 @javax.annotation.Generated(
     value = "by gRPC proto compiler",
@@ -101,6 +103,43 @@
         io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver);
   }
 
+  public static abstract class AbstractTestService implements TestService, io.grpc.BindableService {
+
+    @java.lang.Override
+    public void unaryCall(io.grpc.testing.integration.Test.SimpleRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse> responseObserver) {
+      asyncUnimplementedUnaryCall(METHOD_UNARY_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public void streamingOutputCall(io.grpc.testing.integration.Test.StreamingOutputCallRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      asyncUnimplementedUnaryCall(METHOD_STREAMING_OUTPUT_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallRequest> streamingInputCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_STREAMING_INPUT_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> fullBidiCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_FULL_BIDI_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> halfBidiCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_HALF_BIDI_CALL, responseObserver);
+    }
+
+    @java.lang.Override public io.grpc.ServerServiceDefinition bindService() {
+      return TestServiceGrpc.bindService(this);
+    }
+  }
+
   public static interface TestServiceBlockingClient {
 
     public io.grpc.testing.integration.Test.SimpleResponse unaryCall(io.grpc.testing.integration.Test.SimpleRequest request);
@@ -224,12 +263,6 @@
     }
   }
 
-  public static abstract class AbstractTestService implements TestService, io.grpc.BindableService {
-    @Override public io.grpc.ServerServiceDefinition bindService() {
-      return TestServiceGrpc.bindService(this);
-    }
-  }
-
   private static final int METHODID_UNARY_CALL = 0;
   private static final int METHODID_STREAMING_OUTPUT_CALL = 1;
   private static final int METHODID_STREAMING_INPUT_CALL = 2;
diff --git a/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt
index 726bf70..1270fc7 100644
--- a/compiler/src/testLite/golden/TestService.java.txt
+++ b/compiler/src/testLite/golden/TestService.java.txt
@@ -12,6 +12,8 @@
 import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
 import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
 import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
 
 @javax.annotation.Generated(
     value = "by gRPC proto compiler",
@@ -101,6 +103,43 @@
         io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver);
   }
 
+  public static abstract class AbstractTestService implements TestService, io.grpc.BindableService {
+
+    @java.lang.Override
+    public void unaryCall(io.grpc.testing.integration.Test.SimpleRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse> responseObserver) {
+      asyncUnimplementedUnaryCall(METHOD_UNARY_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public void streamingOutputCall(io.grpc.testing.integration.Test.StreamingOutputCallRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      asyncUnimplementedUnaryCall(METHOD_STREAMING_OUTPUT_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallRequest> streamingInputCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_STREAMING_INPUT_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> fullBidiCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_FULL_BIDI_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> halfBidiCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_HALF_BIDI_CALL, responseObserver);
+    }
+
+    @java.lang.Override public io.grpc.ServerServiceDefinition bindService() {
+      return TestServiceGrpc.bindService(this);
+    }
+  }
+
   public static interface TestServiceBlockingClient {
 
     public io.grpc.testing.integration.Test.SimpleResponse unaryCall(io.grpc.testing.integration.Test.SimpleRequest request);
@@ -224,12 +263,6 @@
     }
   }
 
-  public static abstract class AbstractTestService implements TestService, io.grpc.BindableService {
-    @Override public io.grpc.ServerServiceDefinition bindService() {
-      return TestServiceGrpc.bindService(this);
-    }
-  }
-
   private static final int METHODID_UNARY_CALL = 0;
   private static final int METHODID_STREAMING_OUTPUT_CALL = 1;
   private static final int METHODID_STREAMING_INPUT_CALL = 2;
diff --git a/compiler/src/testNano/golden/TestService.java.txt b/compiler/src/testNano/golden/TestService.java.txt
index 0be68b1..88dc9cd 100644
--- a/compiler/src/testNano/golden/TestService.java.txt
+++ b/compiler/src/testNano/golden/TestService.java.txt
@@ -12,6 +12,8 @@
 import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
 import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
 import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
 
 import java.io.IOException;
 
@@ -104,7 +106,7 @@
       this.id = id;
     }
 
-    @Override
+    @java.lang.Override
     public T newInstance() {
       Object o;
       switch (id) {
@@ -179,6 +181,43 @@
         io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver);
   }
 
+  public static abstract class AbstractTestService implements TestService, io.grpc.BindableService {
+
+    @java.lang.Override
+    public void unaryCall(io.grpc.testing.integration.nano.Test.SimpleRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.SimpleResponse> responseObserver) {
+      asyncUnimplementedUnaryCall(METHOD_UNARY_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public void streamingOutputCall(io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest request,
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver) {
+      asyncUnimplementedUnaryCall(METHOD_STREAMING_OUTPUT_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingInputCallRequest> streamingInputCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingInputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_STREAMING_INPUT_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest> fullBidiCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_FULL_BIDI_CALL, responseObserver);
+    }
+
+    @java.lang.Override
+    public io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest> halfBidiCall(
+        io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver) {
+      return asyncUnimplementedStreamingCall(METHOD_HALF_BIDI_CALL, responseObserver);
+    }
+
+    @java.lang.Override public io.grpc.ServerServiceDefinition bindService() {
+      return TestServiceGrpc.bindService(this);
+    }
+  }
+
   public static interface TestServiceBlockingClient {
 
     public io.grpc.testing.integration.nano.Test.SimpleResponse unaryCall(io.grpc.testing.integration.nano.Test.SimpleRequest request);
@@ -302,12 +341,6 @@
     }
   }
 
-  public static abstract class AbstractTestService implements TestService, io.grpc.BindableService {
-    @Override public io.grpc.ServerServiceDefinition bindService() {
-      return TestServiceGrpc.bindService(this);
-    }
-  }
-
   private static final int METHODID_UNARY_CALL = 0;
   private static final int METHODID_STREAMING_OUTPUT_CALL = 1;
   private static final int METHODID_STREAMING_INPUT_CALL = 2;