Package org.eclipse.ecf.provider.filetransfer.outgoing

Source Code of org.eclipse.ecf.provider.filetransfer.outgoing.AbstractOutgoingFileTransfer

/*******************************************************************************
* Copyright (c) 2004, 2010 Composent, Inc. 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: Composent, Inc. - initial API and implementation
*               Cloudsmith, Inc. - additional API and implementation
*               Henrich Kraemer - bug 295030, Update Manager doesn't work with SOCKS proxy 
******************************************************************************/
package org.eclipse.ecf.provider.filetransfer.outgoing;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.core.identity.IDFactory;
import org.eclipse.ecf.core.identity.Namespace;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.util.Proxy;
import org.eclipse.ecf.filetransfer.FileTransferInfo;
import org.eclipse.ecf.filetransfer.FileTransferJob;
import org.eclipse.ecf.filetransfer.IFileTransferInfo;
import org.eclipse.ecf.filetransfer.IFileTransferListener;
import org.eclipse.ecf.filetransfer.IFileTransferRunnable;
import org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener;
import org.eclipse.ecf.filetransfer.IOutgoingFileTransfer;
import org.eclipse.ecf.filetransfer.SendFileTransferException;
import org.eclipse.ecf.filetransfer.UserCancelledException;
import org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferResponseEvent;
import org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferSendDataEvent;
import org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferSendDoneEvent;
import org.eclipse.ecf.filetransfer.identity.IFileID;
import org.eclipse.ecf.filetransfer.service.ISendFileTransfer;
import org.eclipse.ecf.internal.provider.filetransfer.Activator;
import org.eclipse.ecf.internal.provider.filetransfer.Messages;
import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
import org.eclipse.ecf.provider.filetransfer.util.ProxySetupHelper;
import org.eclipse.osgi.util.NLS;

/**
*
*/
public abstract class AbstractOutgoingFileTransfer implements IOutgoingFileTransfer, ISendFileTransfer {

  public static final int DEFAULT_BUF_LENGTH = 4096;

  protected Job job;

  protected URL remoteFileURL;

  protected IFileID remoteFileID;

  protected IFileTransferListener listener;

  protected int buff_length = DEFAULT_BUF_LENGTH;

  protected boolean done = false;

  protected long bytesSent = 0;

  protected InputStream localFileContents;

  protected OutputStream remoteFileContents;

  protected Exception exception;

  protected IFileTransferInfo fileTransferInfo;

  protected Map options = null;

  protected IConnectContext connectContext;

  protected Proxy proxy;

