1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
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
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.
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.
31
// Author: kenton@google.com (Kenton Varda)
32
// Based on original Protocol Buffers design by
33
// Sanjay Ghemawat, Jeff Dean, and others.
35
#include <google/protobuf/compiler/java/java_service.h>
36
#include <google/protobuf/compiler/java/java_helpers.h>
37
#include <google/protobuf/io/printer.h>
38
#include <google/protobuf/descriptor.pb.h>
39
#include <google/protobuf/stubs/strutil.h>
46
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor)
47
: descriptor_(descriptor) {}
49
ServiceGenerator::~ServiceGenerator() {}
51
void ServiceGenerator::Generate(io::Printer* printer) {
52
bool is_own_file = descriptor_->file()->options().java_multiple_files();
54
"public $static$ abstract class $classname$\n"
55
" implements com.google.protobuf.Service {\n",
56
"static", is_own_file ? "" : "static",
57
"classname", descriptor_->name());
61
"protected $classname$() {}\n\n",
62
"classname", descriptor_->name());
64
GenerateInterface(printer);
66
GenerateNewReflectiveServiceMethod(printer);
67
GenerateNewReflectiveBlockingServiceMethod(printer);
69
GenerateAbstractMethods(printer);
71
// Generate getDescriptor() and getDescriptorForType().
73
"public static final\n"
74
" com.google.protobuf.Descriptors.ServiceDescriptor\n"
75
" getDescriptor() {\n"
76
" return $file$.getDescriptor().getServices().get($index$);\n"
78
"file", ClassName(descriptor_->file()),
79
"index", SimpleItoa(descriptor_->index()));
80
GenerateGetDescriptorForType(printer);
82
// Generate more stuff.
83
GenerateCallMethod(printer);
84
GenerateGetPrototype(REQUEST, printer);
85
GenerateGetPrototype(RESPONSE, printer);
86
GenerateStub(printer);
87
GenerateBlockingStub(printer);
90
printer->Print("}\n\n");
93
void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) {
95
"public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
96
" getDescriptorForType() {\n"
97
" return getDescriptor();\n"
101
void ServiceGenerator::GenerateInterface(io::Printer* printer) {
102
printer->Print("public interface Interface {\n");
104
GenerateAbstractMethods(printer);
106
printer->Print("}\n\n");
109
void ServiceGenerator::GenerateNewReflectiveServiceMethod(
110
io::Printer* printer) {
112
"public static com.google.protobuf.Service newReflectiveService(\n"
113
" final Interface impl) {\n"
114
" return new $classname$() {\n",
115
"classname", descriptor_->name());
119
for (int i = 0; i < descriptor_->method_count(); i++) {
120
const MethodDescriptor* method = descriptor_->method(i);
121
printer->Print("@Override\n");
122
GenerateMethodSignature(printer, method, IS_CONCRETE);
125
" impl.$method$(controller, request, done);\n"
127
"method", UnderscoresToCamelCase(method));
131
printer->Print("};\n");
133
printer->Print("}\n\n");
136
void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
137
io::Printer* printer) {
139
"public static com.google.protobuf.BlockingService\n"
140
" newReflectiveBlockingService(final BlockingInterface impl) {\n"
141
" return new com.google.protobuf.BlockingService() {\n");
145
GenerateGetDescriptorForType(printer);
147
GenerateCallBlockingMethod(printer);
148
GenerateGetPrototype(REQUEST, printer);
149
GenerateGetPrototype(RESPONSE, printer);
152
printer->Print("};\n");
154
printer->Print("}\n\n");
157
void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
158
for (int i = 0; i < descriptor_->method_count(); i++) {
159
const MethodDescriptor* method = descriptor_->method(i);
160
GenerateMethodSignature(printer, method, IS_ABSTRACT);
161
printer->Print(";\n\n");
165
void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
168
"public final void callMethod(\n"
169
" com.google.protobuf.Descriptors.MethodDescriptor method,\n"
170
" com.google.protobuf.RpcController controller,\n"
171
" com.google.protobuf.Message request,\n"
172
" com.google.protobuf.RpcCallback<\n"
173
" com.google.protobuf.Message> done) {\n"
174
" if (method.getService() != getDescriptor()) {\n"
175
" throw new java.lang.IllegalArgumentException(\n"
176
" \"Service.callMethod() given method descriptor for wrong \" +\n"
177
" \"service type.\");\n"
179
" switch(method.getIndex()) {\n");
183
for (int i = 0; i < descriptor_->method_count(); i++) {
184
const MethodDescriptor* method = descriptor_->method(i);
185
map<string, string> vars;
186
vars["index"] = SimpleItoa(i);
187
vars["method"] = UnderscoresToCamelCase(method);
188
vars["input"] = ClassName(method->input_type());
189
vars["output"] = ClassName(method->output_type());
192
" this.$method$(controller, ($input$)request,\n"
193
" com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n"
200
" throw new java.lang.AssertionError(\"Can't get here.\");\n");
211
void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) {
214
"public final com.google.protobuf.Message callBlockingMethod(\n"
215
" com.google.protobuf.Descriptors.MethodDescriptor method,\n"
216
" com.google.protobuf.RpcController controller,\n"
217
" com.google.protobuf.Message request)\n"
218
" throws com.google.protobuf.ServiceException {\n"
219
" if (method.getService() != getDescriptor()) {\n"
220
" throw new java.lang.IllegalArgumentException(\n"
221
" \"Service.callBlockingMethod() given method descriptor for \" +\n"
222
" \"wrong service type.\");\n"
224
" switch(method.getIndex()) {\n");
228
for (int i = 0; i < descriptor_->method_count(); i++) {
229
const MethodDescriptor* method = descriptor_->method(i);
230
map<string, string> vars;
231
vars["index"] = SimpleItoa(i);
232
vars["method"] = UnderscoresToCamelCase(method);
233
vars["input"] = ClassName(method->input_type());
234
vars["output"] = ClassName(method->output_type());
237
" return impl.$method$(controller, ($input$)request);\n");
242
" throw new java.lang.AssertionError(\"Can't get here.\");\n");
253
void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
254
io::Printer* printer) {
256
* TODO(cpovirk): The exception message says "Service.foo" when it may be
257
* "BlockingService.foo." Consider fixing.
260
"public final com.google.protobuf.Message\n"
261
" get$request_or_response$Prototype(\n"
262
" com.google.protobuf.Descriptors.MethodDescriptor method) {\n"
263
" if (method.getService() != getDescriptor()) {\n"
264
" throw new java.lang.IllegalArgumentException(\n"
265
" \"Service.get$request_or_response$Prototype() given method \" +\n"
266
" \"descriptor for wrong service type.\");\n"
268
" switch(method.getIndex()) {\n",
269
"request_or_response", (which == REQUEST) ? "Request" : "Response");
273
for (int i = 0; i < descriptor_->method_count(); i++) {
274
const MethodDescriptor* method = descriptor_->method(i);
275
map<string, string> vars;
276
vars["index"] = SimpleItoa(i);
277
vars["type"] = ClassName(
278
(which == REQUEST) ? method->input_type() : method->output_type());
281
" return $type$.getDefaultInstance();\n");
286
" throw new java.lang.AssertionError(\"Can't get here.\");\n");
297
void ServiceGenerator::GenerateStub(io::Printer* printer) {
299
"public static Stub newStub(\n"
300
" com.google.protobuf.RpcChannel channel) {\n"
301
" return new Stub(channel);\n"
304
"public static final class Stub extends $classname$ implements Interface {"
306
"classname", ClassName(descriptor_));
310
"private Stub(com.google.protobuf.RpcChannel channel) {\n"
311
" this.channel = channel;\n"
314
"private final com.google.protobuf.RpcChannel channel;\n"
316
"public com.google.protobuf.RpcChannel getChannel() {\n"
320
for (int i = 0; i < descriptor_->method_count(); i++) {
321
const MethodDescriptor* method = descriptor_->method(i);
322
printer->Print("\n");
323
GenerateMethodSignature(printer, method, IS_CONCRETE);
324
printer->Print(" {\n");
327
map<string, string> vars;
328
vars["index"] = SimpleItoa(i);
329
vars["output"] = ClassName(method->output_type());
331
"channel.callMethod(\n"
332
" getDescriptor().getMethods().get($index$),\n"
335
" $output$.getDefaultInstance(),\n"
336
" com.google.protobuf.RpcUtil.generalizeCallback(\n"
339
" $output$.getDefaultInstance()));\n");
342
printer->Print("}\n");
351
void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
353
"public static BlockingInterface newBlockingStub(\n"
354
" com.google.protobuf.BlockingRpcChannel channel) {\n"
355
" return new BlockingStub(channel);\n"
360
"public interface BlockingInterface {");
363
for (int i = 0; i < descriptor_->method_count(); i++) {
364
const MethodDescriptor* method = descriptor_->method(i);
365
GenerateBlockingMethodSignature(printer, method);
366
printer->Print(";\n");
375
"private static final class BlockingStub implements BlockingInterface {\n");
379
"private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n"
380
" this.channel = channel;\n"
383
"private final com.google.protobuf.BlockingRpcChannel channel;\n");
385
for (int i = 0; i < descriptor_->method_count(); i++) {
386
const MethodDescriptor* method = descriptor_->method(i);
387
GenerateBlockingMethodSignature(printer, method);
388
printer->Print(" {\n");
391
map<string, string> vars;
392
vars["index"] = SimpleItoa(i);
393
vars["output"] = ClassName(method->output_type());
395
"return ($output$) channel.callBlockingMethod(\n"
396
" getDescriptor().getMethods().get($index$),\n"
399
" $output$.getDefaultInstance());\n");
408
printer->Print("}\n");
411
void ServiceGenerator::GenerateMethodSignature(io::Printer* printer,
412
const MethodDescriptor* method,
413
IsAbstract is_abstract) {
414
map<string, string> vars;
415
vars["name"] = UnderscoresToCamelCase(method);
416
vars["input"] = ClassName(method->input_type());
417
vars["output"] = ClassName(method->output_type());
418
vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
420
"public $abstract$ void $name$(\n"
421
" com.google.protobuf.RpcController controller,\n"
422
" $input$ request,\n"
423
" com.google.protobuf.RpcCallback<$output$> done)");
426
void ServiceGenerator::GenerateBlockingMethodSignature(
427
io::Printer* printer,
428
const MethodDescriptor* method) {
429
map<string, string> vars;
430
vars["method"] = UnderscoresToCamelCase(method);
431
vars["input"] = ClassName(method->input_type());
432
vars["output"] = ClassName(method->output_type());
435
"public $output$ $method$(\n"
436
" com.google.protobuf.RpcController controller,\n"
437
" $input$ request)\n"
438
" throws com.google.protobuf.ServiceException");
442
} // namespace compiler
443
} // namespace protobuf
444
} // namespace google