xref: /OpenGrok/opengrok-indexer/src/test/java/org/opengrok/indexer/util/StreamUtils.java (revision 750b3115a5b8976536ee4dccce497eb97b7a4c9b)
1b5840353SAdam Hornáček /*
2b5840353SAdam Hornáček  * CDDL HEADER START
3b5840353SAdam Hornáček  *
4b5840353SAdam Hornáček  * The contents of this file are subject to the terms of the
5b5840353SAdam Hornáček  * Common Development and Distribution License (the "License").
6b5840353SAdam Hornáček  * You may not use this file except in compliance with the License.
7b5840353SAdam Hornáček  *
8b5840353SAdam Hornáček  * See LICENSE.txt included in this distribution for the specific
9b5840353SAdam Hornáček  * language governing permissions and limitations under the License.
10b5840353SAdam Hornáček  *
11b5840353SAdam Hornáček  * When distributing Covered Code, include this CDDL HEADER in each
12b5840353SAdam Hornáček  * file and include the License file at LICENSE.txt.
13b5840353SAdam Hornáček  * If applicable, add the following below this CDDL HEADER, with the
14b5840353SAdam Hornáček  * fields enclosed by brackets "[]" replaced with your own identifying
15b5840353SAdam Hornáček  * information: Portions Copyright [yyyy] [name of copyright owner]
16b5840353SAdam Hornáček  *
17b5840353SAdam Hornáček  * CDDL HEADER END
18b5840353SAdam Hornáček  */
19b5840353SAdam Hornáček 
20b5840353SAdam Hornáček /*
2152d10766SAdam Hornacek  * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
22*750b3115SChris Fraire  * Portions Copyright (c) 2018, 2021, Chris Fraire <cfraire@me.com>.
23b5840353SAdam Hornáček  */
249805b761SAdam Hornáček package org.opengrok.indexer.util;
25b5840353SAdam Hornáček 
26a8758e23SChris Fraire import org.opengrok.indexer.analysis.CtagsReader;
27a8758e23SChris Fraire import org.opengrok.indexer.analysis.Definitions;
28a8758e23SChris Fraire import org.opengrok.indexer.analysis.StreamSource;
29b5840353SAdam Hornáček import java.io.BufferedInputStream;
30b5840353SAdam Hornáček import java.io.BufferedReader;
31b5840353SAdam Hornáček import java.io.ByteArrayOutputStream;
32b5840353SAdam Hornáček import java.io.IOException;
33b5840353SAdam Hornáček import java.io.InputStream;
34b5840353SAdam Hornáček import java.io.InputStreamReader;
35a8758e23SChris Fraire import java.io.Reader;
36a8758e23SChris Fraire import java.nio.charset.StandardCharsets;
37787af926SChris Fraire import java.util.ArrayList;
38787af926SChris Fraire import java.util.List;
39a8758e23SChris Fraire 
4052d10766SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull;
41b5840353SAdam Hornáček 
42b5840353SAdam Hornáček /**
431161d3e8SAdam Hornacek  * Represents a container for stream utility methods.
44b5840353SAdam Hornáček  */
45b5840353SAdam Hornáček public class StreamUtils {
46b5840353SAdam Hornáček     /**
47b5840353SAdam Hornáček      * Read a stream fully to an in-memory byte array.
48b5840353SAdam Hornáček      * @param iss a defined stream at the chosen starting position
49b5840353SAdam Hornáček      * @return a defined instance
50b5840353SAdam Hornáček      * @throws IOException if I/O fails
51b5840353SAdam Hornáček      */
copyStream(InputStream iss)52b5840353SAdam Hornáček     public static byte[] copyStream(InputStream iss) throws IOException {
53b5840353SAdam Hornáček 
54b5840353SAdam Hornáček         ByteArrayOutputStream baosExp = new ByteArrayOutputStream();
55b5840353SAdam Hornáček         byte[] buffer = new byte[8192];
56b5840353SAdam Hornáček         int read;
57b5840353SAdam Hornáček         do {
58b5840353SAdam Hornáček             read = iss.read(buffer, 0, buffer.length);
59b5840353SAdam Hornáček             if (read > 0) {
60b5840353SAdam Hornáček                 baosExp.write(buffer, 0, read);
61b5840353SAdam Hornáček             }
62b5840353SAdam Hornáček         } while (read >= 0);
63b5840353SAdam Hornáček 
64b5840353SAdam Hornáček         baosExp.close();
65b5840353SAdam Hornáček         return baosExp.toByteArray();
66b5840353SAdam Hornáček     }
67b5840353SAdam Hornáček 
68a8758e23SChris Fraire     /**
69a8758e23SChris Fraire      * Read all bytes from the specified reader.
70a8758e23SChris Fraire      * @param in a required instance
71a8758e23SChris Fraire      * @return a defined instance
72a8758e23SChris Fraire      * @throws IOException thrown if I/O error occurs while reading
73a8758e23SChris Fraire      */
readToEnd(Reader in)74a8758e23SChris Fraire     public static String readToEnd(Reader in) throws IOException {
75a8758e23SChris Fraire 
76a8758e23SChris Fraire         StringBuilder result = new StringBuilder();
77a8758e23SChris Fraire         char[] buf = new char[8 * 1024];
78a8758e23SChris Fraire         int charsRead;
79a8758e23SChris Fraire         while ((charsRead = in.read(buf, 0, buf.length)) != -1) {
80a8758e23SChris Fraire             result.append(buf, 0, charsRead);
81a8758e23SChris Fraire         }
82a8758e23SChris Fraire 
83a8758e23SChris Fraire         return result.toString();
84a8758e23SChris Fraire     }
85a8758e23SChris Fraire 
readTagsFromResource(String resourceName)86a8758e23SChris Fraire     public static Definitions readTagsFromResource(String resourceName)
87b5840353SAdam Hornáček             throws IOException {
88a8758e23SChris Fraire         return readTagsFromResource(resourceName, null);
89b5840353SAdam Hornáček     }
90b5840353SAdam Hornáček 
readTagsFromResource(String tagsResourceName, String rawResourceName)91b5840353SAdam Hornáček     public static Definitions readTagsFromResource(String tagsResourceName,
92b5840353SAdam Hornáček             String rawResourceName) throws IOException {
93b5840353SAdam Hornáček         return readTagsFromResource(tagsResourceName, rawResourceName, 0);
94b5840353SAdam Hornáček     }
95b5840353SAdam Hornáček 
readTagsFromResource(String tagsResourceName, String rawResourceName, int tabSize)96b5840353SAdam Hornáček     public static Definitions readTagsFromResource(String tagsResourceName,
97b5840353SAdam Hornáček         String rawResourceName, int tabSize) throws IOException {
98b5840353SAdam Hornáček 
99b5840353SAdam Hornáček         InputStream res = StreamUtils.class.getClassLoader().
100b5840353SAdam Hornáček             getResourceAsStream(tagsResourceName);
10152d10766SAdam Hornacek         assertNotNull(res, tagsResourceName + " as resource");
102b5840353SAdam Hornáček 
103b5840353SAdam Hornáček         BufferedReader in = new BufferedReader(new InputStreamReader(
104a8758e23SChris Fraire             res, StandardCharsets.UTF_8));
105b5840353SAdam Hornáček 
106b5840353SAdam Hornáček         CtagsReader rdr = new CtagsReader();
107b5840353SAdam Hornáček         rdr.setTabSize(tabSize);
108b5840353SAdam Hornáček         if (rawResourceName != null) {
109b5840353SAdam Hornáček             rdr.setSplitterSupplier(() -> {
110a8758e23SChris Fraire                 /*
111b5840353SAdam Hornáček                  * This should return truly raw content, as the CtagsReader will
112b5840353SAdam Hornáček                  * expand tabs according to its setting.
113b5840353SAdam Hornáček                  */
114b5840353SAdam Hornáček                 SourceSplitter splitter = new SourceSplitter();
115b5840353SAdam Hornáček                 StreamSource src = sourceFromEmbedded(rawResourceName);
116b5840353SAdam Hornáček                 try {
117b5840353SAdam Hornáček                     splitter.reset(src);
118b5840353SAdam Hornáček                 } catch (IOException ex) {
119b5840353SAdam Hornáček                     System.err.println(ex.toString());
120b5840353SAdam Hornáček                     return null;
121b5840353SAdam Hornáček                 }
122b5840353SAdam Hornáček                 return splitter;
123b5840353SAdam Hornáček             });
124b5840353SAdam Hornáček         }
125b5840353SAdam Hornáček 
126b5840353SAdam Hornáček         String line;
127b5840353SAdam Hornáček         while ((line = in.readLine()) != null) {
128b5840353SAdam Hornáček             rdr.readLine(line);
129b5840353SAdam Hornáček         }
130b5840353SAdam Hornáček         return rdr.getDefinitions();
131b5840353SAdam Hornáček     }
132b5840353SAdam Hornáček 
133b5840353SAdam Hornáček     /**
134a8758e23SChris Fraire      * Gets a {@link Reader} from a specified resource name or raises an
135a8758e23SChris Fraire      * assertion error if no defined stream is available.
136a8758e23SChris Fraire      * @param resourceName a required name
137a8758e23SChris Fraire      * @return a defined instance
138a8758e23SChris Fraire      * @throws IOException thrown on I/O error
139a8758e23SChris Fraire      */
readerFromResource(String resourceName)140a8758e23SChris Fraire     public static Reader readerFromResource(String resourceName)
141a8758e23SChris Fraire             throws IOException {
142a8758e23SChris Fraire 
143a8758e23SChris Fraire         InputStream res = StreamUtils.class.getClassLoader().
144a8758e23SChris Fraire                 getResourceAsStream(resourceName);
14552d10766SAdam Hornacek         assertNotNull(res, resourceName + " should be gettable");
146*750b3115SChris Fraire         return IOUtils.createBOMStrippedReader(res, StandardCharsets.UTF_8.name());
147a8758e23SChris Fraire     }
148a8758e23SChris Fraire 
149a8758e23SChris Fraire     /**
150b5840353SAdam Hornáček      * Creates a {@code StreamSource} instance that reads data from an
151b5840353SAdam Hornáček      * embedded resource.
152b5840353SAdam Hornáček      * @param resourceName a required resource name
153b5840353SAdam Hornáček      * @return a stream source that reads from {@code name}
154b5840353SAdam Hornáček      */
sourceFromEmbedded(String resourceName)155b5840353SAdam Hornáček     public static StreamSource sourceFromEmbedded(String resourceName) {
156b5840353SAdam Hornáček         return new StreamSource() {
157b5840353SAdam Hornáček             @Override
158a8758e23SChris Fraire             public InputStream getStream() {
159b5840353SAdam Hornáček                 InputStream res = StreamUtils.class.getClassLoader().
160b5840353SAdam Hornáček                     getResourceAsStream(resourceName);
16152d10766SAdam Hornacek                 assertNotNull(res, "resource " + resourceName);
162b5840353SAdam Hornáček                 return new BufferedInputStream(res);
163b5840353SAdam Hornáček             }
164b5840353SAdam Hornáček         };
165b5840353SAdam Hornáček     }
166b5840353SAdam Hornáček 
167787af926SChris Fraire     /**
168787af926SChris Fraire      * Parses symbols, one per line (trimmed), from a resource stream, but
169787af926SChris Fraire      * recognizing a hash character {@code '#'} as starting a line comment that
170787af926SChris Fraire      * is not included in a symbol.
171787af926SChris Fraire      * @return a defined instance
172787af926SChris Fraire      */
173787af926SChris Fraire     public static List<String> readSampleSymbols(InputStream symbolsResource) throws IOException {
174787af926SChris Fraire         List<String> result = new ArrayList<>();
175787af926SChris Fraire         try (BufferedReader rdr = new BufferedReader(new InputStreamReader(symbolsResource,
176787af926SChris Fraire                 StandardCharsets.UTF_8))) {
177787af926SChris Fraire             String line;
178787af926SChris Fraire             while ((line = rdr.readLine()) != null) {
179787af926SChris Fraire                 int hashOffset = line.indexOf('#');
180787af926SChris Fraire                 if (hashOffset != -1) {
181787af926SChris Fraire                     line = line.substring(0, hashOffset);
182787af926SChris Fraire                 }
183787af926SChris Fraire                 result.add(line.trim());
184787af926SChris Fraire             }
185787af926SChris Fraire         }
186787af926SChris Fraire         return result;
187787af926SChris Fraire     }
188787af926SChris Fraire 
1891161d3e8SAdam Hornacek     // private to enforce static
190b5840353SAdam Hornáček     private StreamUtils() {
191b5840353SAdam Hornáček     }
192b5840353SAdam Hornáček }
193