package hep.io.root.daemon.xrootd; import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.logging.Logger; /** * Encapsulates a response from the xrootd server. * Initially this class reads the response header (always 8 bytes). * @author tonyj */ class Response { private Multiplexor multiplexor; private SocketChannel in; private ByteBuffer buffer = ByteBuffer.allocate(8); private ByteBuffer data; private Short handle; private int status; private int dataLength; private static Logger logger = Logger.getLogger(Response.class.getName()); /** * Create a response object for reading from a specific mumtiiplexor * @param multiplexor * @param in */ Response(Multiplexor multiplexor, SocketChannel in) { this.in = in; this.multiplexor = multiplexor; } SocketChannel getSocketChannel() { return in; } /** * Read an integer from the data associated with this response. * @throws java.io.IOException */ int readInt() throws IOException { readData(); return data.getInt(); } /** * Get all of the data from this response as a ByeBuffer * @return * @throws java.io.IOException */ ByteBuffer getData() throws IOException { readData(); return data; } /** * Read the remaining data associated with this response and convert it * to a String. * @throws java.io.IOException */ String getDataAsString() throws IOException { readData(); byte[] dataArray = data.array(); int start = data.position(); int length = data.remaining(); if (dataArray[start+length-1]==0) length--; // Trim trailing 0 (if any) return new String(dataArray,start,length, "US-ASCII"); } Multiplexor getMultiplexor() { return multiplexor; } void readData() throws IOException { if (data == null) { data = ByteBuffer.allocate(dataLength); readBuffer(data); data.flip(); } } /** Read data into the given byte buffer, which must be large enough to accept * the entire data section of the response. * @param buffer * @throws java.io.IOException */ void readData(ByteBuffer buffer) throws IOException { int oldLimit = -1; try { if (buffer.remaining() > dataLength) { oldLimit = buffer.limit(); buffer.limit(buffer.position() + dataLength); } readBuffer(buffer); } finally { if (oldLimit >= 0) { buffer.limit(oldLimit); } } } Destination getDestination() { return multiplexor.getDestination(); } boolean isComplete() { return status != XrootdProtocol.kXR_oksofar; } int read() throws IOException { buffer.clear(); readBuffer(buffer); buffer.flip(); handle = buffer.getShort(); status = buffer.getShort(); dataLength = buffer.getInt(); data = null; logger.finest("<-" + handle + " " + status + " " + dataLength); return 8 + dataLength; } void regurgitate() { handle = data.getShort(); status = data.getShort(); dataLength = data.getInt(); logger.finest("<-" + handle + " " + status + " " + dataLength); } int getStatus() { return status; } int getLength() { return dataLength; } Short getHandle() { return handle; } @Override public String toString() { return String.format("Response handle: %d status: %d dataLength: %d", handle, status, dataLength); } private void readBuffer(ByteBuffer buffer) throws EOFException, IOException { while (buffer.remaining()>0) { int l = in.read(buffer); if (l < 0) { throw new EOFException(); } } } }