Home | History | Annotate | Download | only in java
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // Author: kenton (at) 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 #include <google/protobuf/compiler/java/java_enum.h>
     37 #include <google/protobuf/compiler/java/java_service.h>
     38 #include <google/protobuf/compiler/java/java_extension.h>
     39 #include <google/protobuf/compiler/java/java_helpers.h>
     40 #include <google/protobuf/compiler/java/java_message.h>
     41 #include <google/protobuf/compiler/code_generator.h>
     42 #include <google/protobuf/io/printer.h>
     43 #include <google/protobuf/io/zero_copy_stream.h>
     44 #include <google/protobuf/descriptor.pb.h>
     45 #include <google/protobuf/dynamic_message.h>
     46 #include <google/protobuf/stubs/strutil.h>
     47 
     48 namespace google {
     49 namespace protobuf {
     50 namespace compiler {
     51 namespace java {
     52 
     53 namespace {
     54 
     55 
     56 // Recursively searches the given message to collect extensions.
     57 // Returns true if all the extensions can be recognized. The extensions will be
     58 // appended in to the extensions parameter.
     59 // Returns false when there are unknown fields, in which case the data in the
     60 // extensions output parameter is not reliable and should be discarded.
     61 bool CollectExtensions(const Message& message,
     62                        vector<const FieldDescriptor*>* extensions) {
     63   const Reflection* reflection = message.GetReflection();
     64 
     65   // There are unknown fields that could be extensions, thus this call fails.
     66   if (reflection->GetUnknownFields(message).field_count() > 0) return false;
     67 
     68   vector<const FieldDescriptor*> fields;
     69   reflection->ListFields(message, &fields);
     70 
     71   for (int i = 0; i < fields.size(); i++) {
     72     if (fields[i]->is_extension()) extensions->push_back(fields[i]);
     73 
     74     if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
     75       if (fields[i]->is_repeated()) {
     76         int size = reflection->FieldSize(message, fields[i]);
     77         for (int j = 0; j < size; j++) {
     78           const Message& sub_message =
     79             reflection->GetRepeatedMessage(message, fields[i], j);
     80           if (!CollectExtensions(sub_message, extensions)) return false;
     81         }
     82       } else {
     83         const Message& sub_message = reflection->GetMessage(message, fields[i]);
     84         if (!CollectExtensions(sub_message, extensions)) return false;
     85       }
     86     }
     87   }
     88 
     89   return true;
     90 }
     91 
     92 // Finds all extensions in the given message and its sub-messages.  If the
     93 // message contains unknown fields (which could be extensions), then those
     94 // extensions are defined in alternate_pool.
     95 // The message will be converted to a DynamicMessage backed by alternate_pool
     96 // in order to handle this case.
     97 void CollectExtensions(const FileDescriptorProto& file_proto,
     98                        const DescriptorPool& alternate_pool,
     99                        vector<const FieldDescriptor*>* extensions,
    100                        const string& file_data) {
    101   if (!CollectExtensions(file_proto, extensions)) {
    102     // There are unknown fields in the file_proto, which are probably
    103     // extensions. We need to parse the data into a dynamic message based on the
    104     // builder-pool to find out all extensions.
    105     const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
    106         file_proto.GetDescriptor()->full_name());
    107     GOOGLE_CHECK(file_proto_desc)
    108         << "Find unknown fields in FileDescriptorProto when building "
    109         << file_proto.name()
    110         << ". It's likely that those fields are custom options, however, "
    111            "descriptor.proto is not in the transitive dependencies. "
    112            "This normally should not happen. Please report a bug.";
    113     DynamicMessageFactory factory;
    114     scoped_ptr<Message> dynamic_file_proto(
    115         factory.GetPrototype(file_proto_desc)->New());
    116     GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
    117     GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
    118 
    119     // Collect the extensions again from the dynamic message. There should be no
    120     // more unknown fields this time, i.e. all the custom options should be
    121     // parsed as extensions now.
    122     extensions->clear();
    123     GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
    124         << "Find unknown fields in FileDescriptorProto when building "
    125         << file_proto.name()
    126         << ". It's likely that those fields are custom options, however, "
    127            "those options cannot be recognized in the builder pool. "
    128            "This normally should not happen. Please report a bug.";
    129   }
    130 }
    131 
    132 
    133 }  // namespace
    134 
    135 FileGenerator::FileGenerator(const FileDescriptor* file)
    136   : file_(file),
    137     java_package_(FileJavaPackage(file)),
    138     classname_(FileClassName(file)) {
    139 }
    140 
    141 FileGenerator::~FileGenerator() {}
    142 
    143 bool FileGenerator::Validate(string* error) {
    144   // Check that no class name matches the file's class name.  This is a common
    145   // problem that leads to Java compile errors that can be hard to understand.
    146   // It's especially bad when using the java_multiple_files, since we would
    147   // end up overwriting the outer class with one of the inner ones.
    148 
    149   bool found_conflict = false;
    150   for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) {
    151     if (file_->enum_type(i)->name() == classname_) {
    152       found_conflict = true;
    153     }
    154   }
    155   for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) {
    156     if (file_->message_type(i)->name() == classname_) {
    157       found_conflict = true;
    158     }
    159   }
    160   for (int i = 0; i < file_->service_count() && !found_conflict; i++) {
    161     if (file_->service(i)->name() == classname_) {
    162       found_conflict = true;
    163     }
    164   }
    165 
    166   if (found_conflict) {
    167     error->assign(file_->name());
    168     error->append(
    169       ": Cannot generate Java output because the file's outer class name, \"");
    170     error->append(classname_);
    171     error->append(
    172       "\", matches the name of one of the types declared inside it.  "
    173       "Please either rename the type or use the java_outer_classname "
    174       "option to specify a different outer class name for the .proto file.");
    175     return false;
    176   }
    177 
    178   return true;
    179 }
    180 
    181 void FileGenerator::Generate(io::Printer* printer) {
    182   // We don't import anything because we refer to all classes by their
    183   // fully-qualified names in the generated source.
    184   printer->Print(
    185     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    186     "// source: $filename$\n"
    187     "\n",
    188     "filename", file_->name());
    189   if (!java_package_.empty()) {
    190     printer->Print(
    191       "package $package$;\n"
    192       "\n",
    193       "package", java_package_);
    194   }
    195   printer->Print(
    196     "public final class $classname$ {\n"
    197     "  private $classname$() {}\n",
    198     "classname", classname_);
    199   printer->Indent();
    200 
    201   // -----------------------------------------------------------------
    202 
    203   printer->Print(
    204     "public static void registerAllExtensions(\n"
    205     "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
    206     "lite", HasDescriptorMethods(file_) ? "" : "Lite");
    207 
    208   printer->Indent();
    209 
    210   for (int i = 0; i < file_->extension_count(); i++) {
    211     ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer);
    212   }
    213 
    214   for (int i = 0; i < file_->message_type_count(); i++) {
    215     MessageGenerator(file_->message_type(i))
    216       .GenerateExtensionRegistrationCode(printer);
    217   }
    218 
    219   printer->Outdent();
    220   printer->Print(
    221     "}\n");
    222 
    223   // -----------------------------------------------------------------
    224 
    225   if (!file_->options().java_multiple_files()) {
    226     for (int i = 0; i < file_->enum_type_count(); i++) {
    227       EnumGenerator(file_->enum_type(i)).Generate(printer);
    228     }
    229     for (int i = 0; i < file_->message_type_count(); i++) {
    230       MessageGenerator messageGenerator(file_->message_type(i));
    231       messageGenerator.GenerateInterface(printer);
    232       messageGenerator.Generate(printer);
    233     }
    234     if (HasGenericServices(file_)) {
    235       for (int i = 0; i < file_->service_count(); i++) {
    236         ServiceGenerator(file_->service(i)).Generate(printer);
    237       }
    238     }
    239   }
    240 
    241   // Extensions must be generated in the outer class since they are values,
    242   // not classes.
    243   for (int i = 0; i < file_->extension_count(); i++) {
    244     ExtensionGenerator(file_->extension(i)).Generate(printer);
    245   }
    246 
    247   // Static variables.
    248   for (int i = 0; i < file_->message_type_count(); i++) {
    249     // TODO(kenton):  Reuse MessageGenerator objects?
    250     MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer);
    251   }
    252 
    253   printer->Print("\n");
    254 
    255   if (HasDescriptorMethods(file_)) {
    256     GenerateEmbeddedDescriptor(printer);
    257   } else {
    258     printer->Print(
    259       "static {\n");
    260     printer->Indent();
    261 
    262     for (int i = 0; i < file_->message_type_count(); i++) {
    263       // TODO(kenton):  Reuse MessageGenerator objects?
    264       MessageGenerator(file_->message_type(i))
    265         .GenerateStaticVariableInitializers(printer);
    266     }
    267 
    268     printer->Outdent();
    269     printer->Print(
    270       "}\n");
    271   }
    272 
    273   printer->Print(
    274     "\n"
    275     "// @@protoc_insertion_point(outer_class_scope)\n");
    276 
    277   printer->Outdent();
    278   printer->Print("}\n");
    279 }
    280 
    281 void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
    282   // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
    283   // and embed it as a string literal, which is parsed and built into real
    284   // descriptors at initialization time.  We unfortunately have to put it in
    285   // a string literal, not a byte array, because apparently using a literal
    286   // byte array causes the Java compiler to generate *instructions* to
    287   // initialize each and every byte of the array, e.g. as if you typed:
    288   //   b[0] = 123; b[1] = 456; b[2] = 789;
    289   // This makes huge bytecode files and can easily hit the compiler's internal
    290   // code size limits (error "code to large").  String literals are apparently
    291   // embedded raw, which is what we want.
    292   FileDescriptorProto file_proto;
    293   file_->CopyTo(&file_proto);
    294 
    295   string file_data;
    296   file_proto.SerializeToString(&file_data);
    297 
    298   printer->Print(
    299     "public static com.google.protobuf.Descriptors.FileDescriptor\n"
    300     "    getDescriptor() {\n"
    301     "  return descriptor;\n"
    302     "}\n"
    303     "private static com.google.protobuf.Descriptors.FileDescriptor\n"
    304     "    descriptor;\n"
    305     "static {\n"
    306     "  java.lang.String[] descriptorData = {\n");
    307   printer->Indent();
    308   printer->Indent();
    309 
    310   // Only write 40 bytes per line.
    311   static const int kBytesPerLine = 40;
    312   for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
    313     if (i > 0) {
    314       // Every 400 lines, start a new string literal, in order to avoid the
    315       // 64k length limit.
    316       if (i % 400 == 0) {
    317         printer->Print(",\n");
    318       } else {
    319         printer->Print(" +\n");
    320       }
    321     }
    322     printer->Print("\"$data$\"",
    323       "data", CEscape(file_data.substr(i, kBytesPerLine)));
    324   }
    325 
    326   printer->Outdent();
    327   printer->Print("\n};\n");
    328 
    329   // -----------------------------------------------------------------
    330   // Create the InternalDescriptorAssigner.
    331 
    332   printer->Print(
    333     "com.google.protobuf.Descriptors.FileDescriptor."
    334       "InternalDescriptorAssigner assigner =\n"
    335     "  new com.google.protobuf.Descriptors.FileDescriptor."
    336       "InternalDescriptorAssigner() {\n"
    337     "    public com.google.protobuf.ExtensionRegistry assignDescriptors(\n"
    338     "        com.google.protobuf.Descriptors.FileDescriptor root) {\n"
    339     "      descriptor = root;\n");
    340 
    341   printer->Indent();
    342   printer->Indent();
    343   printer->Indent();
    344 
    345   for (int i = 0; i < file_->message_type_count(); i++) {
    346     // TODO(kenton):  Reuse MessageGenerator objects?
    347     MessageGenerator(file_->message_type(i))
    348       .GenerateStaticVariableInitializers(printer);
    349   }
    350   for (int i = 0; i < file_->extension_count(); i++) {
    351     // TODO(kenton):  Reuse ExtensionGenerator objects?
    352     ExtensionGenerator(file_->extension(i))
    353         .GenerateNonNestedInitializationCode(printer);
    354   }
    355 
    356   // Proto compiler builds a DescriptorPool, which holds all the descriptors to
    357   // generate, when processing the ".proto" files. We call this DescriptorPool
    358   // the parsed pool (a.k.a. file_->pool()).
    359   //
    360   // Note that when users try to extend the (.*)DescriptorProto in their
    361   // ".proto" files, it does not affect the pre-built FileDescriptorProto class
    362   // in proto compiler. When we put the descriptor data in the file_proto, those
    363   // extensions become unknown fields.
    364   //
    365   // Now we need to find out all the extension value to the (.*)DescriptorProto
    366   // in the file_proto message, and prepare an ExtensionRegistry to return.
    367   //
    368   // To find those extensions, we need to parse the data into a dynamic message
    369   // of the FileDescriptor based on the builder-pool, then we can use
    370   // reflections to find all extension fields
    371   vector<const FieldDescriptor*> extensions;
    372   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
    373 
    374   if (extensions.size() > 0) {
    375     // Must construct an ExtensionRegistry containing all existing extensions
    376     // and return it.
    377     printer->Print(
    378       "com.google.protobuf.ExtensionRegistry registry =\n"
    379       "  com.google.protobuf.ExtensionRegistry.newInstance();\n");
    380     for (int i = 0; i < extensions.size(); i++) {
    381       ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
    382     }
    383     printer->Print(
    384       "return registry;\n");
    385   } else {
    386     printer->Print(
    387       "return null;\n");
    388   }
    389 
    390   printer->Outdent();
    391   printer->Outdent();
    392   printer->Outdent();
    393 
    394   printer->Print(
    395     "    }\n"
    396     "  };\n");
    397 
    398   // -----------------------------------------------------------------
    399   // Invoke internalBuildGeneratedFileFrom() to build the file.
    400 
    401   printer->Print(
    402     "com.google.protobuf.Descriptors.FileDescriptor\n"
    403     "  .internalBuildGeneratedFileFrom(descriptorData,\n"
    404     "    new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
    405 
    406   for (int i = 0; i < file_->dependency_count(); i++) {
    407     if (ShouldIncludeDependency(file_->dependency(i))) {
    408       printer->Print(
    409         "      $dependency$.getDescriptor(),\n",
    410         "dependency", ClassName(file_->dependency(i)));
    411     }
    412   }
    413 
    414   printer->Print(
    415     "    }, assigner);\n");
    416 
    417   printer->Outdent();
    418   printer->Print(
    419     "}\n");
    420 }
    421 
    422 template<typename GeneratorClass, typename DescriptorClass>
    423 static void GenerateSibling(const string& package_dir,
    424                             const string& java_package,
    425                             const DescriptorClass* descriptor,
    426                             GeneratorContext* context,
    427                             vector<string>* file_list,
    428                             const string& name_suffix,
    429                             void (GeneratorClass::*pfn)(io::Printer* printer)) {
    430   string filename = package_dir + descriptor->name() + name_suffix + ".java";
    431   file_list->push_back(filename);
    432 
    433   scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
    434   io::Printer printer(output.get(), '$');
    435 
    436   printer.Print(
    437     "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    438     "// source: $filename$\n"
    439     "\n",
    440     "filename", descriptor->file()->name());
    441   if (!java_package.empty()) {
    442     printer.Print(
    443       "package $package$;\n"
    444       "\n",
    445       "package", java_package);
    446   }
    447 
    448   GeneratorClass generator(descriptor);
    449   (generator.*pfn)(&printer);
    450 }
    451 
    452 void FileGenerator::GenerateSiblings(const string& package_dir,
    453                                      GeneratorContext* context,
    454                                      vector<string>* file_list) {
    455   if (file_->options().java_multiple_files()) {
    456     for (int i = 0; i < file_->enum_type_count(); i++) {
    457       GenerateSibling<EnumGenerator>(package_dir, java_package_,
    458                                      file_->enum_type(i),
    459                                      context, file_list, "",
    460                                      &EnumGenerator::Generate);
    461     }
    462     for (int i = 0; i < file_->message_type_count(); i++) {
    463       GenerateSibling<MessageGenerator>(package_dir, java_package_,
    464                                         file_->message_type(i),
    465                                         context, file_list, "OrBuilder",
    466                                         &MessageGenerator::GenerateInterface);
    467       GenerateSibling<MessageGenerator>(package_dir, java_package_,
    468                                         file_->message_type(i),
    469                                         context, file_list, "",
    470                                         &MessageGenerator::Generate);
    471     }
    472     if (HasGenericServices(file_)) {
    473       for (int i = 0; i < file_->service_count(); i++) {
    474         GenerateSibling<ServiceGenerator>(package_dir, java_package_,
    475                                           file_->service(i),
    476                                           context, file_list, "",
    477                                           &ServiceGenerator::Generate);
    478       }
    479     }
    480   }
    481 }
    482 
    483 bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
    484   return true;
    485 }
    486 
    487 }  // namespace java
    488 }  // namespace compiler
    489 }  // namespace protobuf
    490 }  // namespace google
    491