1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 22 */ 23 package org.opengrok.indexer.util; 24 25 import java.io.BufferedInputStream; 26 import java.io.BufferedReader; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.InputStreamReader; 30 import java.nio.charset.Charset; 31 import java.nio.charset.StandardCharsets; 32 import java.util.ArrayList; 33 import java.util.List; 34 35 /** 36 * The purpose of this class is to provide {@code StreamHandler} that limits the output 37 * to specified number of lines. Compared to {@code SpoolHandler} it consumes 38 * limited amount of heap. 39 */ 40 public class HeadHandler implements Executor.StreamHandler { 41 private final int maxLines; 42 43 private final List<String> lines = new ArrayList<>(); 44 private final Charset charset; 45 46 private static final int bufferedReaderSize = 200; 47 48 /** 49 * Charset of the underlying reader is set to UTF-8. 50 * @param maxLines maximum number of lines to store 51 */ HeadHandler(int maxLines)52 public HeadHandler(int maxLines) { 53 this.maxLines = maxLines; 54 this.charset = StandardCharsets.UTF_8; 55 } 56 57 /** 58 * @param maxLines maximum number of lines to store 59 * @param charset character set 60 */ HeadHandler(int maxLines, Charset charset)61 public HeadHandler(int maxLines, Charset charset) { 62 this.maxLines = maxLines; 63 this.charset = charset; 64 } 65 66 /** 67 * @return number of lines read 68 */ count()69 public int count() { 70 return lines.size(); 71 } 72 73 /** 74 * @param index index 75 * @return line at given index. Will be non {@code null} for valid index. 76 */ get(int index)77 public String get(int index) { 78 return lines.get(index); 79 } 80 81 // for testing getBufferedReaderSize()82 static int getBufferedReaderSize() { 83 return bufferedReaderSize; 84 } 85 86 @Override processStream(InputStream input)87 public void processStream(InputStream input) throws IOException { 88 try (BufferedInputStream bufStream = new BufferedInputStream(input); 89 BufferedReader reader = new BufferedReader(new InputStreamReader(bufStream, this.charset), 90 bufferedReaderSize)) { 91 int lineNum = 0; 92 while (lineNum < maxLines) { 93 String line = reader.readLine(); 94 if (line == null) { // EOF 95 return; 96 } 97 lines.add(line); 98 lineNum++; 99 } 100 101 // Read and forget the rest. 102 byte[] buf = new byte[1024]; 103 while ((bufStream.read(buf)) != -1) { 104 ; 105 } 106 } 107 } 108 } 109