java_service.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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. // Author: kenton@google.com (Kenton Varda)
  31. // Based on original Protocol Buffers design by
  32. // Sanjay Ghemawat, Jeff Dean, and others.
  33. #include <google/protobuf/compiler/java/java_service.h>
  34. #include <google/protobuf/compiler/java/java_context.h>
  35. #include <google/protobuf/compiler/java/java_doc_comment.h>
  36. #include <google/protobuf/compiler/java/java_helpers.h>
  37. #include <google/protobuf/compiler/java/java_name_resolver.h>
  38. #include <google/protobuf/io/printer.h>
  39. #include <google/protobuf/stubs/strutil.h>
  40. namespace google {
  41. namespace protobuf {
  42. namespace compiler {
  43. namespace java {
  44. ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor)
  45. : descriptor_(descriptor) {}
  46. ServiceGenerator::~ServiceGenerator() {}
  47. // ===================================================================
  48. ImmutableServiceGenerator::ImmutableServiceGenerator(
  49. const ServiceDescriptor* descriptor, Context* context)
  50. : ServiceGenerator(descriptor), context_(context),
  51. name_resolver_(context->GetNameResolver()) {}
  52. ImmutableServiceGenerator::~ImmutableServiceGenerator() {}
  53. void ImmutableServiceGenerator::Generate(io::Printer* printer) {
  54. bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
  55. WriteServiceDocComment(printer, descriptor_);
  56. MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
  57. /* immutable = */ true);
  58. printer->Print(
  59. "public $static$ abstract class $classname$\n"
  60. " implements com.google.protobuf.Service {\n",
  61. "static", is_own_file ? "" : "static",
  62. "classname", descriptor_->name());
  63. printer->Indent();
  64. printer->Print(
  65. "protected $classname$() {}\n\n",
  66. "classname", descriptor_->name());
  67. GenerateInterface(printer);
  68. GenerateNewReflectiveServiceMethod(printer);
  69. GenerateNewReflectiveBlockingServiceMethod(printer);
  70. GenerateAbstractMethods(printer);
  71. // Generate getDescriptor() and getDescriptorForType().
  72. printer->Print(
  73. "public static final\n"
  74. " com.google.protobuf.Descriptors.ServiceDescriptor\n"
  75. " getDescriptor() {\n"
  76. " return $file$.getDescriptor().getServices().get($index$);\n"
  77. "}\n",
  78. "file", name_resolver_->GetImmutableClassName(descriptor_->file()),
  79. "index", SimpleItoa(descriptor_->index()));
  80. GenerateGetDescriptorForType(printer);
  81. // Generate more stuff.
  82. GenerateCallMethod(printer);
  83. GenerateGetPrototype(REQUEST, printer);
  84. GenerateGetPrototype(RESPONSE, printer);
  85. GenerateStub(printer);
  86. GenerateBlockingStub(printer);
  87. // Add an insertion point.
  88. printer->Print(
  89. "\n"
  90. "// @@protoc_insertion_point(class_scope:$full_name$)\n",
  91. "full_name", descriptor_->full_name());
  92. printer->Outdent();
  93. printer->Print("}\n\n");
  94. }
  95. void ImmutableServiceGenerator::GenerateGetDescriptorForType(
  96. io::Printer* printer) {
  97. printer->Print(
  98. "public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
  99. " getDescriptorForType() {\n"
  100. " return getDescriptor();\n"
  101. "}\n");
  102. }
  103. void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) {
  104. printer->Print("public interface Interface {\n");
  105. printer->Indent();
  106. GenerateAbstractMethods(printer);
  107. printer->Outdent();
  108. printer->Print("}\n\n");
  109. }
  110. void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod(
  111. io::Printer* printer) {
  112. printer->Print(
  113. "public static com.google.protobuf.Service newReflectiveService(\n"
  114. " final Interface impl) {\n"
  115. " return new $classname$() {\n",
  116. "classname", descriptor_->name());
  117. printer->Indent();
  118. printer->Indent();
  119. for (int i = 0; i < descriptor_->method_count(); i++) {
  120. const MethodDescriptor* method = descriptor_->method(i);
  121. printer->Print("@java.lang.Override\n");
  122. GenerateMethodSignature(printer, method, IS_CONCRETE);
  123. printer->Print(
  124. " {\n"
  125. " impl.$method$(controller, request, done);\n"
  126. "}\n\n",
  127. "method", UnderscoresToCamelCase(method));
  128. }
  129. printer->Outdent();
  130. printer->Print("};\n");
  131. printer->Outdent();
  132. printer->Print("}\n\n");
  133. }
  134. void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
  135. io::Printer* printer) {
  136. printer->Print(
  137. "public static com.google.protobuf.BlockingService\n"
  138. " newReflectiveBlockingService(final BlockingInterface impl) {\n"
  139. " return new com.google.protobuf.BlockingService() {\n");
  140. printer->Indent();
  141. printer->Indent();
  142. GenerateGetDescriptorForType(printer);
  143. GenerateCallBlockingMethod(printer);
  144. GenerateGetPrototype(REQUEST, printer);
  145. GenerateGetPrototype(RESPONSE, printer);
  146. printer->Outdent();
  147. printer->Print("};\n");
  148. printer->Outdent();
  149. printer->Print("}\n\n");
  150. }
  151. void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
  152. for (int i = 0; i < descriptor_->method_count(); i++) {
  153. const MethodDescriptor* method = descriptor_->method(i);
  154. WriteMethodDocComment(printer, method);
  155. GenerateMethodSignature(printer, method, IS_ABSTRACT);
  156. printer->Print(";\n\n");
  157. }
  158. }
  159. string ImmutableServiceGenerator::GetOutput(const MethodDescriptor* method) {
  160. return name_resolver_->GetImmutableClassName(method->output_type());
  161. }
  162. void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
  163. printer->Print(
  164. "\n"
  165. "public final void callMethod(\n"
  166. " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
  167. " com.google.protobuf.RpcController controller,\n"
  168. " com.google.protobuf.Message request,\n"
  169. " com.google.protobuf.RpcCallback<\n"
  170. " com.google.protobuf.Message> done) {\n"
  171. " if (method.getService() != getDescriptor()) {\n"
  172. " throw new java.lang.IllegalArgumentException(\n"
  173. " \"Service.callMethod() given method descriptor for wrong \" +\n"
  174. " \"service type.\");\n"
  175. " }\n"
  176. " switch(method.getIndex()) {\n");
  177. printer->Indent();
  178. printer->Indent();
  179. for (int i = 0; i < descriptor_->method_count(); i++) {
  180. const MethodDescriptor* method = descriptor_->method(i);
  181. std::map<string, string> vars;
  182. vars["index"] = SimpleItoa(i);
  183. vars["method"] = UnderscoresToCamelCase(method);
  184. vars["input"] = name_resolver_->GetImmutableClassName(
  185. method->input_type());
  186. vars["output"] = GetOutput(method);
  187. printer->Print(vars,
  188. "case $index$:\n"
  189. " this.$method$(controller, ($input$)request,\n"
  190. " com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n"
  191. " done));\n"
  192. " return;\n");
  193. }
  194. printer->Print(
  195. "default:\n"
  196. " throw new java.lang.AssertionError(\"Can't get here.\");\n");
  197. printer->Outdent();
  198. printer->Outdent();
  199. printer->Print(
  200. " }\n"
  201. "}\n"
  202. "\n");
  203. }
  204. void ImmutableServiceGenerator::GenerateCallBlockingMethod(
  205. io::Printer* printer) {
  206. printer->Print(
  207. "\n"
  208. "public final com.google.protobuf.Message callBlockingMethod(\n"
  209. " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
  210. " com.google.protobuf.RpcController controller,\n"
  211. " com.google.protobuf.Message request)\n"
  212. " throws com.google.protobuf.ServiceException {\n"
  213. " if (method.getService() != getDescriptor()) {\n"
  214. " throw new java.lang.IllegalArgumentException(\n"
  215. " \"Service.callBlockingMethod() given method descriptor for \" +\n"
  216. " \"wrong service type.\");\n"
  217. " }\n"
  218. " switch(method.getIndex()) {\n");
  219. printer->Indent();
  220. printer->Indent();
  221. for (int i = 0; i < descriptor_->method_count(); i++) {
  222. const MethodDescriptor* method = descriptor_->method(i);
  223. std::map<string, string> vars;
  224. vars["index"] = SimpleItoa(i);
  225. vars["method"] = UnderscoresToCamelCase(method);
  226. vars["input"] = name_resolver_->GetImmutableClassName(
  227. method->input_type());
  228. vars["output"] = GetOutput(method);
  229. printer->Print(vars,
  230. "case $index$:\n"
  231. " return impl.$method$(controller, ($input$)request);\n");
  232. }
  233. printer->Print(
  234. "default:\n"
  235. " throw new java.lang.AssertionError(\"Can't get here.\");\n");
  236. printer->Outdent();
  237. printer->Outdent();
  238. printer->Print(
  239. " }\n"
  240. "}\n"
  241. "\n");
  242. }
  243. void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
  244. io::Printer* printer) {
  245. /*
  246. * TODO(cpovirk): The exception message says "Service.foo" when it may be
  247. * "BlockingService.foo." Consider fixing.
  248. */
  249. printer->Print(
  250. "public final com.google.protobuf.Message\n"
  251. " get$request_or_response$Prototype(\n"
  252. " com.google.protobuf.Descriptors.MethodDescriptor method) {\n"
  253. " if (method.getService() != getDescriptor()) {\n"
  254. " throw new java.lang.IllegalArgumentException(\n"
  255. " \"Service.get$request_or_response$Prototype() given method \" +\n"
  256. " \"descriptor for wrong service type.\");\n"
  257. " }\n"
  258. " switch(method.getIndex()) {\n",
  259. "request_or_response", (which == REQUEST) ? "Request" : "Response");
  260. printer->Indent();
  261. printer->Indent();
  262. for (int i = 0; i < descriptor_->method_count(); i++) {
  263. const MethodDescriptor* method = descriptor_->method(i);
  264. std::map<string, string> vars;
  265. vars["index"] = SimpleItoa(i);
  266. vars["type"] = name_resolver_->GetImmutableClassName(
  267. (which == REQUEST) ? method->input_type() : method->output_type());
  268. printer->Print(vars,
  269. "case $index$:\n"
  270. " return $type$.getDefaultInstance();\n");
  271. }
  272. printer->Print(
  273. "default:\n"
  274. " throw new java.lang.AssertionError(\"Can't get here.\");\n");
  275. printer->Outdent();
  276. printer->Outdent();
  277. printer->Print(
  278. " }\n"
  279. "}\n"
  280. "\n");
  281. }
  282. void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) {
  283. printer->Print(
  284. "public static Stub newStub(\n"
  285. " com.google.protobuf.RpcChannel channel) {\n"
  286. " return new Stub(channel);\n"
  287. "}\n"
  288. "\n"
  289. "public static final class Stub extends $classname$ implements Interface {"
  290. "\n",
  291. "classname", name_resolver_->GetImmutableClassName(descriptor_));
  292. printer->Indent();
  293. printer->Print(
  294. "private Stub(com.google.protobuf.RpcChannel channel) {\n"
  295. " this.channel = channel;\n"
  296. "}\n"
  297. "\n"
  298. "private final com.google.protobuf.RpcChannel channel;\n"
  299. "\n"
  300. "public com.google.protobuf.RpcChannel getChannel() {\n"
  301. " return channel;\n"
  302. "}\n");
  303. for (int i = 0; i < descriptor_->method_count(); i++) {
  304. const MethodDescriptor* method = descriptor_->method(i);
  305. printer->Print("\n");
  306. GenerateMethodSignature(printer, method, IS_CONCRETE);
  307. printer->Print(" {\n");
  308. printer->Indent();
  309. std::map<string, string> vars;
  310. vars["index"] = SimpleItoa(i);
  311. vars["output"] = GetOutput(method);
  312. printer->Print(vars,
  313. "channel.callMethod(\n"
  314. " getDescriptor().getMethods().get($index$),\n"
  315. " controller,\n"
  316. " request,\n"
  317. " $output$.getDefaultInstance(),\n"
  318. " com.google.protobuf.RpcUtil.generalizeCallback(\n"
  319. " done,\n"
  320. " $output$.class,\n"
  321. " $output$.getDefaultInstance()));\n");
  322. printer->Outdent();
  323. printer->Print("}\n");
  324. }
  325. printer->Outdent();
  326. printer->Print(
  327. "}\n"
  328. "\n");
  329. }
  330. void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
  331. printer->Print(
  332. "public static BlockingInterface newBlockingStub(\n"
  333. " com.google.protobuf.BlockingRpcChannel channel) {\n"
  334. " return new BlockingStub(channel);\n"
  335. "}\n"
  336. "\n");
  337. printer->Print(
  338. "public interface BlockingInterface {");
  339. printer->Indent();
  340. for (int i = 0; i < descriptor_->method_count(); i++) {
  341. const MethodDescriptor* method = descriptor_->method(i);
  342. GenerateBlockingMethodSignature(printer, method);
  343. printer->Print(";\n");
  344. }
  345. printer->Outdent();
  346. printer->Print(
  347. "}\n"
  348. "\n");
  349. printer->Print(
  350. "private static final class BlockingStub implements BlockingInterface {\n");
  351. printer->Indent();
  352. printer->Print(
  353. "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n"
  354. " this.channel = channel;\n"
  355. "}\n"
  356. "\n"
  357. "private final com.google.protobuf.BlockingRpcChannel channel;\n");
  358. for (int i = 0; i < descriptor_->method_count(); i++) {
  359. const MethodDescriptor* method = descriptor_->method(i);
  360. GenerateBlockingMethodSignature(printer, method);
  361. printer->Print(" {\n");
  362. printer->Indent();
  363. std::map<string, string> vars;
  364. vars["index"] = SimpleItoa(i);
  365. vars["output"] = GetOutput(method);
  366. printer->Print(vars,
  367. "return ($output$) channel.callBlockingMethod(\n"
  368. " getDescriptor().getMethods().get($index$),\n"
  369. " controller,\n"
  370. " request,\n"
  371. " $output$.getDefaultInstance());\n");
  372. printer->Outdent();
  373. printer->Print(
  374. "}\n"
  375. "\n");
  376. }
  377. printer->Outdent();
  378. printer->Print("}\n");
  379. }
  380. void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer,
  381. const MethodDescriptor* method,
  382. IsAbstract is_abstract) {
  383. std::map<string, string> vars;
  384. vars["name"] = UnderscoresToCamelCase(method);
  385. vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
  386. vars["output"] = GetOutput(method);
  387. vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
  388. printer->Print(vars,
  389. "public $abstract$ void $name$(\n"
  390. " com.google.protobuf.RpcController controller,\n"
  391. " $input$ request,\n"
  392. " com.google.protobuf.RpcCallback<$output$> done)");
  393. }
  394. void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
  395. io::Printer* printer,
  396. const MethodDescriptor* method) {
  397. std::map<string, string> vars;
  398. vars["method"] = UnderscoresToCamelCase(method);
  399. vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
  400. vars["output"] = GetOutput(method);
  401. printer->Print(vars,
  402. "\n"
  403. "public $output$ $method$(\n"
  404. " com.google.protobuf.RpcController controller,\n"
  405. " $input$ request)\n"
  406. " throws com.google.protobuf.ServiceException");
  407. }
  408. } // namespace java
  409. } // namespace compiler
  410. } // namespace protobuf
  411. } // namespace google