• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anona34464030111::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,bool immutable_api,bool enforce_lite)196 FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api,
197                              bool enforce_lite)
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)),
205       name_resolver_(context_->GetNameResolver()),
206       immutable_api_(immutable_api) {
207   classname_ = name_resolver_->GetFileClassName(file, immutable_api);
208   context_->SetEnforceLite(enforce_lite);
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   printer->Print(
257     "public final class $classname$ {\n"
258     "  private $classname$() {}\n",
259     "classname", classname_);
260   printer->Indent();
261 
262   // -----------------------------------------------------------------
263 
264   printer->Print(
265     "public static void registerAllExtensions(\n"
266     "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
267     "lite",
268     HasDescriptorMethods(file_, context_->EnforceLite()) ? "" : "Lite");
269 
270   printer->Indent();
271 
272   for (int i = 0; i < file_->extension_count(); i++) {
273     extension_generators_[i]->GenerateRegistrationCode(printer);
274   }
275 
276   for (int i = 0; i < file_->message_type_count(); i++) {
277     message_generators_[i]->GenerateExtensionRegistrationCode(printer);
278   }
279 
280   printer->Outdent();
281   printer->Print(
282     "}\n");
283 
284   // -----------------------------------------------------------------
285 
286   if (!MultipleJavaFiles(file_, immutable_api_)) {
287     for (int i = 0; i < file_->enum_type_count(); i++) {
288       if (HasDescriptorMethods(file_, context_->EnforceLite())) {
289         EnumGenerator(file_->enum_type(i), immutable_api_, context_.get())
290             .Generate(printer);
291       } else {
292         EnumLiteGenerator(file_->enum_type(i), immutable_api_, context_.get())
293             .Generate(printer);
294       }
295     }
296     for (int i = 0; i < file_->message_type_count(); i++) {
297       message_generators_[i]->GenerateInterface(printer);
298       message_generators_[i]->Generate(printer);
299     }
300     if (HasGenericServices(file_, context_->EnforceLite())) {
301       for (int i = 0; i < file_->service_count(); i++) {
302         google::protobuf::scoped_ptr<ServiceGenerator> generator(
303             generator_factory_->NewServiceGenerator(file_->service(i)));
304         generator->Generate(printer);
305       }
306     }
307   }
308 
309   // Extensions must be generated in the outer class since they are values,
310   // not classes.
311   for (int i = 0; i < file_->extension_count(); i++) {
312     extension_generators_[i]->Generate(printer);
313   }
314 
315   // Static variables. We'd like them to be final if possible, but due to
316   // the JVM's 64k size limit on static blocks, we have to initialize some
317   // of them in methods; thus they cannot be final.
318   int static_block_bytecode_estimate = 0;
319   for (int i = 0; i < file_->message_type_count(); i++) {
320     message_generators_[i]->GenerateStaticVariables(
321         printer, &static_block_bytecode_estimate);
322   }
323 
324   printer->Print("\n");
325 
326   if (HasDescriptorMethods(file_, context_->EnforceLite())) {
327     if (immutable_api_) {
328       GenerateDescriptorInitializationCodeForImmutable(printer);
329     } else {
330       GenerateDescriptorInitializationCodeForMutable(printer);
331     }
332   } else {
333     printer->Print(
334       "static {\n");
335     printer->Indent();
336     int bytecode_estimate = 0;
337     int method_num = 0;
338 
339     for (int i = 0; i < file_->message_type_count(); i++) {
340       bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
341       MaybeRestartJavaMethod(
342         printer,
343         &bytecode_estimate, &method_num,
344         "_clinit_autosplit_$method_num$();\n",
345         "private static void _clinit_autosplit_$method_num$() {\n");
346     }
347 
348     printer->Outdent();
349     printer->Print(
350       "}\n");
351   }
352 
353   printer->Print(
354     "\n"
355     "// @@protoc_insertion_point(outer_class_scope)\n");
356 
357   printer->Outdent();
358   printer->Print("}\n");
359 }
360 
GenerateDescriptorInitializationCodeForImmutable(io::Printer * printer)361 void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
362     io::Printer* printer) {
363   printer->Print(
364     "public static com.google.protobuf.Descriptors.FileDescriptor\n"
365     "    getDescriptor() {\n"
366     "  return descriptor;\n"
367     "}\n"
368     "private static $final$ com.google.protobuf.Descriptors.FileDescriptor\n"
369     "    descriptor;\n"
370     "static {\n",
371     // TODO(dweis): Mark this as final.
372     "final", "");
373   printer->Indent();
374 
375   SharedCodeGenerator shared_code_generator(file_);
376   shared_code_generator.GenerateDescriptors(printer);
377 
378   int bytecode_estimate = 0;
379   int method_num = 0;
380 
381   for (int i = 0; i < file_->message_type_count(); i++) {
382     bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
383     MaybeRestartJavaMethod(
384       printer,
385       &bytecode_estimate, &method_num,
386       "_clinit_autosplit_dinit_$method_num$();\n",
387       "private static void _clinit_autosplit_dinit_$method_num$() {\n");
388   }
389   for (int i = 0; i < file_->extension_count(); i++) {
390     bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
391     MaybeRestartJavaMethod(
392       printer,
393       &bytecode_estimate, &method_num,
394       "_clinit_autosplit_dinit_$method_num$();\n",
395       "private static void _clinit_autosplit_dinit_$method_num$() {\n");
396   }
397 
398   // Proto compiler builds a DescriptorPool, which holds all the descriptors to
399   // generate, when processing the ".proto" files. We call this DescriptorPool
400   // the parsed pool (a.k.a. file_->pool()).
401   //
402   // Note that when users try to extend the (.*)DescriptorProto in their
403   // ".proto" files, it does not affect the pre-built FileDescriptorProto class
404   // in proto compiler. When we put the descriptor data in the file_proto, those
405   // extensions become unknown fields.
406   //
407   // Now we need to find out all the extension value to the (.*)DescriptorProto
408   // in the file_proto message, and prepare an ExtensionRegistry to return.
409   //
410   // To find those extensions, we need to parse the data into a dynamic message
411   // of the FileDescriptor based on the builder-pool, then we can use
412   // reflections to find all extension fields
413   FileDescriptorProto file_proto;
414   file_->CopyTo(&file_proto);
415   string file_data;
416   file_proto.SerializeToString(&file_data);
417   FieldDescriptorSet extensions;
418   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
419 
420   if (extensions.size() > 0) {
421     // Must construct an ExtensionRegistry containing all existing extensions
422     // and use it to parse the descriptor data again to recognize extensions.
423     printer->Print(
424       "com.google.protobuf.ExtensionRegistry registry =\n"
425       "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
426     FieldDescriptorSet::iterator it;
427     for (it = extensions.begin(); it != extensions.end(); it++) {
428       google::protobuf::scoped_ptr<ExtensionGenerator> generator(
429           generator_factory_->NewExtensionGenerator(*it));
430       bytecode_estimate += generator->GenerateRegistrationCode(printer);
431       MaybeRestartJavaMethod(
432         printer,
433         &bytecode_estimate, &method_num,
434         "_clinit_autosplit_dinit_$method_num$(registry);\n",
435         "private static void _clinit_autosplit_dinit_$method_num$(\n"
436         "    com.google.protobuf.ExtensionRegistry registry) {\n");
437     }
438     printer->Print(
439       "com.google.protobuf.Descriptors.FileDescriptor\n"
440       "    .internalUpdateFileDescriptor(descriptor, registry);\n");
441   }
442 
443   // Force descriptor initialization of all dependencies.
444   for (int i = 0; i < file_->dependency_count(); i++) {
445     if (ShouldIncludeDependency(file_->dependency(i), true)) {
446       string dependency =
447           name_resolver_->GetImmutableClassName(file_->dependency(i));
448       printer->Print(
449         "$dependency$.getDescriptor();\n",
450         "dependency", dependency);
451     }
452   }
453 
454   printer->Outdent();
455   printer->Print(
456     "}\n");
457 }
458 
GenerateDescriptorInitializationCodeForMutable(io::Printer * printer)459 void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) {
460   printer->Print(
461     "public static com.google.protobuf.Descriptors.FileDescriptor\n"
462     "    getDescriptor() {\n"
463     "  return descriptor;\n"
464     "}\n"
465     "private static final com.google.protobuf.Descriptors.FileDescriptor\n"
466     "    descriptor;\n"
467     "static {\n");
468   printer->Indent();
469 
470   printer->Print(
471     "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n",
472     "immutable_package", FileJavaPackage(file_, true),
473     "descriptor_classname", name_resolver_->GetDescriptorClassName(file_));
474 
475   for (int i = 0; i < file_->message_type_count(); i++) {
476     message_generators_[i]->GenerateStaticVariableInitializers(printer);
477   }
478   for (int i = 0; i < file_->extension_count(); i++) {
479     extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
480   }
481 
482   // Check if custom options exist. If any, try to load immutable classes since
483   // custom options are only represented with immutable messages.
484   FileDescriptorProto file_proto;
485   file_->CopyTo(&file_proto);
486   string file_data;
487   file_proto.SerializeToString(&file_data);
488   FieldDescriptorSet extensions;
489   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
490 
491   if (extensions.size() > 0) {
492     // Try to load immutable messages' outer class. Its initialization code
493     // will take care of interpreting custom options.
494     printer->Print(
495       "try {\n"
496       // Note that we have to load the immutable class dynamically here as
497       // we want the mutable code to be independent from the immutable code
498       // at compile time. It is required to implement dual-compile for
499       // mutable and immutable API in blaze.
500       "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
501       "      \"$immutable_classname$\");\n"
502       "} catch (java.lang.ClassNotFoundException e) {\n"
503       // The immutable class can not be found. Custom options are left
504       // as unknown fields.
505       // TODO(xiaofeng): inform the user with a warning?
506       "}\n",
507       "immutable_classname", name_resolver_->GetImmutableClassName(file_));
508   }
509 
510   // Force descriptor initialization of all dependencies.
511   for (int i = 0; i < file_->dependency_count(); i++) {
512     if (ShouldIncludeDependency(file_->dependency(i), false)) {
513       string dependency = name_resolver_->GetMutableClassName(
514           file_->dependency(i));
515       printer->Print(
516         "$dependency$.getDescriptor();\n",
517         "dependency", dependency);
518     }
519   }
520 
521   printer->Outdent();
522   printer->Print(
523     "}\n");
524 }
525 
526 template<typename GeneratorClass, typename DescriptorClass>
GenerateSibling(const string & package_dir,const string & java_package,const DescriptorClass * descriptor,GeneratorContext * context,vector<string> * file_list,const string & name_suffix,GeneratorClass * generator,void (GeneratorClass::* pfn)(io::Printer * printer))527 static void GenerateSibling(const string& package_dir,
528                             const string& java_package,
529                             const DescriptorClass* descriptor,
530                             GeneratorContext* context,
531                             vector<string>* file_list,
532                             const string& name_suffix,
533                             GeneratorClass* generator,
534                             void (GeneratorClass::*pfn)(io::Printer* printer)) {
535   string filename = package_dir + descriptor->name() + name_suffix + ".java";
536   file_list->push_back(filename);
537 
538   google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
539   io::Printer printer(output.get(), '$');
540 
541   printer.Print(
542     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
543     "// source: $filename$\n"
544     "\n",
545     "filename", descriptor->file()->name());
546   if (!java_package.empty()) {
547     printer.Print(
548       "package $package$;\n"
549       "\n",
550       "package", java_package);
551   }
552 
553   (generator->*pfn)(&printer);
554 }
555 
GenerateSiblings(const string & package_dir,GeneratorContext * context,vector<string> * file_list)556 void FileGenerator::GenerateSiblings(const string& package_dir,
557                                      GeneratorContext* context,
558                                      vector<string>* file_list) {
559   if (MultipleJavaFiles(file_, immutable_api_)) {
560     for (int i = 0; i < file_->enum_type_count(); i++) {
561       if (HasDescriptorMethods(file_, context_->EnforceLite())) {
562         EnumGenerator generator(file_->enum_type(i), immutable_api_,
563                                 context_.get());
564         GenerateSibling<EnumGenerator>(package_dir, java_package_,
565                                        file_->enum_type(i),
566                                        context, file_list, "",
567                                        &generator,
568                                        &EnumGenerator::Generate);
569       } else {
570         EnumLiteGenerator generator(file_->enum_type(i), immutable_api_,
571                                     context_.get());
572         GenerateSibling<EnumLiteGenerator>(package_dir, java_package_,
573                                            file_->enum_type(i),
574                                            context, file_list, "",
575                                            &generator,
576                                            &EnumLiteGenerator::Generate);
577       }
578     }
579     for (int i = 0; i < file_->message_type_count(); i++) {
580       if (immutable_api_) {
581         GenerateSibling<MessageGenerator>(package_dir, java_package_,
582                                           file_->message_type(i),
583                                           context, file_list,
584                                           "OrBuilder",
585                                           message_generators_[i].get(),
586                                           &MessageGenerator::GenerateInterface);
587       }
588       GenerateSibling<MessageGenerator>(package_dir, java_package_,
589                                         file_->message_type(i),
590                                         context, file_list, "",
591                                         message_generators_[i].get(),
592                                         &MessageGenerator::Generate);
593     }
594     if (HasGenericServices(file_, context_->EnforceLite())) {
595       for (int i = 0; i < file_->service_count(); i++) {
596         google::protobuf::scoped_ptr<ServiceGenerator> generator(
597             generator_factory_->NewServiceGenerator(file_->service(i)));
598         GenerateSibling<ServiceGenerator>(package_dir, java_package_,
599                                           file_->service(i),
600                                           context, file_list, "",
601                                           generator.get(),
602                                           &ServiceGenerator::Generate);
603       }
604     }
605   }
606 }
607 
ShouldIncludeDependency(const FileDescriptor * descriptor,bool immutable_api)608 bool FileGenerator::ShouldIncludeDependency(
609     const FileDescriptor* descriptor, bool immutable_api) {
610   return true;
611 }
612 
613 }  // namespace java
614 }  // namespace compiler
615 }  // namespace protobuf
616 }  // namespace google
617