/** * Switch this stream to using a new socket. Any existing socket is <em>not</em> closed; it's * assumed that we are changing to a new socket that delegates to the original socket (e.g. SSL). * * @param socket the new socket to change to * @throws IOException if something goes wrong */ public void changeSocket(Socket socket) throws IOException { this.connection = socket; // Submitted by Jason Venner <jason@idiom.com>. Disable Nagle // as we are selective about flushing output only when we // really need to. connection.setTcpNoDelay(true); // Buffer sizes submitted by Sverre H Huseby <sverrehu@online.no> pg_input = new VisibleBufferedInputStream(connection.getInputStream(), 8192); pg_output = new BufferedOutputStream(connection.getOutputStream(), 8192); if (encoding != null) { setEncoding(encoding); } }
/** * Check for pending backend messages without blocking. * Might return false when there actually are messages * waiting, depending on the characteristics of the * underlying socket. This is used to detect asynchronous * notifies from the backend, when available. * * @return true if there is a pending backend message */ public boolean hasMessagePending() throws IOException { return pg_input.available() > 0 || connection.getInputStream().available() > 0; }
/** * Closes the connection. * * @throws IOException if an I/O Error occurs */ @Override public void close() throws IOException { if (encodingWriter != null) { encodingWriter.close(); } pg_output.close(); pg_input.close(); connection.close(); }
/** * Receives a null-terminated string from the backend. If we don't see a null, then we assume * something has gone wrong. * * @return string from back end * @throws IOException if an I/O error occurs, or end of file */ public String receiveString() throws IOException { int len = pg_input.scanCStringLength(); String res = encoding.decode(pg_input.getBuffer(), pg_input.getIndex(), len - 1); pg_input.skip(len); return res; }
/** * Receives a fixed-size string from the backend. * * @param len the length of the string to receive, in bytes. * @return the decoded string * @throws IOException if something wrong happens */ public String receiveString(int len) throws IOException { if (!pg_input.ensureBytes(len)) { throw new EOFException(); } String res = encoding.decode(pg_input.getBuffer(), pg_input.getIndex(), len); pg_input.skip(len); return res; }
/** * Reads more bytes into the buffer. * * @param wanted How much should be at least read. * @return True if at least some bytes were read. * @throws IOException If reading of the wrapped stream failed. */ private boolean readMore(int wanted) throws IOException { if (endIndex == index) { index = 0; endIndex = 0; } int canFit = buffer.length - endIndex; if (canFit < wanted) { // would the wanted bytes fit if we compacted the buffer // and still leave some slack if (index + canFit > wanted + MINIMUM_READ) { compact(); } else { doubleBuffer(); } canFit = buffer.length - endIndex; } int read = wrapped.read(buffer, endIndex, canFit); if (read < 0) { return false; } endIndex += read; return true; }
/** * Receives a two byte integer from the backend. * * @return the integer received from the backend * @throws IOException if an I/O error occurs */ public int receiveInteger2() throws IOException { if (pg_input.read(_int2buf) != 2) { throw new EOFException(); } return (_int2buf[0] & 0xFF) << 8 | _int2buf[1] & 0xFF; }
/** * Reads a byte from the buffer without advancing the index pointer. * * @return byte from the buffer without advancing the index pointer * @throws IOException if something wrong happens */ public int peek() throws IOException { if (ensureBytes(1)) { return buffer[index] & 0xFF; } return -1; }
/** * Compacts the unread bytes of the buffer to the beginning of the buffer. */ private void compact() { moveBufferTo(buffer); }
/** * Check for pending backend messages without blocking. Might return false when there actually are * messages waiting, depending on the characteristics of the underlying socket. This is used to * detect asynchronous notifies from the backend, when available. * * @return true if there is a pending backend message * @throws IOException if something wrong happens */ public boolean hasMessagePending() throws IOException { if (pg_input.available() > 0) { return true; } // In certain cases, available returns 0, yet there are bytes int soTimeout = getNetworkTimeout(); setNetworkTimeout(1); try { return pg_input.peek() != -1; } catch (SocketTimeoutException e) { return false; } finally { setNetworkTimeout(soTimeout); } }
/** * Receives a fixed-size string from the backend. * * @param len the length of the string to receive, in bytes. * @return the decoded string */ public String ReceiveString(int len) throws IOException { if (!pg_input.ensureBytes(len)) { throw new EOFException(); } String res = encoding.decode(pg_input.getBuffer(), pg_input.getIndex(), len); pg_input.skip(len); return res; }
/** * Receives a null-terminated string from the backend. If we don't see a * null, then we assume something has gone wrong. * * @return string from back end * @exception IOException if an I/O error occurs, or end of file */ public String ReceiveString() throws IOException { int len = pg_input.scanCStringLength(); String res = encoding.decode(pg_input.getBuffer(), pg_input.getIndex(), len - 1); pg_input.skip(len); return res; }
/** * Receives a single character from the backend. * * @return the character received * @throws IOException if an I/O Error occurs */ public int receiveChar() throws IOException { int c = pg_input.read(); if (c < 0) { throw new EOFException(); } return c; }
/** * Reads more bytes into the buffer. * * @param wanted How much should be at least read. * @return True if at least some bytes were read. * @throws IOException If reading of the wrapped stream failed. */ private boolean readMore(int wanted) throws IOException { if (endIndex == index) { index = 0; endIndex = 0; } int canFit = buffer.length - endIndex; if (canFit < wanted) { // would the wanted bytes fit if we compacted the buffer // and still leave some slack if (index + canFit > wanted + MINIMUM_READ) { compact(); } else { doubleBuffer(); } canFit = buffer.length - endIndex; } int read = wrapped.read(buffer, endIndex, canFit); if (read < 0) { return false; } endIndex += read; return true; }
/** * Reads a byte from the buffer without advancing the index pointer. */ public int peek() throws IOException { if (ensureBytes(1)) { return buffer[index] & 0xFF; } return -1; }
/** * Compacts the unread bytes of the buffer to the beginning of the buffer. */ private void compact() { moveBufferTo(buffer); }
/** * Receives a fixed-size string from the backend, and tries to avoid "UTF-8 decode failed" * errors. * * @param len the length of the string to receive, in bytes. * @return the decoded string * @throws IOException if something wrong happens */ public EncodingPredictor.DecodeResult receiveErrorString(int len) throws IOException { if (!pg_input.ensureBytes(len)) { throw new EOFException(); } EncodingPredictor.DecodeResult res; try { String value = encoding.decode(pg_input.getBuffer(), pg_input.getIndex(), len); // no autodetect warning as the message was converted on its own res = new EncodingPredictor.DecodeResult(value, null); } catch (IOException e) { res = EncodingPredictor.decode(pg_input.getBuffer(), pg_input.getIndex(), len); if (res == null) { Encoding enc = Encoding.defaultEncoding(); String value = enc.decode(pg_input.getBuffer(), pg_input.getIndex(), len); res = new EncodingPredictor.DecodeResult(value, enc.name()); } } pg_input.skip(len); return res; }
/** * Receives a null-terminated string from the backend. If we don't see a * null, then we assume something has gone wrong. * * @return string from back end * @exception IOException if an I/O error occurs, or end of file */ public String ReceiveString() throws IOException { int len = pg_input.scanCStringLength(); String res = encoding.decode(pg_input.getBuffer(), pg_input.getIndex(), len - 1); pg_input.skip(len); return res; }
/** * Receives a four byte integer from the backend * * @return the integer received from the backend * @exception IOException if an I/O error occurs */ public int ReceiveInteger4() throws IOException { if (pg_input.read(_int4buf) != 4) throw new EOFException(); return (_int4buf[0] & 0xFF) << 24 | (_int4buf[1] & 0xFF) << 16 | (_int4buf[2] & 0xFF) << 8 | _int4buf[3] & 0xFF; }
/** * Reads more bytes into the buffer. * * @param wanted How much should be at least read. * @return True if at least some bytes were read. * @throws IOException If reading of the wrapped stream failed. */ private boolean readMore(int wanted) throws IOException { if (endIndex == index) { index = 0; endIndex = 0; } int canFit = buffer.length - endIndex; if (canFit < wanted) { // would the wanted bytes fit if we compacted the buffer // and still leave some slack if (index + canFit > wanted + MINIMUM_READ) { compact(); } else { doubleBuffer(); } canFit = buffer.length - endIndex; } int read = wrapped.read(buffer, endIndex, canFit); if (read < 0) { return false; } endIndex += read; return true; }