aboutsummaryrefslogtreecommitdiff
path: root/src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java')
-rw-r--r--src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java b/src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java
new file mode 100644
index 0000000..5eefe43
--- /dev/null
+++ b/src/org/jivesoftware/smackx/filetransfer/StreamNegotiator.java
@@ -0,0 +1,167 @@
+/**
+ * $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.
+ */
+package org.jivesoftware.smackx.filetransfer;
+
+import org.jivesoftware.smack.PacketCollector;
+import org.jivesoftware.smack.SmackConfiguration;
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.filter.PacketFilter;
+import org.jivesoftware.smack.packet.IQ;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.packet.XMPPError;
+import org.jivesoftware.smackx.Form;
+import org.jivesoftware.smackx.FormField;
+import org.jivesoftware.smackx.packet.DataForm;
+import org.jivesoftware.smackx.packet.StreamInitiation;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * After the file transfer negotiation process is completed according to
+ * JEP-0096, the negotiation process is passed off to a particular stream
+ * negotiator. The stream negotiator will then negotiate the chosen stream and
+ * return the stream to transfer the file.
+ *
+ * @author Alexander Wenckus
+ */
+public abstract class StreamNegotiator {
+
+ /**
+ * Creates the initiation acceptance packet to forward to the stream
+ * initiator.
+ *
+ * @param streamInitiationOffer The offer from the stream initiator to connect for a stream.
+ * @param namespaces The namespace that relates to the accepted means of transfer.
+ * @return The response to be forwarded to the initiator.
+ */
+ public StreamInitiation createInitiationAccept(
+ StreamInitiation streamInitiationOffer, String[] namespaces)
+ {
+ 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);
+ for (String namespace : namespaces) {
+ field.addValue(namespace);
+ }
+ 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;
+ }
+
+ Packet initiateIncomingStream(Connection connection, StreamInitiation initiation) throws XMPPException {
+ 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;
+ }
+
+ /**
+ * Returns the packet filter that will return the initiation packet for the appropriate stream
+ * initiation.
+ *
+ * @param from The initiator of the file transfer.
+ * @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);
+
+
+ abstract InputStream negotiateIncomingStream(Packet streamInitiation) throws XMPPException,
+ InterruptedException;
+
+ /**
+ * 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
+ * to the initiator with the selected means of transfer, then it will handle
+ * any negotiation specific to the particular transfer method. This method
+ * returns the InputStream, ready to transfer the file.
+ *
+ * @param initiation The initiation that triggered this download.
+ * @return After the negotiation process is complete, the InputStream to
+ * write a file to is returned.
+ * @throws XMPPException If an error occurs during this process an XMPPException is
+ * thrown.
+ * @throws InterruptedException If thread is interrupted.
+ */
+ public abstract InputStream createIncomingStream(StreamInitiation initiation)
+ throws XMPPException, InterruptedException;
+
+ /**
+ * 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.
+ * @param target The fully-qualified JID of the target or receiver of the file
+ * 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();
+
+}