2929import com .google .protobuf .DescriptorProtos .OneofOptions ;
3030import com .google .protobuf .DescriptorProtos .ServiceDescriptorProto ;
3131import com .google .protobuf .DescriptorProtos .ServiceOptions ;
32+ import com .google .protobuf .Descriptors .DescriptorValidationException ;
3233import com .google .protobuf .JavaFeaturesProto .JavaFeatures ;
3334import java .lang .ref .ReferenceQueue ;
3435import java .lang .ref .WeakReference ;
@@ -618,14 +619,18 @@ private FileDescriptor(
618619 }
619620
620621 public void resolveAllFeaturesImmutable () {
621- resolveAllFeaturesInternal ();
622+ try {
623+ resolveAllFeaturesInternal ();
624+ } catch (DescriptorValidationException e ) {
625+ throw new IllegalArgumentException ("Invalid features for \" " + proto .getName () + "\" ." , e );
626+ }
622627 }
623628
624629 /**
625630 * This method is to be called by generated code only. It resolves features for the descriptor
626631 * and all of its children.
627632 */
628- private void resolveAllFeaturesInternal () {
633+ private void resolveAllFeaturesInternal () throws DescriptorValidationException {
629634 if (this .features != null ) {
630635 return ;
631636 }
@@ -712,22 +717,26 @@ private void crossLink() throws DescriptorValidationException {
712717 private synchronized void setProto (final FileDescriptorProto proto ) {
713718 this .proto = proto ;
714719 this .options = null ;
715- this .features = resolveFeatures (proto .getOptions ().getFeatures ());
720+ try {
721+ this .features = resolveFeatures (proto .getOptions ().getFeatures ());
716722
717- for (int i = 0 ; i < messageTypes .length ; i ++) {
718- messageTypes [i ].setProto (proto .getMessageType (i ));
719- }
723+ for (int i = 0 ; i < messageTypes .length ; i ++) {
724+ messageTypes [i ].setProto (proto .getMessageType (i ));
725+ }
720726
721- for (int i = 0 ; i < enumTypes .length ; i ++) {
722- enumTypes [i ].setProto (proto .getEnumType (i ));
723- }
727+ for (int i = 0 ; i < enumTypes .length ; i ++) {
728+ enumTypes [i ].setProto (proto .getEnumType (i ));
729+ }
724730
725- for (int i = 0 ; i < services .length ; i ++) {
726- services [i ].setProto (proto .getService (i ));
727- }
731+ for (int i = 0 ; i < services .length ; i ++) {
732+ services [i ].setProto (proto .getService (i ));
733+ }
728734
729- for (int i = 0 ; i < extensions .length ; i ++) {
730- extensions [i ].setProto (proto .getExtension (i ));
735+ for (int i = 0 ; i < extensions .length ; i ++) {
736+ extensions [i ].setProto (proto .getExtension (i ));
737+ }
738+ } catch (DescriptorValidationException e ) {
739+ throw new IllegalArgumentException ("Invalid features for \" " + proto .getName () + "\" ." , e );
731740 }
732741 }
733742 }
@@ -1102,7 +1111,7 @@ private Descriptor(
11021111 }
11031112
11041113 /** See {@link FileDescriptor#resolveAllFeatures}. */
1105- private void resolveAllFeatures () {
1114+ private void resolveAllFeatures () throws DescriptorValidationException {
11061115 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
11071116
11081117 for (Descriptor nestedType : nestedTypes ) {
@@ -1162,7 +1171,7 @@ private void validateNoDuplicateFieldNumbers() throws DescriptorValidationExcept
11621171 }
11631172
11641173 /** See {@link FileDescriptor#setProto}. */
1165- private void setProto (final DescriptorProto proto ) {
1174+ private void setProto (final DescriptorProto proto ) throws DescriptorValidationException {
11661175 this .proto = proto ;
11671176 this .options = null ;
11681177 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
@@ -1327,7 +1336,9 @@ public boolean isRequired() {
13271336
13281337 /** Is this field declared optional? */
13291338 public boolean isOptional () {
1330- return proto .getLabel () == FieldDescriptorProto .Label .LABEL_OPTIONAL ;
1339+ return proto .getLabel () == FieldDescriptorProto .Label .LABEL_OPTIONAL
1340+ && this .features .getFieldPresence ()
1341+ != DescriptorProtos .FeatureSet .FieldPresence .LEGACY_REQUIRED ;
13311342 }
13321343
13331344 /** Is this field declared repeated? */
@@ -1732,7 +1743,7 @@ private FieldDescriptor(
17321743 }
17331744
17341745 /** See {@link FileDescriptor#resolveAllFeatures}. */
1735- private void resolveAllFeatures () {
1746+ private void resolveAllFeatures () throws DescriptorValidationException {
17361747 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
17371748 }
17381749
@@ -1791,6 +1802,19 @@ boolean hasInferredLegacyProtoFeatures() {
17911802 return false ;
17921803 }
17931804
1805+ @ Override
1806+ void validateFeatures (FeatureSet features ) throws DescriptorValidationException {
1807+ if (containingType != null
1808+ && containingType .toProto ().getOptions ().getMessageSetWireFormat ()) {
1809+ if (isExtension ()) {
1810+ if (!isOptional () || getType () != Type .MESSAGE ) {
1811+ throw new DescriptorValidationException (
1812+ this , "Extensions of MessageSets must be optional messages." );
1813+ }
1814+ }
1815+ }
1816+ }
1817+
17941818 /** Look up and cross-link all field types, etc. */
17951819 private void crossLink () throws DescriptorValidationException {
17961820 if (proto .hasExtendee ()) {
@@ -1962,23 +1986,10 @@ private void crossLink() throws DescriptorValidationException {
19621986 }
19631987 }
19641988 }
1965-
1966- if (containingType != null
1967- && containingType .toProto ().getOptions ().getMessageSetWireFormat ()) {
1968- if (isExtension ()) {
1969- if (!isOptional () || getType () != Type .MESSAGE ) {
1970- throw new DescriptorValidationException (
1971- this , "Extensions of MessageSets must be optional messages." );
1972- }
1973- } else {
1974- throw new DescriptorValidationException (
1975- this , "MessageSets cannot have fields, only extensions." );
1976- }
1977- }
19781989 }
19791990
19801991 /** See {@link FileDescriptor#setProto}. */
1981- private void setProto (final FieldDescriptorProto proto ) {
1992+ private void setProto (final FieldDescriptorProto proto ) throws DescriptorValidationException {
19821993 this .proto = proto ;
19831994 this .options = null ;
19841995 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
@@ -2250,15 +2261,15 @@ private EnumDescriptor(
22502261 }
22512262
22522263 /** See {@link FileDescriptor#resolveAllFeatures}. */
2253- private void resolveAllFeatures () {
2264+ private void resolveAllFeatures () throws DescriptorValidationException {
22542265 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
22552266 for (EnumValueDescriptor value : values ) {
22562267 value .resolveAllFeatures ();
22572268 }
22582269 }
22592270
22602271 /** See {@link FileDescriptor#setProto}. */
2261- private void setProto (final EnumDescriptorProto proto ) {
2272+ private void setProto (final EnumDescriptorProto proto ) throws DescriptorValidationException {
22622273 this .proto = proto ;
22632274 this .options = null ;
22642275 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
@@ -2402,12 +2413,13 @@ private EnumValueDescriptor(final EnumDescriptor parent, final Integer number) {
24022413 }
24032414
24042415 /** See {@link FileDescriptor#resolveAllFeatures}. */
2405- private void resolveAllFeatures () {
2416+ private void resolveAllFeatures () throws DescriptorValidationException {
24062417 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
24072418 }
24082419
24092420 /** See {@link FileDescriptor#setProto}. */
2410- private void setProto (final EnumValueDescriptorProto proto ) {
2421+ private void setProto (final EnumValueDescriptorProto proto )
2422+ throws DescriptorValidationException {
24112423 this .proto = proto ;
24122424 this .options = null ;
24132425 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
@@ -2517,7 +2529,7 @@ private ServiceDescriptor(
25172529 }
25182530
25192531 /** See {@link FileDescriptor#resolveAllFeatures}. */
2520- private void resolveAllFeatures () {
2532+ private void resolveAllFeatures () throws DescriptorValidationException {
25212533 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
25222534
25232535 for (MethodDescriptor method : methods ) {
@@ -2532,7 +2544,7 @@ private void crossLink() throws DescriptorValidationException {
25322544 }
25332545
25342546 /** See {@link FileDescriptor#setProto}. */
2535- private void setProto (final ServiceDescriptorProto proto ) {
2547+ private void setProto (final ServiceDescriptorProto proto ) throws DescriptorValidationException {
25362548 this .proto = proto ;
25372549 this .options = null ;
25382550 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
@@ -2655,7 +2667,7 @@ private MethodDescriptor(
26552667 }
26562668
26572669 /** See {@link FileDescriptor#resolveAllFeatures}. */
2658- private void resolveAllFeatures () {
2670+ private void resolveAllFeatures () throws DescriptorValidationException {
26592671 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
26602672 }
26612673
@@ -2682,7 +2694,7 @@ private void crossLink() throws DescriptorValidationException {
26822694 }
26832695
26842696 /** See {@link FileDescriptor#setProto}. */
2685- private void setProto (final MethodDescriptorProto proto ) {
2697+ private void setProto (final MethodDescriptorProto proto ) throws DescriptorValidationException {
26862698 this .proto = proto ;
26872699 this .options = null ;
26882700 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
@@ -2723,7 +2735,7 @@ private GenericDescriptor() {}
27232735
27242736 public abstract FileDescriptor getFile ();
27252737
2726- FeatureSet resolveFeatures (FeatureSet unresolvedFeatures ) {
2738+ FeatureSet resolveFeatures (FeatureSet unresolvedFeatures ) throws DescriptorValidationException {
27272739 if (this .parent != null
27282740 && unresolvedFeatures .equals (FeatureSet .getDefaultInstance ())
27292741 && !hasInferredLegacyProtoFeatures ()) {
@@ -2738,6 +2750,7 @@ FeatureSet resolveFeatures(FeatureSet unresolvedFeatures) {
27382750 }
27392751 features .mergeFrom (inferLegacyProtoFeatures ());
27402752 features .mergeFrom (unresolvedFeatures );
2753+ validateFeatures (features .build ());
27412754 return internFeatures (features .build ());
27422755 }
27432756
@@ -2749,6 +2762,9 @@ boolean hasInferredLegacyProtoFeatures() {
27492762 return false ;
27502763 }
27512764
2765+ void validateFeatures (FeatureSet features ) throws DescriptorValidationException {
2766+ }
2767+
27522768 GenericDescriptor parent ;
27532769 volatile FeatureSet features ;
27542770 }
@@ -3214,11 +3230,11 @@ boolean isSynthetic() {
32143230 }
32153231
32163232 /** See {@link FileDescriptor#resolveAllFeatures}. */
3217- private void resolveAllFeatures () {
3233+ private void resolveAllFeatures () throws DescriptorValidationException {
32183234 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
32193235 }
32203236
3221- private void setProto (final OneofDescriptorProto proto ) {
3237+ private void setProto (final OneofDescriptorProto proto ) throws DescriptorValidationException {
32223238 this .proto = proto ;
32233239 this .options = null ;
32243240 this .features = resolveFeatures (proto .getOptions ().getFeatures ());
0 commit comments