xref: /OpenGrok/opengrok-indexer/src/main/java/org/opengrok/indexer/util/HeadHandler.java (revision 5d9f3aa0ca3da3a714233f987fa732f62c0965f6)
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