1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2006 Jive Software. 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smackx.filetransfer; 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketCollector; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.SmackConfiguration; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Connection; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.XMPPException; 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketFilter; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.IQ; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.XMPPError; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.Form; 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.FormField; 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.DataForm; 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smackx.packet.StreamInitiation; 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.InputStream; 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.OutputStream; 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * After the file transfer negotiation process is completed according to 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * JEP-0096, the negotiation process is passed off to a particular stream 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * negotiator. The stream negotiator will then negotiate the chosen stream and 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * return the stream to transfer the file. 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Alexander Wenckus 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class StreamNegotiator { 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates the initiation acceptance packet to forward to the stream 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initiator. 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param streamInitiationOffer The offer from the stream initiator to connect for a stream. 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param namespaces The namespace that relates to the accepted means of transfer. 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The response to be forwarded to the initiator. 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public StreamInitiation createInitiationAccept( 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StreamInitiation streamInitiationOffer, String[] namespaces) 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen { 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StreamInitiation response = new StreamInitiation(); 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.setTo(streamInitiationOffer.getFrom()); 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.setFrom(streamInitiationOffer.getTo()); 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.setType(IQ.Type.RESULT); 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.setPacketID(streamInitiationOffer.getPacketID()); 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen DataForm form = new DataForm(Form.TYPE_SUBMIT); 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen FormField field = new FormField( 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen FileTransferNegotiator.STREAM_DATA_FIELD_NAME); 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen for (String namespace : namespaces) { 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen field.addValue(namespace); 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen form.addField(field); 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen response.setFeatureNegotiationForm(form); 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return response; 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public IQ createError(String from, String to, String packetID, XMPPError xmppError) { 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen IQ iq = FileTransferNegotiator.createIQ(packetID, to, from, IQ.Type.ERROR); 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen iq.setError(xmppError); 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return iq; 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Packet initiateIncomingStream(Connection connection, StreamInitiation initiation) throws XMPPException { 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen StreamInitiation response = createInitiationAccept(initiation, 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen getNamespaces()); 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // establish collector to await response 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen PacketCollector collector = connection 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .createPacketCollector(getInitiationPacketFilter(initiation.getFrom(), initiation.getSessionID())); 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.sendPacket(response); 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen Packet streamMethodInitiation = collector 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen .nextResult(SmackConfiguration.getPacketReplyTimeout()); 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen collector.cancel(); 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (streamMethodInitiation == null) { 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throw new XMPPException("No response from file transfer initiator"); 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return streamMethodInitiation; 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the packet filter that will return the initiation packet for the appropriate stream 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initiation. 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param from The initiator of the file transfer. 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param streamID The stream ID related to the transfer. 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The <b><i>PacketFilter</b></i> that will return the packet relatable to the stream 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * initiation. 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public abstract PacketFilter getInitiationPacketFilter(String from, String streamID); 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen abstract InputStream negotiateIncomingStream(Packet streamInitiation) throws XMPPException, 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen InterruptedException; 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This method handles the file stream download negotiation process. The 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * appropriate stream negotiator's initiate incoming stream is called after 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * an appropriate file transfer method is selected. The manager will respond 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * to the initiator with the selected means of transfer, then it will handle 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * any negotiation specific to the particular transfer method. This method 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * returns the InputStream, ready to transfer the file. 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param initiation The initiation that triggered this download. 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return After the negotiation process is complete, the InputStream to 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * write a file to is returned. 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException If an error occurs during this process an XMPPException is 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * thrown. 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws InterruptedException If thread is interrupted. 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public abstract InputStream createIncomingStream(StreamInitiation initiation) 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen throws XMPPException, InterruptedException; 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * This method handles the file upload stream negotiation process. The 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * particular stream negotiator is determined during the file transfer 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * negotiation process. This method returns the OutputStream to transmit the 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * file to the remote user. 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param streamID The streamID that uniquely identifies the file transfer. 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param initiator The fully-qualified JID of the initiator of the file transfer. 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param target The fully-qualified JID of the target or receiver of the file 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * transfer. 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The negotiated stream ready for data. 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @throws XMPPException If an error occurs during the negotiation process an 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * exception will be thrown. 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public abstract OutputStream createOutgoingStream(String streamID, 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String initiator, String target) throws XMPPException; 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the XMPP namespace reserved for this particular type of file 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * transfer. 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return Returns the XMPP namespace reserved for this particular type of 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * file transfer. 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public abstract String[] getNamespaces(); 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Cleanup any and all resources associated with this negotiator. 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public abstract void cleanup(); 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 168