Line data Source code
1 : // Protocol Buffers - Google's data interchange format
2 : // Copyright 2008 Google Inc. All rights reserved.
3 : // https://developers.google.com/protocol-buffers/
4 : //
5 : // Redistribution and use in source and binary forms, with or without
6 : // modification, are permitted provided that the following conditions are
7 : // met:
8 : //
9 : // * Redistributions of source code must retain the above copyright
10 : // notice, this list of conditions and the following disclaimer.
11 : // * Redistributions in binary form must reproduce the above
12 : // copyright notice, this list of conditions and the following disclaimer
13 : // in the documentation and/or other materials provided with the
14 : // distribution.
15 : // * Neither the name of Google Inc. nor the names of its
16 : // contributors may be used to endorse or promote products derived from
17 : // this software without specific prior written permission.
18 : //
19 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 :
31 : // Author: kenton@google.com (Kenton Varda)
32 : // Based on original Protocol Buffers design by
33 : // Sanjay Ghemawat, Jeff Dean, and others.
34 :
35 : #include <google/protobuf/compiler/java/java_service.h>
36 :
37 : #include <google/protobuf/compiler/java/java_context.h>
38 : #include <google/protobuf/compiler/java/java_doc_comment.h>
39 : #include <google/protobuf/compiler/java/java_helpers.h>
40 : #include <google/protobuf/compiler/java/java_name_resolver.h>
41 : #include <google/protobuf/io/printer.h>
42 : #include <google/protobuf/stubs/strutil.h>
43 :
44 : namespace google {
45 : namespace protobuf {
46 : namespace compiler {
47 : namespace java {
48 :
49 0 : ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor)
50 0 : : descriptor_(descriptor) {}
51 :
52 0 : ServiceGenerator::~ServiceGenerator() {}
53 :
54 : // ===================================================================
55 0 : ImmutableServiceGenerator::ImmutableServiceGenerator(
56 : const ServiceDescriptor* descriptor, Context* context)
57 : : ServiceGenerator(descriptor), context_(context),
58 0 : name_resolver_(context->GetNameResolver()) {}
59 :
60 0 : ImmutableServiceGenerator::~ImmutableServiceGenerator() {}
61 :
62 0 : void ImmutableServiceGenerator::Generate(io::Printer* printer) {
63 : bool is_own_file =
64 0 : MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
65 0 : WriteServiceDocComment(printer, descriptor_);
66 : printer->Print(
67 : "public $static$ abstract class $classname$\n"
68 : " implements com.google.protobuf.Service {\n",
69 : "static", is_own_file ? "" : "static",
70 0 : "classname", descriptor_->name());
71 0 : printer->Indent();
72 :
73 : printer->Print(
74 : "protected $classname$() {}\n\n",
75 0 : "classname", descriptor_->name());
76 :
77 0 : GenerateInterface(printer);
78 :
79 0 : GenerateNewReflectiveServiceMethod(printer);
80 0 : GenerateNewReflectiveBlockingServiceMethod(printer);
81 :
82 0 : GenerateAbstractMethods(printer);
83 :
84 : // Generate getDescriptor() and getDescriptorForType().
85 : printer->Print(
86 : "public static final\n"
87 : " com.google.protobuf.Descriptors.ServiceDescriptor\n"
88 : " getDescriptor() {\n"
89 : " return $file$.getDescriptor().getServices().get($index$);\n"
90 : "}\n",
91 : "file", name_resolver_->GetImmutableClassName(descriptor_->file()),
92 0 : "index", SimpleItoa(descriptor_->index()));
93 0 : GenerateGetDescriptorForType(printer);
94 :
95 : // Generate more stuff.
96 0 : GenerateCallMethod(printer);
97 0 : GenerateGetPrototype(REQUEST, printer);
98 0 : GenerateGetPrototype(RESPONSE, printer);
99 0 : GenerateStub(printer);
100 0 : GenerateBlockingStub(printer);
101 :
102 : // Add an insertion point.
103 : printer->Print(
104 : "\n"
105 : "// @@protoc_insertion_point(class_scope:$full_name$)\n",
106 0 : "full_name", descriptor_->full_name());
107 :
108 0 : printer->Outdent();
109 0 : printer->Print("}\n\n");
110 0 : }
111 :
112 0 : void ImmutableServiceGenerator::GenerateGetDescriptorForType(
113 : io::Printer* printer) {
114 : printer->Print(
115 : "public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
116 : " getDescriptorForType() {\n"
117 : " return getDescriptor();\n"
118 0 : "}\n");
119 0 : }
120 :
121 0 : void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) {
122 0 : printer->Print("public interface Interface {\n");
123 0 : printer->Indent();
124 0 : GenerateAbstractMethods(printer);
125 0 : printer->Outdent();
126 0 : printer->Print("}\n\n");
127 0 : }
128 :
129 0 : void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod(
130 : io::Printer* printer) {
131 : printer->Print(
132 : "public static com.google.protobuf.Service newReflectiveService(\n"
133 : " final Interface impl) {\n"
134 : " return new $classname$() {\n",
135 0 : "classname", descriptor_->name());
136 0 : printer->Indent();
137 0 : printer->Indent();
138 :
139 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
140 0 : const MethodDescriptor* method = descriptor_->method(i);
141 0 : printer->Print("@java.lang.Override\n");
142 0 : GenerateMethodSignature(printer, method, IS_CONCRETE);
143 : printer->Print(
144 : " {\n"
145 : " impl.$method$(controller, request, done);\n"
146 : "}\n\n",
147 0 : "method", UnderscoresToCamelCase(method));
148 : }
149 :
150 0 : printer->Outdent();
151 0 : printer->Print("};\n");
152 0 : printer->Outdent();
153 0 : printer->Print("}\n\n");
154 0 : }
155 :
156 0 : void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
157 : io::Printer* printer) {
158 : printer->Print(
159 : "public static com.google.protobuf.BlockingService\n"
160 : " newReflectiveBlockingService(final BlockingInterface impl) {\n"
161 0 : " return new com.google.protobuf.BlockingService() {\n");
162 0 : printer->Indent();
163 0 : printer->Indent();
164 :
165 0 : GenerateGetDescriptorForType(printer);
166 :
167 0 : GenerateCallBlockingMethod(printer);
168 0 : GenerateGetPrototype(REQUEST, printer);
169 0 : GenerateGetPrototype(RESPONSE, printer);
170 :
171 0 : printer->Outdent();
172 0 : printer->Print("};\n");
173 0 : printer->Outdent();
174 0 : printer->Print("}\n\n");
175 0 : }
176 :
177 0 : void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
178 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
179 0 : const MethodDescriptor* method = descriptor_->method(i);
180 0 : WriteMethodDocComment(printer, method);
181 0 : GenerateMethodSignature(printer, method, IS_ABSTRACT);
182 0 : printer->Print(";\n\n");
183 : }
184 0 : }
185 :
186 0 : void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
187 : printer->Print(
188 : "\n"
189 : "public final void callMethod(\n"
190 : " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
191 : " com.google.protobuf.RpcController controller,\n"
192 : " com.google.protobuf.Message request,\n"
193 : " com.google.protobuf.RpcCallback<\n"
194 : " com.google.protobuf.Message> done) {\n"
195 : " if (method.getService() != getDescriptor()) {\n"
196 : " throw new java.lang.IllegalArgumentException(\n"
197 : " \"Service.callMethod() given method descriptor for wrong \" +\n"
198 : " \"service type.\");\n"
199 : " }\n"
200 0 : " switch(method.getIndex()) {\n");
201 0 : printer->Indent();
202 0 : printer->Indent();
203 :
204 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
205 0 : const MethodDescriptor* method = descriptor_->method(i);
206 : map<string, string> vars;
207 0 : vars["index"] = SimpleItoa(i);
208 0 : vars["method"] = UnderscoresToCamelCase(method);
209 0 : vars["input"] = name_resolver_->GetImmutableClassName(
210 : method->input_type());
211 0 : vars["output"] = name_resolver_->GetImmutableClassName(
212 : method->output_type());
213 : printer->Print(vars,
214 : "case $index$:\n"
215 : " this.$method$(controller, ($input$)request,\n"
216 : " com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n"
217 : " done));\n"
218 0 : " return;\n");
219 : }
220 :
221 : printer->Print(
222 : "default:\n"
223 0 : " throw new java.lang.AssertionError(\"Can't get here.\");\n");
224 :
225 0 : printer->Outdent();
226 0 : printer->Outdent();
227 :
228 : printer->Print(
229 : " }\n"
230 : "}\n"
231 0 : "\n");
232 0 : }
233 :
234 0 : void ImmutableServiceGenerator::GenerateCallBlockingMethod(
235 : io::Printer* printer) {
236 : printer->Print(
237 : "\n"
238 : "public final com.google.protobuf.Message callBlockingMethod(\n"
239 : " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
240 : " com.google.protobuf.RpcController controller,\n"
241 : " com.google.protobuf.Message request)\n"
242 : " throws com.google.protobuf.ServiceException {\n"
243 : " if (method.getService() != getDescriptor()) {\n"
244 : " throw new java.lang.IllegalArgumentException(\n"
245 : " \"Service.callBlockingMethod() given method descriptor for \" +\n"
246 : " \"wrong service type.\");\n"
247 : " }\n"
248 0 : " switch(method.getIndex()) {\n");
249 0 : printer->Indent();
250 0 : printer->Indent();
251 :
252 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
253 0 : const MethodDescriptor* method = descriptor_->method(i);
254 : map<string, string> vars;
255 0 : vars["index"] = SimpleItoa(i);
256 0 : vars["method"] = UnderscoresToCamelCase(method);
257 0 : vars["input"] = name_resolver_->GetImmutableClassName(
258 : method->input_type());
259 0 : vars["output"] = name_resolver_->GetImmutableClassName(
260 : method->output_type());
261 : printer->Print(vars,
262 : "case $index$:\n"
263 0 : " return impl.$method$(controller, ($input$)request);\n");
264 : }
265 :
266 : printer->Print(
267 : "default:\n"
268 0 : " throw new java.lang.AssertionError(\"Can't get here.\");\n");
269 :
270 0 : printer->Outdent();
271 0 : printer->Outdent();
272 :
273 : printer->Print(
274 : " }\n"
275 : "}\n"
276 0 : "\n");
277 0 : }
278 :
279 0 : void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
280 : io::Printer* printer) {
281 : /*
282 : * TODO(cpovirk): The exception message says "Service.foo" when it may be
283 : * "BlockingService.foo." Consider fixing.
284 : */
285 : printer->Print(
286 : "public final com.google.protobuf.Message\n"
287 : " get$request_or_response$Prototype(\n"
288 : " com.google.protobuf.Descriptors.MethodDescriptor method) {\n"
289 : " if (method.getService() != getDescriptor()) {\n"
290 : " throw new java.lang.IllegalArgumentException(\n"
291 : " \"Service.get$request_or_response$Prototype() given method \" +\n"
292 : " \"descriptor for wrong service type.\");\n"
293 : " }\n"
294 : " switch(method.getIndex()) {\n",
295 0 : "request_or_response", (which == REQUEST) ? "Request" : "Response");
296 0 : printer->Indent();
297 0 : printer->Indent();
298 :
299 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
300 0 : const MethodDescriptor* method = descriptor_->method(i);
301 : map<string, string> vars;
302 0 : vars["index"] = SimpleItoa(i);
303 0 : vars["type"] = name_resolver_->GetImmutableClassName(
304 : (which == REQUEST) ? method->input_type() : method->output_type());
305 : printer->Print(vars,
306 : "case $index$:\n"
307 0 : " return $type$.getDefaultInstance();\n");
308 : }
309 :
310 : printer->Print(
311 : "default:\n"
312 0 : " throw new java.lang.AssertionError(\"Can't get here.\");\n");
313 :
314 0 : printer->Outdent();
315 0 : printer->Outdent();
316 :
317 : printer->Print(
318 : " }\n"
319 : "}\n"
320 0 : "\n");
321 0 : }
322 :
323 0 : void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) {
324 : printer->Print(
325 : "public static Stub newStub(\n"
326 : " com.google.protobuf.RpcChannel channel) {\n"
327 : " return new Stub(channel);\n"
328 : "}\n"
329 : "\n"
330 : "public static final class Stub extends $classname$ implements Interface {"
331 : "\n",
332 0 : "classname", name_resolver_->GetImmutableClassName(descriptor_));
333 0 : printer->Indent();
334 :
335 : printer->Print(
336 : "private Stub(com.google.protobuf.RpcChannel channel) {\n"
337 : " this.channel = channel;\n"
338 : "}\n"
339 : "\n"
340 : "private final com.google.protobuf.RpcChannel channel;\n"
341 : "\n"
342 : "public com.google.protobuf.RpcChannel getChannel() {\n"
343 : " return channel;\n"
344 0 : "}\n");
345 :
346 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
347 0 : const MethodDescriptor* method = descriptor_->method(i);
348 0 : printer->Print("\n");
349 0 : GenerateMethodSignature(printer, method, IS_CONCRETE);
350 0 : printer->Print(" {\n");
351 0 : printer->Indent();
352 :
353 : map<string, string> vars;
354 0 : vars["index"] = SimpleItoa(i);
355 0 : vars["output"] = name_resolver_->GetImmutableClassName(
356 : method->output_type());
357 : printer->Print(vars,
358 : "channel.callMethod(\n"
359 : " getDescriptor().getMethods().get($index$),\n"
360 : " controller,\n"
361 : " request,\n"
362 : " $output$.getDefaultInstance(),\n"
363 : " com.google.protobuf.RpcUtil.generalizeCallback(\n"
364 : " done,\n"
365 : " $output$.class,\n"
366 0 : " $output$.getDefaultInstance()));\n");
367 :
368 0 : printer->Outdent();
369 0 : printer->Print("}\n");
370 : }
371 :
372 0 : printer->Outdent();
373 : printer->Print(
374 : "}\n"
375 0 : "\n");
376 0 : }
377 :
378 0 : void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
379 : printer->Print(
380 : "public static BlockingInterface newBlockingStub(\n"
381 : " com.google.protobuf.BlockingRpcChannel channel) {\n"
382 : " return new BlockingStub(channel);\n"
383 : "}\n"
384 0 : "\n");
385 :
386 : printer->Print(
387 0 : "public interface BlockingInterface {");
388 0 : printer->Indent();
389 :
390 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
391 0 : const MethodDescriptor* method = descriptor_->method(i);
392 0 : GenerateBlockingMethodSignature(printer, method);
393 0 : printer->Print(";\n");
394 : }
395 :
396 0 : printer->Outdent();
397 : printer->Print(
398 : "}\n"
399 0 : "\n");
400 :
401 : printer->Print(
402 0 : "private static final class BlockingStub implements BlockingInterface {\n");
403 0 : printer->Indent();
404 :
405 : printer->Print(
406 : "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n"
407 : " this.channel = channel;\n"
408 : "}\n"
409 : "\n"
410 0 : "private final com.google.protobuf.BlockingRpcChannel channel;\n");
411 :
412 0 : for (int i = 0; i < descriptor_->method_count(); i++) {
413 0 : const MethodDescriptor* method = descriptor_->method(i);
414 0 : GenerateBlockingMethodSignature(printer, method);
415 0 : printer->Print(" {\n");
416 0 : printer->Indent();
417 :
418 : map<string, string> vars;
419 0 : vars["index"] = SimpleItoa(i);
420 0 : vars["output"] = name_resolver_->GetImmutableClassName(
421 : method->output_type());
422 : printer->Print(vars,
423 : "return ($output$) channel.callBlockingMethod(\n"
424 : " getDescriptor().getMethods().get($index$),\n"
425 : " controller,\n"
426 : " request,\n"
427 0 : " $output$.getDefaultInstance());\n");
428 :
429 0 : printer->Outdent();
430 : printer->Print(
431 : "}\n"
432 0 : "\n");
433 : }
434 :
435 0 : printer->Outdent();
436 0 : printer->Print("}\n");
437 0 : }
438 :
439 0 : void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer,
440 0 : const MethodDescriptor* method,
441 : IsAbstract is_abstract) {
442 : map<string, string> vars;
443 0 : vars["name"] = UnderscoresToCamelCase(method);
444 0 : vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
445 0 : vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
446 0 : vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
447 : printer->Print(vars,
448 : "public $abstract$ void $name$(\n"
449 : " com.google.protobuf.RpcController controller,\n"
450 : " $input$ request,\n"
451 0 : " com.google.protobuf.RpcCallback<$output$> done)");
452 0 : }
453 :
454 0 : void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
455 : io::Printer* printer,
456 0 : const MethodDescriptor* method) {
457 : map<string, string> vars;
458 0 : vars["method"] = UnderscoresToCamelCase(method);
459 0 : vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
460 0 : vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
461 : printer->Print(vars,
462 : "\n"
463 : "public $output$ $method$(\n"
464 : " com.google.protobuf.RpcController controller,\n"
465 : " $input$ request)\n"
466 0 : " throws com.google.protobuf.ServiceException");
467 0 : }
468 :
469 : } // namespace java
470 : } // namespace compiler
471 : } // namespace protobuf
472 : } // namespace google
|