/*******************************************************************************
* Copyright (c) 2006-2008, Cloudsmith Inc.
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the copyright holder
* listed above, as the Initial Contributor under such license. The text of
* such license is available at www.eclipse.org.
******************************************************************************/
package org.eclipse.equinox.p2.authoring.internal;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.URL;
import java.util.Date;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.ecf.filetransfer.FileTransferJob;
import org.eclipse.ecf.filetransfer.IFileTransferListener;
import org.eclipse.ecf.filetransfer.IIncomingFileTransfer;
import org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter;
import org.eclipse.ecf.filetransfer.IncomingFileTransferException;
import org.eclipse.ecf.filetransfer.events.IFileTransferEvent;
import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferEvent;
import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferReceiveDataEvent;
import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferReceiveDoneEvent;
import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferReceiveStartEvent;
import org.eclipse.ecf.filetransfer.identity.FileIDFactory;
import org.eclipse.ecf.filetransfer.identity.IFileID;
import org.eclipse.equinox.p2.authoring.P2AuthoringUIPlugin;
/**
* @author Thomas Hallgren
*/
public class FileReader extends FileTransferJob implements IFileTransferListener
{
private boolean m_closeStreamWhenFinished = false;
private Exception m_exception;
private IFileInfo m_fileInfo;
private long m_lastProgressCount;
private long m_lastStatsCount;
private IProgressMonitor m_monitor;
private boolean m_onlyGetInfo = false;
private OutputStream m_outputStream;
private ProgressStatistics m_statistics;
public FileReader()
{
super("URL reader");
// Hide this job.
setSystem(true);
setUser(false);
}
public IFileInfo getLastFileInfo()
{
return m_fileInfo;
}
public synchronized void handleTransferEvent(IFileTransferEvent event)
{
IIncomingFileTransfer source = ((IIncomingFileTransferEvent)event).getSource();
if(event instanceof IIncomingFileTransferReceiveStartEvent)
{
try
{
FileInfoBuilder fi = new FileInfoBuilder();
Date lastModified = source.getRemoteLastModified();
if(lastModified != null)
fi.setLastModified(lastModified.getTime());
fi.setName(source.getRemoteFileName());
fi.setSize(source.getFileLength());
m_fileInfo = fi;
if(m_onlyGetInfo)
((IIncomingFileTransferReceiveStartEvent)event).cancel();
else
((IIncomingFileTransferReceiveStartEvent)event).receive(m_outputStream, this);
}
catch(IOException e)
{
m_exception = e;
return;
}
if(m_monitor != null)
{
long fileLength = source.getFileLength();
m_statistics = new ProgressStatistics(source.getRemoteFileName(), fileLength);
m_monitor.beginTask(null, 1000);
m_monitor.subTask(m_statistics.report());
m_lastStatsCount = 0;
m_lastProgressCount = 0;
}
}
else if(event instanceof IIncomingFileTransferReceiveDataEvent)
{
if(m_monitor != null)
{
if(m_monitor.isCanceled())
{
source.cancel();
return;
}
long br = source.getBytesReceived();
long count = br - m_lastStatsCount;
m_lastStatsCount = br;
m_statistics.increase(count);
if(m_statistics.shouldReport())
{
count = br - m_lastProgressCount;
m_lastProgressCount = br;
m_monitor.subTask(m_statistics.report());
m_monitor.worked((int)(1000 * count / m_statistics.getTotal()));
}
}
}
else if(event instanceof IIncomingFileTransferReceiveDoneEvent)
{
if(m_closeStreamWhenFinished)
if(m_outputStream != null)
{
try
{
m_outputStream.close();
}
catch(IOException e)
{
}
}
if(m_exception == null)
m_exception = ((IIncomingFileTransferReceiveDoneEvent)event).getException();
}
}
public InputStream read(URL url) throws CoreException, FileNotFoundException
{
final PipedInputStream input = new PipedInputStream();
PipedOutputStream output;
try
{
output = new PipedOutputStream(input);
}
catch(IOException e)
{
throw P2AuthoringException.wrap(e);
}
sendRetrieveRequest(url, output, true, false, null);
return new InputStream()
{
@Override
public int available() throws IOException
{
checkException();
return input.available();
}
@Override
public void close() throws IOException
{
checkException();
input.close();
}
@Override
public synchronized void mark(int readlimit)
{
input.mark(readlimit);
}
@Override
public boolean markSupported()
{
return input.markSupported();
}
@Override
public int read() throws IOException
{
checkException();
return input.read();
}
@Override
public int read(byte b[]) throws IOException
{
checkException();
return input.read(b);
}
@Override
public int read(byte b[], int off, int len) throws IOException
{
checkException();
return input.read(b, off, len);
}
@Override
public synchronized void reset() throws IOException
{
checkException();
input.reset();
}
@Override
public long skip(long n) throws IOException
{
checkException();
return input.skip(n);
}
private void checkException() throws IOException
{
if(m_exception == null)
return;
IOException e;
Throwable t = P2AuthoringException.unwind(m_exception);
if(t instanceof IOException)
e = (IOException)t;
else
{
e = new IOException(t.getMessage());
e.initCause(t);
}
throw e;
}
};
}
public IFileInfo readInfo(URL url) throws CoreException, FileNotFoundException
{
sendRetrieveRequest(url, null, false, true, null);
return getLastFileInfo();
}
public void readInto(URL url, OutputStream outputStream, IProgressMonitor monitor) throws CoreException, FileNotFoundException
{
try
{
sendRetrieveRequest(url, outputStream, false, false, monitor);
join();
}
catch(InterruptedException e)
{
monitor.setCanceled(true);
throw new OperationCanceledException();
}
finally
{
if(monitor != null)
{
if(m_statistics == null)
//
// Monitor was never started. See to that it's balanced
//
monitor.beginTask(null, 1);
else
m_statistics = null;
monitor.done();
}
}
}
protected void sendRetrieveRequest(URL url, OutputStream outputStream, boolean closeStreamWhenFinished, boolean onlyGetInfo, IProgressMonitor monitor) throws CoreException, FileNotFoundException
{
IRetrieveFileTransferContainerAdapter adapter = P2AuthoringUIPlugin.getDefault().createRetrieveFileTransfer();
m_exception = null;
m_closeStreamWhenFinished = closeStreamWhenFinished;
m_onlyGetInfo = onlyGetInfo;
m_fileInfo = null;
m_statistics = null;
m_lastProgressCount = 0L;
m_lastStatsCount = 0L;
m_monitor = monitor;
m_outputStream = outputStream;
try
{
IFileID fileID = FileIDFactory.getDefault().createFileID(adapter.getRetrieveNamespace(), url);
adapter.sendRetrieveRequest(fileID, this, null);
}
catch(IncomingFileTransferException e)
{
m_exception = e;
}
if(m_exception != null)
{
Throwable t = P2AuthoringException.unwind(m_exception);
if(t instanceof CoreException)
throw (CoreException)t;
if(t instanceof FileNotFoundException)
throw (FileNotFoundException)t;
throw P2AuthoringException.wrap(m_exception);
}
}
}