blob: 5eefe4370a281de509abe76ef9a04ad7b8668ecd [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001/**
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 */
20package org.jivesoftware.smackx.filetransfer;
21
22import org.jivesoftware.smack.PacketCollector;
23import org.jivesoftware.smack.SmackConfiguration;
24import org.jivesoftware.smack.Connection;
25import org.jivesoftware.smack.XMPPException;
26import org.jivesoftware.smack.filter.PacketFilter;
27import org.jivesoftware.smack.packet.IQ;
28import org.jivesoftware.smack.packet.Packet;
29import org.jivesoftware.smack.packet.XMPPError;
30import org.jivesoftware.smackx.Form;
31import org.jivesoftware.smackx.FormField;
32import org.jivesoftware.smackx.packet.DataForm;
33import org.jivesoftware.smackx.packet.StreamInitiation;
34
35import java.io.InputStream;
36import java.io.OutputStream;
37
38/**
39 * After the file transfer negotiation process is completed according to
40 * JEP-0096, the negotiation process is passed off to a particular stream
41 * negotiator. The stream negotiator will then negotiate the chosen stream and
42 * return the stream to transfer the file.
43 *
44 * @author Alexander Wenckus
45 */
46public abstract class StreamNegotiator {
47
48 /**
49 * Creates the initiation acceptance packet to forward to the stream
50 * initiator.
51 *
52 * @param streamInitiationOffer The offer from the stream initiator to connect for a stream.
53 * @param namespaces The namespace that relates to the accepted means of transfer.
54 * @return The response to be forwarded to the initiator.
55 */
56 public StreamInitiation createInitiationAccept(
57 StreamInitiation streamInitiationOffer, String[] namespaces)
58 {
59 StreamInitiation response = new StreamInitiation();
60 response.setTo(streamInitiationOffer.getFrom());
61 response.setFrom(streamInitiationOffer.getTo());
62 response.setType(IQ.Type.RESULT);
63 response.setPacketID(streamInitiationOffer.getPacketID());
64
65 DataForm form = new DataForm(Form.TYPE_SUBMIT);
66 FormField field = new FormField(
67 FileTransferNegotiator.STREAM_DATA_FIELD_NAME);
68 for (String namespace : namespaces) {
69 field.addValue(namespace);
70 }
71 form.addField(field);
72
73 response.setFeatureNegotiationForm(form);
74 return response;
75 }
76
77
78 public IQ createError(String from, String to, String packetID, XMPPError xmppError) {
79 IQ iq = FileTransferNegotiator.createIQ(packetID, to, from, IQ.Type.ERROR);
80 iq.setError(xmppError);
81 return iq;
82 }
83
84 Packet initiateIncomingStream(Connection connection, StreamInitiation initiation) throws XMPPException {
85 StreamInitiation response = createInitiationAccept(initiation,
86 getNamespaces());
87
88 // establish collector to await response
89 PacketCollector collector = connection
90 .createPacketCollector(getInitiationPacketFilter(initiation.getFrom(), initiation.getSessionID()));
91 connection.sendPacket(response);
92
93 Packet streamMethodInitiation = collector
94 .nextResult(SmackConfiguration.getPacketReplyTimeout());
95 collector.cancel();
96 if (streamMethodInitiation == null) {
97 throw new XMPPException("No response from file transfer initiator");
98 }
99
100 return streamMethodInitiation;
101 }
102
103 /**
104 * Returns the packet filter that will return the initiation packet for the appropriate stream
105 * initiation.
106 *
107 * @param from The initiator of the file transfer.
108 * @param streamID The stream ID related to the transfer.
109 * @return The <b><i>PacketFilter</b></i> that will return the packet relatable to the stream
110 * initiation.
111 */
112 public abstract PacketFilter getInitiationPacketFilter(String from, String streamID);
113
114
115 abstract InputStream negotiateIncomingStream(Packet streamInitiation) throws XMPPException,
116 InterruptedException;
117
118 /**
119 * This method handles the file stream download negotiation process. The
120 * appropriate stream negotiator's initiate incoming stream is called after
121 * an appropriate file transfer method is selected. The manager will respond
122 * to the initiator with the selected means of transfer, then it will handle
123 * any negotiation specific to the particular transfer method. This method
124 * returns the InputStream, ready to transfer the file.
125 *
126 * @param initiation The initiation that triggered this download.
127 * @return After the negotiation process is complete, the InputStream to
128 * write a file to is returned.
129 * @throws XMPPException If an error occurs during this process an XMPPException is
130 * thrown.
131 * @throws InterruptedException If thread is interrupted.
132 */
133 public abstract InputStream createIncomingStream(StreamInitiation initiation)
134 throws XMPPException, InterruptedException;
135
136 /**
137 * This method handles the file upload stream negotiation process. The
138 * particular stream negotiator is determined during the file transfer
139 * negotiation process. This method returns the OutputStream to transmit the
140 * file to the remote user.
141 *
142 * @param streamID The streamID that uniquely identifies the file transfer.
143 * @param initiator The fully-qualified JID of the initiator of the file transfer.
144 * @param target The fully-qualified JID of the target or receiver of the file
145 * transfer.
146 * @return The negotiated stream ready for data.
147 * @throws XMPPException If an error occurs during the negotiation process an
148 * exception will be thrown.
149 */
150 public abstract OutputStream createOutgoingStream(String streamID,
151 String initiator, String target) throws XMPPException;
152
153 /**
154 * Returns the XMPP namespace reserved for this particular type of file
155 * transfer.
156 *
157 * @return Returns the XMPP namespace reserved for this particular type of
158 * file transfer.
159 */
160 public abstract String[] getNamespaces();
161
162 /**
163 * Cleanup any and all resources associated with this negotiator.
164 */
165 public abstract void cleanup();
166
167}