Mercurial > hg > monetdb-java
view src/main/java/org/monetdb/mcl/io/BufferedMCLReader.java @ 702:b4e968e5bd74
Some improvements.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Thu, 08 Dec 2022 19:13:46 +0100 (2022-12-08) |
parents | 940e266eeccd |
children | 21fd1eebbd0e |
line wrap: on
line source
/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 1997 - July 2008 CWI, August 2008 - 2022 MonetDB B.V. */ package org.monetdb.mcl.io; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; /** * Read text from a character-input stream, buffering characters so as to * provide a means for efficient reading of characters, arrays and lines. * * The BufferedMCLReader is typically used as layer inbetween an * InputStream and a specific interpreter of the data. * <pre> * / Response * BufferedMCLReader ---o <- Tuple * \ DataBlock * </pre> * Because the BufferedMCLReader provides an efficient way to access the * data from the stream in a linewise fashion, whereby each line is * identified as a certain type, consumers can easily decide how to * parse each retrieved line. The line parsers from * org.monetdb.mcl.parser are well suited to work with the lines * outputted by the BufferedMCLReader. * This class is client-oriented, as it doesn't take into account the * messages as the server receives them. * * @author Fabian Groffen * @see org.monetdb.mcl.net.MapiSocket * @see org.monetdb.mcl.io.BufferedMCLWriter */ public final class BufferedMCLReader { private final BufferedReader inner; private String current = null; private LineType lineType = LineType.UNKNOWN; /** * Create a buffering character-input stream that uses a * default-sized input buffer. * * @param in A Reader */ public BufferedMCLReader(final Reader in) { inner = new BufferedReader(in); } /** * Create a buffering character-input stream that uses a * default-sized input buffer, from an InputStream. * * @param in An InputStream * @param enc Encoding * @throws UnsupportedEncodingException If encoding is not supported */ public BufferedMCLReader(final InputStream in, final String enc) throws UnsupportedEncodingException { this(new java.io.InputStreamReader(in, enc)); } public void advance() throws IOException { if (lineType == LineType.PROMPT) return; current = inner.readLine(); lineType = LineType.classify(current); if (lineType == LineType.ERROR && current != null && !current.matches("^![0-9A-Z]{5}!.+")) { current = "!22000!" + current.substring(1); } } /** * Resets the linetype to UNKNOWN. */ public void resetLineType() { lineType = LineType.UNKNOWN; } /** * Return the current line, or null if we're at the end or before the beginning. * @return the current line or null */ public String getLine() { return current; } /** * getLineType returns the type of the current line. * * @return Linetype representing the kind of line this is, one of the * following enums: UNKNOWN, HEADER, ERROR, RESULT, * PROMPT, MORE, FILETRANSFER, SOHEADER, REDIRECT, INFO */ public LineType getLineType() { return lineType; } /** * Discard the remainder of the response but collect any further error messages. * * @return a string containing error messages, or null if there aren't any * @throws IOException if an IO exception occurs while talking to the server */ final public String discardRemainder() throws IOException { return discard(null); } /** * Discard the remainder of the response but collect any further error messages. * * @return a string containing error messages, or null if there aren't any * @throws IOException if an IO exception occurs while talking to the server */ final public String discardRemainder(String error) throws IOException { final StringBuilder sb; if (error != null) { sb = makeErrorBuffer(); sb.append(error); } else { sb = null; } return discard(sb); } /** * Discard the remainder of the response but collect any further error messages. * * @return a string containing error messages, or null if there aren't any * @throws IOException if an IO exception occurs while talking to the server * * TODO(Wouter): should probably not have to be synchronized. */ final synchronized String discard(StringBuilder errmsgs) throws IOException { while (lineType != LineType.PROMPT) { advance(); if (getLine() == null) throw new IOException("Connection to server lost!"); if (getLineType() == LineType.ERROR) { if (errmsgs == null) errmsgs = new StringBuilder(128); errmsgs.append('\n').append(getLine().substring(1)); } } if (errmsgs == null) return null; return errmsgs.toString().trim(); } private final StringBuilder makeErrorBuffer() { return new StringBuilder(128); } public void close() throws IOException { inner.close(); } }