15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/java/java_file.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/java/java_enum.h>
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/java/java_service.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/java/java_extension.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/java/java_helpers.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/java/java_message.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/compiler/code_generator.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/printer.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/zero_copy_stream.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.pb.h>
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include <google/protobuf/dynamic_message.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace compiler {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace java {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Recursively searches the given message to collect extensions.
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Returns true if all the extensions can be recognized. The extensions will be
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// appended in to the extensions parameter.
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Returns false when there are unknown fields, in which case the data in the
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// extensions output parameter is not reliable and should be discarded.
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool CollectExtensions(const Message& message,
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       vector<const FieldDescriptor*>* extensions) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Reflection* reflection = message.GetReflection();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // There are unknown fields that could be extensions, thus this call fails.
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (reflection->GetUnknownFields(message).field_count() > 0) return false;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vector<const FieldDescriptor*> fields;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  reflection->ListFields(message, &fields);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < fields.size(); i++) {
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (fields[i]->is_extension()) extensions->push_back(fields[i]);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (fields[i]->is_repeated()) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int size = reflection->FieldSize(message, fields[i]);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int j = 0; j < size; j++) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const Message& sub_message =
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reflection->GetRepeatedMessage(message, fields[i], j);
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          if (!CollectExtensions(sub_message, extensions)) return false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const Message& sub_message = reflection->GetMessage(message, fields[i]);
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        if (!CollectExtensions(sub_message, extensions)) return false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return true;
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Finds all extensions in the given message and its sub-messages.  If the
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// message contains unknown fields (which could be extensions), then those
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// extensions are defined in alternate_pool.
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// The message will be converted to a DynamicMessage backed by alternate_pool
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// in order to handle this case.
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid CollectExtensions(const FileDescriptorProto& file_proto,
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       const DescriptorPool& alternate_pool,
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       vector<const FieldDescriptor*>* extensions,
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       const string& file_data) {
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!CollectExtensions(file_proto, extensions)) {
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // There are unknown fields in the file_proto, which are probably
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // extensions. We need to parse the data into a dynamic message based on the
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // builder-pool to find out all extensions.
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        file_proto.GetDescriptor()->full_name());
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GOOGLE_CHECK(file_proto_desc)
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        << "Find unknown fields in FileDescriptorProto when building "
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        << file_proto.name()
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        << ". It's likely that those fields are custom options, however, "
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           "descriptor.proto is not in the transitive dependencies. "
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           "This normally should not happen. Please report a bug.";
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DynamicMessageFactory factory;
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_ptr<Message> dynamic_file_proto(
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        factory.GetPrototype(file_proto_desc)->New());
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Collect the extensions again from the dynamic message. There should be no
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // more unknown fields this time, i.e. all the custom options should be
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // parsed as extensions now.
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    extensions->clear();
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        << "Find unknown fields in FileDescriptorProto when building "
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        << file_proto.name()
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        << ". It's likely that those fields are custom options, however, "
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           "those options cannot be recognized in the builder pool. "
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch           "This normally should not happen. Please report a bug.";
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileGenerator::FileGenerator(const FileDescriptor* file)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : file_(file),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    java_package_(FileJavaPackage(file)),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    classname_(FileClassName(file)) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FileGenerator::~FileGenerator() {}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FileGenerator::Validate(string* error) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that no class name matches the file's class name.  This is a common
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // problem that leads to Java compile errors that can be hard to understand.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's especially bad when using the java_multiple_files, since we would
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // end up overwriting the outer class with one of the inner ones.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_conflict = false;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_->enum_type(i)->name() == classname_) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_conflict = true;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_->message_type(i)->name() == classname_) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_conflict = true;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->service_count() && !found_conflict; i++) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_->service(i)->name() == classname_) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_conflict = true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (found_conflict) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error->assign(file_->name());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error->append(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ": Cannot generate Java output because the file's outer class name, \"");
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error->append(classname_);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error->append(
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\", matches the name of one of the types declared inside it.  "
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Please either rename the type or use the java_outer_classname "
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "option to specify a different outer class name for the .proto file.");
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FileGenerator::Generate(io::Printer* printer) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't import anything because we refer to all classes by their
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fully-qualified names in the generated source.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// source: $filename$\n"
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n",
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "filename", file_->name());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!java_package_.empty()) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "package $package$;\n"
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n",
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "package", java_package_);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "public final class $classname$ {\n"
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  private $classname$() {}\n",
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "classname", classname_);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "public static void registerAllExtensions(\n"
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "lite", HasDescriptorMethods(file_) ? "" : "Lite");
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->extension_count(); i++) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); i++) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageGenerator(file_->message_type(i))
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .GenerateExtensionRegistrationCode(printer);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_->options().java_multiple_files()) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < file_->enum_type_count(); i++) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EnumGenerator(file_->enum_type(i)).Generate(printer);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < file_->message_type_count(); i++) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageGenerator messageGenerator(file_->message_type(i));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      messageGenerator.GenerateInterface(printer);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      messageGenerator.Generate(printer);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasGenericServices(file_)) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < file_->service_count(); i++) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ServiceGenerator(file_->service(i)).Generate(printer);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extensions must be generated in the outer class since they are values,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not classes.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->extension_count(); i++) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionGenerator(file_->extension(i)).Generate(printer);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Static variables.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); i++) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kenton):  Reuse MessageGenerator objects?
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n");
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasDescriptorMethods(file_)) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GenerateEmbeddedDescriptor(printer);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "static {\n");
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Indent();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < file_->message_type_count(); i++) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(kenton):  Reuse MessageGenerator objects?
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageGenerator(file_->message_type(i))
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .GenerateStaticVariableInitializers(printer);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Outdent();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}\n");
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\n"
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// @@protoc_insertion_point(outer_class_scope)\n");
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("}\n");
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Embed the descriptor.  We simply serialize the entire FileDescriptorProto
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and embed it as a string literal, which is parsed and built into real
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptors at initialization time.  We unfortunately have to put it in
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a string literal, not a byte array, because apparently using a literal
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // byte array causes the Java compiler to generate *instructions* to
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initialize each and every byte of the array, e.g. as if you typed:
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   b[0] = 123; b[1] = 456; b[2] = 789;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This makes huge bytecode files and can easily hit the compiler's internal
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // code size limits (error "code to large").  String literals are apparently
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // embedded raw, which is what we want.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorProto file_proto;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_->CopyTo(&file_proto);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string file_data;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_proto.SerializeToString(&file_data);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "public static com.google.protobuf.Descriptors.FileDescriptor\n"
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    getDescriptor() {\n"
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  return descriptor;\n"
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n"
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "private static com.google.protobuf.Descriptors.FileDescriptor\n"
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    descriptor;\n"
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "static {\n"
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  java.lang.String[] descriptorData = {\n");
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only write 40 bytes per line.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kBytesPerLine = 40;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i > 0) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Every 400 lines, start a new string literal, in order to avoid the
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 64k length limit.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i % 400 == 0) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(",\n");
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        printer->Print(" +\n");
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print("\"$data$\"",
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "data", CEscape(file_data.substr(i, kBytesPerLine)));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print("\n};\n");
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the InternalDescriptorAssigner.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "com.google.protobuf.Descriptors.FileDescriptor."
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "InternalDescriptorAssigner assigner =\n"
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  new com.google.protobuf.Descriptors.FileDescriptor."
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "InternalDescriptorAssigner() {\n"
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    public com.google.protobuf.ExtensionRegistry assignDescriptors(\n"
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "        com.google.protobuf.Descriptors.FileDescriptor root) {\n"
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "      descriptor = root;\n");
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Indent();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->message_type_count(); i++) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kenton):  Reuse MessageGenerator objects?
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageGenerator(file_->message_type(i))
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .GenerateStaticVariableInitializers(printer);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->extension_count(); i++) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kenton):  Reuse ExtensionGenerator objects?
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionGenerator(file_->extension(i))
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .GenerateNonNestedInitializationCode(printer);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Proto compiler builds a DescriptorPool, which holds all the descriptors to
357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // generate, when processing the ".proto" files. We call this DescriptorPool
358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the parsed pool (a.k.a. file_->pool()).
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Note that when users try to extend the (.*)DescriptorProto in their
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // ".proto" files, it does not affect the pre-built FileDescriptorProto class
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // in proto compiler. When we put the descriptor data in the file_proto, those
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // extensions become unknown fields.
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Now we need to find out all the extension value to the (.*)DescriptorProto
366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // in the file_proto message, and prepare an ExtensionRegistry to return.
367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // To find those extensions, we need to parse the data into a dynamic message
369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // of the FileDescriptor based on the builder-pool, then we can use
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // reflections to find all extension fields
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  vector<const FieldDescriptor*> extensions;
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
373ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
374ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (extensions.size() > 0) {
375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Must construct an ExtensionRegistry containing all existing extensions
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and return it.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "com.google.protobuf.ExtensionRegistry registry =\n"
379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "  com.google.protobuf.ExtensionRegistry.newInstance();\n");
380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    for (int i = 0; i < extensions.size(); i++) {
381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return registry;\n");
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer->Print(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "return null;\n");
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    }\n"
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  };\n");
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke internalBuildGeneratedFileFrom() to build the file.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "com.google.protobuf.Descriptors.FileDescriptor\n"
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "  .internalBuildGeneratedFileFrom(descriptorData,\n"
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < file_->dependency_count(); i++) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldIncludeDependency(file_->dependency(i))) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printer->Print(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "      $dependency$.getDescriptor(),\n",
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "dependency", ClassName(file_->dependency(i)));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "    }, assigner);\n");
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Outdent();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer->Print(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "}\n");
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename GeneratorClass, typename DescriptorClass>
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void GenerateSibling(const string& package_dir,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const string& java_package,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const DescriptorClass* descriptor,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            GeneratorContext* context,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            vector<string>* file_list,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const string& name_suffix,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            void (GeneratorClass::*pfn)(io::Printer* printer)) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename = package_dir + descriptor->name() + name_suffix + ".java";
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_list->push_back(filename);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::Printer printer(output.get(), '$');
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printer.Print(
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    "// source: $filename$\n"
439ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    "\n",
440ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    "filename", descriptor->file()->name());
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!java_package.empty()) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printer.Print(
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "package $package$;\n"
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\n",
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "package", java_package);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GeneratorClass generator(descriptor);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (generator.*pfn)(&printer);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FileGenerator::GenerateSiblings(const string& package_dir,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     GeneratorContext* context,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     vector<string>* file_list) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_->options().java_multiple_files()) {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < file_->enum_type_count(); i++) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSibling<EnumGenerator>(package_dir, java_package_,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     file_->enum_type(i),
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     context, file_list, "",
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &EnumGenerator::Generate);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < file_->message_type_count(); i++) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSibling<MessageGenerator>(package_dir, java_package_,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        file_->message_type(i),
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        context, file_list, "OrBuilder",
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &MessageGenerator::GenerateInterface);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GenerateSibling<MessageGenerator>(package_dir, java_package_,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        file_->message_type(i),
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        context, file_list, "",
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        &MessageGenerator::Generate);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasGenericServices(file_)) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < file_->service_count(); i++) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GenerateSibling<ServiceGenerator>(package_dir, java_package_,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          file_->service(i),
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          context, file_list, "",
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          &ServiceGenerator::Generate);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace java
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace compiler
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
491