diff --git a/jprotoc/README.md b/jprotoc/README.md index 878c9735..15307056 100644 --- a/jprotoc/README.md +++ b/jprotoc/README.md @@ -130,4 +130,45 @@ Using the Jdk8 Protoc generator 3. Reference the java 8 client stubs like this: ```java MyServiceGrpc8.GreeterCompletableFutureStub stub = MyServiceGrpc8.newCompletableFutureStub(channel); - ``` \ No newline at end of file + ``` + +Implementing Custom Protoc Options +================================== +1. Create a custom option as per https://developers.google.com/protocol-buffers/docs/reference/java-generated#extension. +For example: + + ``` + syntax = "proto3"; + + package com.example.proto.options; + + import "google/protobuf/descriptor.proto"; + + option java_multiple_files = true; + option java_outer_classname = "ServerOptionsProto"; + option java_package = "com.example.proto.options"; + + extend google.protobuf.FileOptions { + ServerOptions server = 50621; + } + + message ServerOptions { + // Java classname + string name = 1; + } + ``` + +2. Run the Protoc generator on the Extension proto. + +3. Use `ProtocPlugin.generate(List generators, List extensions)` so +that the option gets registered: + + ``` + class Generator extends com.salesforce.jprotoc.Generator { + public static void main(String[] args) { + ProtocPlugin.generate([new Generator()], [com.example.proto.options.ServerOptionsProto.server]); + } + + // ? + } + ``` diff --git a/jprotoc/src/main/java/com/salesforce/jprotoc/ProtocPlugin.java b/jprotoc/src/main/java/com/salesforce/jprotoc/ProtocPlugin.java index 00aefc4f..8d825711 100644 --- a/jprotoc/src/main/java/com/salesforce/jprotoc/ProtocPlugin.java +++ b/jprotoc/src/main/java/com/salesforce/jprotoc/ProtocPlugin.java @@ -9,13 +9,14 @@ import com.google.common.base.Preconditions; import com.google.common.io.ByteStreams; +import com.google.protobuf.ExtensionRegistry; +import com.google.protobuf.GeneratedMessage.GeneratedExtension; import com.google.protobuf.compiler.PluginProtos; - -import javax.annotation.Nonnull; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import javax.annotation.Nonnull; /** * ProtocPlugin is the main entry point for running one or more java-base protoc plugins. This class handles @@ -40,13 +41,34 @@ public static void generate(@Nonnull Generator generator) { * @param generators The list of generators to run. */ public static void generate(@Nonnull List generators) { + generate(generators, Collections.emptyList()); + } + + /** + * Apply multiple generators to the parsed proto descriptor, aggregating their results. + * Also register the given extensions so they may be processed by the generator. + * + * @param generators The list of generators to run. + * @param extensions The list of extensions to register. + */ + public static void generate( + @Nonnull List generators, List extensions) { Preconditions.checkNotNull(generators, "generators"); Preconditions.checkArgument(!generators.isEmpty(), "generators.isEmpty()"); + Preconditions.checkNotNull(extensions, "extensions"); + + // As per https://developers.google.com/protocol-buffers/docs/reference/java-generated#extension, + // extensions must be registered in order to be processed. + ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance(); + for (GeneratedExtension extension : extensions) { + extensionRegistry.add(extension); + } try { // Parse the input stream to extract the generator request byte[] generatorRequestBytes = ByteStreams.toByteArray(System.in); - PluginProtos.CodeGeneratorRequest request = PluginProtos.CodeGeneratorRequest.parseFrom(generatorRequestBytes); + PluginProtos.CodeGeneratorRequest request = PluginProtos.CodeGeneratorRequest.parseFrom( + generatorRequestBytes, extensionRegistry); // Run each file generator, collecting the output List outputFiles = generators