2006-02-03 19:44:22 +01:00
|
|
|
/**
|
2006-02-03 20:13:23 +01:00
|
|
|
* $RCSfile$
|
|
|
|
* $Revision: $
|
|
|
|
* $Date: $
|
|
|
|
*
|
|
|
|
* Copyright 2003-2006 Jive Software.
|
|
|
|
*
|
|
|
|
* All rights reserved. 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.
|
2006-02-03 19:44:22 +01:00
|
|
|
*/
|
|
|
|
package org.jivesoftware.smackx.filetransfer;
|
|
|
|
|
2006-02-08 01:31:17 +01:00
|
|
|
import org.jivesoftware.smack.PacketCollector;
|
|
|
|
import org.jivesoftware.smack.SmackConfiguration;
|
2010-02-09 12:55:56 +01:00
|
|
|
import org.jivesoftware.smack.Connection;
|
2006-02-03 19:44:22 +01:00
|
|
|
import org.jivesoftware.smack.XMPPException;
|
2006-02-08 01:31:17 +01:00
|
|
|
import org.jivesoftware.smack.filter.PacketFilter;
|
2006-02-03 19:44:22 +01:00
|
|
|
import org.jivesoftware.smack.packet.IQ;
|
2006-02-08 01:31:17 +01:00
|
|
|
import org.jivesoftware.smack.packet.Packet;
|
|
|
|
import org.jivesoftware.smack.packet.XMPPError;
|
2006-02-03 19:44:22 +01:00
|
|
|
import org.jivesoftware.smackx.Form;
|
|
|
|
import org.jivesoftware.smackx.FormField;
|
|
|
|
import org.jivesoftware.smackx.packet.DataForm;
|
|
|
|
import org.jivesoftware.smackx.packet.StreamInitiation;
|
|
|
|
|
2006-02-08 01:31:17 +01:00
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
2006-02-03 19:44:22 +01:00
|
|
|
/**
|
|
|
|
* After the file transfer negotiation process is completed according to
|
2010-08-15 12:49:11 +02:00
|
|
|
* JEP-0096, the negotiation process is passed off to a particular stream
|
2006-02-03 19:44:22 +01:00
|
|
|
* negotiator. The stream negotiator will then negotiate the chosen stream and
|
|
|
|
* return the stream to transfer the file.
|
2006-02-08 01:31:17 +01:00
|
|
|
*
|
2006-02-03 19:44:22 +01:00
|
|
|
* @author Alexander Wenckus
|
|
|
|
*/
|
|
|
|
public abstract class StreamNegotiator {
|
|
|
|
|
2006-02-08 01:31:17 +01:00
|
|
|
/**
|
|
|
|
* Creates the initiation acceptance packet to forward to the stream
|
|
|
|
* initiator.
|
|
|
|
*
|
2010-08-15 12:49:11 +02:00
|
|
|
* @param streamInitiationOffer The offer from the stream initiator to connect for a stream.
|
2006-02-08 01:31:17 +01:00
|
|
|
* @param namespaces The namespace that relates to the accepted means of transfer.
|
2010-08-15 12:49:11 +02:00
|
|
|
* @return The response to be forwarded to the initiator.
|
2006-02-08 01:31:17 +01:00
|
|
|
*/
|
|
|
|
public StreamInitiation createInitiationAccept(
|
2007-03-21 05:09:52 +01:00
|
|
|
StreamInitiation streamInitiationOffer, String[] namespaces)
|
|
|
|
{
|
2006-02-08 01:31:17 +01:00
|
|
|
StreamInitiation response = new StreamInitiation();
|
|
|
|
response.setTo(streamInitiationOffer.getFrom());
|
|
|
|
response.setFrom(streamInitiationOffer.getTo());
|
|
|
|
response.setType(IQ.Type.RESULT);
|
|
|
|
response.setPacketID(streamInitiationOffer.getPacketID());
|
|
|
|
|
|
|
|
DataForm form = new DataForm(Form.TYPE_SUBMIT);
|
|
|
|
FormField field = new FormField(
|
|
|
|
FileTransferNegotiator.STREAM_DATA_FIELD_NAME);
|
2007-03-21 05:09:52 +01:00
|
|
|
for (String namespace : namespaces) {
|
|
|
|
field.addValue(namespace);
|
2006-02-08 01:31:17 +01:00
|
|
|
}
|
|
|
|
form.addField(field);
|
|
|
|
|
|
|
|
response.setFeatureNegotiationForm(form);
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public IQ createError(String from, String to, String packetID, XMPPError xmppError) {
|
|
|
|
IQ iq = FileTransferNegotiator.createIQ(packetID, to, from, IQ.Type.ERROR);
|
|
|
|
iq.setError(xmppError);
|
|
|
|
return iq;
|
|
|
|
}
|
|
|
|
|
2010-02-09 12:55:56 +01:00
|
|
|
Packet initiateIncomingStream(Connection connection, StreamInitiation initiation) throws XMPPException {
|
2006-02-08 01:31:17 +01:00
|
|
|
StreamInitiation response = createInitiationAccept(initiation,
|
|
|
|
getNamespaces());
|
|
|
|
|
|
|
|
// establish collector to await response
|
|
|
|
PacketCollector collector = connection
|
|
|
|
.createPacketCollector(getInitiationPacketFilter(initiation.getFrom(), initiation.getSessionID()));
|
|
|
|
connection.sendPacket(response);
|
|
|
|
|
|
|
|
Packet streamMethodInitiation = collector
|
|
|
|
.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
|
|
|
collector.cancel();
|
|
|
|
if (streamMethodInitiation == null) {
|
|
|
|
throw new XMPPException("No response from file transfer initiator");
|
|
|
|
}
|
|
|
|
|
|
|
|
return streamMethodInitiation;
|
|
|
|
}
|
2006-02-03 19:44:22 +01:00
|
|
|
|
|
|
|
/**
|
2006-02-08 01:31:17 +01:00
|
|
|
* Returns the packet filter that will return the initiation packet for the appropriate stream
|
|
|
|
* initiation.
|
|
|
|
*
|
2010-08-15 12:49:11 +02:00
|
|
|
* @param from The initiator of the file transfer.
|
2006-02-08 01:31:17 +01:00
|
|
|
* @param streamID The stream ID related to the transfer.
|
|
|
|
* @return The <b><i>PacketFilter</b></i> that will return the packet relatable to the stream
|
|
|
|
* initiation.
|
|
|
|
*/
|
|
|
|
public abstract PacketFilter getInitiationPacketFilter(String from, String streamID);
|
|
|
|
|
|
|
|
|
2010-08-15 12:49:11 +02:00
|
|
|
abstract InputStream negotiateIncomingStream(Packet streamInitiation) throws XMPPException,
|
|
|
|
InterruptedException;
|
2006-02-08 01:31:17 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This method handles the file stream download negotiation process. The
|
|
|
|
* appropriate stream negotiator's initiate incoming stream is called after
|
|
|
|
* an appropriate file transfer method is selected. The manager will respond
|
2010-08-15 12:49:11 +02:00
|
|
|
* to the initiator with the selected means of transfer, then it will handle
|
|
|
|
* any negotiation specific to the particular transfer method. This method
|
2006-02-08 01:31:17 +01:00
|
|
|
* returns the InputStream, ready to transfer the file.
|
|
|
|
*
|
2010-08-15 12:49:11 +02:00
|
|
|
* @param initiation The initiation that triggered this download.
|
|
|
|
* @return After the negotiation process is complete, the InputStream to
|
2006-02-08 01:31:17 +01:00
|
|
|
* write a file to is returned.
|
|
|
|
* @throws XMPPException If an error occurs during this process an XMPPException is
|
|
|
|
* thrown.
|
2010-08-15 12:49:11 +02:00
|
|
|
* @throws InterruptedException If thread is interrupted.
|
2006-02-08 01:31:17 +01:00
|
|
|
*/
|
2010-08-15 12:49:11 +02:00
|
|
|
public abstract InputStream createIncomingStream(StreamInitiation initiation)
|
|
|
|
throws XMPPException, InterruptedException;
|
2006-02-08 01:31:17 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This method handles the file upload stream negotiation process. The
|
|
|
|
* particular stream negotiator is determined during the file transfer
|
|
|
|
* negotiation process. This method returns the OutputStream to transmit the
|
|
|
|
* file to the remote user.
|
|
|
|
*
|
|
|
|
* @param streamID The streamID that uniquely identifies the file transfer.
|
|
|
|
* @param initiator The fully-qualified JID of the initiator of the file transfer.
|
2010-08-15 12:49:11 +02:00
|
|
|
* @param target The fully-qualified JID of the target or receiver of the file
|
2006-02-08 01:31:17 +01:00
|
|
|
* transfer.
|
|
|
|
* @return The negotiated stream ready for data.
|
|
|
|
* @throws XMPPException If an error occurs during the negotiation process an
|
|
|
|
* exception will be thrown.
|
|
|
|
*/
|
|
|
|
public abstract OutputStream createOutgoingStream(String streamID,
|
|
|
|
String initiator, String target) throws XMPPException;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the XMPP namespace reserved for this particular type of file
|
|
|
|
* transfer.
|
|
|
|
*
|
|
|
|
* @return Returns the XMPP namespace reserved for this particular type of
|
|
|
|
* file transfer.
|
|
|
|
*/
|
|
|
|
public abstract String[] getNamespaces();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cleanup any and all resources associated with this negotiator.
|
|
|
|
*/
|
|
|
|
public abstract void cleanup();
|
|
|
|
|
2006-02-03 19:44:22 +01:00
|
|
|
}
|