Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion jprotoc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```
```

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;
}
```

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I have to run the protobuf generator as part of the build process for my protobuf plugin? Do I need to add this to my plugin project's POM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with Maven but I don't see any reason anything in the build would have to change. All the processing is done at protoc run-time when protoc calls the protoc plugin.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm not understanding correctly. Where does the type com.example.proto.options.ServerOptionsProto.server come from in the example below? Perhaps you could add an elaborated example in jprotoc-test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's generated by protoc. Those not creating custom options don't need to run protoc to generate the related Java code for the option. I'm assuming those creating custom options would know how to run protoc to do that. I can add a blurb about running protoc if you want.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see...My JProtoc Protobuf generator project would itself contain Protobuf generated code (it's proto all the way down!). A line to say "Run the Protoc generator on the Extension proto" should suffice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

2. Run the Protoc generator on the Extension proto.

3. Use `ProtocPlugin.generate(List<Generator> generators, List<GeneratedExtension> 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]);
}

// ?
}
```
28 changes: 25 additions & 3 deletions jprotoc/src/main/java/com/salesforce/jprotoc/ProtocPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<Generator> 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<Generator> generators, List<GeneratedExtension> 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<PluginProtos.CodeGeneratorResponse.File> outputFiles = generators
Expand Down