/******************************************************************************* * Copyright (c) 2001, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jem.internal.proxy.remote; /* */ import java.io.*; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jem.internal.proxy.core.ProxyPlugin; import org.eclipse.jem.internal.proxy.common.CommandException; import org.eclipse.jem.internal.proxy.common.remote.Commands; import org.eclipse.jem.internal.proxy.common.remote.IOCommandException; /** * This is the inputstream used to return a lot of data from * the server. */ public class REMCallbackInputStream extends InputStream { protected DataInputStream fIn; protected DataOutputStream fOut; protected byte[] fBuffer; protected int fNextByte = 0; protected int fLastByte = 0; public REMCallbackInputStream(DataInputStream in, DataOutputStream out) { fIn = in; fOut = out; Integer bufSize = Integer.getInteger("proxyvm.bufsize"); //$NON-NLS-1$ if (bufSize == null) bufSize = new Integer(16000); fBuffer = new byte[bufSize.intValue()]; } protected void clearStream() { fIn = null; fOut = null; fBuffer = null; } protected void fillBuffer() throws IOException { if (fIn == null) throw new InterruptedIOException(); try { if (fLastByte != -1) { fLastByte = Commands.readBytes(fIn, fBuffer); if (fLastByte != -1) fNextByte = 0; else { fNextByte = -1; } } } catch (CommandException e) { try { close(false); } catch (IOException e1) { ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.WARNING, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e1)); // Error during close, just log it. //$NON-NLS-1$ } throw new IOCommandException(e); } } public int read() throws IOException { if (fNextByte >= fLastByte) { fillBuffer(); } if (fLastByte == -1) return -1; // We've previously reached the end. return fBuffer[fNextByte++] & 0xFF; // So that it is in range 0 to 255. } public int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int read = 0; while (len > 0) { if (fNextByte >= fLastByte) fillBuffer(); if (fLastByte == -1) return read != 0 ? read : -1; // No more, return amount read, or if none read, then -1 int move = fLastByte - fNextByte; if (move > len) move = len; System.arraycopy(fBuffer, fNextByte, b, off, move); read += move; fNextByte += move; off += move; len -= move; } return read; } public int available() throws IOException { return fLastByte != -1 ? fLastByte - fNextByte : 0; } public void close() throws IOException { close(true); } protected void close(boolean wait) throws IOException { if (fOut == null) return; // Already closed. try { fOut.writeByte(Commands.CALLBACK_STREAM_TERMINATE); fOut.flush(); fOut = null; // So that we know we closed already if error occurs during in read() below. if (wait) { // Need to read until End of stream because we need to flush out the // stream so that next time we use this connection we start fresh. // If the server has already finished writing, we will read until then. // If the server has not yet finished writing, when it reads the terminate // request it will send an end of stream marker for us to read. But either // way we can't leave until we've read everything from the stream. // If called with no wait, then we are closing hard and will be closing the socket too. while (read() != -1) { } } } finally { clearStream(); } } }