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