  private final IFileTransferRunnable fileTransferRunnable = new IFileTransferRunnable() {
    public IStatus performFileTransfer(IProgressMonitor monitor) {
      final byte[] buf = new byte[buff_length];
      final long totalWork = ((fileTransferInfo.getFileSize() == -1) ? 100 : fileTransferInfo.getFileSize());
      double factor = (totalWork > Integer.MAX_VALUE) ? (((double) Integer.MAX_VALUE) / ((double) totalWork)) : 1.0;
      int work = (totalWork > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) totalWork;
      monitor.beginTask(getRemoteFileURL().toString() + Messages.AbstractOutgoingFileTransfer_Progress_Data, work);
      try {
        while (!isDone()) {
          if (monitor.isCanceled())
            throw new UserCancelledException(Messages.AbstractOutgoingFileTransfer_Exception_User_Cancelled);
          final int bytes = localFileContents.read(buf);
          if (bytes != -1) {
            bytesSent += bytes;
            remoteFileContents.write(buf, 0, bytes);
            fireTransferSendDataEvent();
            monitor.worked((int) Math.round(factor * bytes));
          } else {
            done = true;
          }
        }
      } catch (final Exception e) {
        exception = e;
        done = true;
      } finally {
        hardClose();
        monitor.done();
        try {
          fireTransferSendDoneEvent();
        } catch (Exception e) {
          Activator.getDefault().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, Messages.AbstractOutgoingFileTransfer_EXCEPTION_IN_FINALLY, e));
        }
      }
      return getFinalStatus(exception);
    }
  };

  FileTransferJob fileTransferJob;

  protected URL getRemoteFileURL() {
    return remoteFileURL;
  }

  protected void setInputStream(InputStream ins) {
    localFileContents = ins;
  }

  protected void setOutputStream(OutputStream outs) {
    remoteFileContents = outs;
  }

  protected IFileTransferInfo getFileTransferInfo() {
    return fileTransferInfo;
  }

  protected Map getOptions() {
    return options;
  }

  public AbstractOutgoingFileTransfer() {
    //
  }

  protected IStatus getFinalStatus(Throwable exception1) {
    return Status.OK_STATUS;
  }

  protected void hardClose() {
    try {
      if (remoteFileContents != null)
        remoteFileContents.close();
    } catch (final IOException e) {
      Activator.getDefault().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, "hardClose", e)); //$NON-NLS-1$
    }
    try {
      if (localFileContents != null)
        localFileContents.close();
    } catch (final IOException e) {
      Activator.getDefault().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, "hardClose", e)); //$NON-NLS-1$
    }
    job = null;
    remoteFileContents = null;
    localFileContents = null;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.core.identity.IIdentifiable#getID()
   */
  public ID getID() {
    return remoteFileID;
  }

  protected void fireTransferSendDoneEvent() {
    listener.handleTransferEvent(new IOutgoingFileTransferSendDoneEvent() {

      public IOutgoingFileTransfer getSource() {
        return AbstractOutgoingFileTransfer.this;
      }

      public Exception getException() {
        return AbstractOutgoingFileTransfer.this.getException();
      }

      public String toString() {
        final StringBuffer sb = new StringBuffer("IOutgoingFileTransferSendDoneEvent["); //$NON-NLS-1$
        sb.append("bytesSent=").append(bytesSent) //$NON-NLS-1$
            .append(";fileLength=").append(fileTransferInfo.getFileSize()).append(";exception=").append(getException()) //$NON-NLS-1$ //$NON-NLS-2$
            .append("]"); //$NON-NLS-1$
        return sb.toString();
      }
    });
  }

  protected void fireTransferSendDataEvent() {
    listener.handleTransferEvent(new IOutgoingFileTransferSendDataEvent() {

      public IOutgoingFileTransfer getSource() {
        return AbstractOutgoingFileTransfer.this;
      }

      public String toString() {
        final StringBuffer sb = new StringBuffer("IOutgoingFileTransferSendDataEvent["); //$NON-NLS-1$
        sb.append("bytesSent=").append(bytesSent) //$NON-NLS-1$
            .append(";fileLength=").append(fileTransferInfo.getFileSize()) //$NON-NLS-1$
            .append("]"); //$NON-NLS-1$
        return sb.toString();
      }
    });
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.IOutgoingFileTransfer#getBytesSent()
   */
  public long getBytesSent() {
    return bytesSent;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.IFileTransfer#cancel()
   */
  public void cancel() {
    if (job != null)
      job.cancel();
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.IFileTransfer#getException()
   */
  public Exception getException() {
    return exception;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ecf.filetransfer.IFileTransfer#getPercentComplete()
   */
  public double getPercentComplete() {
    long fileLength = getFileLength();
    if (fileLength == -1 || fileLength == 0)
      return fileLength;
    return ((double) bytesSent / (double) fileLength);
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.IFileTransfer#getFileLength()
   */
  public long getFileLength() {
    return fileTransferInfo.getFileSize();
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.IFileTransfer#isDone()
   */
  public boolean isDone() {
    return done;
  }

  /* (non-Javadoc)
   * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
   */
  public Object getAdapter(Class adapter) {
    if (adapter == null)
      return null;
    if (adapter.isInstance(this)) {
      return this;
    }
    final IAdapterManager adapterManager = Activator.getDefault().getAdapterManager();
    return (adapterManager == null) ? null : adapterManager.loadAdapter(this, adapter.getName());
  }

  /**
   * Open incoming and outgoing streams associated with this file transfer.
   * Subclasses must implement this method to open input and output streams.
   * The <code>remoteFileContents</code> and <code>localFileContent</code>
   * must be non-<code>null</code> after successful completion of the
   * implementation of this method.
   *
   * @throws SendFileTransferException
   */
  protected abstract void openStreams() throws SendFileTransferException;

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#getOutgoingNamespace()
   */
  public Namespace getOutgoingNamespace() {
    return IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL);
  }

  public IFileTransferListener getListener() {
    return listener;
  }

  protected String createJobName() {
    return getRemoteFileURL().toString();
  }

  protected void setupAndScheduleJob() {
    if (fileTransferJob == null)
      fileTransferJob = new FileTransferJob(createJobName());
    fileTransferJob.setFileTransferRunnable(fileTransferRunnable);
    fileTransferJob.setFileTransfer(this);
    job = fileTransferJob;
    job.schedule();
  }

  protected void fireSendStartEvent() {
    listener.handleTransferEvent(new IOutgoingFileTransferResponseEvent() {

      public String toString() {
        final StringBuffer sb = new StringBuffer("IOutgoingFileTransferResponseEvent["); //$NON-NLS-1$
        sb.append("isdone=").append(done).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
        sb.append("bytesSent=").append(bytesSent) //$NON-NLS-1$
            .append("]"); //$NON-NLS-1$
        return sb.toString();
      }

      /* (non-Javadoc)
       * @see org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferResponseEvent#requestAccepted()
       */
      public boolean requestAccepted() {
        return true;
      }

      /* (non-Javadoc)
       * @see org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferEvent#getSource()
       */
      public IOutgoingFileTransfer getSource() {
        return AbstractOutgoingFileTransfer.this;
      }

      /* (non-Javadoc)
       * @see org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferResponseEvent#setFileTransferJob(org.eclipse.ecf.filetransfer.FileTransferJob)
       */
      public void setFileTransferJob(org.eclipse.ecf.filetransfer.FileTransferJob ftj) {
        AbstractOutgoingFileTransfer.this.fileTransferJob = ftj;
      }

    });
  }

  protected abstract void setupProxy(Proxy proxy);

  protected void setupProxies() {
    // If it's been set directly (via ECF API) then this overrides platform settings
    if (proxy == null) {
      try {
        proxy = ProxySetupHelper.getProxy(getRemoteFileURL().toExternalForm());
      } catch (NoClassDefFoundError e) {
        // If the proxy API is not available a NoClassDefFoundError will be thrown here.
        // If that happens then we just want to continue on.
        Activator.logNoProxyWarning(e);
      }
    }
    if (proxy != null)
      setupProxy(proxy);

  }

  /**
   * Select a single proxy from a set of proxies available for the given host.  This implementation
   * selects in the following manner:  1) If proxies provided is null or array of 0 length, null
   * is returned.  If only one proxy is available (array of length 1) then the entry is returned.
   * If proxies provided is length > 1, then if the type of a proxy in the array matches the given
   * protocol (e.g. http, https), then the first matching proxy is returned.  If the protocol does
   * not match any of the proxies, then the *first* proxy (i.e. proxies[0]) is returned.  Subclasses may
   * override if desired.
   *
   * @param protocol the target protocol (e.g. http, https, scp, etc).  Will not be <code>null</code>.
   * @param proxies the proxies to select from.  May be <code>null</code> or array of length 0.
   * @return proxy data selected from the proxies provided. 
   */
  protected IProxyData selectProxyFromProxies(String protocol, IProxyData[] proxies) {
    if (proxies == null || proxies.length == 0)
      return null;
    // If only one proxy is available, then use that
    if (proxies.length == 1)
      return proxies[0];
    // If more than one proxy is available, then if http/https protocol then look for that
    // one...if not found then use first
    if (protocol.equalsIgnoreCase("http")) { //$NON-NLS-1$
      for (int i = 0; i < proxies.length; i++) {
        if (proxies[i].getType().equals(IProxyData.HTTP_PROXY_TYPE))
          return proxies[i];
      }
    } else if (protocol.equalsIgnoreCase("https")) { //$NON-NLS-1$
      for (int i = 0; i < proxies.length; i++) {
        if (proxies[i].getType().equals(IProxyData.HTTPS_PROXY_TYPE))
          return proxies[i];
      }
    }
    // If we haven't found it yet, then return the first one.
    return proxies[0];
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#sendOutgoingRequest(org.eclipse.ecf.filetransfer.identity.IFileID, org.eclipse.ecf.filetransfer.IFileTransferInfo, org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
   */
  public void sendOutgoingRequest(IFileID targetReceiver, IFileTransferInfo localFileToSend, IFileTransferListener transferListener, Map ops) throws SendFileTransferException {
    Assert.isNotNull(targetReceiver, Messages.AbstractOutgoingFileTransfer_RemoteFileID_Not_Null);
    Assert.isNotNull(transferListener, Messages.AbstractOutgoingFileTransfer_TransferListener_Not_Null);
    Assert.isNotNull(localFileToSend, Messages.AbstractOutgoingFileTransfer_EXCEPTION_FILE_TRANSFER_INFO_NOT_NULL);
    this.done = false;
    this.bytesSent = 0;
    this.exception = null;
    this.fileTransferInfo = localFileToSend;
    this.remoteFileID = targetReceiver;
    this.options = ops;

    try {
      this.remoteFileURL = targetReceiver.getURL();
    } catch (final MalformedURLException e) {
      throw new SendFileTransferException(NLS.bind(Messages.AbstractOutgoingFileTransfer_MalformedURLException, targetReceiver), e);
    }
    this.listener = transferListener;
    setupProxies();
    openStreams();
    fireSendStartEvent();
    setupAndScheduleJob();
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#sendOutgoingRequest(org.eclipse.ecf.filetransfer.identity.IFileID, java.io.File, org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
   */
  public void sendOutgoingRequest(IFileID targetReceiver, final File localFileToSend, IFileTransferListener transferListener, Map ops) throws SendFileTransferException {
    sendOutgoingRequest(targetReceiver, new FileTransferInfo(localFileToSend, null, null), transferListener, ops);
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#addListener(org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener)
   */
  public void addListener(IIncomingFileTransferRequestListener l) {
    // Not needed
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#removeListener(org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener)
   */
  public boolean removeListener(IIncomingFileTransferRequestListener l) {
    return false;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#setConnectContextForAuthentication(org.eclipse.ecf.core.security.IConnectContext)
   */
  public void setConnectContextForAuthentication(IConnectContext connectContext) {
    this.connectContext = connectContext;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#setProxy(org.eclipse.ecf.core.util.Proxy)
   */
  public void setProxy(Proxy proxy) {
    this.proxy = proxy;
  }

}
TOP

Related Classes of org.eclipse.ecf.provider.filetransfer.outgoing.AbstractOutgoingFileTransfer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.