• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.PacketListener;
23 import org.jivesoftware.smack.Connection;
24 import org.jivesoftware.smack.filter.AndFilter;
25 import org.jivesoftware.smack.filter.IQTypeFilter;
26 import org.jivesoftware.smack.filter.PacketTypeFilter;
27 import org.jivesoftware.smack.packet.IQ;
28 import org.jivesoftware.smack.packet.Packet;
29 import org.jivesoftware.smack.packet.XMPPError;
30 import org.jivesoftware.smack.util.StringUtils;
31 import org.jivesoftware.smackx.packet.StreamInitiation;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 /**
37  * The file transfer manager class handles the sending and recieving of files.
38  * To send a file invoke the {@link #createOutgoingFileTransfer(String)} method.
39  * <p>
40  * And to recieve a file add a file transfer listener to the manager. The
41  * listener will notify you when there is a new file transfer request. To create
42  * the {@link IncomingFileTransfer} object accept the transfer, or, if the
43  * transfer is not desirable reject it.
44  *
45  * @author Alexander Wenckus
46  *
47  */
48 public class FileTransferManager {
49 
50 	private final FileTransferNegotiator fileTransferNegotiator;
51 
52 	private List<FileTransferListener> listeners;
53 
54 	private Connection connection;
55 
56 	/**
57 	 * Creates a file transfer manager to initiate and receive file transfers.
58 	 *
59 	 * @param connection
60 	 *            The Connection that the file transfers will use.
61 	 */
FileTransferManager(Connection connection)62 	public FileTransferManager(Connection connection) {
63 		this.connection = connection;
64 		this.fileTransferNegotiator = FileTransferNegotiator
65 				.getInstanceFor(connection);
66 	}
67 
68 	/**
69 	 * Add a file transfer listener to listen to incoming file transfer
70 	 * requests.
71 	 *
72 	 * @param li
73 	 *            The listener
74 	 * @see #removeFileTransferListener(FileTransferListener)
75 	 * @see FileTransferListener
76 	 */
addFileTransferListener(final FileTransferListener li)77 	public void addFileTransferListener(final FileTransferListener li) {
78 		if (listeners == null) {
79 			initListeners();
80 		}
81 		synchronized (this.listeners) {
82 			listeners.add(li);
83 		}
84 	}
85 
initListeners()86 	private void initListeners() {
87 		listeners = new ArrayList<FileTransferListener>();
88 
89 		connection.addPacketListener(new PacketListener() {
90 			public void processPacket(Packet packet) {
91 				fireNewRequest((StreamInitiation) packet);
92 			}
93 		}, new AndFilter(new PacketTypeFilter(StreamInitiation.class),
94 				new IQTypeFilter(IQ.Type.SET)));
95 	}
96 
fireNewRequest(StreamInitiation initiation)97 	protected void fireNewRequest(StreamInitiation initiation) {
98 		FileTransferListener[] listeners = null;
99 		synchronized (this.listeners) {
100 			listeners = new FileTransferListener[this.listeners.size()];
101 			this.listeners.toArray(listeners);
102 		}
103 		FileTransferRequest request = new FileTransferRequest(this, initiation);
104 		for (int i = 0; i < listeners.length; i++) {
105 			listeners[i].fileTransferRequest(request);
106 		}
107 	}
108 
109 	/**
110 	 * Removes a file transfer listener.
111 	 *
112 	 * @param li
113 	 *            The file transfer listener to be removed
114 	 * @see FileTransferListener
115 	 */
removeFileTransferListener(final FileTransferListener li)116 	public void removeFileTransferListener(final FileTransferListener li) {
117 		if (listeners == null) {
118 			return;
119 		}
120 		synchronized (this.listeners) {
121 			listeners.remove(li);
122 		}
123 	}
124 
125 	/**
126 	 * Creates an OutgoingFileTransfer to send a file to another user.
127 	 *
128 	 * @param userID
129 	 *            The fully qualified jabber ID (i.e. full JID) with resource of the user to
130 	 *            send the file to.
131 	 * @return The send file object on which the negotiated transfer can be run.
132 	 * @exception IllegalArgumentException if userID is null or not a full JID
133 	 */
createOutgoingFileTransfer(String userID)134 	public OutgoingFileTransfer createOutgoingFileTransfer(String userID) {
135         if (userID == null) {
136             throw new IllegalArgumentException("userID was null");
137         }
138         // We need to create outgoing file transfers with a full JID since this method will later
139         // use XEP-0095 to negotiate the stream. This is done with IQ stanzas that need to be addressed to a full JID
140         // in order to reach an client entity.
141         else if (!StringUtils.isFullJID(userID)) {
142             throw new IllegalArgumentException("The provided user id was not a full JID (i.e. with resource part)");
143         }
144 
145 		return new OutgoingFileTransfer(connection.getUser(), userID,
146 				fileTransferNegotiator.getNextStreamID(),
147 				fileTransferNegotiator);
148 	}
149 
150 	/**
151 	 * When the file transfer request is acceptable, this method should be
152 	 * invoked. It will create an IncomingFileTransfer which allows the
153 	 * transmission of the file to procede.
154 	 *
155 	 * @param request
156 	 *            The remote request that is being accepted.
157 	 * @return The IncomingFileTransfer which manages the download of the file
158 	 *         from the transfer initiator.
159 	 */
createIncomingFileTransfer( FileTransferRequest request)160 	protected IncomingFileTransfer createIncomingFileTransfer(
161 			FileTransferRequest request) {
162 		if (request == null) {
163 			throw new NullPointerException("RecieveRequest cannot be null");
164 		}
165 
166 		IncomingFileTransfer transfer = new IncomingFileTransfer(request,
167                 fileTransferNegotiator);
168 		transfer.setFileInfo(request.getFileName(), request.getFileSize());
169 
170 		return transfer;
171 	}
172 
rejectIncomingFileTransfer(FileTransferRequest request)173 	protected void rejectIncomingFileTransfer(FileTransferRequest request) {
174 		StreamInitiation initiation = request.getStreamInitiation();
175 
176 		IQ rejection = FileTransferNegotiator.createIQ(
177 				initiation.getPacketID(), initiation.getFrom(), initiation
178 						.getTo(), IQ.Type.ERROR);
179 		rejection.setError(new XMPPError(XMPPError.Condition.no_acceptable));
180 		connection.sendPacket(rejection);
181 	}
182 }
183