@SuppressWarnings("unchecked") @Override public Mono<Void> write(Publisher<? extends Message> inputStream, ResolvableType elementType, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) { try { Message.Builder builder = getMessageBuilder(elementType.toClass()); Descriptors.Descriptor descriptor = builder.getDescriptorForType(); message.getHeaders().add(X_PROTOBUF_SCHEMA_HEADER, descriptor.getFile().getName()); message.getHeaders().add(X_PROTOBUF_MESSAGE_HEADER, descriptor.getFullName()); if (inputStream instanceof Flux) { if (mediaType == null) { message.getHeaders().setContentType(((HttpMessageEncoder<?>)getEncoder()).getStreamingMediaTypes().get(0)); } else if (!ProtobufEncoder.DELIMITED_VALUE.equals(mediaType.getParameters().get(ProtobufEncoder.DELIMITED_KEY))) { Map<String, String> parameters = new HashMap<>(mediaType.getParameters()); parameters.put(ProtobufEncoder.DELIMITED_KEY, ProtobufEncoder.DELIMITED_VALUE); message.getHeaders().setContentType(new MediaType(mediaType.getType(), mediaType.getSubtype(), parameters)); } } return super.write(inputStream, elementType, mediaType, message, hints); } catch (Exception ex) { return Mono.error(new DecodingException("Could not read Protobuf message: " + ex.getMessage(), ex)); } }
/** * Set the "X-Protobuf-*" HTTP headers when responding with a message of * content type "application/x-protobuf" * <p><b>Note:</b> <code>outputMessage.getBody()</code> should not have been called * before because it writes HTTP headers (making them read only).</p> */ private void setProtoHeader(HttpOutputMessage response, Message message) { response.getHeaders().set(X_PROTOBUF_SCHEMA_HEADER, message.getDescriptorForType().getFile().getName()); response.getHeaders().set(X_PROTOBUF_MESSAGE_HEADER, message.getDescriptorForType().getFullName()); }
private Schema getSchema(Descriptor descriptor) { Map<Descriptor,Schema> seen = SEEN.get(); if (seen.containsKey(descriptor)) // stop recursion return seen.get(descriptor); boolean first = seen.isEmpty(); try { Schema result = Schema.createRecord(descriptor.getName(), null, getNamespace(descriptor.getFile(), descriptor.getContainingType()), false); seen.put(descriptor, result); List<Field> fields = new ArrayList<>(); for (FieldDescriptor f : descriptor.getFields()) fields.add(Accessor.createField(f.getName(), getSchema(f), null, getDefault(f))); result.setFields(fields); return result; } finally { if (first) seen.clear(); } }
@Test public void testAnyIsNotProto2() { // Any is a core Protocol Buffers type that uses proto3 syntax. thrown.expect(IllegalArgumentException.class); thrown.expectMessage(Any.class.getCanonicalName()); thrown.expectMessage("in file " + Any.getDescriptor().getFile().getName()); checkProto2Syntax(Any.class, ExtensionRegistry.getEmptyRegistry()); }
/** * @return the filename of the protocol buffer (.proto) file where the message * is defined */ public String getFilename() { return descriptor.getFile().getName(); }
/** * Adds a message type and all types defined in the same .proto file as * well as all transitively imported .proto files to this {@link Builder}. */ public Builder add(Descriptor messageType) { if (types == null) { throw new IllegalStateException("A TypeRegistry.Builer can only be used once."); } addFile(messageType.getFile()); return this; }
@Test public void testMessageWithTransitiveMapIsNotDeterministic() throws NonDeterministicException { String mapFieldName = MessageWithMap.getDescriptor().findFieldByNumber(1).getFullName(); thrown.expect(NonDeterministicException.class); thrown.expectMessage(ReferencesMessageWithMap.class.getName()); thrown.expectMessage("transitively includes Map field " + mapFieldName); thrown.expectMessage("file " + MessageWithMap.getDescriptor().getFile().getName()); verifyDeterministic(ProtoCoder.of(ReferencesMessageWithMap.class)); }
@Test public void testMessageWithMapIsNotDeterministic() throws NonDeterministicException { String mapFieldName = MessageWithMap.getDescriptor().findFieldByNumber(1).getFullName(); thrown.expect(NonDeterministicException.class); thrown.expectMessage(MessageWithMap.class.getName()); thrown.expectMessage("transitively includes Map field " + mapFieldName); thrown.expectMessage("file " + MessageWithMap.getDescriptor().getFile().getName()); verifyDeterministic(ProtoCoder.of(MessageWithMap.class)); }
/** * Gets the fully qualified name for generated classes in Java convention. Nested classes will be * separated using '$' instead of '.'. */ public static String getClassName(Descriptor descriptor, ProtoFlavor flavor) { return getClassName(classNameWithoutPackage(descriptor, flavor), descriptor.getFile(), flavor); }
/** * Adds a message type and all types defined in the same .proto file as * well as all transitively imported .proto files to this {@link Builder}. */ public Builder add(Descriptor messageType) { if (types == null) { throw new IllegalStateException("A TypeRegistry.Builer can only be used once."); } addFile(messageType.getFile()); return this; }
/** * Gets the fully qualified name for generated classes in Java convention. Nested classes will be * separated using '$' instead of '.'. */ public static String getClassName(Descriptor descriptor, ProtoFlavor flavor) { return getClassName(classNameWithoutPackage(descriptor, flavor), descriptor.getFile(), flavor); }
@Test public void testDurationIsNotProto2() { // Duration is a core Protocol Buffers type that uses proto3 syntax. thrown.expect(IllegalArgumentException.class); thrown.expectMessage(Duration.class.getCanonicalName()); thrown.expectMessage("in file " + Duration.getDescriptor().getFile().getName()); checkProto2Syntax(Duration.class, ExtensionRegistry.getEmptyRegistry()); }
public TableMetadataPersistence.ColumnValueDescription.Builder persistToProto() { Builder builder = TableMetadataPersistence.ColumnValueDescription.newBuilder(); builder.setType(type.persistToProto()); builder.setCompression(compression.persistToProto()); if (className != null) { builder.setClassName(className); } if (canonicalClassName != null) { builder.setCanonicalClassName(canonicalClassName); } builder.setFormat(format.persistToProto()); if (protoDescriptor != null) { builder.setProtoMessageName(protoDescriptor.getName()); builder.setProtoFileDescriptorTree(persistFileDescriptorTree(protoDescriptor.getFile())); if (protoDescriptor.getContainingType() != null) { log.error("proto descriptors should be top level types: {}", protoDescriptor.getName()); } } return builder; }
throws IOException { boolean discardUnknown = getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3 ? input.shouldDiscardUnknownFieldsProto3() : input.shouldDiscardUnknownFields();
private static Class<?> getJavaClassIgnoreRepeated(final Descriptors.FieldDescriptor descriptor, BeanContainer beanContainer) { switch (descriptor.getJavaType()) { case INT: return Integer.class; case LONG: return Long.class; case FLOAT: return Float.class; case DOUBLE: return Double.class; case BOOLEAN: return Boolean.class; case STRING: return String.class; case BYTE_STRING: return ByteString.class; //code duplicate, but GenericDescriptor interface is private in protobuf case ENUM: return getEnumClassByEnumDescriptor(descriptor.getEnumType(), beanContainer); case MESSAGE: return MappingUtils.loadClass(StringUtils.join( getFullyQualifiedClassName(descriptor.getMessageType().getContainingType(), descriptor.getMessageType().getFile().getOptions(), descriptor.getMessageType().getName()), '.'), beanContainer); default: throw new MappingException("Unable to find " + descriptor.getJavaType()); } }
@SuppressWarnings("unchecked") @Override public Mono<Void> write(Publisher<? extends Message> inputStream, ResolvableType elementType, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map<String, Object> hints) { try { Message.Builder builder = getMessageBuilder(elementType.toClass()); Descriptors.Descriptor descriptor = builder.getDescriptorForType(); message.getHeaders().add(X_PROTOBUF_SCHEMA_HEADER, descriptor.getFile().getName()); message.getHeaders().add(X_PROTOBUF_MESSAGE_HEADER, descriptor.getFullName()); if (inputStream instanceof Flux) { if (mediaType == null) { message.getHeaders().setContentType(((HttpMessageEncoder<?>)getEncoder()).getStreamingMediaTypes().get(0)); } else if (!ProtobufEncoder.DELIMITED_VALUE.equals(mediaType.getParameters().get(ProtobufEncoder.DELIMITED_KEY))) { Map<String, String> parameters = new HashMap<>(mediaType.getParameters()); parameters.put(ProtobufEncoder.DELIMITED_KEY, ProtobufEncoder.DELIMITED_VALUE); message.getHeaders().setContentType(new MediaType(mediaType.getType(), mediaType.getSubtype(), parameters)); } } return super.write(inputStream, elementType, mediaType, message, hints); } catch (Exception ex) { return Mono.error(new DecodingException("Could not read Protobuf message: " + ex.getMessage(), ex)); } }
@Override void validate(FieldDescriptor fieldDescriptor) { checkArgument( !fieldDescriptor.isRepeated(), "%s is a repeated field; repeated fields cannot be absent, only empty", fieldDescriptor); checkArgument( fieldDescriptor.getContainingType().getFile().getSyntax() != Syntax.PROTO3 || fieldDescriptor.getJavaType() == JavaType.MESSAGE, "%s is a primitive field in a Proto 3 message; it cannot be absent", fieldDescriptor); } },
@Override public Builder mergeUnknownFields(UnknownFieldSet unknownFields) { if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3 && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { return this; } this.unknownFields = UnknownFieldSet.newBuilder(this.unknownFields) .mergeFrom(unknownFields) .build(); return this; }
@Override public Builder setUnknownFields(UnknownFieldSet unknownFields) { if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3 && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) { return this; } this.unknownFields = unknownFields; return this; }
/** * Set the "X-Protobuf-*" HTTP headers when responding with a message of * content type "application/x-protobuf" * <p><b>Note:</b> <code>outputMessage.getBody()</code> should not have been called * before because it writes HTTP headers (making them read only).</p> */ private void setProtoHeader(HttpOutputMessage response, Message message) { response.getHeaders().set(X_PROTOBUF_SCHEMA_HEADER, message.getDescriptorForType().getFile().getName()); response.getHeaders().set(X_PROTOBUF_MESSAGE_HEADER, message.getDescriptorForType().getFullName()); }