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 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/java/java_file.h>
36 
37 #include <memory>
38 #ifndef _SHARED_PTR_H
39 #include <google/protobuf/stubs/shared_ptr.h>
40 #endif
41 #include <set>
42 
43 #include <google/protobuf/compiler/java/java_context.h>
44 #include <google/protobuf/compiler/java/java_enum.h>
45 #include <google/protobuf/compiler/java/java_enum_lite.h>
46 #include <google/protobuf/compiler/java/java_extension.h>
47 #include <google/protobuf/compiler/java/java_generator_factory.h>
48 #include <google/protobuf/compiler/java/java_helpers.h>
49 #include <google/protobuf/compiler/java/java_message.h>
50 #include <google/protobuf/compiler/java/java_name_resolver.h>
51 #include <google/protobuf/compiler/java/java_service.h>
52 #include <google/protobuf/compiler/java/java_shared_code_generator.h>
53 #include <google/protobuf/compiler/code_generator.h>
54 #include <google/protobuf/io/printer.h>
55 #include <google/protobuf/io/zero_copy_stream.h>
56 #include <google/protobuf/descriptor.pb.h>
57 #include <google/protobuf/dynamic_message.h>
58 #include <google/protobuf/stubs/strutil.h>
59 
60 namespace google {
61 namespace protobuf {
62 namespace compiler {
63 namespace java {
64 
65 namespace {
66 
67 struct FieldDescriptorCompare {
operator ()google::protobuf::compiler::java::__anonccd189240111::FieldDescriptorCompare68   bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) {
69     if(f1 == NULL) {
70       return false;
71     }
72     if(f2 == NULL) {
73       return true;
74     }
75     return f1->full_name() < f2->full_name();
76   }
77 };
78 
79 typedef std::set<const FieldDescriptor*, FieldDescriptorCompare> FieldDescriptorSet;
80 
81 // Recursively searches the given message to collect extensions.
82 // Returns true if all the extensions can be recognized. The extensions will be
83 // appended in to the extensions parameter.
84 // Returns false when there are unknown fields, in which case the data in the
85 // extensions output parameter is not reliable and should be discarded.
CollectExtensions(const Message & message,FieldDescriptorSet * extensions)86 bool CollectExtensions(const Message& message,
87                        FieldDescriptorSet* extensions) {
88   const Reflection* reflection = message.GetReflection();
89 
90   // There are unknown fields that could be extensions, thus this call fails.
91   if (reflection->GetUnknownFields(message).field_count() > 0) return false;
92 
93   vector<const FieldDescriptor*> fields;
94   reflection->ListFields(message, &fields);
95 
96   for (int i = 0; i < fields.size(); i++) {
97     if (fields[i]->is_extension()) extensions->insert(fields[i]);
98 
99     if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
100       if (fields[i]->is_repeated()) {
101         int size = reflection->FieldSize(message, fields[i]);
102         for (int j = 0; j < size; j++) {
103           const Message& sub_message =
104             reflection->GetRepeatedMessage(message, fields[i], j);
105           if (!CollectExtensions(sub_message, extensions)) return false;
106         }
107       } else {
108         const Message& sub_message = reflection->GetMessage(message, fields[i]);
109         if (!CollectExtensions(sub_message, extensions)) return false;
110       }
111     }
112   }
113 
114   return true;
115 }
116 
117 // Finds all extensions in the given message and its sub-messages.  If the
118 // message contains unknown fields (which could be extensions), then those
119 // extensions are defined in alternate_pool.
120 // The message will be converted to a DynamicMessage backed by alternate_pool
121 // in order to handle this case.
CollectExtensions(const FileDescriptorProto & file_proto,const DescriptorPool & alternate_pool,FieldDescriptorSet * extensions,const string & file_data)122 void CollectExtensions(const FileDescriptorProto& file_proto,
123                        const DescriptorPool& alternate_pool,
124                        FieldDescriptorSet* extensions,
125                        const string& file_data) {
126   if (!CollectExtensions(file_proto, extensions)) {
127     // There are unknown fields in the file_proto, which are probably
128     // extensions. We need to parse the data into a dynamic message based on the
129     // builder-pool to find out all extensions.
130     const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
131         file_proto.GetDescriptor()->full_name());
132     GOOGLE_CHECK(file_proto_desc)
133         << "Find unknown fields in FileDescriptorProto when building "
134         << file_proto.name()
135         << ". It's likely that those fields are custom options, however, "
136            "descriptor.proto is not in the transitive dependencies. "
137            "This normally should not happen. Please report a bug.";
138     DynamicMessageFactory factory;
139     google::protobuf::scoped_ptr<Message> dynamic_file_proto(
140         factory.GetPrototype(file_proto_desc)->New());
141     GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
142     GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
143 
144     // Collect the extensions again from the dynamic message. There should be no
145     // more unknown fields this time, i.e. all the custom options should be
146     // parsed as extensions now.
147     extensions->clear();
148     GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
149         << "Find unknown fields in FileDescriptorProto when building "
150         << file_proto.name()
151         << ". It's likely that those fields are custom options, however, "
152            "those options cannot be recognized in the builder pool. "
153            "This normally should not happen. Please report a bug.";
154   }
155 }
156 
157 // Compare two field descriptors, returning true if the first should come
158 // before the second.
CompareFieldsByName(const FieldDescriptor * a,const FieldDescriptor * b)159 bool CompareFieldsByName(const FieldDescriptor *a, const FieldDescriptor *b) {
160   return a->full_name() < b->full_name();
161 }
162 
163 // Our static initialization methods can become very, very large.
164 // So large that if we aren't careful we end up blowing the JVM's
165 // 64K bytes of bytecode/method. Fortunately, since these static
166 // methods are executed only once near the beginning of a program,
167 // there's usually plenty of stack space available and we can
168 // extend our methods by simply chaining them to another method
169 // with a tail call. This inserts the sequence call-next-method,
170 // end this one, begin-next-method as needed.
MaybeRestartJavaMethod(io::Printer * printer,int * bytecode_estimate,int * method_num,const char * chain_statement,const char * method_decl)171 void MaybeRestartJavaMethod(io::Printer* printer,
172                             int *bytecode_estimate,
173                             int *method_num,
174                             const char *chain_statement,
175                             const char *method_decl) {
176   // The goal here is to stay under 64K bytes of jvm bytecode/method,
177   // since otherwise we hit a hardcoded limit in the jvm and javac will
178   // then fail with the error "code too large". This limit lets our
179   // estimates be off by a factor of two and still we're okay.
180   static const int bytesPerMethod = kMaxStaticSize;
181 
182   if ((*bytecode_estimate) > bytesPerMethod) {
183     ++(*method_num);
184     printer->Print(chain_statement, "method_num", SimpleItoa(*method_num));
185     printer->Outdent();
186     printer->Print("}\n");
187     printer->Print(method_decl, "method_num", SimpleItoa(*method_num));
188     printer->Indent();
189     *bytecode_estimate = 0;
190   }
191 }
192 
193 
194 }  // namespace
195 
FileGenerator(const FileDescriptor * file,const Options & options,bool immutable_api)196 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options,
197                              bool immutable_api)
198     : file_(file),
199       java_package_(FileJavaPackage(file, immutable_api)),
200       message_generators_(
201           new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
202       extension_generators_(
203           new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
204       context_(new Context(file, options)),
205       name_resolver_(context_->GetNameResolver()),
206       options_(options),
207       immutable_api_(immutable_api) {
208   classname_ = name_resolver_->GetFileClassName(file, immutable_api);
209   generator_factory_.reset(
210       new ImmutableGeneratorFactory(context_.get()));
211   for (int i = 0; i < file_->message_type_count(); ++i) {
212     message_generators_[i].reset(
213         generator_factory_->NewMessageGenerator(file_->message_type(i)));
214   }
215   for (int i = 0; i < file_->extension_count(); ++i) {
216     extension_generators_[i].reset(
217         generator_factory_->NewExtensionGenerator(file_->extension(i)));
218   }
219 }
220 
~FileGenerator()221 FileGenerator::~FileGenerator() {}
222 
Validate(string * error)223 bool FileGenerator::Validate(string* error) {
224   // Check that no class name matches the file's class name.  This is a common
225   // problem that leads to Java compile errors that can be hard to understand.
226   // It's especially bad when using the java_multiple_files, since we would
227   // end up overwriting the outer class with one of the inner ones.
228   if (name_resolver_->HasConflictingClassName(file_, classname_)) {
229     error->assign(file_->name());
230     error->append(
231       ": Cannot generate Java output because the file's outer class name, \"");
232     error->append(classname_);
233     error->append(
234       "\", matches the name of one of the types declared inside it.  "
235       "Please either rename the type or use the java_outer_classname "
236       "option to specify a different outer class name for the .proto file.");
237     return false;
238   }
239   return true;
240 }
241 
Generate(io::Printer * printer)242 void FileGenerator::Generate(io::Printer* printer) {
243   // We don't import anything because we refer to all classes by their
244   // fully-qualified names in the generated source.
245   printer->Print(
246     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
247     "// source: $filename$\n"
248     "\n",
249     "filename", file_->name());
250   if (!java_package_.empty()) {
251     printer->Print(
252       "package $package$;\n"
253       "\n",
254       "package", java_package_);
255   }
256   PrintGeneratedAnnotation(
257       printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : "");
258   printer->Print(
259       "public final class $classname$ {\n"
260       "  private $ctor$() {}\n",
261       "classname", classname_, "ctor", classname_);
262   printer->Annotate("classname", file_->name());
263   printer->Indent();
264 
265   // -----------------------------------------------------------------
266 
267   printer->Print(
268     "public static void registerAllExtensions(\n"
269     "    com.google.protobuf.ExtensionRegistryLite registry) {\n");
270 
271   printer->Indent();
272 
273   for (int i = 0; i < file_->extension_count(); i++) {
274     extension_generators_[i]->GenerateRegistrationCode(printer);
275   }
276 
277   for (int i = 0; i < file_->message_type_count(); i++) {
278     message_generators_[i]->GenerateExtensionRegistrationCode(printer);
279   }
280 
281   printer->Outdent();
282   printer->Print(
283     "}\n");
284   if (HasDescriptorMethods(file_, context_->EnforceLite())) {
285     // Overload registerAllExtensions for the non-lite usage to
286     // redundantly maintain the original signature (this is
287     // redundant because ExtensionRegistryLite now invokes
288     // ExtensionRegistry in the non-lite usage). Intent is
289     // to remove this in the future.
290     printer->Print(
291       "\n"
292       "public static void registerAllExtensions(\n"
293       "    com.google.protobuf.ExtensionRegistry registry) {\n"
294       "  registerAllExtensions(\n"
295       "      (com.google.protobuf.ExtensionRegistryLite) registry);\n"
296       "}\n");
297   }
298 
299   // -----------------------------------------------------------------
300 
301   if (!MultipleJavaFiles(file_, immutable_api_)) {
302     for (int i = 0; i < file_->enum_type_count(); i++) {
303       if (HasDescriptorMethods(file_, context_->EnforceLite())) {
304         EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
305             .Generate(printer);
306       } else {
307         EnumLiteGenerator(file_->enum_type(i), immutable_api_, context_.get())
308             .Generate(printer);
309       }
310     }
311     for (int i = 0; i < file_->message_type_count(); i++) {
312       message_generators_[i]->GenerateInterface(printer);
313       message_generators_[i]->Generate(printer);
314     }
315     if (HasGenericServices(file_, context_->EnforceLite())) {
316       for (int i = 0; i < file_->service_count(); i++) {
317         google::protobuf::scoped_ptr<ServiceGenerator> generator(
318             generator_factory_->NewServiceGenerator(file_->service(i)));
319         generator->Generate(printer);
320       }
321     }
322   }
323 
324   // Extensions must be generated in the outer class since they are values,
325   // not classes.
326   for (int i = 0; i < file_->extension_count(); i++) {
327     extension_generators_[i]->Generate(printer);
328   }
329 
330   // Static variables. We'd like them to be final if possible, but due to
331   // the JVM's 64k size limit on static blocks, we have to initialize some
332   // of them in methods; thus they cannot be final.
333   int static_block_bytecode_estimate = 0;
334   for (int i = 0; i < file_->message_type_count(); i++) {
335     message_generators_[i]->GenerateStaticVariables(
336         printer, &static_block_bytecode_estimate);
337   }
338 
339   printer->Print("\n");
340 
341   if (HasDescriptorMethods(file_, context_->EnforceLite())) {
342     if (immutable_api_) {
343       GenerateDescriptorInitializationCodeForImmutable(printer);
344     } else {
345       GenerateDescriptorInitializationCodeForMutable(printer);
346     }
347   } else {
348     printer->Print(
349       "static {\n");
350     printer->Indent();
351     int bytecode_estimate = 0;
352     int method_num = 0;
353 
354     for (int i = 0; i < file_->message_type_count(); i++) {
355       bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
356       MaybeRestartJavaMethod(
357         printer,
358         &bytecode_estimate, &method_num,
359         "_clinit_autosplit_$method_num$();\n",
360         "private static void _clinit_autosplit_$method_num$() {\n");
361     }
362 
363     printer->Outdent();
364     printer->Print(
365       "}\n");
366   }
367 
368   printer->Print(
369     "\n"
370     "// @@protoc_insertion_point(outer_class_scope)\n");
371 
372   printer->Outdent();
373   printer->Print("}\n");
374 }
375 
GenerateDescriptorInitializationCodeForImmutable(io::Printer * printer)376 void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
377     io::Printer* printer) {
378   printer->Print(
379     "public static com.google.protobuf.Descriptors.FileDescriptor\n"
380     "    getDescriptor() {\n"
381     "  return descriptor;\n"
382     "}\n"
383     "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
384     "    descriptor;\n"
385     "static {\n",
386     // TODO(dweis): Mark this as final.
387     "final", "");
388   printer->Indent();
389 
390   SharedCodeGenerator shared_code_generator(file_, options_);
391   shared_code_generator.GenerateDescriptors(printer);
392 
393   int bytecode_estimate = 0;
394   int method_num = 0;
395 
396   for (int i = 0; i < file_->message_type_count(); i++) {
397     bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
398     MaybeRestartJavaMethod(
399       printer,
400       &bytecode_estimate, &method_num,
401       "_clinit_autosplit_dinit_$method_num$();\n",
402       "private static void _clinit_autosplit_dinit_$method_num$() {\n");
403   }
404   for (int i = 0; i < file_->extension_count(); i++) {
405     bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
406     MaybeRestartJavaMethod(
407       printer,
408       &bytecode_estimate, &method_num,
409       "_clinit_autosplit_dinit_$method_num$();\n",
410       "private static void _clinit_autosplit_dinit_$method_num$() {\n");
411   }
412 
413   // Proto compiler builds a DescriptorPool, which holds all the descriptors to
414   // generate, when processing the ".proto" files. We call this DescriptorPool
415   // the parsed pool (a.k.a. file_->pool()).
416   //
417   // Note that when users try to extend the (.*)DescriptorProto in their
418   // ".proto" files, it does not affect the pre-built FileDescriptorProto class
419   // in proto compiler. When we put the descriptor data in the file_proto, those
420   // extensions become unknown fields.
421   //
422   // Now we need to find out all the extension value to the (.*)DescriptorProto
423   // in the file_proto message, and prepare an ExtensionRegistry to return.
424   //
425   // To find those extensions, we need to parse the data into a dynamic message
426   // of the FileDescriptor based on the builder-pool, then we can use
427   // reflections to find all extension fields
428   FileDescriptorProto file_proto;
429   file_->CopyTo(&file_proto);
430   string file_data;
431   file_proto.SerializeToString(&file_data);
432   FieldDescriptorSet extensions;
433   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
434 
435   if (extensions.size() > 0) {
436     // Must construct an ExtensionRegistry containing all existing extensions
437     // and use it to parse the descriptor data again to recognize extensions.
438     printer->Print(
439       "com.google.protobuf.ExtensionRegistry registry =\n"
440       "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
441     FieldDescriptorSet::iterator it;
442     for (it = extensions.begin(); it != extensions.end(); it++) {
443       google::protobuf::scoped_ptr<ExtensionGenerator> generator(
444           generator_factory_->NewExtensionGenerator(*it));
445       bytecode_estimate += generator->GenerateRegistrationCode(printer);
446       MaybeRestartJavaMethod(
447         printer,
448         &bytecode_estimate, &method_num,
449         "_clinit_autosplit_dinit_$method_num$(registry);\n",
450         "private static void _clinit_autosplit_dinit_$method_num$(\n"
451         "    com.google.protobuf.ExtensionRegistry registry) {\n");
452     }
453     printer->Print(
454       "com.google.protobuf.Descriptors.FileDescriptor\n"
455       "    .internalUpdateFileDescriptor(descriptor, registry);\n");
456   }
457 
458   // Force descriptor initialization of all dependencies.
459   for (int i = 0; i < file_->dependency_count(); i++) {
460     if (ShouldIncludeDependency(file_->dependency(i), true)) {
461       string dependency =
462           name_resolver_->GetImmutableClassName(file_->dependency(i));
463       printer->Print(
464         "$dependency$.getDescriptor();\n",
465         "dependency", dependency);
466     }
467   }
468 
469   printer->Outdent();
470   printer->Print(
471     "}\n");
472 }
473 
GenerateDescriptorInitializationCodeForMutable(io::Printer * printer)474 void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) {
475   printer->Print(
476     "public static com.google.protobuf.Descriptors.FileDescriptor\n"
477     "    getDescriptor() {\n"
478     "  return descriptor;\n"
479     "}\n"
480     "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
481     "    descriptor;\n"
482     "static {\n");
483   printer->Indent();
484 
485   printer->Print(
486     "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n",
487     "immutable_package", FileJavaPackage(file_, true),
488     "descriptor_classname", name_resolver_->GetDescriptorClassName(file_));
489 
490   for (int i = 0; i < file_->message_type_count(); i++) {
491     message_generators_[i]->GenerateStaticVariableInitializers(printer);
492   }
493   for (int i = 0; i < file_->extension_count(); i++) {
494     extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
495   }
496 
497   // Check if custom options exist. If any, try to load immutable classes since
498   // custom options are only represented with immutable messages.
499   FileDescriptorProto file_proto;
500   file_->CopyTo(&file_proto);
501   string file_data;
502   file_proto.SerializeToString(&file_data);
503   FieldDescriptorSet extensions;
504   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
505 
506   if (extensions.size() > 0) {
507     // Try to load immutable messages' outer class. Its initialization code
508     // will take care of interpreting custom options.
509     printer->Print(
510       "try {\n"
511       // Note that we have to load the immutable class dynamically here as
512       // we want the mutable code to be independent from the immutable code
513       // at compile time. It is required to implement dual-compile for
514       // mutable and immutable API in blaze.
515       "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
516       "      \"$immutable_classname$\");\n"
517       "} catch (java.lang.ClassNotFoundException e) {\n"
518       // The immutable class can not be found. Custom options are left
519       // as unknown fields.
520       // TODO(xiaofeng): inform the user with a warning?
521       "}\n",
522       "immutable_classname", name_resolver_->GetImmutableClassName(file_));
523   }
524 
525   // Force descriptor initialization of all dependencies.
526   for (int i = 0; i < file_->dependency_count(); i++) {
527     if (ShouldIncludeDependency(file_->dependency(i), false)) {
528       string dependency = name_resolver_->GetMutableClassName(
529           file_->dependency(i));
530       printer->Print(
531         "$dependency$.getDescriptor();\n",
532         "dependency", dependency);
533     }
534   }
535 
536   printer->Outdent();
537   printer->Print(
538     "}\n");
539 }
540 
541 template <typename GeneratorClass, typename DescriptorClass>
GenerateSibling(const string & package_dir,const string & java_package,const DescriptorClass * descriptor,GeneratorContext * context,vector<string> * file_list,bool annotate_code,vector<string> * annotation_list,const string & name_suffix,GeneratorClass * generator,void (GeneratorClass::* pfn)(io::Printer * printer))542 static void GenerateSibling(const string& package_dir,
543                             const string& java_package,
544                             const DescriptorClass* descriptor,
545                             GeneratorContext* context,
546                             vector<string>* file_list, bool annotate_code,
547                             vector<string>* annotation_list,
548                             const string& name_suffix,
549                             GeneratorClass* generator,
550                             void (GeneratorClass::*pfn)(io::Printer* printer)) {
551   string filename = package_dir + descriptor->name() + name_suffix + ".java";
552   file_list->push_back(filename);
553   string info_full_path = filename + ".pb.meta";
554   GeneratedCodeInfo annotations;
555   io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
556       &annotations);
557 
558   google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
559   io::Printer printer(output.get(), '$',
560                       annotate_code ? &annotation_collector : NULL);
561 
562   printer.Print(
563     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
564     "// source: $filename$\n"
565     "\n",
566     "filename", descriptor->file()->name());
567   if (!java_package.empty()) {
568     printer.Print(
569       "package $package$;\n"
570       "\n",
571       "package", java_package);
572   }
573 
574   (generator->*pfn)(&printer);
575 
576   if (annotate_code) {
577     google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
578         context->Open(info_full_path));
579     annotations.SerializeToZeroCopyStream(info_output.get());
580     annotation_list->push_back(info_full_path);
581   }
582 }
583 
GenerateSiblings(const string & package_dir,GeneratorContext * context,vector<string> * file_list,vector<string> * annotation_list)584 void FileGenerator::GenerateSiblings(const string& package_dir,
585                                      GeneratorContext* context,
586                                      vector<string>* file_list,
587                                      vector<string>* annotation_list) {
588   if (MultipleJavaFiles(file_, immutable_api_)) {
589     for (int i = 0; i < file_->enum_type_count(); i++) {
590       if (HasDescriptorMethods(file_, context_->EnforceLite())) {
591         EnumGenerator generator(file_->enum_type(i), immutable_api_,
592                                 context_.get());
593         GenerateSibling<EnumGenerator>(
594             package_dir, java_package_, file_->enum_type(i), context, file_list,
595             options_.annotate_code, annotation_list, "", &generator,
596             &EnumGenerator::Generate);
597       } else {
598         EnumLiteGenerator generator(file_->enum_type(i), immutable_api_,
599                                     context_.get());
600         GenerateSibling<EnumLiteGenerator>(
601             package_dir, java_package_, file_->enum_type(i), context, file_list,
602             options_.annotate_code, annotation_list, "", &generator,
603             &EnumLiteGenerator::Generate);
604       }
605     }
606     for (int i = 0; i < file_->message_type_count(); i++) {
607       if (immutable_api_) {
608         GenerateSibling<MessageGenerator>(
609             package_dir, java_package_, file_->message_type(i), context,
610             file_list, options_.annotate_code, annotation_list, "OrBuilder",
611             message_generators_[i].get(), &MessageGenerator::GenerateInterface);
612       }
613       GenerateSibling<MessageGenerator>(
614           package_dir, java_package_, file_->message_type(i), context,
615           file_list, options_.annotate_code, annotation_list, "",
616           message_generators_[i].get(), &MessageGenerator::Generate);
617     }
618     if (HasGenericServices(file_, context_->EnforceLite())) {
619       for (int i = 0; i < file_->service_count(); i++) {
620         google::protobuf::scoped_ptr<ServiceGenerator> generator(
621             generator_factory_->NewServiceGenerator(file_->service(i)));
622         GenerateSibling<ServiceGenerator>(
623             package_dir, java_package_, file_->service(i), context, file_list,
624             options_.annotate_code, annotation_list, "", generator.get(),
625             &ServiceGenerator::Generate);
626       }
627     }
628   }
629 }
630 
ShouldIncludeDependency(const FileDescriptor * descriptor,bool immutable_api)631 bool FileGenerator::ShouldIncludeDependency(
632     const FileDescriptor* descriptor, bool immutable_api) {
633   return true;
634 }
635 
636 }  // namespace java
637 }  // namespace compiler
638 }  // namespace protobuf
639 }  // namespace google
640