PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://protobuf.googlecode.com/
C++ | 490 lines | 329 code | 63 blank | 98 comment | 56 complexity | fd9e9d7f9302711db4675878c53b28e2 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_file.h>
  34. #include <google/protobuf/compiler/java/java_enum.h>
  35. #include <google/protobuf/compiler/java/java_service.h>
  36. #include <google/protobuf/compiler/java/java_extension.h>
  37. #include <google/protobuf/compiler/java/java_helpers.h>
  38. #include <google/protobuf/compiler/java/java_message.h>
  39. #include <google/protobuf/compiler/code_generator.h>
  40. #include <google/protobuf/io/printer.h>
  41. #include <google/protobuf/io/zero_copy_stream.h>
  42. #include <google/protobuf/descriptor.pb.h>
  43. #include <google/protobuf/dynamic_message.h>
  44. #include <google/protobuf/stubs/strutil.h>
  45. namespace google {
  46. namespace protobuf {
  47. namespace compiler {
  48. namespace java {
  49. namespace {
  50. // Recursively searches the given message to collect extensions.
  51. // Returns true if all the extensions can be recognized. The extensions will be
  52. // appended in to the extensions parameter.
  53. // Returns false when there are unknown fields, in which case the data in the
  54. // extensions output parameter is not reliable and should be discarded.
  55. bool CollectExtensions(const Message& message,
  56. vector<const FieldDescriptor*>* extensions) {
  57. const Reflection* reflection = message.GetReflection();
  58. // There are unknown fields that could be extensions, thus this call fails.
  59. if (reflection->GetUnknownFields(message).field_count() > 0) return false;
  60. vector<const FieldDescriptor*> fields;
  61. reflection->ListFields(message, &fields);
  62. for (int i = 0; i < fields.size(); i++) {
  63. if (fields[i]->is_extension()) extensions->push_back(fields[i]);
  64. if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
  65. if (fields[i]->is_repeated()) {
  66. int size = reflection->FieldSize(message, fields[i]);
  67. for (int j = 0; j < size; j++) {
  68. const Message& sub_message =
  69. reflection->GetRepeatedMessage(message, fields[i], j);
  70. if (!CollectExtensions(sub_message, extensions)) return false;
  71. }
  72. } else {
  73. const Message& sub_message = reflection->GetMessage(message, fields[i]);
  74. if (!CollectExtensions(sub_message, extensions)) return false;
  75. }
  76. }
  77. }
  78. return true;
  79. }
  80. // Finds all extensions in the given message and its sub-messages. If the
  81. // message contains unknown fields (which could be extensions), then those
  82. // extensions are defined in alternate_pool.
  83. // The message will be converted to a DynamicMessage backed by alternate_pool
  84. // in order to handle this case.
  85. void CollectExtensions(const FileDescriptorProto& file_proto,
  86. const DescriptorPool& alternate_pool,
  87. vector<const FieldDescriptor*>* extensions,
  88. const string& file_data) {
  89. if (!CollectExtensions(file_proto, extensions)) {
  90. // There are unknown fields in the file_proto, which are probably
  91. // extensions. We need to parse the data into a dynamic message based on the
  92. // builder-pool to find out all extensions.
  93. const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
  94. file_proto.GetDescriptor()->full_name());
  95. GOOGLE_CHECK(file_proto_desc)
  96. << "Find unknown fields in FileDescriptorProto when building "
  97. << file_proto.name()
  98. << ". It's likely that those fields are custom options, however, "
  99. "descriptor.proto is not in the transitive dependencies. "
  100. "This normally should not happen. Please report a bug.";
  101. DynamicMessageFactory factory;
  102. scoped_ptr<Message> dynamic_file_proto(
  103. factory.GetPrototype(file_proto_desc)->New());
  104. GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
  105. GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
  106. // Collect the extensions again from the dynamic message. There should be no
  107. // more unknown fields this time, i.e. all the custom options should be
  108. // parsed as extensions now.
  109. extensions->clear();
  110. GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
  111. << "Find unknown fields in FileDescriptorProto when building "
  112. << file_proto.name()
  113. << ". It's likely that those fields are custom options, however, "
  114. "those options cannot be recognized in the builder pool. "
  115. "This normally should not happen. Please report a bug.";
  116. }
  117. }
  118. } // namespace
  119. FileGenerator::FileGenerator(const FileDescriptor* file)
  120. : file_(file),
  121. java_package_(FileJavaPackage(file)),
  122. classname_(FileClassName(file)) {
  123. }
  124. FileGenerator::~FileGenerator() {}
  125. bool FileGenerator::Validate(string* error) {
  126. // Check that no class name matches the file's class name. This is a common
  127. // problem that leads to Java compile errors that can be hard to understand.
  128. // It's especially bad when using the java_multiple_files, since we would
  129. // end up overwriting the outer class with one of the inner ones.
  130. bool found_conflict = false;
  131. for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) {
  132. if (file_->enum_type(i)->name() == classname_) {
  133. found_conflict = true;
  134. }
  135. }
  136. for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) {
  137. if (file_->message_type(i)->name() == classname_) {
  138. found_conflict = true;
  139. }
  140. }
  141. for (int i = 0; i < file_->service_count() && !found_conflict; i++) {
  142. if (file_->service(i)->name() == classname_) {
  143. found_conflict = true;
  144. }
  145. }
  146. if (found_conflict) {
  147. error->assign(file_->name());
  148. error->append(
  149. ": Cannot generate Java output because the file's outer class name, \"");
  150. error->append(classname_);
  151. error->append(
  152. "\", matches the name of one of the types declared inside it. "
  153. "Please either rename the type or use the java_outer_classname "
  154. "option to specify a different outer class name for the .proto file.");
  155. return false;
  156. }
  157. return true;
  158. }
  159. void FileGenerator::Generate(io::Printer* printer) {
  160. // We don't import anything because we refer to all classes by their
  161. // fully-qualified names in the generated source.
  162. printer->Print(
  163. "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
  164. "// source: $filename$\n"
  165. "\n",
  166. "filename", file_->name());
  167. if (!java_package_.empty()) {
  168. printer->Print(
  169. "package $package$;\n"
  170. "\n",
  171. "package", java_package_);
  172. }
  173. printer->Print(
  174. "public final class $classname$ {\n"
  175. " private $classname$() {}\n",
  176. "classname", classname_);
  177. printer->Indent();
  178. // -----------------------------------------------------------------
  179. printer->Print(
  180. "public static void registerAllExtensions(\n"
  181. " com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
  182. "lite", HasDescriptorMethods(file_) ? "" : "Lite");
  183. printer->Indent();
  184. for (int i = 0; i < file_->extension_count(); i++) {
  185. ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer);
  186. }
  187. for (int i = 0; i < file_->message_type_count(); i++) {
  188. MessageGenerator(file_->message_type(i))
  189. .GenerateExtensionRegistrationCode(printer);
  190. }
  191. printer->Outdent();
  192. printer->Print(
  193. "}\n");
  194. // -----------------------------------------------------------------
  195. if (!file_->options().java_multiple_files()) {
  196. for (int i = 0; i < file_->enum_type_count(); i++) {
  197. EnumGenerator(file_->enum_type(i)).Generate(printer);
  198. }
  199. for (int i = 0; i < file_->message_type_count(); i++) {
  200. MessageGenerator messageGenerator(file_->message_type(i));
  201. messageGenerator.GenerateInterface(printer);
  202. messageGenerator.Generate(printer);
  203. }
  204. if (HasGenericServices(file_)) {
  205. for (int i = 0; i < file_->service_count(); i++) {
  206. ServiceGenerator(file_->service(i)).Generate(printer);
  207. }
  208. }
  209. }
  210. // Extensions must be generated in the outer class since they are values,
  211. // not classes.
  212. for (int i = 0; i < file_->extension_count(); i++) {
  213. ExtensionGenerator(file_->extension(i)).Generate(printer);
  214. }
  215. // Static variables.
  216. for (int i = 0; i < file_->message_type_count(); i++) {
  217. // TODO(kenton): Reuse MessageGenerator objects?
  218. MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer);
  219. }
  220. printer->Print("\n");
  221. if (HasDescriptorMethods(file_)) {
  222. GenerateEmbeddedDescriptor(printer);
  223. } else {
  224. printer->Print(
  225. "static {\n");
  226. printer->Indent();
  227. for (int i = 0; i < file_->message_type_count(); i++) {
  228. // TODO(kenton): Reuse MessageGenerator objects?
  229. MessageGenerator(file_->message_type(i))
  230. .GenerateStaticVariableInitializers(printer);
  231. }
  232. printer->Outdent();
  233. printer->Print(
  234. "}\n");
  235. }
  236. printer->Print(
  237. "\n"
  238. "// @@protoc_insertion_point(outer_class_scope)\n");
  239. printer->Outdent();
  240. printer->Print("}\n");
  241. }
  242. void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
  243. // Embed the descriptor. We simply serialize the entire FileDescriptorProto
  244. // and embed it as a string literal, which is parsed and built into real
  245. // descriptors at initialization time. We unfortunately have to put it in
  246. // a string literal, not a byte array, because apparently using a literal
  247. // byte array causes the Java compiler to generate *instructions* to
  248. // initialize each and every byte of the array, e.g. as if you typed:
  249. // b[0] = 123; b[1] = 456; b[2] = 789;
  250. // This makes huge bytecode files and can easily hit the compiler's internal
  251. // code size limits (error "code to large"). String literals are apparently
  252. // embedded raw, which is what we want.
  253. FileDescriptorProto file_proto;
  254. file_->CopyTo(&file_proto);
  255. string file_data;
  256. file_proto.SerializeToString(&file_data);
  257. printer->Print(
  258. "public static com.google.protobuf.Descriptors.FileDescriptor\n"
  259. " getDescriptor() {\n"
  260. " return descriptor;\n"
  261. "}\n"
  262. "private static com.google.protobuf.Descriptors.FileDescriptor\n"
  263. " descriptor;\n"
  264. "static {\n"
  265. " java.lang.String[] descriptorData = {\n");
  266. printer->Indent();
  267. printer->Indent();
  268. // Only write 40 bytes per line.
  269. static const int kBytesPerLine = 40;
  270. for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
  271. if (i > 0) {
  272. // Every 400 lines, start a new string literal, in order to avoid the
  273. // 64k length limit.
  274. if (i % 400 == 0) {
  275. printer->Print(",\n");
  276. } else {
  277. printer->Print(" +\n");
  278. }
  279. }
  280. printer->Print("\"$data$\"",
  281. "data", CEscape(file_data.substr(i, kBytesPerLine)));
  282. }
  283. printer->Outdent();
  284. printer->Print("\n};\n");
  285. // -----------------------------------------------------------------
  286. // Create the InternalDescriptorAssigner.
  287. printer->Print(
  288. "com.google.protobuf.Descriptors.FileDescriptor."
  289. "InternalDescriptorAssigner assigner =\n"
  290. " new com.google.protobuf.Descriptors.FileDescriptor."
  291. "InternalDescriptorAssigner() {\n"
  292. " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n"
  293. " com.google.protobuf.Descriptors.FileDescriptor root) {\n"
  294. " descriptor = root;\n");
  295. printer->Indent();
  296. printer->Indent();
  297. printer->Indent();
  298. for (int i = 0; i < file_->message_type_count(); i++) {
  299. // TODO(kenton): Reuse MessageGenerator objects?
  300. MessageGenerator(file_->message_type(i))
  301. .GenerateStaticVariableInitializers(printer);
  302. }
  303. for (int i = 0; i < file_->extension_count(); i++) {
  304. // TODO(kenton): Reuse ExtensionGenerator objects?
  305. ExtensionGenerator(file_->extension(i))
  306. .GenerateNonNestedInitializationCode(printer);
  307. }
  308. // Proto compiler builds a DescriptorPool, which holds all the descriptors to
  309. // generate, when processing the ".proto" files. We call this DescriptorPool
  310. // the parsed pool (a.k.a. file_->pool()).
  311. //
  312. // Note that when users try to extend the (.*)DescriptorProto in their
  313. // ".proto" files, it does not affect the pre-built FileDescriptorProto class
  314. // in proto compiler. When we put the descriptor data in the file_proto, those
  315. // extensions become unknown fields.
  316. //
  317. // Now we need to find out all the extension value to the (.*)DescriptorProto
  318. // in the file_proto message, and prepare an ExtensionRegistry to return.
  319. //
  320. // To find those extensions, we need to parse the data into a dynamic message
  321. // of the FileDescriptor based on the builder-pool, then we can use
  322. // reflections to find all extension fields
  323. vector<const FieldDescriptor*> extensions;
  324. CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
  325. if (extensions.size() > 0) {
  326. // Must construct an ExtensionRegistry containing all existing extensions
  327. // and return it.
  328. printer->Print(
  329. "com.google.protobuf.ExtensionRegistry registry =\n"
  330. " com.google.protobuf.ExtensionRegistry.newInstance();\n");
  331. for (int i = 0; i < extensions.size(); i++) {
  332. ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
  333. }
  334. printer->Print(
  335. "return registry;\n");
  336. } else {
  337. printer->Print(
  338. "return null;\n");
  339. }
  340. printer->Outdent();
  341. printer->Outdent();
  342. printer->Outdent();
  343. printer->Print(
  344. " }\n"
  345. " };\n");
  346. // -----------------------------------------------------------------
  347. // Invoke internalBuildGeneratedFileFrom() to build the file.
  348. printer->Print(
  349. "com.google.protobuf.Descriptors.FileDescriptor\n"
  350. " .internalBuildGeneratedFileFrom(descriptorData,\n"
  351. " new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
  352. for (int i = 0; i < file_->dependency_count(); i++) {
  353. if (ShouldIncludeDependency(file_->dependency(i))) {
  354. printer->Print(
  355. " $dependency$.getDescriptor(),\n",
  356. "dependency", ClassName(file_->dependency(i)));
  357. }
  358. }
  359. printer->Print(
  360. " }, assigner);\n");
  361. printer->Outdent();
  362. printer->Print(
  363. "}\n");
  364. }
  365. template<typename GeneratorClass, typename DescriptorClass>
  366. static void GenerateSibling(const string& package_dir,
  367. const string& java_package,
  368. const DescriptorClass* descriptor,
  369. GeneratorContext* context,
  370. vector<string>* file_list,
  371. const string& name_suffix,
  372. void (GeneratorClass::*pfn)(io::Printer* printer)) {
  373. string filename = package_dir + descriptor->name() + name_suffix + ".java";
  374. file_list->push_back(filename);
  375. scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
  376. io::Printer printer(output.get(), '$');
  377. printer.Print(
  378. "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
  379. "// source: $filename$\n"
  380. "\n",
  381. "filename", descriptor->file()->name());
  382. if (!java_package.empty()) {
  383. printer.Print(
  384. "package $package$;\n"
  385. "\n",
  386. "package", java_package);
  387. }
  388. GeneratorClass generator(descriptor);
  389. (generator.*pfn)(&printer);
  390. }
  391. void FileGenerator::GenerateSiblings(const string& package_dir,
  392. GeneratorContext* context,
  393. vector<string>* file_list) {
  394. if (file_->options().java_multiple_files()) {
  395. for (int i = 0; i < file_->enum_type_count(); i++) {
  396. GenerateSibling<EnumGenerator>(package_dir, java_package_,
  397. file_->enum_type(i),
  398. context, file_list, "",
  399. &EnumGenerator::Generate);
  400. }
  401. for (int i = 0; i < file_->message_type_count(); i++) {
  402. GenerateSibling<MessageGenerator>(package_dir, java_package_,
  403. file_->message_type(i),
  404. context, file_list, "OrBuilder",
  405. &MessageGenerator::GenerateInterface);
  406. GenerateSibling<MessageGenerator>(package_dir, java_package_,
  407. file_->message_type(i),
  408. context, file_list, "",
  409. &MessageGenerator::Generate);
  410. }
  411. if (HasGenericServices(file_)) {
  412. for (int i = 0; i < file_->service_count(); i++) {
  413. GenerateSibling<ServiceGenerator>(package_dir, java_package_,
  414. file_->service(i),
  415. context, file_list, "",
  416. &ServiceGenerator::Generate);
  417. }
  418. }
  419. }
  420. }
  421. bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
  422. return true;
  423. }
  424. } // namespace java
  425. } // namespace compiler
  426. } // namespace protobuf
  427. } // namespace google