1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11
12 #include "google/protobuf/compiler/java/full/message.h"
13
14 #include <algorithm>
15 #include <cstdint>
16 #include <memory>
17 #include <string>
18 #include <vector>
19
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/log/absl_check.h"
22 #include "absl/strings/ascii.h"
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/string_view.h"
25 #include "absl/strings/substitute.h"
26 #include "google/protobuf/compiler/java/context.h"
27 #include "google/protobuf/compiler/java/doc_comment.h"
28 #include "google/protobuf/compiler/java/field_common.h"
29 #include "google/protobuf/compiler/java/generator_common.h"
30 #include "google/protobuf/compiler/java/helpers.h"
31 #include "google/protobuf/compiler/java/full/enum.h"
32 #include "google/protobuf/compiler/java/full/extension.h"
33 #include "google/protobuf/compiler/java/full/make_field_gens.h"
34 #include "google/protobuf/compiler/java/full/message_builder.h"
35 #include "google/protobuf/compiler/java/message_serialization.h"
36 #include "google/protobuf/compiler/java/name_resolver.h"
37 #include "google/protobuf/descriptor.h"
38 #include "google/protobuf/descriptor.pb.h"
39 #include "google/protobuf/io/coded_stream.h"
40 #include "google/protobuf/io/printer.h"
41 #include "google/protobuf/wire_format.h"
42
43 // Must be last.
44 #include "google/protobuf/port_def.inc"
45
46 namespace google {
47 namespace protobuf {
48 namespace compiler {
49 namespace java {
50
51 using internal::WireFormat;
52 using internal::WireFormatLite;
53
54 namespace {
MapValueImmutableClassdName(const Descriptor * descriptor,ClassNameResolver * name_resolver)55 std::string MapValueImmutableClassdName(const Descriptor* descriptor,
56 ClassNameResolver* name_resolver) {
57 const FieldDescriptor* value_field = descriptor->map_value();
58 ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
59 return name_resolver->GetImmutableClassName(value_field->message_type());
60 }
61 } // namespace
62
63 // ===================================================================
64
MessageGenerator(const Descriptor * descriptor)65 MessageGenerator::MessageGenerator(const Descriptor* descriptor)
66 : descriptor_(descriptor) {
67 for (int i = 0; i < descriptor_->field_count(); i++) {
68 if (IsRealOneof(descriptor_->field(i))) {
69 const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof();
70 ABSL_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof);
71 }
72 }
73 }
74
~MessageGenerator()75 MessageGenerator::~MessageGenerator() {}
76
77 // ===================================================================
ImmutableMessageGenerator(const Descriptor * descriptor,Context * context)78 ImmutableMessageGenerator::ImmutableMessageGenerator(
79 const Descriptor* descriptor, Context* context)
80 : MessageGenerator(descriptor),
81 context_(context),
82 name_resolver_(context->GetNameResolver()),
83 field_generators_(MakeImmutableFieldGenerators(descriptor, context_)) {
84 ABSL_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
85 << "Generator factory error: A non-lite message generator is used to "
86 "generate lite messages.";
87 }
88
~ImmutableMessageGenerator()89 ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
90
GenerateStaticVariables(io::Printer * printer,int * bytecode_estimate)91 void ImmutableMessageGenerator::GenerateStaticVariables(
92 io::Printer* printer, int* bytecode_estimate) {
93 // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
94 // used in the construction of descriptors, we have a tricky bootstrapping
95 // problem. To help control static initialization order, we make sure all
96 // descriptors and other static data that depends on them are members of
97 // the outermost class in the file. This way, they will be initialized in
98 // a deterministic order.
99
100 absl::flat_hash_map<absl::string_view, std::string> vars;
101 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
102 vars["index"] = absl::StrCat(descriptor_->index());
103 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
104 if (descriptor_->containing_type() != nullptr) {
105 vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
106 }
107 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
108 // We can only make these package-private since the classes that use them
109 // are in separate files.
110 vars["private"] = "";
111 } else {
112 vars["private"] = "private ";
113 }
114 if (*bytecode_estimate <= kMaxStaticSize) {
115 vars["final"] = "final ";
116 } else {
117 vars["final"] = "";
118 }
119
120 // The descriptor for this type.
121 printer->Print(
122 vars,
123 // TODO: final needs to be added back. The way to fix it is to
124 // generate methods that can construct the types, and then still declare
125 // the types, and then init them in clinit with the new method calls.
126 "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
127 " internal_$identifier$_descriptor;\n");
128 *bytecode_estimate += 30;
129
130 // And the FieldAccessorTable.
131 GenerateFieldAccessorTable(printer, bytecode_estimate);
132
133 // Generate static members for all nested types.
134 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
135 // TODO: Reuse MessageGenerator objects?
136 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
137 .GenerateStaticVariables(printer, bytecode_estimate);
138 }
139 }
140
GenerateStaticVariableInitializers(io::Printer * printer)141 int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
142 io::Printer* printer) {
143 int bytecode_estimate = 0;
144 absl::flat_hash_map<absl::string_view, std::string> vars;
145 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
146 vars["index"] = absl::StrCat(descriptor_->index());
147 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
148 if (descriptor_->containing_type() != nullptr) {
149 vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
150 }
151
152 // The descriptor for this type.
153 if (descriptor_->containing_type() == nullptr) {
154 printer->Print(vars,
155 "internal_$identifier$_descriptor =\n"
156 " getDescriptor().getMessageTypes().get($index$);\n");
157 bytecode_estimate += 30;
158 } else {
159 printer->Print(
160 vars,
161 "internal_$identifier$_descriptor =\n"
162 " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
163 bytecode_estimate += 30;
164 }
165
166 // And the FieldAccessorTable.
167 bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
168
169 // Generate static member initializers for all nested types.
170 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
171 // TODO: Reuse MessageGenerator objects?
172 bytecode_estimate +=
173 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
174 .GenerateStaticVariableInitializers(printer);
175 }
176 return bytecode_estimate;
177 }
178
GenerateFieldAccessorTable(io::Printer * printer,int * bytecode_estimate)179 void ImmutableMessageGenerator::GenerateFieldAccessorTable(
180 io::Printer* printer, int* bytecode_estimate) {
181 absl::flat_hash_map<absl::string_view, std::string> vars;
182 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
183 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
184 // We can only make these package-private since the classes that use them
185 // are in separate files.
186 vars["private"] = "";
187 } else {
188 vars["private"] = "private ";
189 }
190 if (*bytecode_estimate <= kMaxStaticSize) {
191 vars["final"] = "final ";
192 } else {
193 vars["final"] = "";
194 }
195 printer->Print(vars,
196 "$private$static $final$\n"
197 " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
198 " internal_$identifier$_fieldAccessorTable;\n");
199
200 // The following bytecode_estimate calculation logic must stay in sync with
201 // the similar logic in the GenerateFieldAccessorTableInitializer method below
202 // to make sure that the generated static final fields are initialized in the
203 // static initialization block directly.
204 //
205 // 6 bytes per field and oneof
206 *bytecode_estimate +=
207 10 + 6 * descriptor_->field_count() + 6 * descriptor_->oneof_decl_count();
208 }
209
GenerateFieldAccessorTableInitializer(io::Printer * printer)210 int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer(
211 io::Printer* printer) {
212 int bytecode_estimate = 10;
213 printer->Print(
214 "internal_$identifier$_fieldAccessorTable = new\n"
215 " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
216 " internal_$identifier$_descriptor,\n"
217 " new java.lang.String[] { ",
218 "identifier", UniqueFileScopeIdentifier(descriptor_));
219 // All the bytecode_estimate calculation logic in this method must stay in
220 // sync with the similar logic in the GenerateFieldAccessorTable method
221 // above. See the corresponding comment in GenerateFieldAccessorTable for
222 // details.
223 for (int i = 0; i < descriptor_->field_count(); i++) {
224 const FieldDescriptor* field = descriptor_->field(i);
225 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
226 bytecode_estimate += 6;
227 printer->Print("\"$field_name$\", ", "field_name", info->capitalized_name);
228 }
229
230 for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
231 const OneofDescriptor* oneof = descriptor_->real_oneof_decl(i);
232 const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
233 bytecode_estimate += 6;
234 printer->Print("\"$oneof_name$\", ", "oneof_name", info->capitalized_name);
235 }
236 printer->Print("});\n");
237 return bytecode_estimate;
238 }
239
240 // ===================================================================
241
GenerateInterface(io::Printer * printer)242 void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
243 MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
244 /* immutable = */ true, "OrBuilder");
245 if (!context_->options().opensource_runtime) {
246 printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
247 }
248 if (descriptor_->extension_range_count() > 0) {
249 printer->Print(
250 "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
251 " $extra_interfaces$\n"
252 " com.google.protobuf.GeneratedMessage.\n"
253 " ExtendableMessageOrBuilder<$classname$> {\n",
254 "deprecation",
255 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
256 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
257 "classname", descriptor_->name(), "{", "", "}", "");
258 } else {
259 printer->Print(
260 "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
261 " $extra_interfaces$\n"
262 " com.google.protobuf.MessageOrBuilder {\n",
263 "deprecation",
264 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
265 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
266 "classname", descriptor_->name(), "{", "", "}", "");
267 }
268 printer->Annotate("{", "}", descriptor_);
269
270 printer->Indent();
271 for (int i = 0; i < descriptor_->field_count(); i++) {
272 printer->Print("\n");
273 field_generators_.get(descriptor_->field(i))
274 .GenerateInterfaceMembers(printer);
275 }
276 for (auto& kv : oneofs_) {
277 printer->Print(
278 "\n"
279 "$classname$.$oneof_capitalized_name$Case "
280 "get$oneof_capitalized_name$Case();\n",
281 "oneof_capitalized_name",
282 context_->GetOneofGeneratorInfo(kv.second)->capitalized_name,
283 "classname",
284 context_->GetNameResolver()->GetImmutableClassName(descriptor_));
285 }
286 printer->Outdent();
287
288 printer->Print("}\n");
289 }
290
291 // ===================================================================
292
Generate(io::Printer * printer)293 void ImmutableMessageGenerator::Generate(io::Printer* printer) {
294 bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
295
296 absl::flat_hash_map<absl::string_view, std::string> variables;
297 variables["static"] = is_own_file ? "" : "static ";
298 variables["classname"] = descriptor_->name();
299 variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
300 variables["deprecation"] =
301 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";
302
303 WriteMessageDocComment(printer, descriptor_, context_->options());
304 MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
305 /* immutable = */ true);
306 if (!context_->options().opensource_runtime) {
307 printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
308 }
309
310 // The builder_type stores the super type name of the nested Builder class.
311 std::string builder_type;
312 if (descriptor_->extension_range_count() > 0) {
313 printer->Print(
314 variables,
315 "$deprecation$public $static$final class $classname$ extends\n");
316 printer->Annotate("classname", descriptor_);
317 printer->Print(
318 variables,
319 " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
320 " $classname$> implements\n"
321 " $extra_interfaces$\n"
322 " $classname$OrBuilder {\n");
323 builder_type = absl::Substitute(
324 "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
325 name_resolver_->GetImmutableClassName(descriptor_));
326 } else {
327 printer->Print(
328 variables,
329 "$deprecation$public $static$final class $classname$ extends\n");
330 printer->Annotate("classname", descriptor_);
331 printer->Print(variables,
332 " com.google.protobuf.GeneratedMessage implements\n"
333 " $extra_interfaces$\n"
334 " $classname$OrBuilder {\n");
335 builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
336 }
337 printer->Print("private static final long serialVersionUID = 0L;\n");
338
339 printer->Indent();
340
341 printer->Print("static {\n");
342 printer->Indent();
343 PrintGencodeVersionValidator(printer, context_->options().opensource_runtime,
344 descriptor_->name());
345 printer->Outdent();
346 printer->Print("}\n");
347
348 // Using builder_type, instead of Builder, prevents the Builder class from
349 // being loaded into PermGen space when the default instance is created.
350 // This optimizes the PermGen space usage for clients that do not modify
351 // messages.
352 printer->Print(
353 "// Use $classname$.newBuilder() to construct.\n"
354 "private $classname$($buildertype$ builder) {\n"
355 " super(builder);\n"
356 "}\n",
357 "classname", descriptor_->name(), "buildertype", builder_type);
358 printer->Print("private $classname$() {\n", "classname", descriptor_->name());
359 printer->Indent();
360 GenerateInitializers(printer);
361 printer->Outdent();
362 printer->Print(
363 "}\n"
364 "\n");
365
366 GenerateDescriptorMethods(printer);
367
368 // Nested types
369 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
370 EnumNonLiteGenerator(descriptor_->enum_type(i), true, context_)
371 .Generate(printer);
372 }
373
374 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
375 // Don't generate Java classes for map entry messages.
376 if (IsMapEntry(descriptor_->nested_type(i))) continue;
377 ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(i),
378 context_);
379 messageGenerator.GenerateInterface(printer);
380 messageGenerator.Generate(printer);
381 }
382
383 // Integers for bit fields.
384 int totalBits = 0;
385 for (int i = 0; i < descriptor_->field_count(); i++) {
386 totalBits +=
387 field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
388 }
389 int totalInts = (totalBits + 31) / 32;
390 for (int i = 0; i < totalInts; i++) {
391 printer->Print("private int $bit_field_name$;\n", "bit_field_name",
392 GetBitFieldName(i));
393 }
394
395 // oneof
396 absl::flat_hash_map<absl::string_view, std::string> vars;
397 for (auto& kv : oneofs_) {
398 const OneofDescriptor* oneof = kv.second;
399 vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
400 vars["oneof_capitalized_name"] =
401 context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
402 vars["oneof_index"] = absl::StrCat((oneof)->index());
403 vars["{"] = "";
404 vars["}"] = "";
405 // oneofCase_ and oneof_
406 printer->Print(vars,
407 "private int $oneof_name$Case_ = 0;\n"
408 "@SuppressWarnings(\"serial\")\n"
409 "private java.lang.Object $oneof_name$_;\n");
410 // OneofCase enum
411 printer->Print(
412 vars,
413 "public enum ${$$oneof_capitalized_name$Case$}$\n"
414 // TODO: Remove EnumLite when we want to break compatibility with
415 // 3.x users
416 " implements com.google.protobuf.Internal.EnumLite,\n"
417 " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
418 printer->Annotate("{", "}", oneof);
419 printer->Indent();
420 for (int j = 0; j < (oneof)->field_count(); j++) {
421 const FieldDescriptor* field = (oneof)->field(j);
422 printer->Print(
423 "$deprecation$$field_name$($field_number$),\n", "deprecation",
424 field->options().deprecated() ? "@java.lang.Deprecated " : "",
425 "field_name", absl::AsciiStrToUpper(field->name()), "field_number",
426 absl::StrCat(field->number()));
427 printer->Annotate("field_name", field);
428 }
429 printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
430 absl::AsciiStrToUpper(vars["oneof_name"]));
431 printer->Print(vars,
432 "private final int value;\n"
433 "private $oneof_capitalized_name$Case(int value) {\n"
434 " this.value = value;\n"
435 "}\n");
436 if (context_->options().opensource_runtime) {
437 printer->Print(
438 vars,
439 "/**\n"
440 " * @param value The number of the enum to look for.\n"
441 " * @return The enum associated with the given number.\n"
442 " * @deprecated Use {@link #forNumber(int)} instead.\n"
443 " */\n"
444 "@java.lang.Deprecated\n"
445 "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
446 " return forNumber(value);\n"
447 "}\n"
448 "\n");
449 }
450 if (!context_->options().opensource_runtime) {
451 printer->Print(
452 "@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n");
453 }
454 printer->Print(
455 vars,
456 "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
457 " switch (value) {\n");
458 for (int j = 0; j < (oneof)->field_count(); j++) {
459 const FieldDescriptor* field = (oneof)->field(j);
460 printer->Print(" case $field_number$: return $field_name$;\n",
461 "field_number", absl::StrCat(field->number()),
462 "field_name", absl::AsciiStrToUpper(field->name()));
463 }
464 printer->Print(
465 " case 0: return $cap_oneof_name$_NOT_SET;\n"
466 " default: return null;\n"
467 " }\n"
468 "}\n"
469 "public int getNumber() {\n"
470 " return this.value;\n"
471 "}\n",
472 "cap_oneof_name", absl::AsciiStrToUpper(vars["oneof_name"]));
473 printer->Outdent();
474 printer->Print("};\n\n");
475 // oneofCase()
476 printer->Print(vars,
477 "public $oneof_capitalized_name$Case\n"
478 "${$get$oneof_capitalized_name$Case$}$() {\n"
479 " return $oneof_capitalized_name$Case.forNumber(\n"
480 " $oneof_name$Case_);\n"
481 "}\n"
482 "\n");
483 printer->Annotate("{", "}", oneof);
484 }
485
486 if (IsAnyMessage(descriptor_)) {
487 GenerateAnyMethods(printer);
488 }
489
490 // Fields
491 for (int i = 0; i < descriptor_->field_count(); i++) {
492 printer->Print("public static final int $constant_name$ = $number$;\n",
493 "constant_name", FieldConstantName(descriptor_->field(i)),
494 "number", absl::StrCat(descriptor_->field(i)->number()));
495 printer->Annotate("constant_name", descriptor_->field(i));
496 field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
497 printer->Print("\n");
498 }
499
500 if (context_->HasGeneratedMethods(descriptor_)) {
501 GenerateIsInitialized(printer);
502 GenerateMessageSerializationMethods(printer);
503 GenerateEqualsAndHashCode(printer);
504 }
505
506
507 GenerateParseFromMethods(printer);
508 GenerateBuilder(printer);
509
510 printer->Print(
511 "\n"
512 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
513 "full_name", descriptor_->full_name());
514
515 // Carefully initialize the default instance in such a way that it doesn't
516 // conflict with other initialization.
517 printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n",
518 "classname",
519 name_resolver_->GetImmutableClassName(descriptor_));
520 printer->Print(
521 "static {\n"
522 " DEFAULT_INSTANCE = new $classname$();\n"
523 "}\n"
524 "\n",
525 "classname", name_resolver_->GetImmutableClassName(descriptor_));
526
527 printer->Print(
528 "public static $classname$ getDefaultInstance() {\n"
529 " return DEFAULT_INSTANCE;\n"
530 "}\n"
531 "\n",
532 "classname", name_resolver_->GetImmutableClassName(descriptor_));
533
534 // 'of' method for Wrappers
535 if (IsWrappersProtoFile(descriptor_->file())) {
536 printer->Print(
537 "public static $classname$ of($field_type$ value) {\n"
538 " return newBuilder().setValue(value).build();\n"
539 "}\n"
540 "\n",
541 "classname", name_resolver_->GetImmutableClassName(descriptor_),
542 "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
543 }
544
545 GenerateParser(printer);
546
547 printer->Print(
548 "@java.lang.Override\n"
549 "public $classname$ getDefaultInstanceForType() {\n"
550 " return DEFAULT_INSTANCE;\n"
551 "}\n"
552 "\n",
553 "classname", name_resolver_->GetImmutableClassName(descriptor_));
554
555 // Extensions must be declared after the DEFAULT_INSTANCE is initialized
556 // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
557 // the outer class's FileDescriptor.
558 for (int i = 0; i < descriptor_->extension_count(); i++) {
559 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
560 .Generate(printer);
561 }
562
563 printer->Outdent();
564 printer->Print("}\n\n");
565 }
566
567 // ===================================================================
568
GenerateMessageSerializationMethods(io::Printer * printer)569 void ImmutableMessageGenerator::GenerateMessageSerializationMethods(
570 io::Printer* printer) {
571 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
572 SortFieldsByNumber(descriptor_));
573
574 printer->Print(
575 "@java.lang.Override\n"
576 "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
577 " throws java.io.IOException {\n");
578 printer->Indent();
579
580 if (HasPackedFields(descriptor_)) {
581 // writeTo(CodedOutputStream output) might be invoked without
582 // getSerializedSize() ever being called, but we need the memoized
583 // sizes in case this message has packed fields. Rather than emit checks
584 // for each packed field, just call getSerializedSize() up front. In most
585 // cases, getSerializedSize() will have already been called anyway by one
586 // of the wrapper writeTo() methods, making this call cheap.
587 printer->Print("getSerializedSize();\n");
588 }
589
590 if (descriptor_->extension_range_count() > 0) {
591 if (descriptor_->options().message_set_wire_format()) {
592 printer->Print(
593 "com.google.protobuf.GeneratedMessage\n"
594 " .ExtendableMessage.ExtensionSerializer\n"
595 " extensionWriter = newMessageSetExtensionSerializer();\n");
596 } else {
597 printer->Print(
598 "com.google.protobuf.GeneratedMessage\n"
599 " .ExtendableMessage.ExtensionSerializer\n"
600 " extensionWriter = newExtensionSerializer();\n");
601 }
602 }
603
604 GenerateSerializeFieldsAndExtensions(printer,
605 field_generators_.field_generators(),
606 descriptor_, sorted_fields.get());
607
608 if (descriptor_->options().message_set_wire_format()) {
609 printer->Print("getUnknownFields().writeAsMessageSetTo(output);\n");
610 } else {
611 printer->Print("getUnknownFields().writeTo(output);\n");
612 }
613
614 printer->Outdent();
615 printer->Print(
616 "}\n"
617 "\n"
618 "@java.lang.Override\n"
619 "public int getSerializedSize() {\n"
620 " int size = memoizedSize;\n"
621 " if (size != -1) return size;\n"
622 "\n");
623 printer->Indent();
624
625 printer->Print("size = 0;\n");
626
627 for (int i = 0; i < descriptor_->field_count(); i++) {
628 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
629 }
630
631 if (descriptor_->extension_range_count() > 0) {
632 if (descriptor_->options().message_set_wire_format()) {
633 printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
634 } else {
635 printer->Print("size += extensionsSerializedSize();\n");
636 }
637 }
638
639 if (descriptor_->options().message_set_wire_format()) {
640 printer->Print(
641 "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
642 } else {
643 printer->Print("size += getUnknownFields().getSerializedSize();\n");
644 }
645
646 printer->Print(
647 "memoizedSize = size;\n"
648 "return size;\n");
649
650 printer->Outdent();
651 printer->Print(
652 "}\n"
653 "\n");
654 }
655
GenerateParseFromMethods(io::Printer * printer)656 void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) {
657 // Note: These are separate from GenerateMessageSerializationMethods()
658 // because they need to be generated even for messages that are optimized
659 // for code size.
660 printer->Print(
661 "public static $classname$ parseFrom(\n"
662 " java.nio.ByteBuffer data)\n"
663 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
664 " return PARSER.parseFrom(data);\n"
665 "}\n"
666 "public static $classname$ parseFrom(\n"
667 " java.nio.ByteBuffer data,\n"
668 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
669 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
670 " return PARSER.parseFrom(data, extensionRegistry);\n"
671 "}\n"
672 "public static $classname$ parseFrom(\n"
673 " com.google.protobuf.ByteString data)\n"
674 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
675 " return PARSER.parseFrom(data);\n"
676 "}\n"
677 "public static $classname$ parseFrom(\n"
678 " com.google.protobuf.ByteString data,\n"
679 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
680 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
681 " return PARSER.parseFrom(data, extensionRegistry);\n"
682 "}\n"
683 "public static $classname$ parseFrom(byte[] data)\n"
684 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
685 " return PARSER.parseFrom(data);\n"
686 "}\n"
687 "public static $classname$ parseFrom(\n"
688 " byte[] data,\n"
689 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
690 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
691 " return PARSER.parseFrom(data, extensionRegistry);\n"
692 "}\n"
693 "public static $classname$ parseFrom(java.io.InputStream input)\n"
694 " throws java.io.IOException {\n"
695 " return com.google.protobuf.GeneratedMessage\n"
696 " .parseWithIOException(PARSER, input);\n"
697 "}\n"
698 "public static $classname$ parseFrom(\n"
699 " java.io.InputStream input,\n"
700 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
701 " throws java.io.IOException {\n"
702 " return com.google.protobuf.GeneratedMessage\n"
703 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
704 "}\n"
705 "$parsedelimitedreturnannotation$\n"
706 "public static $classname$ parseDelimitedFrom(java.io.InputStream "
707 "input)\n"
708 " throws java.io.IOException {\n"
709 " return com.google.protobuf.GeneratedMessage\n"
710 " .parseDelimitedWithIOException(PARSER, input);\n"
711 "}\n"
712 "$parsedelimitedreturnannotation$\n"
713 "public static $classname$ parseDelimitedFrom(\n"
714 " java.io.InputStream input,\n"
715 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
716 " throws java.io.IOException {\n"
717 " return com.google.protobuf.GeneratedMessage\n"
718 " .parseDelimitedWithIOException(PARSER, input, "
719 "extensionRegistry);\n"
720 "}\n"
721 "public static $classname$ parseFrom(\n"
722 " com.google.protobuf.CodedInputStream input)\n"
723 " throws java.io.IOException {\n"
724 " return com.google.protobuf.GeneratedMessage\n"
725 " .parseWithIOException(PARSER, input);\n"
726 "}\n"
727 "public static $classname$ parseFrom(\n"
728 " com.google.protobuf.CodedInputStream input,\n"
729 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
730 " throws java.io.IOException {\n"
731 " return com.google.protobuf.GeneratedMessage\n"
732 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
733 "}\n"
734 "\n",
735 "classname", name_resolver_->GetImmutableClassName(descriptor_),
736 "parsedelimitedreturnannotation",
737 context_->options().opensource_runtime
738 ? ""
739 : "@com.google.protobuf.Internal.ProtoMethodMayReturnNull");
740 }
741
742 // ===================================================================
743
GenerateBuilder(io::Printer * printer)744 void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
745 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
746 printer->Print(
747 "@java.lang.Override\n"
748 "public Builder newBuilderForType() { return newBuilder(); }\n");
749
750 printer->Print(
751 "public static Builder newBuilder() {\n"
752 " return DEFAULT_INSTANCE.toBuilder();\n"
753 "}\n"
754 "public static Builder newBuilder($classname$ prototype) {\n"
755 " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
756 "}\n"
757 "@java.lang.Override\n"
758 "public Builder toBuilder() {\n"
759 " return this == DEFAULT_INSTANCE\n"
760 " ? new Builder() : new Builder().mergeFrom(this);\n"
761 "}\n"
762 "\n",
763 "classname", name_resolver_->GetImmutableClassName(descriptor_));
764
765 printer->Print(
766 "@java.lang.Override\n"
767 "protected Builder newBuilderForType(\n"
768 " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
769 " Builder builder = new Builder(parent);\n"
770 " return builder;\n"
771 "}\n");
772
773 MessageBuilderGenerator builderGenerator(descriptor_, context_);
774 builderGenerator.Generate(printer);
775 }
776
GenerateDescriptorMethods(io::Printer * printer)777 void ImmutableMessageGenerator::GenerateDescriptorMethods(
778 io::Printer* printer) {
779 if (!descriptor_->options().no_standard_descriptor_accessor()) {
780 printer->Print(
781 "public static final com.google.protobuf.Descriptors.Descriptor\n"
782 " getDescriptor() {\n"
783 " return $fileclass$.internal_$identifier$_descriptor;\n"
784 "}\n"
785 "\n",
786 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
787 "identifier", UniqueFileScopeIdentifier(descriptor_));
788 }
789 std::vector<const FieldDescriptor*> map_fields;
790 for (int i = 0; i < descriptor_->field_count(); i++) {
791 const FieldDescriptor* field = descriptor_->field(i);
792 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
793 IsMapEntry(field->message_type())) {
794 map_fields.push_back(field);
795 }
796 }
797 if (!map_fields.empty()) {
798 printer->Print(
799 "@SuppressWarnings({\"rawtypes\"})\n"
800 "@java.lang.Override\n"
801 "protected com.google.protobuf.MapFieldReflectionAccessor "
802 "internalGetMapFieldReflection(\n"
803 " int number) {\n"
804 " switch (number) {\n");
805 printer->Indent();
806 printer->Indent();
807 for (int i = 0; i < map_fields.size(); ++i) {
808 const FieldDescriptor* field = map_fields[i];
809 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
810 printer->Print(
811 "case $number$:\n"
812 " return internalGet$capitalized_name$();\n",
813 "number", absl::StrCat(field->number()), "capitalized_name",
814 info->capitalized_name);
815 }
816 printer->Print(
817 "default:\n"
818 " throw new RuntimeException(\n"
819 " \"Invalid map field number: \" + number);\n");
820 printer->Outdent();
821 printer->Outdent();
822 printer->Print(
823 " }\n"
824 "}\n");
825 }
826 printer->Print(
827 "@java.lang.Override\n"
828 "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
829 " internalGetFieldAccessorTable() {\n"
830 " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
831 " .ensureFieldAccessorsInitialized(\n"
832 " $classname$.class, $classname$.Builder.class);\n"
833 "}\n"
834 "\n",
835 "classname", name_resolver_->GetImmutableClassName(descriptor_),
836 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
837 "identifier", UniqueFileScopeIdentifier(descriptor_));
838 }
839
840 // ===================================================================
841
GenerateIsInitialized(io::Printer * printer)842 void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) {
843 // Memoizes whether the protocol buffer is fully initialized (has all
844 // required fields). -1 means not yet computed. 0 means false and 1 means
845 // true.
846 printer->Print("private byte memoizedIsInitialized = -1;\n");
847 printer->Print(
848 "@java.lang.Override\n"
849 "public final boolean isInitialized() {\n");
850 printer->Indent();
851
852 // Don't directly compare to -1 to avoid an Android x86 JIT bug.
853 printer->Print(
854 "byte isInitialized = memoizedIsInitialized;\n"
855 "if (isInitialized == 1) return true;\n"
856 "if (isInitialized == 0) return false;\n"
857 "\n");
858
859 // Check that all required fields in this message are set.
860 // TODO: We can optimize this when we switch to putting all the
861 // "has" fields into a single bitfield.
862 for (int i = 0; i < descriptor_->field_count(); i++) {
863 const FieldDescriptor* field = descriptor_->field(i);
864 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
865
866 if (field->is_required()) {
867 printer->Print(
868 "if (!has$name$()) {\n"
869 " memoizedIsInitialized = 0;\n"
870 " return false;\n"
871 "}\n",
872 "name", info->capitalized_name);
873 }
874 }
875
876 // Now check that all embedded messages are initialized.
877 for (int i = 0; i < descriptor_->field_count(); i++) {
878 const FieldDescriptor* field = descriptor_->field(i);
879 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
880 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
881 HasRequiredFields(field->message_type())) {
882 switch (field->label()) {
883 case FieldDescriptor::LABEL_REQUIRED:
884 printer->Print(
885 "if (!get$name$().isInitialized()) {\n"
886 " memoizedIsInitialized = 0;\n"
887 " return false;\n"
888 "}\n",
889 "type",
890 name_resolver_->GetImmutableClassName(field->message_type()),
891 "name", info->capitalized_name);
892 break;
893 case FieldDescriptor::LABEL_OPTIONAL:
894 printer->Print(
895 "if (has$name$()) {\n"
896 " if (!get$name$().isInitialized()) {\n"
897 " memoizedIsInitialized = 0;\n"
898 " return false;\n"
899 " }\n"
900 "}\n",
901 "name", info->capitalized_name);
902 break;
903 case FieldDescriptor::LABEL_REPEATED:
904 if (IsMapEntry(field->message_type())) {
905 printer->Print(
906 "for ($type$ item : get$name$Map().values()) {\n"
907 " if (!item.isInitialized()) {\n"
908 " memoizedIsInitialized = 0;\n"
909 " return false;\n"
910 " }\n"
911 "}\n",
912 "type",
913 MapValueImmutableClassdName(field->message_type(),
914 name_resolver_),
915 "name", info->capitalized_name);
916 } else {
917 printer->Print(
918 "for (int i = 0; i < get$name$Count(); i++) {\n"
919 " if (!get$name$(i).isInitialized()) {\n"
920 " memoizedIsInitialized = 0;\n"
921 " return false;\n"
922 " }\n"
923 "}\n",
924 "type",
925 name_resolver_->GetImmutableClassName(field->message_type()),
926 "name", info->capitalized_name);
927 }
928 break;
929 }
930 }
931 }
932
933 if (descriptor_->extension_range_count() > 0) {
934 printer->Print(
935 "if (!extensionsAreInitialized()) {\n"
936 " memoizedIsInitialized = 0;\n"
937 " return false;\n"
938 "}\n");
939 }
940
941 printer->Outdent();
942
943 printer->Print(" memoizedIsInitialized = 1;\n");
944
945 printer->Print(
946 " return true;\n"
947 "}\n"
948 "\n");
949 }
950
951 // ===================================================================
952
GenerateEqualsAndHashCode(io::Printer * printer)953 void ImmutableMessageGenerator::GenerateEqualsAndHashCode(
954 io::Printer* printer) {
955 printer->Print(
956 "@java.lang.Override\n"
957 "public boolean equals(");
958 if (!context_->options().opensource_runtime) {
959 printer->Print(
960 "@com.google.protobuf.Internal.ProtoMethodAcceptsNullParameter\n");
961 }
962 printer->Print("final java.lang.Object obj) {\n");
963 printer->Indent();
964 printer->Print(
965 "if (obj == this) {\n"
966 " return true;\n"
967 "}\n"
968 "if (!(obj instanceof $classname$)) {\n"
969 // don't simply return false because mutable and immutable types
970 // can be equal
971 " return super.equals(obj);\n"
972 "}\n"
973 "$classname$ other = ($classname$) obj;\n"
974 "\n",
975 "classname", name_resolver_->GetImmutableClassName(descriptor_));
976
977 for (int i = 0; i < descriptor_->field_count(); i++) {
978 const FieldDescriptor* field = descriptor_->field(i);
979 if (!IsRealOneof(field)) {
980 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
981 if (field->has_presence()) {
982 printer->Print(
983 "if (has$name$() != other.has$name$()) return false;\n"
984 "if (has$name$()) {\n",
985 "name", info->capitalized_name);
986 printer->Indent();
987 }
988 field_generators_.get(field).GenerateEqualsCode(printer);
989 if (field->has_presence()) {
990 printer->Outdent();
991 printer->Print("}\n");
992 }
993 }
994 }
995
996 // Compare oneofs.
997 for (auto& kv : oneofs_) {
998 const OneofDescriptor* oneof = kv.second;
999 printer->Print(
1000 "if (!get$oneof_capitalized_name$Case().equals("
1001 "other.get$oneof_capitalized_name$Case())) return false;\n",
1002 "oneof_capitalized_name",
1003 context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
1004 printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
1005 context_->GetOneofGeneratorInfo(oneof)->name);
1006 printer->Indent();
1007 for (int j = 0; j < (oneof)->field_count(); j++) {
1008 const FieldDescriptor* field = (oneof)->field(j);
1009 printer->Print("case $field_number$:\n", "field_number",
1010 absl::StrCat(field->number()));
1011 printer->Indent();
1012 field_generators_.get(field).GenerateEqualsCode(printer);
1013 printer->Print("break;\n");
1014 printer->Outdent();
1015 }
1016 printer->Print(
1017 "case 0:\n"
1018 "default:\n");
1019 printer->Outdent();
1020 printer->Print("}\n");
1021 }
1022
1023 // Always consider unknown fields for equality. This will sometimes return
1024 // false for non-canonical ordering when running in LITE_RUNTIME but it's
1025 // the best we can do.
1026 printer->Print(
1027 "if (!getUnknownFields().equals(other.getUnknownFields())) return "
1028 "false;\n");
1029 if (descriptor_->extension_range_count() > 0) {
1030 printer->Print(
1031 "if (!getExtensionFields().equals(other.getExtensionFields()))\n"
1032 " return false;\n");
1033 }
1034 printer->Print("return true;\n");
1035 printer->Outdent();
1036 printer->Print(
1037 "}\n"
1038 "\n");
1039
1040 printer->Print(
1041 "@java.lang.Override\n"
1042 "public int hashCode() {\n");
1043 printer->Indent();
1044 printer->Print("if (memoizedHashCode != 0) {\n");
1045 printer->Indent();
1046 printer->Print("return memoizedHashCode;\n");
1047 printer->Outdent();
1048 printer->Print(
1049 "}\n"
1050 "int hash = 41;\n");
1051
1052 // If we output a getDescriptor() method, use that as it is more efficient.
1053 if (descriptor_->options().no_standard_descriptor_accessor()) {
1054 printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
1055 } else {
1056 printer->Print("hash = (19 * hash) + getDescriptor().hashCode();\n");
1057 }
1058
1059 // hashCode non-oneofs.
1060 for (int i = 0; i < descriptor_->field_count(); i++) {
1061 const FieldDescriptor* field = descriptor_->field(i);
1062 if (!IsRealOneof(field)) {
1063 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1064 if (field->has_presence()) {
1065 printer->Print("if (has$name$()) {\n", "name", info->capitalized_name);
1066 printer->Indent();
1067 }
1068 field_generators_.get(field).GenerateHashCode(printer);
1069 if (field->has_presence()) {
1070 printer->Outdent();
1071 printer->Print("}\n");
1072 }
1073 }
1074 }
1075
1076 // hashCode oneofs.
1077 for (auto& kv : oneofs_) {
1078 const OneofDescriptor* oneof = kv.second;
1079 printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
1080 context_->GetOneofGeneratorInfo(oneof)->name);
1081 printer->Indent();
1082 for (int j = 0; j < (oneof)->field_count(); j++) {
1083 const FieldDescriptor* field = (oneof)->field(j);
1084 printer->Print("case $field_number$:\n", "field_number",
1085 absl::StrCat(field->number()));
1086 printer->Indent();
1087 field_generators_.get(field).GenerateHashCode(printer);
1088 printer->Print("break;\n");
1089 printer->Outdent();
1090 }
1091 printer->Print(
1092 "case 0:\n"
1093 "default:\n");
1094 printer->Outdent();
1095 printer->Print("}\n");
1096 }
1097
1098 if (descriptor_->extension_range_count() > 0) {
1099 printer->Print("hash = hashFields(hash, getExtensionFields());\n");
1100 }
1101
1102 printer->Print("hash = (29 * hash) + getUnknownFields().hashCode();\n");
1103 printer->Print(
1104 "memoizedHashCode = hash;\n"
1105 "return hash;\n");
1106 printer->Outdent();
1107 printer->Print(
1108 "}\n"
1109 "\n");
1110 }
1111
1112 // ===================================================================
1113
GenerateExtensionRegistrationCode(io::Printer * printer)1114 void ImmutableMessageGenerator::GenerateExtensionRegistrationCode(
1115 io::Printer* printer) {
1116 for (int i = 0; i < descriptor_->extension_count(); i++) {
1117 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
1118 .GenerateRegistrationCode(printer);
1119 }
1120
1121 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1122 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
1123 .GenerateExtensionRegistrationCode(printer);
1124 }
1125 }
1126
1127 // ===================================================================
GenerateParser(io::Printer * printer)1128 void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
1129 printer->Print(
1130 "private static final com.google.protobuf.Parser<$classname$>\n"
1131 " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n"
1132 " @java.lang.Override\n"
1133 " public $classname$ parsePartialFrom(\n"
1134 " com.google.protobuf.CodedInputStream input,\n"
1135 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1136 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
1137 " Builder builder = newBuilder();\n"
1138 " try {\n"
1139 " builder.mergeFrom(input, extensionRegistry);\n"
1140 " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1141 " throw e.setUnfinishedMessage(builder.buildPartial());\n"
1142 " } catch (com.google.protobuf.UninitializedMessageException e) {\n"
1143 " throw "
1144 "e.asInvalidProtocolBufferException().setUnfinishedMessage(builder."
1145 "buildPartial());\n"
1146 " } catch (java.io.IOException e) {\n"
1147 " throw new com.google.protobuf.InvalidProtocolBufferException(e)\n"
1148 " .setUnfinishedMessage(builder.buildPartial());\n"
1149 " }\n"
1150 " return builder.buildPartial();\n"
1151 " }\n"
1152 "};\n"
1153 "\n"
1154 "public static com.google.protobuf.Parser<$classname$> parser() {\n"
1155 " return PARSER;\n"
1156 "}\n"
1157 "\n"
1158 "@java.lang.Override\n"
1159 "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
1160 " return PARSER;\n"
1161 "}\n"
1162 "\n",
1163 "classname", descriptor_->name());
1164 }
1165
1166 // ===================================================================
GenerateInitializers(io::Printer * printer)1167 void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
1168 for (int i = 0; i < descriptor_->field_count(); i++) {
1169 if (!IsRealOneof(descriptor_->field(i))) {
1170 field_generators_.get(descriptor_->field(i))
1171 .GenerateInitializationCode(printer);
1172 }
1173 }
1174 }
1175
1176 // ===================================================================
GenerateMutableCopy(io::Printer * printer)1177 void ImmutableMessageGenerator::GenerateMutableCopy(io::Printer* printer) {
1178 printer->Print(
1179 "protected com.google.protobuf.MutableMessage\n"
1180 " internalMutableDefault() {\n"
1181 " return MutableDefaultLoader.get();\n"
1182 "}\n"
1183 "\n"
1184 "private static final class MutableDefaultLoader {\n"
1185 " private static final java.lang.Object defaultOrRuntimeException;\n"
1186 " static {\n"
1187 " java.lang.Object local;\n"
1188 " try {\n"
1189 " local = internalMutableDefault(\"$mutable_name$\");\n"
1190 " } catch (java.lang.RuntimeException e) {\n"
1191 " local = e;\n"
1192 " }\n"
1193 " defaultOrRuntimeException = local;\n"
1194 " }\n"
1195 "\n"
1196 " private MutableDefaultLoader() {}\n"
1197 "\n"
1198 " public static com.google.protobuf.MutableMessage get() {\n"
1199 " if (defaultOrRuntimeException\n"
1200 " instanceof java.lang.RuntimeException) {\n"
1201 " throw (java.lang.RuntimeException) defaultOrRuntimeException;\n"
1202 " }\n"
1203 " return\n"
1204 " (com.google.protobuf.MutableMessage) "
1205 "defaultOrRuntimeException;\n"
1206 " }\n"
1207 "}\n",
1208 "mutable_name", name_resolver_->GetJavaMutableClassName(descriptor_));
1209 }
1210
GenerateAnyMethods(io::Printer * printer)1211 void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
1212 printer->Print(
1213 "private static String getTypeUrl(\n"
1214 " java.lang.String typeUrlPrefix,\n"
1215 " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
1216 " return typeUrlPrefix.endsWith(\"/\")\n"
1217 " ? typeUrlPrefix + descriptor.getFullName()\n"
1218 " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
1219 "}\n"
1220 "\n"
1221 "private static String getTypeNameFromTypeUrl(\n"
1222 " java.lang.String typeUrl) {\n"
1223 " int pos = typeUrl.lastIndexOf('/');\n"
1224 " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
1225 "}\n"
1226 "\n"
1227 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1228 " T message) {\n"
1229 " return Any.newBuilder()\n"
1230 " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
1231 " message.getDescriptorForType()))\n"
1232 " .setValue(message.toByteString())\n"
1233 " .build();\n"
1234 "}\n"
1235 "\n"
1236 "/**\n"
1237 " * Packs a message using the given type URL prefix. The type URL will\n"
1238 " * be constructed by concatenating the message type's full name to the\n"
1239 " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
1240 " * with \"/\" already.\n"
1241 " */\n"
1242 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1243 " T message, java.lang.String typeUrlPrefix) {\n"
1244 " return Any.newBuilder()\n"
1245 " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
1246 " message.getDescriptorForType()))\n"
1247 " .setValue(message.toByteString())\n"
1248 " .build();\n"
1249 "}\n"
1250 "\n"
1251 "public <T extends com.google.protobuf.Message> boolean is(\n"
1252 " java.lang.Class<T> clazz) {\n"
1253 " T defaultInstance =\n"
1254 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1255 " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
1256 " defaultInstance.getDescriptorForType().getFullName());\n"
1257 "}\n"
1258 "\n"
1259 "public boolean isSameTypeAs(com.google.protobuf.Message message) {\n"
1260 " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
1261 " message.getDescriptorForType().getFullName());\n"
1262 "}\n"
1263 "\n"
1264 "@SuppressWarnings(\"serial\")\n"
1265 "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
1266 "\n"
1267 "@java.lang.SuppressWarnings(\"unchecked\")\n"
1268 "public <T extends com.google.protobuf.Message> T unpack(\n"
1269 " java.lang.Class<T> clazz)\n"
1270 " throws com.google.protobuf.InvalidProtocolBufferException {\n");
1271 printer->Print(
1272 " boolean invalidClazz = false;\n"
1273 " if (cachedUnpackValue != null) {\n"
1274 " if (cachedUnpackValue.getClass() == clazz) {\n"
1275 " return (T) cachedUnpackValue;\n"
1276 " }\n"
1277 " invalidClazz = true;\n"
1278 " }\n"
1279 " if (invalidClazz || !is(clazz)) {\n"
1280 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1281 " \"Type of the Any message does not match the given class.\");\n"
1282 " }\n"
1283 " T defaultInstance =\n"
1284 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1285 " T result = (T) defaultInstance.getParserForType()\n"
1286 " .parseFrom(getValue());\n"
1287 " cachedUnpackValue = result;\n"
1288 " return result;\n"
1289 "}\n"
1290 "\n"
1291 "@java.lang.SuppressWarnings(\"unchecked\")\n"
1292 "public <T extends com.google.protobuf.Message> T unpackSameTypeAs("
1293 "T message)\n"
1294 " throws com.google.protobuf.InvalidProtocolBufferException {\n");
1295 printer->Print(
1296 " boolean invalidValue = false;\n"
1297 " if (cachedUnpackValue != null) {\n"
1298 " if (cachedUnpackValue.getClass() == message.getClass()) {\n"
1299 " return (T) cachedUnpackValue;\n"
1300 " }\n"
1301 " invalidValue = true;\n"
1302 " }\n"
1303 " if (invalidValue || !isSameTypeAs(message)) {\n"
1304 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1305 " \"Type of the Any message does not match the given "
1306 "exemplar.\");\n"
1307 " }\n"
1308 " T result = (T) message.getParserForType().parseFrom(getValue());\n"
1309 " cachedUnpackValue = result;\n"
1310 " return result;\n"
1311 "}\n"
1312 "\n");
1313 }
1314
1315 } // namespace java
1316 } // namespace compiler
1317 } // namespace protobuf
1318 } // namespace google
1319
1320 #include "google/protobuf/port_undef.inc"
1321