/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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.apache.ambari.view.hive2.resources.uploads; import com.opencsv.CSVWriter; import org.apache.ambari.view.hive2.client.ColumnDescription; import org.apache.ambari.view.hive2.client.Row; import org.apache.commons.codec.binary.Hex; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.util.Iterator; import java.util.List; /** * Takes row iterator as input. * iterate over rows and creates a CSV formated stream separating rows by endline "\n" * Note : column values should not contain "\n". */ public class TableDataReader extends Reader { private static final int CAPACITY = 1024; private final List<ColumnDescriptionImpl> header; private StringReader stringReader = new StringReader(""); private Iterator<Row> iterator; private boolean encode = false; public static final char CSV_DELIMITER = '\001'; public TableDataReader(Iterator<Row> rowIterator, List<ColumnDescriptionImpl> header, boolean encode) { this.iterator = rowIterator; this.encode = encode; this.header = header; } @Override public int read(char[] cbuf, int off, int len) throws IOException { int totalLen = len; int count = 0; do { int n = stringReader.read(cbuf, off, len); if (n != -1) { // n were read len = len - n; // len more to be read off = off + n; // off now shifted to n more count += n; } if (count == totalLen) return count; // all totalLen characters were read if (iterator.hasNext()) { // keep reading as long as we keep getting rows StringWriter stringWriter = new StringWriter(CAPACITY); CSVWriter csvPrinter = new CSVWriter(stringWriter,CSV_DELIMITER); Row row = iterator.next(); // encode values so that \n and \r are overridden Object[] columnValues = row.getRow(); String[] columns = new String[columnValues.length]; for(int i = 0; i < columnValues.length; i++){ String type = header.get(i).getType(); if(this.encode && ( ColumnDescription.DataTypes.STRING.toString().equals(type) || ColumnDescription.DataTypes.VARCHAR.toString().equals(type) || ColumnDescription.DataTypes.CHAR.toString().equals(type) ) ){ columns[i] = Hex.encodeHexString(((String)columnValues[i]).getBytes()); //default charset }else { columns[i] = (String) columnValues[i]; } } csvPrinter.writeNext(columns,false); stringReader.close(); // close the old string reader stringReader = new StringReader(stringWriter.getBuffer().toString()); csvPrinter.close(); stringWriter.close(); } else { return count == 0 ? -1 : count; } } while (count < totalLen); return count; } @Override public void close() throws IOException { } }