Skip to content

Commit 4f187b1

Browse files
authored
feat: Add code request generator dumper and an ability to run generator from dumped file (#765)
For debugging purposes. Usage example: ```bzl load("@gapic_generator_java//rules_java_gapic:java_gapic.bzl", "java_generator_request_dump") java_generator_request_dump( name = "compute_small_request_dump", srcs = [":compute_small_proto_with_info"], transport = "rest", )
1 parent b7d9399 commit 4f187b1

7 files changed

Lines changed: 259 additions & 31 deletions

File tree

BUILD.bazel

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ load(
88
package(default_visibility = ["//visibility:public"])
99

1010
JAVA_SRCS = [
11+
"//src/main/java/com/google/api/generator/debug:debug_files",
1112
"//src/main/java/com/google/api/generator:generator_files",
1213
"//src/main/java/com/google/api/generator/engine:engine_files",
1314
"//src/main/java/com/google/api/generator/gapic:gapic_files",
@@ -47,6 +48,57 @@ java_binary(
4748
],
4849
)
4950

51+
# Request dumper binary, which dumps the CodeGeneratorRequest to a file on disk
52+
# which will be identical to the one passed to the protoc-gen-java_gapic during
53+
# normal execution. The dumped file then can be used to run this gapic-generator
54+
# directly (instead of relying on protoc to start the process), which would give
55+
# much greater flexibility in terms of debugging features, like attaching a
56+
# debugger, easier work with stdout and stderr etc.
57+
#
58+
# Usage example, via the rule in a corresponding BUILD.bazel file:
59+
#
60+
# load("@gapic_generator_java//rules_java_gapic:java_gapic.bzl", "java_generator_request_dump")
61+
# java_generator_request_dump(
62+
# name = "compute_small_request_dump",
63+
# srcs = [":compute_small_proto_with_info"],
64+
# transport = "rest",
65+
# )
66+
#
67+
java_binary(
68+
name = "protoc-gen-code_generator_request_dumper",
69+
main_class = "com.google.api.generator.debug.CodeGeneratorRequestDumper",
70+
runtime_deps = [
71+
"//src/main/java/com/google/api/generator",
72+
"//src/main/java/com/google/api/generator/debug",
73+
"//src/main/java/com/google/api/generator/gapic",
74+
"@com_google_googleapis//google/api:api_java_proto",
75+
"@com_google_googleapis//google/longrunning:longrunning_java_proto",
76+
"@com_google_guava_guava",
77+
"@com_google_protobuf//:protobuf_java",
78+
],
79+
)
80+
81+
# A binary similar to protoc-gen-java_gapic but reads the CodeGeneratorRequest
82+
# directly from a file instead of relying on protoc to pipe it in.
83+
#
84+
# Usage example:
85+
#
86+
# bazel run code_generator_request_file_to_gapic_main desc-dump.bin dump.jar
87+
#
88+
java_binary(
89+
name = "code_generator_request_file_to_gapic_main",
90+
main_class = "com.google.api.generator.debug.CodeGeneratorRequestFileToGapicMain",
91+
runtime_deps = [
92+
"//src/main/java/com/google/api/generator",
93+
"//src/main/java/com/google/api/generator/debug",
94+
"//src/main/java/com/google/api/generator/gapic",
95+
"@com_google_googleapis//google/api:api_java_proto",
96+
"@com_google_googleapis//google/longrunning:longrunning_java_proto",
97+
"@com_google_guava_guava",
98+
"@com_google_protobuf//:protobuf_java",
99+
],
100+
)
101+
50102
# google-java-format
51103
java_binary(
52104
name = "google_java_format_binary",

rules_java_gapic/java_gapic.bzl

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,18 @@ def _append_dep_without_duplicates(dest_deps, new_deps):
119119
dest_deps.append(new_deps[i])
120120
return dest_deps
121121

122-
def java_gapic_library(
122+
def _java_gapic_srcjar(
123123
name,
124124
srcs,
125-
grpc_service_config = None,
126-
gapic_yaml = None,
127-
service_yaml = None,
128-
deps = [],
129-
test_deps = [],
125+
grpc_service_config,
126+
gapic_yaml,
127+
service_yaml,
130128
# possible values are: "grpc", "rest", "grpc+rest"
131-
transport = None,
129+
transport,
132130
# Can be used to provide a java_library with a customized generator,
133131
# like the one which dumps descriptor to a file for future debugging.
134-
_java_generator_name = "java_gapic",
132+
java_generator_name = "java_gapic",
133+
output_suffix = ".srcjar",
135134
**kwargs):
136135
file_args_dict = {}
137136

@@ -159,8 +158,6 @@ def java_gapic_library(
159158
else:
160159
fail("Service.yaml is no longer supported in the Java microgenerator")
161160

162-
srcjar_name = name + "_srcjar"
163-
raw_srcjar_name = srcjar_name + "_raw"
164161
output_suffix = ".srcjar"
165162
opt_args = []
166163

@@ -172,18 +169,43 @@ def java_gapic_library(
172169
plugin_args = ["metadata"]
173170

174171
proto_custom_library(
175-
name = raw_srcjar_name,
172+
name = name,
176173
deps = srcs,
177-
plugin = Label("@gapic_generator_java//:protoc-gen-%s" % _java_generator_name),
174+
plugin = Label("@gapic_generator_java//:protoc-gen-%s" % java_generator_name),
178175
plugin_args = plugin_args,
179176
plugin_file_args = {},
180177
opt_file_args = file_args_dict,
181-
output_type = _java_generator_name,
178+
output_type = java_generator_name,
182179
output_suffix = output_suffix,
183180
opt_args = opt_args,
184181
**kwargs
185182
)
186183

184+
def java_gapic_library(
185+
name,
186+
srcs,
187+
grpc_service_config = None,
188+
gapic_yaml = None,
189+
service_yaml = None,
190+
deps = [],
191+
test_deps = [],
192+
# possible values are: "grpc", "rest", "grpc+rest"
193+
transport = None,
194+
**kwargs):
195+
srcjar_name = name + "_srcjar"
196+
raw_srcjar_name = srcjar_name + "_raw"
197+
198+
_java_gapic_srcjar(
199+
name = raw_srcjar_name,
200+
srcs = srcs,
201+
grpc_service_config = grpc_service_config,
202+
gapic_yaml = gapic_yaml,
203+
service_yaml = service_yaml,
204+
transport = transport,
205+
java_generator_name = "java_gapic",
206+
**kwargs
207+
)
208+
187209
_java_gapic_postprocess_srcjar(
188210
name = srcjar_name,
189211
gapic_srcjar = "%s.srcjar" % raw_srcjar_name,
@@ -282,3 +304,26 @@ def java_gapic_test(name, runtime_deps, test_classes, **kwargs):
282304
tests = test_classes,
283305
**kwargs
284306
)
307+
308+
# A debugging rule, to dump CodeGenereatorRequest from protoc as is to a file,
309+
# which then can be used to run gapic-generator directly instead of relying on
310+
# protoc to launch it. This would simplify attaching the debugger and/or
311+
# working with stdin/stderr.
312+
def java_generator_request_dump(
313+
name,
314+
srcs,
315+
grpc_service_config = None,
316+
gapic_yaml = None,
317+
service_yaml = None,
318+
transport = None,
319+
**kwargs):
320+
_java_gapic_srcjar(
321+
name = name,
322+
srcs = srcs,
323+
grpc_service_config = grpc_service_config,
324+
gapic_yaml = gapic_yaml,
325+
service_yaml = service_yaml,
326+
transport = transport,
327+
java_generator_name = "code_generator_request_dumper",
328+
**kwargs
329+
)

src/main/java/com/google/api/generator/Main.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,18 @@
1414

1515
package com.google.api.generator;
1616

17-
import com.google.api.AnnotationsProto;
18-
import com.google.api.ClientProto;
19-
import com.google.api.FieldBehaviorProto;
20-
import com.google.api.ResourceProto;
2117
import com.google.api.generator.gapic.Generator;
22-
import com.google.longrunning.OperationsProto;
23-
import com.google.protobuf.Descriptors.DescriptorValidationException;
2418
import com.google.protobuf.ExtensionRegistry;
2519
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
2620
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
2721
import java.io.IOException;
2822

2923
public class Main {
30-
public static void main(String[] args)
31-
throws IOException, InterruptedException, DescriptorValidationException {
24+
public static void main(String[] args) throws IOException {
3225
ExtensionRegistry registry = ExtensionRegistry.newInstance();
33-
registerAllExtensions(registry);
26+
ProtoRegistry.registerAllExtensions(registry);
3427
CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(System.in, registry);
3528
CodeGeneratorResponse response = Generator.generateGapic(request);
3629
response.writeTo(System.out);
3730
}
38-
39-
/** Register all extensions needed to process API protofiles. */
40-
private static void registerAllExtensions(ExtensionRegistry extensionRegistry) {
41-
OperationsProto.registerAllExtensions(extensionRegistry);
42-
AnnotationsProto.registerAllExtensions(extensionRegistry);
43-
ClientProto.registerAllExtensions(extensionRegistry);
44-
ResourceProto.registerAllExtensions(extensionRegistry);
45-
FieldBehaviorProto.registerAllExtensions(extensionRegistry);
46-
}
4731
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator;
16+
17+
import com.google.api.AnnotationsProto;
18+
import com.google.api.ClientProto;
19+
import com.google.api.FieldBehaviorProto;
20+
import com.google.api.ResourceProto;
21+
import com.google.longrunning.OperationsProto;
22+
import com.google.protobuf.ExtensionRegistry;
23+
24+
public class ProtoRegistry {
25+
/** Register all extensions needed to process API protofiles. */
26+
public static void registerAllExtensions(ExtensionRegistry extensionRegistry) {
27+
OperationsProto.registerAllExtensions(extensionRegistry);
28+
AnnotationsProto.registerAllExtensions(extensionRegistry);
29+
ClientProto.registerAllExtensions(extensionRegistry);
30+
ResourceProto.registerAllExtensions(extensionRegistry);
31+
FieldBehaviorProto.registerAllExtensions(extensionRegistry);
32+
}
33+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
load("@rules_java//java:defs.bzl", "java_library", "java_plugin")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
filegroup(
6+
name = "debug_files",
7+
srcs = glob(["*.java"]),
8+
)
9+
10+
java_library(
11+
name = "debug",
12+
srcs = [
13+
":debug_files",
14+
],
15+
deps = [
16+
"//src/main/java/com/google/api/generator",
17+
"//src/main/java/com/google/api/generator/engine",
18+
"//src/main/java/com/google/api/generator/engine/ast",
19+
"//src/main/java/com/google/api/generator/gapic",
20+
"//src/main/java/com/google/api/generator/gapic/model",
21+
"//src/main/java/com/google/api/generator/util",
22+
"@com_google_googleapis//google/api:api_java_proto",
23+
"@com_google_googleapis//google/longrunning:longrunning_java_proto",
24+
"@com_google_guava_guava//jar",
25+
"@com_google_protobuf//:protobuf_java",
26+
],
27+
)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.debug;
16+
17+
import com.google.api.generator.ProtoRegistry;
18+
import com.google.protobuf.ExtensionRegistry;
19+
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
20+
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
21+
import java.io.IOException;
22+
23+
// Request dumper class, which dumps the CodeGeneratorRequest to a file on disk which will be
24+
// identical to the one passed to the Main class during normal execution. The dumped file then can
25+
// be used to run this gapic-generator directly (instead of relying on protoc to start the process),
26+
// which would give much greater flexibility in terms of debugging features, like attaching a
27+
// debugger, easier work with stdout and stderr etc.
28+
public class CodeGeneratorRequestDumper {
29+
public static void main(String[] args) throws IOException {
30+
ExtensionRegistry registry = ExtensionRegistry.newInstance();
31+
ProtoRegistry.registerAllExtensions(registry);
32+
CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(System.in, registry);
33+
34+
CodeGeneratorResponse.Builder response = CodeGeneratorResponse.newBuilder();
35+
response
36+
.setSupportedFeatures(CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL_VALUE)
37+
.addFileBuilder()
38+
.setName("desc-dump.bin")
39+
.setContentBytes(request.toByteString());
40+
response.build().writeTo(System.out);
41+
}
42+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.api.generator.debug;
16+
17+
import com.google.api.generator.ProtoRegistry;
18+
import com.google.api.generator.gapic.Generator;
19+
import com.google.protobuf.ExtensionRegistry;
20+
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorRequest;
21+
import com.google.protobuf.compiler.PluginProtos.CodeGeneratorResponse;
22+
import java.io.FileInputStream;
23+
import java.io.FileOutputStream;
24+
import java.io.IOException;
25+
import java.io.InputStream;
26+
import java.io.OutputStream;
27+
28+
// A generator entry point class, similar to Main but reads the CodeGeneratorRequest directly from a
29+
// file instead of relying on protoc to pipe it in.
30+
public class CodeGeneratorRequestFileToGapicMain {
31+
public static void main(String[] args) throws IOException {
32+
ExtensionRegistry registry = ExtensionRegistry.newInstance();
33+
ProtoRegistry.registerAllExtensions(registry);
34+
35+
String inputFile = args[0];
36+
String outputFile = args[1];
37+
38+
try (InputStream inputStream = new FileInputStream(inputFile);
39+
OutputStream outputStream = new FileOutputStream(outputFile)) {
40+
CodeGeneratorRequest request = CodeGeneratorRequest.parseFrom(inputStream, registry);
41+
CodeGeneratorResponse response = Generator.generateGapic(request);
42+
response.writeTo(outputStream);
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)