PageRenderTime 84ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/google/protobuf/compiler/java/java_service.cc

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