/* * MIT License * * NiFi Protobuf Processor * Copyright (c) 2017 William Hiver * https://github.com/whiver/nifi-protobuf-processor * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.github.whiver.nifi.service; import com.github.os72.protobuf.dynamic.DynamicSchema; import com.github.whiver.nifi.exception.*; import com.github.whiver.nifi.mapper.JSONMapper; import com.github.whiver.nifi.parser.SchemaParser; import com.google.protobuf.Descriptors; import com.google.protobuf.DynamicMessage; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import java.io.*; public class ProtobufService { /** * Handle all the logic leading to the decoding of a Protobuf-encoded binary given a schema file path. * @param schema Schema used to decode the binary data * @param messageType Type of Protobuf Message * @param encodedData Encoded data source * @return A JSON representation of the data, contained in a Java String * @throws InvalidProtocolBufferException Thrown when an error occurs during the encoding of the decoded data into JSON * @throws Descriptors.DescriptorValidationException Thrown when the schema is invalid * @throws UnknownMessageTypeException Thrown when the given message type is not contained in the schema * @throws MessageDecodingException Thrown when an error occurs during the binary decoding * @throws SchemaLoadingException Thrown when an error occurs while reading the schema file */ public static String decodeProtobuf(DynamicSchema schema, String messageType, InputStream encodedData) throws InvalidProtocolBufferException, Descriptors.DescriptorValidationException, UnknownMessageTypeException, MessageDecodingException, SchemaLoadingException { Descriptors.Descriptor descriptor; DynamicMessage message; descriptor = schema.getMessageDescriptor(messageType); if (descriptor == null) { throw new UnknownMessageTypeException(messageType); } try { message = DynamicMessage.parseFrom(descriptor, encodedData); } catch (IOException e) { throw new MessageDecodingException(e); } return JSONMapper.toJSON(message); } /** * Handle all the logic leading to the decoding of a Protobuf-encoded binary given a schema file path. * @param pathToSchema Path to the .desc schema file on disk * @param compileSchema true if the given schema is still in raw .proto format * @param messageType Type of Protobuf Message * @param encodedData Encoded data source * @return A JSON representation of the data, contained in a Java String * @throws InvalidProtocolBufferException Thrown when an error occurs during the encoding of the decoded data into JSON * @throws Descriptors.DescriptorValidationException Thrown when the schema is invalid * @throws UnknownMessageTypeException Thrown when the given message type is not contained in the schema * @throws MessageDecodingException Thrown when an error occurs during the binary decoding * @throws SchemaLoadingException Thrown when an error occurs while reading the schema file */ public static String decodeProtobuf(String pathToSchema, boolean compileSchema, String messageType, InputStream encodedData) throws IOException, Descriptors.DescriptorValidationException, UnknownMessageTypeException, MessageDecodingException, SchemaLoadingException, InterruptedException, SchemaCompilationException { return decodeProtobuf(SchemaParser.parseSchema(pathToSchema, compileSchema), messageType, encodedData); } /** * Handle all the logic leading to the encoding of a Protobuf-encoded binary given a schema file path and a JSON * data file. * @param schema Schema object to use to encode binary data * @param messageType Type of Protobuf Message * @param jsonData Data to encode, structured in a JSON format * @param binaryOutput The stream where to output the encoded data * @throws Descriptors.DescriptorValidationException Thrown when the schema is invalid * @throws IOException Thrown when an errors occurs while parsing the JSON data * @throws MessageEncodingException Thrown when an error occurs during the binary encoding * @throws UnknownMessageTypeException Thrown when the given message type is not contained in the schema * @throws SchemaLoadingException Thrown when an error occurs while reading the schema file */ public static void encodeProtobuf(DynamicSchema schema, String messageType, InputStream jsonData, OutputStream binaryOutput) throws Descriptors.DescriptorValidationException, IOException, MessageEncodingException, UnknownMessageTypeException, SchemaLoadingException { Descriptors.Descriptor descriptor; Message message; descriptor = schema.getMessageDescriptor(messageType); if (descriptor == null) { throw new UnknownMessageTypeException(messageType); } DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor); BufferedReader jsonReader = new BufferedReader(new InputStreamReader(jsonData)); try { message = JSONMapper.fromJSON(new BufferedReader(jsonReader), builder); } catch (IOException e) { throw new IOException("Unable to parse JSON data: " + e.getMessage(), e); } try { message.writeTo(binaryOutput); } catch (IOException e) { throw new MessageEncodingException(e); } } /** * Handle all the logic leading to the encoding of a Protobuf-encoded binary given a schema file path and a JSON * data file. * @param pathToSchema Path to the .desc schema file on disk * @param compileSchema true if the given schema is still in raw .proto format * @param messageType Type of Protobuf Message * @param jsonData Data to encode, structured in a JSON format * @param binaryOutput The stream where to output the encoded data * @throws Descriptors.DescriptorValidationException Thrown when the schema is invalid * @throws IOException Thrown when an errors occurs while parsing the JSON data * @throws MessageEncodingException Thrown when an error occurs during the binary encoding * @throws UnknownMessageTypeException Thrown when the given message type is not contained in the schema * @throws SchemaLoadingException Thrown when an error occurs while reading the schema file */ public static void encodeProtobuf(String pathToSchema, boolean compileSchema, String messageType, InputStream jsonData, OutputStream binaryOutput) throws Descriptors.DescriptorValidationException, IOException, MessageEncodingException, UnknownMessageTypeException, SchemaLoadingException, SchemaCompilationException, InterruptedException { encodeProtobuf(SchemaParser.parseSchema(pathToSchema, compileSchema), messageType, jsonData, binaryOutput); } }