/* * Copyright 2014-2016 CyberVision, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kaaproject.kaa.server.common.log.shared; import org.apache.avro.io.BinaryDecoder; import org.apache.avro.io.DecoderFactory; import org.apache.avro.specific.SpecificDatumReader; import org.apache.avro.specific.SpecificRecordBase; import org.kaaproject.kaa.server.common.log.shared.avro.gen.RecordData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; /** * Utility class to decode Avro records from Apache Flume events generated by Kaa Flume appender. * * @param <T> the type T * @author Andrew Shvayka */ public class KaaFlumeEventReader<T extends SpecificRecordBase> { private static final Logger LOG = LoggerFactory.getLogger(KaaFlumeEventReader.class); // Datum reader for generic Kaa Flume object private SpecificDatumReader<RecordData> recordDataReader; // Datum reader for user-defined object private SpecificDatumReader<T> recordReader; public KaaFlumeEventReader(Class<T> clazz) { recordDataReader = new SpecificDatumReader<>(RecordData.class); recordReader = new SpecificDatumReader<>(clazz); } // Extracts byte array from byte buffer private static final byte[] toByteArray(ByteBuffer buffer) { byte[] data = new byte[buffer.remaining()]; buffer.get(data); return data; } /** * Decode records from <code>ByteBuffer</code> and return <code>Iterable</code>. * * @param bb the <code>ByteBuffer</code> which decode * @return decoded <code>Iterable</code> */ public Iterable<T> decodeRecords(ByteBuffer bb) throws IOException { byte[] recordDataBody = toByteArray(bb); BinaryDecoder recordDataDecoder = DecoderFactory.get().binaryDecoder(recordDataBody, null); RecordData recordData = recordDataReader.read(null, recordDataDecoder); LOG.debug("Avro event header: {}", recordData.getRecordHeader()); LOG.debug("Avro event data.size: {}", recordData.getEventRecords().size()); List<T> results = new ArrayList<T>(); BinaryDecoder recordDecoder = null; for (ByteBuffer eventBuf : recordData.getEventRecords()) { byte[] recordBody = toByteArray(eventBuf); recordDecoder = DecoderFactory.get().binaryDecoder(recordBody, recordDecoder); T record = recordReader.read(null, recordDecoder); results.add(record); LOG.trace("Parsed record: {}", record); } return results; } }