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 package com.google.protobuf; 32 33 import java.io.IOException; 34 import java.io.ObjectStreamException; 35 import java.io.Serializable; 36 import java.lang.reflect.InvocationTargetException; 37 import java.lang.reflect.Method; 38 import java.util.Collections; 39 import java.util.Iterator; 40 import java.util.List; 41 import java.util.Map; 42 43 /** 44 * Lite version of {@link GeneratedMessage}. 45 * 46 * @author kenton (at) google.com Kenton Varda 47 */ 48 public abstract class GeneratedMessageLite extends AbstractMessageLite 49 implements Serializable { 50 private static final long serialVersionUID = 1L; 51 52 protected GeneratedMessageLite() { 53 } 54 55 protected GeneratedMessageLite(Builder builder) { 56 } 57 58 public Parser<? extends MessageLite> getParserForType() { 59 throw new UnsupportedOperationException( 60 "This is supposed to be overridden by subclasses."); 61 } 62 63 /** 64 * Called by subclasses to parse an unknown field. 65 * @return {@code true} unless the tag is an end-group tag. 66 */ 67 protected boolean parseUnknownField( 68 CodedInputStream input, 69 ExtensionRegistryLite extensionRegistry, 70 int tag) throws IOException { 71 return input.skipField(tag); 72 } 73 74 /** 75 * Used by parsing constructors in generated classes. 76 */ 77 protected void makeExtensionsImmutable() { 78 // Noop for messages without extensions. 79 } 80 81 @SuppressWarnings("unchecked") 82 public abstract static class Builder<MessageType extends GeneratedMessageLite, 83 BuilderType extends Builder> 84 extends AbstractMessageLite.Builder<BuilderType> { 85 protected Builder() {} 86 87 //@Override (Java 1.6 override semantics, but we must support 1.5) 88 public BuilderType clear() { 89 return (BuilderType) this; 90 } 91 92 // This is implemented here only to work around an apparent bug in the 93 // Java compiler and/or build system. See bug #1898463. The mere presence 94 // of this dummy clone() implementation makes it go away. 95 @Override 96 public BuilderType clone() { 97 throw new UnsupportedOperationException( 98 "This is supposed to be overridden by subclasses."); 99 } 100 101 /** All subclasses implement this. */ 102 public abstract BuilderType mergeFrom(MessageType message); 103 104 // Defined here for return type covariance. 105 public abstract MessageType getDefaultInstanceForType(); 106 107 /** 108 * Called by subclasses to parse an unknown field. 109 * @return {@code true} unless the tag is an end-group tag. 110 */ 111 protected boolean parseUnknownField( 112 CodedInputStream input, 113 ExtensionRegistryLite extensionRegistry, 114 int tag) throws IOException { 115 return input.skipField(tag); 116 } 117 } 118 119 // ================================================================= 120 // Extensions-related stuff 121 122 /** 123 * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. 124 */ 125 public interface ExtendableMessageOrBuilder< 126 MessageType extends ExtendableMessage> extends MessageLiteOrBuilder { 127 128 /** Check if a singular extension is present. */ 129 <Type> boolean hasExtension( 130 GeneratedExtension<MessageType, Type> extension); 131 132 /** Get the number of elements in a repeated extension. */ 133 <Type> int getExtensionCount( 134 GeneratedExtension<MessageType, List<Type>> extension); 135 136 /** Get the value of an extension. */ 137 <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension); 138 139 /** Get one element of a repeated extension. */ 140 <Type> Type getExtension( 141 GeneratedExtension<MessageType, List<Type>> extension, 142 int index); 143 } 144 145 /** 146 * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. 147 */ 148 public abstract static class ExtendableMessage< 149 MessageType extends ExtendableMessage<MessageType>> 150 extends GeneratedMessageLite 151 implements ExtendableMessageOrBuilder<MessageType> { 152 153 private final FieldSet<ExtensionDescriptor> extensions; 154 155 protected ExtendableMessage() { 156 this.extensions = FieldSet.newFieldSet(); 157 } 158 159 protected ExtendableMessage(ExtendableBuilder<MessageType, ?> builder) { 160 this.extensions = builder.buildExtensions(); 161 } 162 163 private void verifyExtensionContainingType( 164 final GeneratedExtension<MessageType, ?> extension) { 165 if (extension.getContainingTypeDefaultInstance() != 166 getDefaultInstanceForType()) { 167 // This can only happen if someone uses unchecked operations. 168 throw new IllegalArgumentException( 169 "This extension is for a different message type. Please make " + 170 "sure that you are not suppressing any generics type warnings."); 171 } 172 } 173 174 /** Check if a singular extension is present. */ 175 //@Override (Java 1.6 override semantics, but we must support 1.5) 176 public final <Type> boolean hasExtension( 177 final GeneratedExtension<MessageType, Type> extension) { 178 verifyExtensionContainingType(extension); 179 return extensions.hasField(extension.descriptor); 180 } 181 182 /** Get the number of elements in a repeated extension. */ 183 //@Override (Java 1.6 override semantics, but we must support 1.5) 184 public final <Type> int getExtensionCount( 185 final GeneratedExtension<MessageType, List<Type>> extension) { 186 verifyExtensionContainingType(extension); 187 return extensions.getRepeatedFieldCount(extension.descriptor); 188 } 189 190 /** Get the value of an extension. */ 191 //@Override (Java 1.6 override semantics, but we must support 1.5) 192 @SuppressWarnings("unchecked") 193 public final <Type> Type getExtension( 194 final GeneratedExtension<MessageType, Type> extension) { 195 verifyExtensionContainingType(extension); 196 final Object value = extensions.getField(extension.descriptor); 197 if (value == null) { 198 return extension.defaultValue; 199 } else { 200 return (Type) value; 201 } 202 } 203 204 /** Get one element of a repeated extension. */ 205 //@Override (Java 1.6 override semantics, but we must support 1.5) 206 @SuppressWarnings("unchecked") 207 public final <Type> Type getExtension( 208 final GeneratedExtension<MessageType, List<Type>> extension, 209 final int index) { 210 verifyExtensionContainingType(extension); 211 return (Type) extensions.getRepeatedField(extension.descriptor, index); 212 } 213 214 /** Called by subclasses to check if all extensions are initialized. */ 215 protected boolean extensionsAreInitialized() { 216 return extensions.isInitialized(); 217 } 218 219 /** 220 * Called by subclasses to parse an unknown field or an extension. 221 * @return {@code true} unless the tag is an end-group tag. 222 */ 223 @Override 224 protected boolean parseUnknownField( 225 CodedInputStream input, 226 ExtensionRegistryLite extensionRegistry, 227 int tag) throws IOException { 228 return GeneratedMessageLite.parseUnknownField( 229 extensions, 230 getDefaultInstanceForType(), 231 input, 232 extensionRegistry, 233 tag); 234 } 235 236 /** 237 * Used by parsing constructors in generated classes. 238 */ 239 @Override 240 protected void makeExtensionsImmutable() { 241 extensions.makeImmutable(); 242 } 243 244 /** 245 * Used by subclasses to serialize extensions. Extension ranges may be 246 * interleaved with field numbers, but we must write them in canonical 247 * (sorted by field number) order. ExtensionWriter helps us write 248 * individual ranges of extensions at once. 249 */ 250 protected class ExtensionWriter { 251 // Imagine how much simpler this code would be if Java iterators had 252 // a way to get the next element without advancing the iterator. 253 254 private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter = 255 extensions.iterator(); 256 private Map.Entry<ExtensionDescriptor, Object> next; 257 private final boolean messageSetWireFormat; 258 259 private ExtensionWriter(boolean messageSetWireFormat) { 260 if (iter.hasNext()) { 261 next = iter.next(); 262 } 263 this.messageSetWireFormat = messageSetWireFormat; 264 } 265 266 public void writeUntil(final int end, final CodedOutputStream output) 267 throws IOException { 268 while (next != null && next.getKey().getNumber() < end) { 269 ExtensionDescriptor extension = next.getKey(); 270 if (messageSetWireFormat && extension.getLiteJavaType() == 271 WireFormat.JavaType.MESSAGE && 272 !extension.isRepeated()) { 273 output.writeMessageSetExtension(extension.getNumber(), 274 (MessageLite) next.getValue()); 275 } else { 276 FieldSet.writeField(extension, next.getValue(), output); 277 } 278 if (iter.hasNext()) { 279 next = iter.next(); 280 } else { 281 next = null; 282 } 283 } 284 } 285 } 286 287 protected ExtensionWriter newExtensionWriter() { 288 return new ExtensionWriter(false); 289 } 290 protected ExtensionWriter newMessageSetExtensionWriter() { 291 return new ExtensionWriter(true); 292 } 293 294 /** Called by subclasses to compute the size of extensions. */ 295 protected int extensionsSerializedSize() { 296 return extensions.getSerializedSize(); 297 } 298 protected int extensionsSerializedSizeAsMessageSet() { 299 return extensions.getMessageSetSerializedSize(); 300 } 301 } 302 303 /** 304 * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}. 305 */ 306 @SuppressWarnings("unchecked") 307 public abstract static class ExtendableBuilder< 308 MessageType extends ExtendableMessage<MessageType>, 309 BuilderType extends ExtendableBuilder<MessageType, BuilderType>> 310 extends Builder<MessageType, BuilderType> 311 implements ExtendableMessageOrBuilder<MessageType> { 312 protected ExtendableBuilder() {} 313 314 private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet(); 315 private boolean extensionsIsMutable; 316 317 @Override 318 public BuilderType clear() { 319 extensions.clear(); 320 extensionsIsMutable = false; 321 return super.clear(); 322 } 323 324 private void ensureExtensionsIsMutable() { 325 if (!extensionsIsMutable) { 326 extensions = extensions.clone(); 327 extensionsIsMutable = true; 328 } 329 } 330 331 /** 332 * Called by the build code path to create a copy of the extensions for 333 * building the message. 334 */ 335 private FieldSet<ExtensionDescriptor> buildExtensions() { 336 extensions.makeImmutable(); 337 extensionsIsMutable = false; 338 return extensions; 339 } 340 341 private void verifyExtensionContainingType( 342 final GeneratedExtension<MessageType, ?> extension) { 343 if (extension.getContainingTypeDefaultInstance() != 344 getDefaultInstanceForType()) { 345 // This can only happen if someone uses unchecked operations. 346 throw new IllegalArgumentException( 347 "This extension is for a different message type. Please make " + 348 "sure that you are not suppressing any generics type warnings."); 349 } 350 } 351 352 /** Check if a singular extension is present. */ 353 //@Override (Java 1.6 override semantics, but we must support 1.5) 354 public final <Type> boolean hasExtension( 355 final GeneratedExtension<MessageType, Type> extension) { 356 verifyExtensionContainingType(extension); 357 return extensions.hasField(extension.descriptor); 358 } 359 360 /** Get the number of elements in a repeated extension. */ 361 //@Override (Java 1.6 override semantics, but we must support 1.5) 362 public final <Type> int getExtensionCount( 363 final GeneratedExtension<MessageType, List<Type>> extension) { 364 verifyExtensionContainingType(extension); 365 return extensions.getRepeatedFieldCount(extension.descriptor); 366 } 367 368 /** Get the value of an extension. */ 369 //@Override (Java 1.6 override semantics, but we must support 1.5) 370 @SuppressWarnings("unchecked") 371 public final <Type> Type getExtension( 372 final GeneratedExtension<MessageType, Type> extension) { 373 verifyExtensionContainingType(extension); 374 final Object value = extensions.getField(extension.descriptor); 375 if (value == null) { 376 return extension.defaultValue; 377 } else { 378 return (Type) value; 379 } 380 } 381 382 /** Get one element of a repeated extension. */ 383 @SuppressWarnings("unchecked") 384 //@Override (Java 1.6 override semantics, but we must support 1.5) 385 public final <Type> Type getExtension( 386 final GeneratedExtension<MessageType, List<Type>> extension, 387 final int index) { 388 verifyExtensionContainingType(extension); 389 return (Type) extensions.getRepeatedField(extension.descriptor, index); 390 } 391 392 // This is implemented here only to work around an apparent bug in the 393 // Java compiler and/or build system. See bug #1898463. The mere presence 394 // of this dummy clone() implementation makes it go away. 395 @Override 396 public BuilderType clone() { 397 throw new UnsupportedOperationException( 398 "This is supposed to be overridden by subclasses."); 399 } 400 401 /** Set the value of an extension. */ 402 public final <Type> BuilderType setExtension( 403 final GeneratedExtension<MessageType, Type> extension, 404 final Type value) { 405 verifyExtensionContainingType(extension); 406 ensureExtensionsIsMutable(); 407 extensions.setField(extension.descriptor, value); 408 return (BuilderType) this; 409 } 410 411 /** Set the value of one element of a repeated extension. */ 412 public final <Type> BuilderType setExtension( 413 final GeneratedExtension<MessageType, List<Type>> extension, 414 final int index, final Type value) { 415 verifyExtensionContainingType(extension); 416 ensureExtensionsIsMutable(); 417 extensions.setRepeatedField(extension.descriptor, index, value); 418 return (BuilderType) this; 419 } 420 421 /** Append a value to a repeated extension. */ 422 public final <Type> BuilderType addExtension( 423 final GeneratedExtension<MessageType, List<Type>> extension, 424 final Type value) { 425 verifyExtensionContainingType(extension); 426 ensureExtensionsIsMutable(); 427 extensions.addRepeatedField(extension.descriptor, value); 428 return (BuilderType) this; 429 } 430 431 /** Clear an extension. */ 432 public final <Type> BuilderType clearExtension( 433 final GeneratedExtension<MessageType, ?> extension) { 434 verifyExtensionContainingType(extension); 435 ensureExtensionsIsMutable(); 436 extensions.clearField(extension.descriptor); 437 return (BuilderType) this; 438 } 439 440 /** Called by subclasses to check if all extensions are initialized. */ 441 protected boolean extensionsAreInitialized() { 442 return extensions.isInitialized(); 443 } 444 445 /** 446 * Called by subclasses to parse an unknown field or an extension. 447 * @return {@code true} unless the tag is an end-group tag. 448 */ 449 @Override 450 protected boolean parseUnknownField( 451 CodedInputStream input, 452 ExtensionRegistryLite extensionRegistry, 453 int tag) throws IOException { 454 ensureExtensionsIsMutable(); 455 return GeneratedMessageLite.parseUnknownField( 456 extensions, 457 getDefaultInstanceForType(), 458 input, 459 extensionRegistry, 460 tag); 461 } 462 463 protected final void mergeExtensionFields(final MessageType other) { 464 ensureExtensionsIsMutable(); 465 extensions.mergeFrom(((ExtendableMessage) other).extensions); 466 } 467 } 468 469 // ----------------------------------------------------------------- 470 471 /** 472 * Parse an unknown field or an extension. 473 * @return {@code true} unless the tag is an end-group tag. 474 */ 475 private static <MessageType extends MessageLite> 476 boolean parseUnknownField( 477 FieldSet<ExtensionDescriptor> extensions, 478 MessageType defaultInstance, 479 CodedInputStream input, 480 ExtensionRegistryLite extensionRegistry, 481 int tag) throws IOException { 482 int wireType = WireFormat.getTagWireType(tag); 483 int fieldNumber = WireFormat.getTagFieldNumber(tag); 484 485 GeneratedExtension<MessageType, ?> extension = 486 extensionRegistry.findLiteExtensionByNumber( 487 defaultInstance, fieldNumber); 488 489 boolean unknown = false; 490 boolean packed = false; 491 if (extension == null) { 492 unknown = true; // Unknown field. 493 } else if (wireType == FieldSet.getWireFormatForFieldType( 494 extension.descriptor.getLiteType(), 495 false /* isPacked */)) { 496 packed = false; // Normal, unpacked value. 497 } else if (extension.descriptor.isRepeated && 498 extension.descriptor.type.isPackable() && 499 wireType == FieldSet.getWireFormatForFieldType( 500 extension.descriptor.getLiteType(), 501 true /* isPacked */)) { 502 packed = true; // Packed value. 503 } else { 504 unknown = true; // Wrong wire type. 505 } 506 507 if (unknown) { // Unknown field or wrong wire type. Skip. 508 return input.skipField(tag); 509 } 510 511 if (packed) { 512 int length = input.readRawVarint32(); 513 int limit = input.pushLimit(length); 514 if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) { 515 while (input.getBytesUntilLimit() > 0) { 516 int rawValue = input.readEnum(); 517 Object value = 518 extension.descriptor.getEnumType().findValueByNumber(rawValue); 519 if (value == null) { 520 // If the number isn't recognized as a valid value for this 521 // enum, drop it (don't even add it to unknownFields). 522 return true; 523 } 524 extensions.addRepeatedField(extension.descriptor, value); 525 } 526 } else { 527 while (input.getBytesUntilLimit() > 0) { 528 Object value = 529 FieldSet.readPrimitiveField(input, 530 extension.descriptor.getLiteType()); 531 extensions.addRepeatedField(extension.descriptor, value); 532 } 533 } 534 input.popLimit(limit); 535 } else { 536 Object value; 537 switch (extension.descriptor.getLiteJavaType()) { 538 case MESSAGE: { 539 MessageLite.Builder subBuilder = null; 540 if (!extension.descriptor.isRepeated()) { 541 MessageLite existingValue = 542 (MessageLite) extensions.getField(extension.descriptor); 543 if (existingValue != null) { 544 subBuilder = existingValue.toBuilder(); 545 } 546 } 547 if (subBuilder == null) { 548 subBuilder = extension.messageDefaultInstance.newBuilderForType(); 549 } 550 if (extension.descriptor.getLiteType() == 551 WireFormat.FieldType.GROUP) { 552 input.readGroup(extension.getNumber(), 553 subBuilder, extensionRegistry); 554 } else { 555 input.readMessage(subBuilder, extensionRegistry); 556 } 557 value = subBuilder.build(); 558 break; 559 } 560 case ENUM: 561 int rawValue = input.readEnum(); 562 value = extension.descriptor.getEnumType() 563 .findValueByNumber(rawValue); 564 // If the number isn't recognized as a valid value for this enum, 565 // drop it. 566 if (value == null) { 567 return true; 568 } 569 break; 570 default: 571 value = FieldSet.readPrimitiveField(input, 572 extension.descriptor.getLiteType()); 573 break; 574 } 575 576 if (extension.descriptor.isRepeated()) { 577 extensions.addRepeatedField(extension.descriptor, value); 578 } else { 579 extensions.setField(extension.descriptor, value); 580 } 581 } 582 583 return true; 584 } 585 586 // ----------------------------------------------------------------- 587 588 /** For use by generated code only. */ 589 public static <ContainingType extends MessageLite, Type> 590 GeneratedExtension<ContainingType, Type> 591 newSingularGeneratedExtension( 592 final ContainingType containingTypeDefaultInstance, 593 final Type defaultValue, 594 final MessageLite messageDefaultInstance, 595 final Internal.EnumLiteMap<?> enumTypeMap, 596 final int number, 597 final WireFormat.FieldType type) { 598 return new GeneratedExtension<ContainingType, Type>( 599 containingTypeDefaultInstance, 600 defaultValue, 601 messageDefaultInstance, 602 new ExtensionDescriptor(enumTypeMap, number, type, 603 false /* isRepeated */, 604 false /* isPacked */)); 605 } 606 607 /** For use by generated code only. */ 608 public static <ContainingType extends MessageLite, Type> 609 GeneratedExtension<ContainingType, Type> 610 newRepeatedGeneratedExtension( 611 final ContainingType containingTypeDefaultInstance, 612 final MessageLite messageDefaultInstance, 613 final Internal.EnumLiteMap<?> enumTypeMap, 614 final int number, 615 final WireFormat.FieldType type, 616 final boolean isPacked) { 617 @SuppressWarnings("unchecked") // Subclasses ensure Type is a List 618 Type emptyList = (Type) Collections.emptyList(); 619 return new GeneratedExtension<ContainingType, Type>( 620 containingTypeDefaultInstance, 621 emptyList, 622 messageDefaultInstance, 623 new ExtensionDescriptor( 624 enumTypeMap, number, type, true /* isRepeated */, isPacked)); 625 } 626 627 private static final class ExtensionDescriptor 628 implements FieldSet.FieldDescriptorLite< 629 ExtensionDescriptor> { 630 private ExtensionDescriptor( 631 final Internal.EnumLiteMap<?> enumTypeMap, 632 final int number, 633 final WireFormat.FieldType type, 634 final boolean isRepeated, 635 final boolean isPacked) { 636 this.enumTypeMap = enumTypeMap; 637 this.number = number; 638 this.type = type; 639 this.isRepeated = isRepeated; 640 this.isPacked = isPacked; 641 } 642 643 private final Internal.EnumLiteMap<?> enumTypeMap; 644 private final int number; 645 private final WireFormat.FieldType type; 646 private final boolean isRepeated; 647 private final boolean isPacked; 648 649 public int getNumber() { 650 return number; 651 } 652 653 public WireFormat.FieldType getLiteType() { 654 return type; 655 } 656 657 public WireFormat.JavaType getLiteJavaType() { 658 return type.getJavaType(); 659 } 660 661 public boolean isRepeated() { 662 return isRepeated; 663 } 664 665 public boolean isPacked() { 666 return isPacked; 667 } 668 669 public Internal.EnumLiteMap<?> getEnumType() { 670 return enumTypeMap; 671 } 672 673 @SuppressWarnings("unchecked") 674 public MessageLite.Builder internalMergeFrom( 675 MessageLite.Builder to, MessageLite from) { 676 return ((Builder) to).mergeFrom((GeneratedMessageLite) from); 677 } 678 679 public int compareTo(ExtensionDescriptor other) { 680 return number - other.number; 681 } 682 } 683 684 /** 685 * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}. 686 * 687 * Users should ignore the contents of this class and only use objects of 688 * this type as parameters to extension accessors and ExtensionRegistry.add(). 689 */ 690 public static final class GeneratedExtension< 691 ContainingType extends MessageLite, Type> { 692 693 private GeneratedExtension( 694 final ContainingType containingTypeDefaultInstance, 695 final Type defaultValue, 696 final MessageLite messageDefaultInstance, 697 final ExtensionDescriptor descriptor) { 698 // Defensive checks to verify the correct initialization order of 699 // GeneratedExtensions and their related GeneratedMessages. 700 if (containingTypeDefaultInstance == null) { 701 throw new IllegalArgumentException( 702 "Null containingTypeDefaultInstance"); 703 } 704 if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE && 705 messageDefaultInstance == null) { 706 throw new IllegalArgumentException( 707 "Null messageDefaultInstance"); 708 } 709 this.containingTypeDefaultInstance = containingTypeDefaultInstance; 710 this.defaultValue = defaultValue; 711 this.messageDefaultInstance = messageDefaultInstance; 712 this.descriptor = descriptor; 713 } 714 715 private final ContainingType containingTypeDefaultInstance; 716 private final Type defaultValue; 717 private final MessageLite messageDefaultInstance; 718 private final ExtensionDescriptor descriptor; 719 720 /** 721 * Default instance of the type being extended, used to identify that type. 722 */ 723 public ContainingType getContainingTypeDefaultInstance() { 724 return containingTypeDefaultInstance; 725 } 726 727 /** Get the field number. */ 728 public int getNumber() { 729 return descriptor.getNumber(); 730 } 731 732 /** 733 * If the extension is an embedded message, this is the default instance of 734 * that type. 735 */ 736 public MessageLite getMessageDefaultInstance() { 737 return messageDefaultInstance; 738 } 739 } 740 741 /** 742 * A serialized (serializable) form of the generated message. Stores the 743 * message as a class name and a byte array. 744 */ 745 static final class SerializedForm implements Serializable { 746 private static final long serialVersionUID = 0L; 747 748 private String messageClassName; 749 private byte[] asBytes; 750 751 /** 752 * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}. 753 * @param regularForm the message to serialize 754 */ 755 SerializedForm(MessageLite regularForm) { 756 messageClassName = regularForm.getClass().getName(); 757 asBytes = regularForm.toByteArray(); 758 } 759 760 /** 761 * When read from an ObjectInputStream, this method converts this object 762 * back to the regular form. Part of Java's serialization magic. 763 * @return a GeneratedMessage of the type that was serialized 764 */ 765 @SuppressWarnings("unchecked") 766 protected Object readResolve() throws ObjectStreamException { 767 try { 768 Class messageClass = Class.forName(messageClassName); 769 Method newBuilder = messageClass.getMethod("newBuilder"); 770 MessageLite.Builder builder = 771 (MessageLite.Builder) newBuilder.invoke(null); 772 builder.mergeFrom(asBytes); 773 return builder.buildPartial(); 774 } catch (ClassNotFoundException e) { 775 throw new RuntimeException("Unable to find proto buffer class", e); 776 } catch (NoSuchMethodException e) { 777 throw new RuntimeException("Unable to find newBuilder method", e); 778 } catch (IllegalAccessException e) { 779 throw new RuntimeException("Unable to call newBuilder method", e); 780 } catch (InvocationTargetException e) { 781 throw new RuntimeException("Error calling newBuilder", e.getCause()); 782 } catch (InvalidProtocolBufferException e) { 783 throw new RuntimeException("Unable to understand proto buffer", e); 784 } 785 } 786 } 787 788 /** 789 * Replaces this object in the output stream with a serialized form. 790 * Part of Java's serialization magic. Generated sub-classes must override 791 * this method by calling {@code return super.writeReplace();} 792 * @return a SerializedForm of this message 793 */ 794 protected Object writeReplace() throws ObjectStreamException { 795 return new SerializedForm(this); 796 } 797 } 798