When you parse the serialized descriptor proto, you must supply an
ExtensionRegistry and make sure that custom option is registered therein.

----
*Josh Humphries*
jh...@bluegosling.com

On Tue, Mar 7, 2017 at 11:02 AM, Bill Smith <william.m.sm...@gmail.com>
wrote:

> I'm using protocol buffers 2.5 with Java. I have a proto file that defines
> a custom option. Another proto file uses that custom option. If I persist
> the corresponding FileDescriptorProto's and then read them and convert
> them to FileDescriptors, the reference to the custom option is manifested
> as unknown field. How do I cause that custom option to be resolved
> correctly?
>
> Here's the code. I have two .proto files. protobuf-options.proto looks
> like this:
>
> package options;
> import "google/protobuf/descriptor.proto";
>
> option java_package = "com.example.proto";
> option java_outer_classname = "Options";
>
> extend google.protobuf.FieldOptions {
>     optional bool scrub = 50000;}
>
> The imported google/protobuf/descriptor.proto is exactly the
> descriptor.proto that ships with Protocol Buffers 2.5.
>
> example.proto looks like this:
>
> package example;
> option java_package = "com.example.protos";
> option java_outer_classname = "ExampleProtos";
> option optimize_for = SPEED;
> option java_generic_services = false;
> import "protobuf-options.proto";
>
> message M {
>     optional int32 field1 = 1;
>     optional string field2 = 2 [(options.scrub) = true];}
>
> As you can see, field2 references the custom option defined by
> protobuf-options.proto.
>
> The following code writes a binary-encoded version of all three protos to
> /tmp:
>
> package com.example;
> import com.google.protobuf.ByteString;import 
> com.google.protobuf.DescriptorProtos.FileDescriptorProto;import 
> com.google.protobuf.Descriptors.FileDescriptor;import 
> com.example.protos.ExampleProtos;
> import java.io.FileOutputStream;import java.io.OutputStream;
> /**
>  *
>  */public class PersistFDs {
>     public void persist(final FileDescriptor fileDescriptor) throws Exception 
> {
>         System.out.println("persisting "+fileDescriptor.getName());
>         try (final OutputStream outputStream = new 
> FileOutputStream("/tmp/"+fileDescriptor.getName())) {
>             final FileDescriptorProto fileDescriptorProto = 
> fileDescriptor.toProto();
>             final ByteString byteString = fileDescriptorProto.toByteString();
>             byteString.writeTo(outputStream);
>         }
>         for (final FileDescriptor dependency : 
> fileDescriptor.getDependencies()) {
>             persist(dependency);
>         }
>     }
>     public static void main(String[] args) throws Exception {
>         final PersistFDs self = new PersistFDs();
>         self.persist(ExampleProtos.getDescriptor());
>     }}
>
> Finally, the following code loads those those protos from /tmp, converts
> them back into FileDescriptors, and then checks for the custom option on
> field2:
>
> package com.example;
> import com.google.protobuf.ByteString;import 
> com.google.protobuf.DescriptorProtos.FileDescriptorProto;import 
> com.google.protobuf.Descriptors.FieldDescriptor;import 
> com.google.protobuf.Descriptors.FileDescriptor;import 
> com.google.protobuf.UnknownFieldSet.Field;
> import java.io.FileInputStream;import java.io.InputStream;
> /**
>  *
>  */public class LoadFDs {
>     public FileDescriptorProto loadProto(final String filePath) throws 
> Exception {
>         try (final InputStream inputStream = new FileInputStream(filePath)) {
>             final ByteString byteString = ByteString.readFrom(inputStream);
>             final FileDescriptorProto result = 
> FileDescriptorProto.parseFrom(byteString);
>
>             return result;
>         }
>     }
>
>     public static void main(final String[] args) throws Exception {
>         final LoadFDs self = new LoadFDs();
>
>         final FileDescriptorProto descriptorFDProto = 
> self.loadProto("/tmp/google/protobuf/descriptor.proto");
>         final FileDescriptorProto optionsFDProto = 
> self.loadProto("/tmp/protobuf-options.proto");
>         final FileDescriptorProto fakeBoxcarFDProto = 
> self.loadProto("/tmp/example.proto");
>
>         final FileDescriptor fD = FileDescriptor.buildFrom(descriptorFDProto, 
> new FileDescriptor[0]);
>         final FileDescriptor optionsFD = 
> FileDescriptor.buildFrom(optionsFDProto, new FileDescriptor[] { fD });
>         final FileDescriptor fakeBoxcarFD = 
> FileDescriptor.buildFrom(fakeBoxcarFDProto, new FileDescriptor[] { optionsFD 
> });
>
>         final FieldDescriptor optionsFieldDescriptor = 
> optionsFD.findExtensionByName("scrub");
>         if (optionsFieldDescriptor == null) {
>             System.out.println("Did not find scrub's FieldDescriptor");
>             System.exit(1);
>         }
>         final FieldDescriptor sFieldDescriptor = 
> fakeBoxcarFD.findMessageTypeByName("M").findFieldByName("field2");
>         System.out.println("unknown option fields 
> "+sFieldDescriptor.getOptions().getUnknownFields());
>         final boolean hasScrubOption = 
> sFieldDescriptor.getOptions().hasField(optionsFieldDescriptor);
>         System.out.println("hasScrubOption: "+hasScrubOption);
>
>     }}
>
> When I run LoadFDs, it fails with this exception:
>
> unknown option fields 50000: 1
>
> Exception in thread "main" java.lang.IllegalArgumentException:
> FieldDescriptor does not match message type. at com.google.protobuf.
> GeneratedMessage$ExtendableMessage.verifyContainingType(GeneratedMessage.java:812)
> at 
> com.google.protobuf.GeneratedMessage$ExtendableMessage.hasField(GeneratedMessage.java:761)
> at com.example.LoadFDs.main(LoadFDs.java:42)
>
> The options for FieldDescriptor for the s field ought to have a field for
> that custom option, but instead it has an unknown field. The field number
> and value on the unknown field are correct. It's just that the custom
> option is not getting resolved. How do I fix that?
> Bill Smith
> Austin, TX
>
> --
> You received this message because you are subscribed to the Google Groups
> "Protocol Buffers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to protobuf+unsubscr...@googlegroups.com.
> To post to this group, send email to protobuf@googlegroups.com.
> Visit this group at https://groups.google.com/group/protobuf.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to protobuf+unsubscr...@googlegroups.com.
To post to this group, send email to protobuf@googlegroups.com.
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.

Reply via email to