content: package hip.ch5.kafka;
  
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.IOException;
  import java.util.Properties;
  
  import hip.ch3.avro.AvroStockUtils;
  import hip.ch3.avro.gen.Stock;
  import hip.util.Cli;
  import kafka.producer.KeyedMessage;
  import kafka.producer.ProducerConfig;
  import kafka.javaapi.producer.Producer;
  import org.apache.avro.io.BinaryEncoder;
  import org.apache.avro.io.DatumWriter;
  import org.apache.avro.io.EncoderFactory;
  import org.apache.avro.specific.SpecificDatumWriter;
  import org.apache.hadoop.conf.Configuration;
  import org.apache.hadoop.conf.Configured;
  import org.apache.hadoop.util.Tool;
  import org.apache.hadoop.util.ToolRunner;
  
  import static hip.util.Cli.ArgBuilder;
  
  /**
   * Writes Avro {@link Stock} data into a Kafka topic.
   */
  public class KafkaAvroWriter extends Configured implements Tool {
  
    /**
     * Main entry point for the example.
     *
     * @param args arguments
     * @throws Exception when something goes wrong
     */
    public static void main(final String[] args) throws Exception {
      int res = ToolRunner.run(new Configuration(), new KafkaAvroWriter(), args);
      System.exit(res);
    }
  
    /**
     * The MapReduce driver - setup and launch the job.
     *
     * @param args the command-line arguments
     * @return the process exit code
     * @throws Exception if something goes wrong
     */
    public int run(final String[] args) throws Exception {
  
      Cli cli = Cli.builder().setArgs(args).addOptions(Options.values()).build();
      int result = cli.runCmd();
  
      if (result != 0) {
        return result;
      }
  
      File inputFile = new File(cli.getArgValueAsString(Options.STOCKSFILE));
      String brokerList = cli.getArgValueAsString(Options.BROKER_LIST);
      String kTopic = cli.getArgValueAsString(Options.TOPIC);
  
      Properties props = new Properties();
      props.put("metadata.broker.list", brokerList);
      props.put("serializer.class", kafka.serializer.DefaultEncoder.class.getName());
  
      ProducerConfig config = new ProducerConfig(props);
  
      Producer<Integer, byte[]> producer = new Producer<Integer, byte[]>(config);
  
      for (Stock stock : AvroStockUtils.fromCsvFile(inputFile)) {
        KeyedMessage<Integer, byte[]> msg = new KeyedMessage<Integer, byte[]>(kTopic, toBytes(stock));
        System.out.println("Sending " + msg + " to kafka @ topic " + kTopic);
        producer.send(msg);
  
      }
      producer.close();
      System.out.println("done!");
      return 0;
    }
  
    private static final EncoderFactory encoderFactory = EncoderFactory.get();
  
    public static byte[] toBytes(Stock stock) {
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      BinaryEncoder encoder = encoderFactory.directBinaryEncoder(outputStream, null);
  
      DatumWriter<Stock> userDatumWriter = new SpecificDatumWriter<Stock>(Stock.class);
      try {
        userDatumWriter.write(stock, encoder);
        encoder.flush();
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
  
      return outputStream.toByteArray();
    }
  
    public enum Options implements Cli.ArgGetter {
      STOCKSFILE(ArgBuilder.builder().hasArgument(true).required(true).description("Sample stocks file")),
      BROKER_LIST(ArgBuilder.builder().hasArgument(true).required(true).description("List of CSV-separated Kafka brokers host and port (i.e. localhost:9092,host2:port2")),
      TOPIC(ArgBuilder.builder().hasArgument(true).required(true).description("Kafka topic")),;
      private final Cli.ArgInfo argInfo;
  
      Options(final ArgBuilder builder) {
        this.argInfo = builder.setArgName(name()).build();
      }
  
      @Override
      public Cli.ArgInfo getArgInfo() {
        return argInfo;
      }
    }
  }
  