FileTransfer.java
- /**
- *
- * 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.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import org.jxmpp.jid.Jid;
- /**
- * Contains the generic file information and progress related to a particular
- * file transfer.
- *
- * @author Alexander Wenckus
- *
- */
- public abstract class FileTransfer {
- private String fileName;
- private String filePath;
- private long fileSize;
- private Jid peer;
- private Status status = Status.initial;
- private final Object statusMonitor = new Object();
- protected FileTransferNegotiator negotiator;
- protected String streamID;
- protected long amountWritten = -1;
- private Error error;
- private Exception exception;
- /**
- * Buffer size between input and output
- */
- private static final int BUFFER_SIZE = 8192;
- protected FileTransfer(Jid peer, String streamID,
- FileTransferNegotiator negotiator) {
- this.peer = peer;
- this.streamID = streamID;
- this.negotiator = negotiator;
- }
- protected void setFileInfo(String fileName, long fileSize) {
- this.fileName = fileName;
- this.fileSize = fileSize;
- }
- protected void setFileInfo(String path, String fileName, long fileSize) {
- this.filePath = path;
- this.fileName = fileName;
- this.fileSize = fileSize;
- }
- /**
- * Returns the size of the file being transfered.
- *
- * @return Returns the size of the file being transfered.
- */
- public long getFileSize() {
- return fileSize;
- }
- /**
- * Returns the name of the file being transfered.
- *
- * @return Returns the name of the file being transfered.
- */
- public String getFileName() {
- return fileName;
- }
- /**
- * Returns the local path of the file.
- *
- * @return Returns the local path of the file.
- */
- public String getFilePath() {
- return filePath;
- }
- /**
- * Returns the JID of the peer for this file transfer.
- *
- * @return Returns the JID of the peer for this file transfer.
- */
- public Jid getPeer() {
- return peer;
- }
- /**
- * Returns the progress of the file transfer as a number between 0 and 1.
- *
- * @return Returns the progress of the file transfer as a number between 0
- * and 1.
- */
- public double getProgress() {
- if (amountWritten <= 0 || fileSize <= 0) {
- return 0;
- }
- return (double) amountWritten / (double) fileSize;
- }
- /**
- * Returns true if the transfer has been cancelled, if it has stopped because
- * of a an error, or the transfer completed successfully.
- *
- * @return Returns true if the transfer has been cancelled, if it has stopped
- * because of a an error, or the transfer completed successfully.
- */
- public boolean isDone() {
- return status == Status.cancelled || status == Status.error
- || status == Status.complete || status == Status.refused;
- }
- /**
- * Returns the current status of the file transfer.
- *
- * @return Returns the current status of the file transfer.
- */
- public Status getStatus() {
- return status;
- }
- protected void setError(Error type) {
- this.error = type;
- }
- /**
- * When {@link #getStatus()} returns that there was an {@link Status#error}
- * during the transfer, the type of error can be retrieved through this
- * method.
- *
- * @return Returns the type of error that occurred if one has occurred.
- */
- public Error getError() {
- return error;
- }
- /**
- * If an exception occurs asynchronously it will be stored for later
- * retrieval. If there is an error there maybe an exception set.
- *
- * @return The exception that occurred or null if there was no exception.
- * @see #getError()
- */
- public Exception getException() {
- return exception;
- }
- public String getStreamID() {
- return streamID;
- }
- /**
- * Cancels the file transfer.
- */
- public abstract void cancel();
- protected void setException(Exception exception) {
- this.exception = exception;
- }
- protected void setStatus(Status status) {
- synchronized (statusMonitor) {
- this.status = status;
- }
- }
- protected boolean updateStatus(Status oldStatus, Status newStatus) {
- synchronized (statusMonitor) {
- if (oldStatus != status) {
- return false;
- }
- status = newStatus;
- return true;
- }
- }
- protected void writeToStream(final InputStream in, final OutputStream out)
- throws IOException
- {
- final byte[] b = new byte[BUFFER_SIZE];
- int count = 0;
- amountWritten = 0;
- while ((count = in.read(b)) > 0 && !getStatus().equals(Status.cancelled)) {
- out.write(b, 0, count);
- amountWritten += count;
- }
- // the connection was likely terminated abruptly if these are not equal
- if (!getStatus().equals(Status.cancelled) && getError() == Error.none
- && amountWritten != fileSize) {
- setStatus(Status.error);
- this.error = Error.connection;
- }
- }
- /**
- * A class to represent the current status of the file transfer.
- *
- * @author Alexander Wenckus
- *
- */
- public enum Status {
- /**
- * An error occurred during the transfer.
- *
- * @see FileTransfer#getError()
- */
- error("Error"),
- /**
- * The initial status of the file transfer.
- */
- initial("Initial"),
- /**
- * The file transfer is being negotiated with the peer. The party
- * Receiving the file has the option to accept or refuse a file transfer
- * request. If they accept, then the process of stream negotiation will
- * begin. If they refuse the file will not be transfered.
- *
- * @see #negotiating_stream
- */
- negotiating_transfer("Negotiating Transfer"),
- /**
- * The peer has refused the file transfer request halting the file
- * transfer negotiation process.
- */
- refused("Refused"),
- /**
- * The stream to transfer the file is being negotiated over the chosen
- * stream type. After the stream negotiating process is complete the
- * status becomes negotiated.
- *
- * @see #negotiated
- */
- negotiating_stream("Negotiating Stream"),
- /**
- * After the stream negotiation has completed the intermediate state
- * between the time when the negotiation is finished and the actual
- * transfer begins.
- */
- negotiated("Negotiated"),
- /**
- * The transfer is in progress.
- *
- * @see FileTransfer#getProgress()
- */
- in_progress("In Progress"),
- /**
- * The transfer has completed successfully.
- */
- complete("Complete"),
- /**
- * The file transfer was cancelled
- */
- cancelled("Cancelled");
- private String status;
- private Status(String status) {
- this.status = status;
- }
- public String toString() {
- return status;
- }
- }
- /**
- * Return the length of bytes written out to the stream.
- * @return the amount in bytes written out.
- */
- public long getAmountWritten(){
- return amountWritten;
- }
- public enum Error {
- /**
- * No error
- */
- none("No error"),
- /**
- * The peer did not find any of the provided stream mechanisms
- * acceptable.
- */
- not_acceptable("The peer did not find any of the provided stream mechanisms acceptable."),
- /**
- * The provided file to transfer does not exist or could not be read.
- */
- bad_file("The provided file to transfer does not exist or could not be read."),
- /**
- * The remote user did not respond or the connection timed out.
- */
- no_response("The remote user did not respond or the connection timed out."),
- /**
- * An error occurred over the socket connected to send the file.
- */
- connection("An error occured over the socket connected to send the file."),
- /**
- * An error occurred while sending or receiving the file
- */
- stream("An error occured while sending or recieving the file.");
- private final String msg;
- private Error(String msg) {
- this.msg = msg;
- }
- /**
- * Returns a String representation of this error.
- *
- * @return Returns a String representation of this error.
- */
- public String getMessage() {
- return msg;
- }
- public String toString() {
- return msg;
- }
- }
- }