All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jivesoftware.smackx.filetransfer.IncomingFileTransfer Maven / Gradle / Ivy

Go to download

Smack extensions. Classes and methods that implement support for the various XMPP XEPs (Multi-User Chat, PubSub, …) and other XMPP extensions.

There is a newer version: 4.5.0-beta5
Show newest version
/**
 *
 * Copyright 2003-2006 Jive Software.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jivesoftware.smackx.filetransfer;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger;

import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.util.CloseableUtil;


/**
 * An incoming file transfer is created when the
 * {@link FileTransferManager#createIncomingFileTransfer(FileTransferRequest)}
 * method is invoked. It is a file being sent to the local user from another
 * user on the jabber network. There are two stages of the file transfer to be
 * concerned with and they can be handled in different ways depending upon the
 * method that is invoked on this class.
 *
 * The first way that a file is received is by calling the
 * {@link #receiveFile()} method. This method, negotiates the appropriate stream
 * method and then returns the InputStream to read the file
 * data from.
 *
 * The second way that a file can be received through this class is by invoking
 * the {@link #receiveFile(File)} method. This method returns immediately and
 * takes as its parameter a file on the local file system where the file
 * recieved from the transfer will be put.
 *
 * @author Alexander Wenckus
 */
public class IncomingFileTransfer extends FileTransfer {

    private static final Logger LOGGER = Logger.getLogger(IncomingFileTransfer.class.getName());

    private FileTransferRequest receiveRequest;

    private InputStream inputStream;

    protected IncomingFileTransfer(FileTransferRequest request,
            FileTransferNegotiator transferNegotiator) {
        super(request.getRequestor(), request.getStreamID(), transferNegotiator);
        this.receiveRequest = request;
    }

    /**
     * Negotiates the stream method to transfer the file over and then returns
     * the negotiated stream.
     *
     * @return The negotiated InputStream from which to read the data.
     * @throws SmackException if Smack detected an exceptional situation.
     * @throws XMPPErrorException If there is an error in the negotiation process an exception
     *                       is thrown.
     * @throws InterruptedException if the calling thread was interrupted.
     */
    public InputStream receiveFile() throws SmackException, XMPPErrorException, InterruptedException {
        if (inputStream != null) {
            throw new IllegalStateException("Transfer already negotiated!");
        }

        try {
            inputStream = negotiateStream();
        }
        catch (XMPPErrorException e) {
            setException(e);
            throw e;
        }

        return inputStream;
    }

    /**
     * This method negotiates the stream and then transfer's the file over the negotiated stream.
     * The transferred file will be saved at the provided location.
     *
     * This method will return immediately, file transfer progress can be monitored through several
     * methods:
     *
     * 
    *
  • {@link FileTransfer#getStatus()}
  • *
  • {@link FileTransfer#getProgress()}
  • *
  • {@link FileTransfer#isDone()}
  • *
* * @param file The location to save the file. * @throws SmackException when the file transfer fails * @throws IOException if an I/O error occurred. * @throws IllegalArgumentException This exception is thrown when the the provided file is * either null, or cannot be written to. */ public void receiveFile(final File file) throws SmackException, IOException { if (file == null) { throw new IllegalArgumentException("File cannot be null"); } if (!file.exists()) { file.createNewFile(); } if (!file.canWrite()) { throw new IllegalArgumentException("Cannot write to provided file"); } Thread transferThread = new Thread(new Runnable() { @Override public void run() { try { inputStream = negotiateStream(); } catch (Exception e) { setStatus(FileTransfer.Status.error); setException(e); return; } OutputStream outputStream = null; try { outputStream = new FileOutputStream(file); setStatus(Status.in_progress); writeToStream(inputStream, outputStream); } catch (FileNotFoundException e) { setStatus(Status.error); setError(Error.bad_file); setException(e); } catch (IOException e) { setStatus(Status.error); setError(Error.stream); setException(e); } if (getStatus().equals(Status.in_progress)) { setStatus(Status.complete); } CloseableUtil.maybeClose(inputStream, LOGGER); CloseableUtil.maybeClose(outputStream, LOGGER); } }, "File Transfer " + streamID); transferThread.start(); } private InputStream negotiateStream() throws SmackException, XMPPErrorException, InterruptedException { setStatus(Status.negotiating_transfer); final StreamNegotiator streamNegotiator = negotiator .selectStreamNegotiator(receiveRequest); setStatus(Status.negotiating_stream); FutureTask streamNegotiatorTask = new FutureTask<>( new Callable() { @Override public InputStream call() throws Exception { return streamNegotiator .createIncomingStream(receiveRequest.getStreamInitiation()); } }); streamNegotiatorTask.run(); InputStream inputStream; try { inputStream = streamNegotiatorTask.get(15, TimeUnit.SECONDS); } catch (ExecutionException e) { final Throwable cause = e.getCause(); if (cause instanceof XMPPErrorException) { throw (XMPPErrorException) cause; } if (cause instanceof InterruptedException) { throw (InterruptedException) cause; } if (cause instanceof NoResponseException) { throw (NoResponseException) cause; } if (cause instanceof SmackException) { throw (SmackException) cause; } throw new SmackException.SmackWrappedException("Error in execution", e); } catch (TimeoutException e) { throw new SmackException.SmackWrappedException("Request timed out", e); } finally { streamNegotiatorTask.cancel(true); } setStatus(Status.negotiated); return inputStream; } @Override public void cancel() { setStatus(Status.cancelled); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy