Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[mylyn-dev] attachment upload progress

Hi

The current infrastructure doesn't seem to report upload progress when adding an attachment to a task. Looking at AbstractTaskAttachmentSource the code seems designed for progress reporting but neither TaskAttachmentPartSource nor any of the concrete TaskAttachmentSource classes seem to make any use of it.

I got some quite good results with the attached code. The only issue it has is that the monitor handed to me trough AbstractTaskAttachmentHandler seems to use only about a third of the ticks of the parent monitor. So the visual effect is that the progress bar steadily moving form 0% to 33% and the suddenly jumping to 100%. Four fifths or even nine tenths of the ticks would probably yield much better results.

Cheers
Philippe
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.httpclient.methods.multipart.PartSource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskAttachmentSource;

/**
 * Like {@link org.eclipse.mylyn.tasks.core.data.TaskAttachmentPartSource} but
 * uses a monitor.
 */
public class TaskAttachmentPartSource2 implements PartSource {

  private final AbstractTaskAttachmentSource attachment;

  private final String fileName;
  
  private final IProgressMonitor monitor;

  /**
   * Initializes a {@link TaskAttachmentPartSource}.
   * 
   * @param attachment the attachment
   * @param fileName the file name
   * @param monitor the monitor
   */
  TaskAttachmentPartSource(AbstractTaskAttachmentSource attachment, String fileName, IProgressMonitor monitor) {
    this.attachment = attachment;
    this.fileName = fileName;
    this.monitor = monitor;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public InputStream createInputStream() throws IOException {
    try {
      this.monitor.beginTask("Uploading Attachment " + this.getFileName(), (int) this.getLength());
      return new ProgressInputStream(this.attachment.createInputStream(null), this.monitor);
    } catch (CoreException e) {
      this.monitor.done();
      String message = "Failed to create source stream"; //$NON-NLS-1$
      throw new IOException(message, e);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String getFileName() {
    return this.fileName;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public long getLength() {
    return this.attachment.getLength();
  }
  
  /**
   * An {@link InputStream} that wraps an other one an reports how much has
   * been read.
   */
  static final class ProgressInputStream extends InputStream {

    private final IProgressMonitor monitor;
    
    private final InputStream delegate;

    /**
     * Initializes a {@link ProgressInputStream}.
     * 
     * @param delegate the actual {@link InputStream} from which to read
     * @param monitor the monitor to use
     */
    ProgressInputStream(InputStream delegate, IProgressMonitor monitor) {
      super();
      this.delegate = delegate;
      this.monitor = monitor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int available() throws IOException {
      return this.delegate.available();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException {
      try {
        this.delegate.close();
      } finally {
        this.monitor.done();
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mark(int readlimit) {
      this.delegate.mark(readlimit);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean markSupported() {
      return this.delegate.markSupported();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int read() throws IOException {
      try {
        return this.delegate.read();
      } finally {
        this.monitor.worked(1);
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int read(byte[] b, int off, int len) throws IOException {
      try {
        return this.delegate.read(b, off, len);
      } finally {
        this.monitor.worked(len);
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int read(byte[] b) throws IOException {
      try {
        return this.delegate.read(b);
      } finally {
        this.monitor.worked(b.length);
      }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void reset() throws IOException {
      // screws up the monitor
      this.delegate.reset();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long skip(long n) throws IOException {
      try {
        return this.delegate.skip(n);
      } finally {
        this.monitor.worked((int) n);
      }
    }
    
  }

}

Back to the top