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@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/javanano/javanano_params.h> 36#include <google/protobuf/compiler/javanano/javanano_generator.h> 37#include <google/protobuf/compiler/javanano/javanano_file.h> 38#include <google/protobuf/compiler/javanano/javanano_helpers.h> 39#include <google/protobuf/io/printer.h> 40#include <google/protobuf/io/zero_copy_stream.h> 41#include <google/protobuf/descriptor.pb.h> 42#include <google/protobuf/stubs/strutil.h> 43 44namespace google { 45namespace protobuf { 46namespace compiler { 47namespace javanano { 48 49namespace { 50 51string TrimString(const string& s) { 52 string::size_type start = s.find_first_not_of(" \n\r\t"); 53 if (start == string::npos) { 54 return ""; 55 } 56 string::size_type end = s.find_last_not_of(" \n\r\t") + 1; 57 return s.substr(start, end - start); 58} 59 60} // namespace 61 62void UpdateParamsRecursively(Params& params, 63 const FileDescriptor* file) { 64 // Add any parameters for this file 65 if (file->options().has_java_outer_classname()) { 66 params.set_java_outer_classname( 67 file->name(), file->options().java_outer_classname()); 68 } 69 if (file->options().has_java_package()) { 70 params.set_java_package( 71 file->name(), file->options().java_package()); 72 } 73 if (file->options().has_java_multiple_files()) { 74 params.set_java_multiple_files( 75 file->name(), file->options().java_multiple_files()); 76 } 77 78 // Loop through all dependent files recursively 79 // adding dep 80 for (int i = 0; i < file->dependency_count(); i++) { 81 UpdateParamsRecursively(params, file->dependency(i)); 82 } 83} 84 85JavaNanoGenerator::JavaNanoGenerator() {} 86JavaNanoGenerator::~JavaNanoGenerator() {} 87 88bool JavaNanoGenerator::Generate(const FileDescriptor* file, 89 const string& parameter, 90 OutputDirectory* output_directory, 91 string* error) const { 92 vector<pair<string, string> > options; 93 94 ParseGeneratorParameter(parameter, &options); 95 96 // ----------------------------------------------------------------- 97 // parse generator options 98 99 // Name a file where we will write a list of generated file names, one 100 // per line. 101 string output_list_file; 102 Params params(file->name()); 103 104 // Update per file params 105 UpdateParamsRecursively(params, file); 106 107 // Replace any existing options with ones from command line 108 for (int i = 0; i < options.size(); i++) { 109 string option_name = TrimString(options[i].first); 110 string option_value = TrimString(options[i].second); 111 if (option_name == "output_list_file") { 112 output_list_file = option_value; 113 } else if (option_name == "java_package") { 114 vector<string> parts; 115 SplitStringUsing(option_value, "|", &parts); 116 if (parts.size() != 2) { 117 *error = "Bad java_package, expecting filename|PackageName found '" 118 + option_value + "'"; 119 return false; 120 } 121 params.set_java_package(parts[0], parts[1]); 122 } else if (option_name == "java_outer_classname") { 123 vector<string> parts; 124 SplitStringUsing(option_value, "|", &parts); 125 if (parts.size() != 2) { 126 *error = "Bad java_outer_classname, " 127 "expecting filename|ClassName found '" 128 + option_value + "'"; 129 return false; 130 } 131 params.set_java_outer_classname(parts[0], parts[1]); 132 } else if (option_name == "store_unknown_fields") { 133 params.set_store_unknown_fields(option_value == "true"); 134 } else if (option_name == "java_multiple_files") { 135 params.set_override_java_multiple_files(option_value == "true"); 136 } else if (option_name == "java_nano_generate_has") { 137 params.set_generate_has(option_value == "true"); 138 } else if (option_name == "enum_style") { 139 params.set_java_enum_style(option_value == "java"); 140 } else if (option_name == "optional_field_style") { 141 params.set_optional_field_accessors(option_value == "accessors"); 142 params.set_use_reference_types_for_primitives(option_value == "reftypes"); 143 } else if (option_name == "generate_equals") { 144 params.set_generate_equals(option_value == "true"); 145 } else if (option_name == "ignore_services") { 146 params.set_ignore_services(option_value == "true"); 147 } else if (option_name == "parcelable_messages") { 148 params.set_parcelable_messages(option_value == "true"); 149 } else { 150 *error = "Ignore unknown javanano generator option: " + option_name; 151 } 152 } 153 154 // Check illegal parameter combinations 155 // Note: the enum-like optional_field_style generator param ensures 156 // that we can never have illegal combinations of field styles 157 // (e.g. reftypes and accessors can't be on at the same time). 158 if (params.generate_has() 159 && (params.optional_field_accessors() 160 || params.use_reference_types_for_primitives())) { 161 error->assign("java_nano_generate_has=true cannot be used in conjunction" 162 " with optional_field_style=accessors or optional_field_style=reftypes"); 163 return false; 164 } 165 166 // ----------------------------------------------------------------- 167 168 FileGenerator file_generator(file, params); 169 if (!file_generator.Validate(error)) { 170 return false; 171 } 172 173 string package_dir = 174 StringReplace(file_generator.java_package(), ".", "/", true); 175 if (!package_dir.empty()) package_dir += "/"; 176 177 vector<string> all_files; 178 179 if (IsOuterClassNeeded(params, file)) { 180 string java_filename = package_dir; 181 java_filename += file_generator.classname(); 182 java_filename += ".java"; 183 all_files.push_back(java_filename); 184 185 // Generate main java file. 186 scoped_ptr<io::ZeroCopyOutputStream> output( 187 output_directory->Open(java_filename)); 188 io::Printer printer(output.get(), '$'); 189 file_generator.Generate(&printer); 190 } 191 192 // Generate sibling files. 193 file_generator.GenerateSiblings(package_dir, output_directory, &all_files); 194 195 // Generate output list if requested. 196 if (!output_list_file.empty()) { 197 // Generate output list. This is just a simple text file placed in a 198 // deterministic location which lists the .java files being generated. 199 scoped_ptr<io::ZeroCopyOutputStream> srclist_raw_output( 200 output_directory->Open(output_list_file)); 201 io::Printer srclist_printer(srclist_raw_output.get(), '$'); 202 for (int i = 0; i < all_files.size(); i++) { 203 srclist_printer.Print("$filename$\n", "filename", all_files[i]); 204 } 205 } 206 207 return true; 208} 209 210} // namespace java 211} // namespace compiler 212} // namespace protobuf 213} // namespace google 214