/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004-2008], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.agent.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.hyperic.hq.agent.AgentRemoteException;
import org.hyperic.hq.agent.FileData;
import org.hyperic.hq.agent.FileDataResult;
import org.hyperic.util.math.MathUtil;
/**
* A utility combining one or more file input streams into a single output
* stream.
*/
public class FileStreamMultiplexer {
/**
* The default buffer size (8kb).
*/
public static final int DEFAULT_BUFFER_SIZE = 8*1024;
private final int _bufferSize;
/**
* Creates an instance using the default max output stream buffer size.
*/
public FileStreamMultiplexer() {
this(DEFAULT_BUFFER_SIZE);
}
/**
* Creates an instance where the max output stream buffer size is specified.
*
* @param bufferSize The buffer size.
* @throws IllegalArgumentException if the buffer size is not greater than zero.
*/
public FileStreamMultiplexer(int bufferSize) {
if (bufferSize <= 0) {
throw new IllegalArgumentException("buffer size must be greater than zero: "+bufferSize);
}
_bufferSize = bufferSize;
}
/**
* Muliplex the input streams into a single output stream.
*
* @param outStream The output stream where the combined streams are written.
* @param destFiles The files representing each input stream.
* @param streams The file input streams.
* @return The file data result.
*/
public FileDataResult[] sendData(OutputStream outStream,
FileData[] destFiles,
InputStream[] streams)
throws IOException, AgentRemoteException {
FileDataResult[] res = new FileDataResult[destFiles.length];
byte[] sendBuf = new byte[_bufferSize];
for(int i=0; i<destFiles.length; i++){
long startTime = System.currentTimeMillis();
long toSend = destFiles[i].getSize();
while(toSend > 0){
int nToRead, nBytes;
if((nToRead = streams[i].available()) == 0){
throw new AgentRemoteException("No available bytes to " +
"read for '" +
destFiles[i].getDestFile() +
"' - needed " + toSend +
" more bytes to complete");
}
nToRead = MathUtil.clamp(nToRead, 1, sendBuf.length);
nBytes = streams[i].read(sendBuf, 0, nToRead);
if(nBytes == -1){
throw new AgentRemoteException("Error reading from for '" +
destFiles[i].getDestFile() +
"' - read returned -1");
}
outStream.write(sendBuf, 0, nBytes);
toSend -= nBytes;
}
long sendTime = System.currentTimeMillis() - startTime;
res[i] = new FileDataResult(destFiles[i].getDestFile(),
destFiles[i].getSize(), sendTime);
}
return res;
}
}