java_generator.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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_generator.h>
  34. #include <memory>
  35. #include <google/protobuf/compiler/java/java_file.h>
  36. #include <google/protobuf/compiler/java/java_generator_factory.h>
  37. #include <google/protobuf/compiler/java/java_helpers.h>
  38. #include <google/protobuf/compiler/java/java_name_resolver.h>
  39. #include <google/protobuf/compiler/java/java_options.h>
  40. #include <google/protobuf/compiler/java/java_shared_code_generator.h>
  41. #include <google/protobuf/descriptor.pb.h>
  42. #include <google/protobuf/io/printer.h>
  43. #include <google/protobuf/io/zero_copy_stream.h>
  44. #include <google/protobuf/stubs/strutil.h>
  45. namespace google {
  46. namespace protobuf {
  47. namespace compiler {
  48. namespace java {
  49. JavaGenerator::JavaGenerator() {}
  50. JavaGenerator::~JavaGenerator() {}
  51. bool JavaGenerator::Generate(const FileDescriptor* file,
  52. const string& parameter,
  53. GeneratorContext* context,
  54. string* error) const {
  55. // -----------------------------------------------------------------
  56. // parse generator options
  57. std::vector<std::pair<string, string> > options;
  58. ParseGeneratorParameter(parameter, &options);
  59. Options file_options;
  60. for (int i = 0; i < options.size(); i++) {
  61. if (options[i].first == "output_list_file") {
  62. file_options.output_list_file = options[i].second;
  63. } else if (options[i].first == "immutable") {
  64. file_options.generate_immutable_code = true;
  65. } else if (options[i].first == "mutable") {
  66. file_options.generate_mutable_code = true;
  67. } else if (options[i].first == "shared") {
  68. file_options.generate_shared_code = true;
  69. } else if (options[i].first == "annotate_code") {
  70. file_options.annotate_code = true;
  71. } else if (options[i].first == "annotation_list_file") {
  72. file_options.annotation_list_file = options[i].second;
  73. } else {
  74. *error = "Unknown generator option: " + options[i].first;
  75. return false;
  76. }
  77. }
  78. if (file_options.enforce_lite && file_options.generate_mutable_code) {
  79. *error = "lite runtime generator option cannot be used with mutable API.";
  80. return false;
  81. }
  82. // By default we generate immutable code and shared code for immutable API.
  83. if (!file_options.generate_immutable_code &&
  84. !file_options.generate_mutable_code &&
  85. !file_options.generate_shared_code) {
  86. file_options.generate_immutable_code = true;
  87. file_options.generate_shared_code = true;
  88. }
  89. // -----------------------------------------------------------------
  90. std::vector<string> all_files;
  91. std::vector<string> all_annotations;
  92. std::vector<FileGenerator*> file_generators;
  93. if (file_options.generate_immutable_code) {
  94. file_generators.push_back(new FileGenerator(file, file_options,
  95. /* immutable = */ true));
  96. }
  97. if (file_options.generate_mutable_code) {
  98. file_generators.push_back(new FileGenerator(file, file_options,
  99. /* mutable = */ false));
  100. }
  101. for (int i = 0; i < file_generators.size(); ++i) {
  102. if (!file_generators[i]->Validate(error)) {
  103. for (int j = 0; j < file_generators.size(); ++j) {
  104. delete file_generators[j];
  105. }
  106. return false;
  107. }
  108. }
  109. for (int i = 0; i < file_generators.size(); ++i) {
  110. FileGenerator* file_generator = file_generators[i];
  111. string package_dir = JavaPackageToDir(file_generator->java_package());
  112. string java_filename = package_dir;
  113. java_filename += file_generator->classname();
  114. java_filename += ".java";
  115. all_files.push_back(java_filename);
  116. string info_full_path = java_filename + ".pb.meta";
  117. if (file_options.annotate_code) {
  118. all_annotations.push_back(info_full_path);
  119. }
  120. // Generate main java file.
  121. std::unique_ptr<io::ZeroCopyOutputStream> output(
  122. context->Open(java_filename));
  123. GeneratedCodeInfo annotations;
  124. io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
  125. &annotations);
  126. io::Printer printer(output.get(), '$', file_options.annotate_code
  127. ? &annotation_collector
  128. : NULL);
  129. file_generator->Generate(&printer);
  130. // Generate sibling files.
  131. file_generator->GenerateSiblings(package_dir, context, &all_files,
  132. &all_annotations);
  133. if (file_options.annotate_code) {
  134. std::unique_ptr<io::ZeroCopyOutputStream> info_output(
  135. context->Open(info_full_path));
  136. annotations.SerializeToZeroCopyStream(info_output.get());
  137. }
  138. }
  139. for (int i = 0; i < file_generators.size(); ++i) {
  140. delete file_generators[i];
  141. }
  142. file_generators.clear();
  143. // Generate output list if requested.
  144. if (!file_options.output_list_file.empty()) {
  145. // Generate output list. This is just a simple text file placed in a
  146. // deterministic location which lists the .java files being generated.
  147. std::unique_ptr<io::ZeroCopyOutputStream> srclist_raw_output(
  148. context->Open(file_options.output_list_file));
  149. io::Printer srclist_printer(srclist_raw_output.get(), '$');
  150. for (int i = 0; i < all_files.size(); i++) {
  151. srclist_printer.Print("$filename$\n", "filename", all_files[i]);
  152. }
  153. }
  154. if (!file_options.annotation_list_file.empty()) {
  155. // Generate output list. This is just a simple text file placed in a
  156. // deterministic location which lists the .java files being generated.
  157. std::unique_ptr<io::ZeroCopyOutputStream> annotation_list_raw_output(
  158. context->Open(file_options.annotation_list_file));
  159. io::Printer annotation_list_printer(annotation_list_raw_output.get(), '$');
  160. for (int i = 0; i < all_annotations.size(); i++) {
  161. annotation_list_printer.Print("$filename$\n", "filename",
  162. all_annotations[i]);
  163. }
  164. }
  165. return true;
  166. }
  167. } // namespace java
  168. } // namespace compiler
  169. } // namespace protobuf
  170. } // namespace google