Advertisement
Guest User

myOutgoingFileTransfer

a guest
Jul 10th, 2012
538
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.67 KB | None | 0 0
  1. /**
  2.  * $RCSfile$
  3.  * $Revision: $
  4.  * $Date: $
  5.  *
  6.  * Copyright 2003-2006 Jive Software.
  7.  *
  8.  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
  9.  * you may not use this file except in compliance with the License.
  10.  * You may obtain a copy of the License at
  11.  *
  12.  *     http://www.apache.org/licenses/LICENSE-2.0
  13.  *
  14.  * Unless required by applicable law or agreed to in writing, software
  15.  * distributed under the License is distributed on an "AS IS" BASIS,
  16.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17.  * See the License for the specific language governing permissions and
  18.  * limitations under the License.
  19.  */
  20. package org.jivesoftware.smackx.filetransfer;
  21.  
  22. import org.jivesoftware.smack.Connection;
  23. import org.jivesoftware.smack.XMPPException;
  24. import org.jivesoftware.smack.packet.XMPPError;
  25.  
  26. import android.util.Log;
  27.  
  28. import java.io.*;
  29.  
  30. /**
  31.  * Handles the sending of a file to another user. File transfer's in jabber have
  32.  * several steps and there are several methods in this class that handle these
  33.  * steps differently.
  34.  *
  35.  * @author Alexander Wenckus
  36.  *
  37.  */
  38. public class myOutgoingFileTransfer extends OutgoingFileTransfer {
  39.  
  40.     private static int RESPONSE_TIMEOUT = 60 * 1000;
  41.     private NegotiationProgress callback;
  42.  
  43.     /**
  44.      * Returns the time in milliseconds after which the file transfer
  45.      * negotiation process will timeout if the other user has not responded.
  46.      *
  47.      * @return Returns the time in milliseconds after which the file transfer
  48.      *         negotiation process will timeout if the remote user has not
  49.      *         responded.
  50.      */
  51.     public static int getResponseTimeout() {
  52.         return RESPONSE_TIMEOUT;
  53.     }
  54.  
  55.     /**
  56.      * Sets the time in milliseconds after which the file transfer negotiation
  57.      * process will timeout if the other user has not responded.
  58.      *
  59.      * @param responseTimeout
  60.      *            The timeout time in milliseconds.
  61.      */
  62.     public static void setResponseTimeout(int responseTimeout) {
  63.         RESPONSE_TIMEOUT = responseTimeout;
  64.     }
  65.  
  66.     private OutputStream outputStream;
  67.  
  68.     private String initiator;
  69.  
  70.     private Thread transferThread;
  71.  
  72.     public myOutgoingFileTransfer(String initiator, String target,
  73.             String streamID, FileTransferNegotiator transferNegotiator) {
  74.         super(initiator, target,
  75.                 streamID, transferNegotiator);
  76.         this.initiator = initiator;
  77.     }
  78.    
  79.     public static myOutgoingFileTransfer createOutgoingFileTransfer(Connection connection, String userID) {
  80.  
  81.         FileTransferNegotiator fileTransferNegotiator = FileTransferNegotiator.getInstanceFor(connection);
  82.         return new myOutgoingFileTransfer(connection.getUser(), userID,
  83.                 fileTransferNegotiator.getNextStreamID(),
  84.                 fileTransferNegotiator);
  85.     }
  86.  
  87.     protected void setOutputStream(OutputStream stream) {
  88.         if (outputStream == null) {
  89.             this.outputStream = stream;
  90.         }
  91.     }
  92.  
  93.     /**
  94.      * Returns the output stream connected to the peer to transfer the file. It
  95.      * is only available after it has been succesfully negotiated by the
  96.      * {@link StreamNegotiator}.
  97.      *
  98.      * @return Returns the output stream connected to the peer to transfer the
  99.      *         file.
  100.      */
  101.     protected OutputStream getOutputStream() {
  102.         if (getStatus().equals(FileTransfer.Status.negotiated)) {
  103.             return outputStream;
  104.         } else {
  105.             return null;
  106.         }
  107.     }
  108.  
  109.     /**
  110.      * This method handles the negotiation of the file transfer and the stream,
  111.      * it only returns the created stream after the negotiation has been completed.
  112.      *
  113.      * @param fileName
  114.      *            The name of the file that will be transmitted. It is
  115.      *            preferable for this name to have an extension as it will be
  116.      *            used to determine the type of file it is.
  117.      * @param fileSize
  118.      *            The size in bytes of the file that will be transmitted.
  119.      * @param description
  120.      *            A description of the file that will be transmitted.
  121.      * @return The OutputStream that is connected to the peer to transmit the
  122.      *         file.
  123.      * @throws XMPPException
  124.      *             Thrown if an error occurs during the file transfer
  125.      *             negotiation process.
  126.      */
  127.     public synchronized OutputStream sendFile(String fileName, long fileSize,
  128.             String description) throws XMPPException {
  129.         if (isDone() || outputStream != null) {
  130.             throw new IllegalStateException(
  131.                     "The negotation process has already"
  132.                             + " been attempted on this file transfer");
  133.         }
  134.         try {
  135.             this.outputStream = negotiateStream(fileName, fileSize, description);
  136.         } catch (XMPPException e) {
  137.             handleXMPPException(e);
  138.             throw e;
  139.         }
  140.         return outputStream;
  141.     }
  142.  
  143.     /**
  144.      * This methods handles the transfer and stream negotiation process. It
  145.      * returns immediately and its progress will be updated through the
  146.      * {@link NegotiationProgress} callback.
  147.      *
  148.      * @param fileName
  149.      *            The name of the file that will be transmitted. It is
  150.      *            preferable for this name to have an extension as it will be
  151.      *            used to determine the type of file it is.
  152.      * @param fileSize
  153.      *            The size in bytes of the file that will be transmitted.
  154.      * @param description
  155.      *            A description of the file that will be transmitted.
  156.      * @param progress
  157.      *            A callback to monitor the progress of the file transfer
  158.      *            negotiation process and to retrieve the OutputStream when it
  159.      *            is complete.
  160.      */
  161.     public synchronized void sendFile(final String fileName,
  162.             final long fileSize, final String description,
  163.             final NegotiationProgress progress)
  164.     {
  165.         if(progress == null) {
  166.             throw new IllegalArgumentException("Callback progress cannot be null.");
  167.         }
  168.         checkTransferThread();
  169.         if (isDone() || outputStream != null) {
  170.             throw new IllegalStateException(
  171.                     "The negotation process has already"
  172.                             + " been attempted for this file transfer");
  173.         }
  174.         this.callback = progress;
  175.         transferThread = new Thread(new Runnable() {
  176.             public void run() {
  177.                 try {
  178.                     outputStream = negotiateStream(
  179.                             fileName, fileSize, description);
  180.                     progress.outputStreamEstablished(outputStream);
  181.                 }
  182.                 catch (XMPPException e) {
  183.                     handleXMPPException(e);
  184.                 }
  185.             }
  186.         }, "File Transfer Negotiation " + streamID);
  187.         transferThread.start();
  188.     }
  189.  
  190.     private void checkTransferThread() {
  191.         if (transferThread != null && transferThread.isAlive() || isDone()) {
  192.             throw new IllegalStateException(
  193.                     "File transfer in progress or has already completed.");
  194.         }
  195.     }
  196.  
  197.     /**
  198.      * This method handles the stream negotiation process and transmits the file
  199.      * to the remote user. It returns immediatly and the progress of the file
  200.      * transfer can be monitored through several methods:
  201.      *
  202.      * <UL>
  203.      * <LI>{@link FileTransfer#getStatus()}
  204.      * <LI>{@link FileTransfer#getProgress()}
  205.      * <LI>{@link FileTransfer#isDone()}
  206.      * </UL>
  207.      *
  208.      * @param file the file to transfer to the remote entity.
  209.      * @param description a description for the file to transfer.
  210.      * @throws XMPPException
  211.      *             If there is an error during the negotiation process or the
  212.      *             sending of the file.
  213.      */
  214.     public synchronized void sendFile2(final File file, final String description)
  215.             throws XMPPException {
  216.         checkTransferThread();
  217.         if (file == null || !file.exists() || !file.canRead()) {
  218.             throw new IllegalArgumentException("Could not read file");
  219.         } else {
  220.             setFileInfo(file.getAbsolutePath(), file.getName(), file.length());
  221.         }
  222.        
  223.         Log.d("myOoutgoingFileTransfer","setted File Info");
  224.         try {
  225.            
  226.             outputStream = negotiateStream(file.getName(), file
  227.                     .length(), "DESCRIPTION");
  228.             Log.d("myOoutgoingFileTransfer","negotiated");
  229.         } catch (XMPPException e) {
  230.             e.printStackTrace();
  231.             Log.e("myOoutgoingFileTransfer","Error");
  232.            
  233.             handleXMPPException(e);
  234.             return;
  235.         }
  236.         if (outputStream == null) {
  237.             return;
  238.         }
  239.         if (!updateStatus(Status.negotiated, Status.in_progress)) {
  240.             return;
  241.         }
  242.         InputStream inputStream = null;
  243.         try {
  244.             Log.d("myOoutgoingFileTransfer","Opening stream...");
  245.             inputStream = new FileInputStream(file);
  246.             Log.d("myOoutgoingFileTransfer","Writing to stream...");
  247.             int val;  
  248.               while ((val = inputStream.read()) != -1)  
  249.                 outputStream.write(val);
  250.         } catch (FileNotFoundException e) {
  251.             Log.e("myOoutgoingFileTransfer","File Not Founs");
  252.             e.printStackTrace();
  253.             setStatus(FileTransfer.Status.error);
  254.             setError(Error.bad_file);
  255.             setException(e);
  256.         } catch (Throwable e) {
  257.             e.printStackTrace();
  258.         } finally {
  259.             try {
  260.                 if (inputStream != null) {
  261.                     inputStream.close();
  262.                 }
  263.                 outputStream.flush();
  264.                 outputStream.close();
  265.             } catch (IOException e) {
  266.                        /* Do Nothing */
  267.             }
  268.         }
  269.         updateStatus(Status.in_progress, FileTransfer.Status.complete);
  270.                
  271.  
  272.     }
  273.  
  274.     /**
  275.      * This method handles the stream negotiation process and transmits the file
  276.      * to the remote user. It returns immediatly and the progress of the file
  277.      * transfer can be monitored through several methods:
  278.      *
  279.      * <UL>
  280.      * <LI>{@link FileTransfer#getStatus()}
  281.      * <LI>{@link FileTransfer#getProgress()}
  282.      * <LI>{@link FileTransfer#isDone()}
  283.      * </UL>
  284.      *
  285.      * @param in the stream to transfer to the remote entity.
  286.      * @param fileName the name of the file that is transferred
  287.      * @param fileSize the size of the file that is transferred
  288.      * @param description a description for the file to transfer.
  289.      */
  290.     public synchronized void sendStream(final InputStream in, final String fileName, final long fileSize, final String description){
  291.         checkTransferThread();
  292.  
  293.         transferThread = new Thread(new Runnable() {
  294.             public void run() {
  295.                 //Create packet filter
  296.                 try {
  297.                     outputStream = negotiateStream(fileName, fileSize, description);
  298.                 } catch (XMPPException e) {
  299.                     handleXMPPException(e);
  300.                     return;
  301.                 }
  302.                 if (outputStream == null) {
  303.                     return;
  304.                 }
  305.  
  306.                 if (!updateStatus(Status.negotiated, Status.in_progress)) {
  307.                     return;
  308.                 }
  309.                 try {
  310.                     writeToStream(in, outputStream);
  311.                 } catch (XMPPException e) {
  312.                     setStatus(FileTransfer.Status.error);
  313.                     setException(e);
  314.                 } finally {
  315.                     try {
  316.                         if (in != null) {
  317.                             in.close();
  318.                         }
  319.  
  320.                         outputStream.flush();
  321.                         outputStream.close();
  322.                     } catch (IOException e) {
  323.                         /* Do Nothing */
  324.                     }
  325.                 }
  326.                 updateStatus(Status.in_progress, FileTransfer.Status.complete);
  327.                 }
  328.  
  329.         }, "File Transfer " + streamID);
  330.         transferThread.start();
  331.     }
  332.  
  333.     private void handleXMPPException(XMPPException e) {
  334.         XMPPError error = e.getXMPPError();
  335.         if (error != null) {
  336.             int code = error.getCode();
  337.             if (code == 403) {
  338.                 setStatus(Status.refused);
  339.                 return;
  340.             }
  341.             else if (code == 400) {
  342.                 setStatus(Status.error);
  343.                 setError(Error.not_acceptable);
  344.             }
  345.             else {
  346.                 setStatus(FileTransfer.Status.error);
  347.             }
  348.         }
  349.  
  350.         setException(e);
  351.     }
  352.  
  353.     /**
  354.      * Returns the amount of bytes that have been sent for the file transfer. Or
  355.      * -1 if the file transfer has not started.
  356.      * <p>
  357.      * Note: This method is only useful when the {@link #sendFile(File, String)}
  358.      * method is called, as it is the only method that actualy transmits the
  359.      * file.
  360.      *
  361.      * @return Returns the amount of bytes that have been sent for the file
  362.      *         transfer. Or -1 if the file transfer has not started.
  363.      */
  364.     public long getBytesSent() {
  365.         return amountWritten;
  366.     }
  367.  
  368.     private OutputStream negotiateStream(String fileName, long fileSize,
  369.             String description) throws XMPPException {
  370.         // Negotiate the file transfer profile
  371.  
  372.         if (!updateStatus(Status.initial, Status.negotiating_transfer)) {
  373.             throw new XMPPException("Illegal state change");
  374.         }
  375.         StreamNegotiator streamNegotiator = negotiator.negotiateOutgoingTransfer(
  376.                 getPeer(), streamID, fileName, fileSize, description,
  377.                 RESPONSE_TIMEOUT);
  378.  
  379.         if (streamNegotiator == null) {
  380.             setStatus(Status.error);
  381.             setError(Error.no_response);
  382.             return null;
  383.         }
  384.  
  385.         // Negotiate the stream
  386.         if (!updateStatus(Status.negotiating_transfer, Status.negotiating_stream)) {
  387.             throw new XMPPException("Illegal state change");
  388.         }
  389.         if (streamID==null)
  390.             Log.e("myOutgoingFileTransfer", "null STREAMID");
  391.        if(initiator == null)
  392.            Log.e("myOutgoingFileTransfer", "null INITIATOR");
  393.        if(getPeer() == null)
  394.            Log.e("myOutgoingFileTransfer", "null GETPEER");
  395.         outputStream = streamNegotiator.createOutgoingStream(streamID,
  396.                 initiator, getPeer());
  397.  
  398.         if (!updateStatus(Status.negotiating_stream, Status.negotiated)) {
  399.             throw new XMPPException("Illegal state change");
  400.         }
  401.         return outputStream;
  402.     }
  403.  
  404.     public void cancel() {
  405.         setStatus(Status.cancelled);
  406.     }
  407.  
  408.     @Override
  409.     protected boolean updateStatus(Status oldStatus, Status newStatus) {
  410.         boolean isUpdated = super.updateStatus(oldStatus, newStatus);
  411.         if(callback != null && isUpdated) {
  412.             callback.statusUpdated(oldStatus, newStatus);
  413.         }
  414.         return isUpdated;
  415.     }
  416.  
  417.     @Override
  418.     protected void setStatus(Status status) {
  419.         Status oldStatus = getStatus();
  420.         super.setStatus(status);
  421.         if(callback != null) {
  422.             callback.statusUpdated(oldStatus, status);
  423.         }
  424.     }
  425.  
  426.     @Override
  427.     protected void setException(Exception exception) {
  428.         super.setException(exception);
  429.         if(callback != null) {
  430.             callback.errorEstablishingStream(exception);
  431.         }
  432.     }
  433.  
  434.     /**
  435.      * A callback class to retrive the status of an outgoing transfer
  436.      * negotiation process.
  437.      *
  438.      * @author Alexander Wenckus
  439.      *
  440.      */
  441.     public interface NegotiationProgress {
  442.  
  443.         /**
  444.          * Called when the status changes
  445.          *
  446.          * @param oldStatus the previous status of the file transfer.
  447.          * @param newStatus the new status of the file transfer.
  448.          */
  449.         void statusUpdated(Status oldStatus, Status newStatus);
  450.  
  451.         /**
  452.          * Once the negotiation process is completed the output stream can be
  453.          * retrieved.
  454.          *
  455.          * @param stream the established stream which can be used to transfer the file to the remote
  456.          * entity
  457.          */
  458.         void outputStreamEstablished(OutputStream stream);
  459.  
  460.         /**
  461.          * Called when an exception occurs during the negotiation progress.
  462.          *
  463.          * @param e the exception that occured.
  464.          */
  465.         void errorEstablishingStream(Exception e);
  466.     }
  467.  
  468. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement