mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-27 14:32:06 +01:00
Improve JFT API
This commit is contained in:
parent
d7df408661
commit
e53165a96c
8 changed files with 112 additions and 40 deletions
|
@ -78,7 +78,11 @@ public final class JetManager extends Manager implements JingleDescriptionManage
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingFileOfferController sendEncryptedFile(FullJid recipient, File file, JingleEncryptionMethod method) throws Exception {
|
public OutgoingFileOfferController sendEncryptedFile(File file, FullJid recipient, JingleEncryptionMethod method) throws Exception {
|
||||||
|
return sendEncryptedFile(file, null, recipient, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutgoingFileOfferController sendEncryptedFile(File file, String filename, FullJid recipient, JingleEncryptionMethod method) throws Exception {
|
||||||
if (file == null || !file.exists()) {
|
if (file == null || !file.exists()) {
|
||||||
throw new IllegalArgumentException("File MUST NOT be null and MUST exist.");
|
throw new IllegalArgumentException("File MUST NOT be null and MUST exist.");
|
||||||
}
|
}
|
||||||
|
@ -94,6 +98,9 @@ public final class JetManager extends Manager implements JingleDescriptionManage
|
||||||
session.addContent(content);
|
session.addContent(content);
|
||||||
|
|
||||||
JingleOutgoingFileOffer offer = new JingleOutgoingFileOffer(file);
|
JingleOutgoingFileOffer offer = new JingleOutgoingFileOffer(file);
|
||||||
|
if (filename != null) {
|
||||||
|
offer.getFile().setName(filename);
|
||||||
|
}
|
||||||
content.setDescription(offer);
|
content.setDescription(offer);
|
||||||
|
|
||||||
JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);
|
JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
package org.jivesoftware.smackx.jingle_filetransfer;
|
package org.jivesoftware.smackx.jingle_filetransfer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -29,6 +31,7 @@ import org.jivesoftware.smack.Manager;
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
|
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
|
||||||
import org.jivesoftware.smackx.jingle.JingleManager;
|
import org.jivesoftware.smackx.jingle.JingleManager;
|
||||||
|
@ -64,6 +67,7 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
|
||||||
|
|
||||||
private final List<IncomingFileOfferListener> offerListeners =
|
private final List<IncomingFileOfferListener> offerListeners =
|
||||||
Collections.synchronizedList(new ArrayList<IncomingFileOfferListener>());
|
Collections.synchronizedList(new ArrayList<IncomingFileOfferListener>());
|
||||||
|
|
||||||
private final List<IncomingFileRequestListener> requestListeners =
|
private final List<IncomingFileRequestListener> requestListeners =
|
||||||
Collections.synchronizedList(new ArrayList<IncomingFileRequestListener>());
|
Collections.synchronizedList(new ArrayList<IncomingFileRequestListener>());
|
||||||
|
|
||||||
|
@ -93,7 +97,7 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
|
||||||
public OutgoingFileOfferController sendFile(File file, FullJid to)
|
public OutgoingFileOfferController sendFile(File file, FullJid to)
|
||||||
throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException,
|
throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException,
|
||||||
SmackException.NoResponseException, SmackException.FeatureNotSupportedException {
|
SmackException.NoResponseException, SmackException.FeatureNotSupportedException {
|
||||||
return sendFile(file, null, to);
|
return sendFile(file, null, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingFileOfferController sendFile(File file, String alternativeFilename, FullJid to)
|
public OutgoingFileOfferController sendFile(File file, String alternativeFilename, FullJid to)
|
||||||
|
@ -127,9 +131,60 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
|
||||||
return offer;
|
return offer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingFileOfferController sendStream(InputStream stream, String filename, FullJid to) {
|
public OutgoingFileOfferController sendStream(final InputStream stream, JingleFileTransferFile.LocalFile file, FullJid recipient) throws SmackException.FeatureNotSupportedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
|
||||||
//TODO: Implement
|
if (!ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(recipient, getNamespace())) {
|
||||||
return null;
|
throw new SmackException.FeatureNotSupportedException(getNamespace(), recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
JingleSession session = jingleManager.createSession(Role.initiator, recipient);
|
||||||
|
|
||||||
|
JingleContent content = new JingleContent(JingleContentElement.Creator.initiator, JingleContentElement.Senders.initiator);
|
||||||
|
session.addContent(content);
|
||||||
|
|
||||||
|
JingleOutgoingFileOffer outgoingFileOffer = new JingleOutgoingFileOffer(file) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBytestreamReady(BytestreamSession bytestreamSession) {
|
||||||
|
OutputStream outputStream;
|
||||||
|
try {
|
||||||
|
outputStream = bytestreamSession.getOutputStream();
|
||||||
|
|
||||||
|
byte[] buf = new byte[4096];
|
||||||
|
while (true) {
|
||||||
|
int r = stream.read(buf);
|
||||||
|
if (r < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
outputStream.write(buf, 0, r);
|
||||||
|
}
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Exception while sending file: " + e, e);
|
||||||
|
} finally {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Could not close FileInputStream: " + e, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyProgressListenersFinished();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
content.setDescription(outgoingFileOffer);
|
||||||
|
|
||||||
|
JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);
|
||||||
|
JingleTransport<?> transport = transportManager.createTransportForInitiator(content);
|
||||||
|
content.setTransport(transport);
|
||||||
|
|
||||||
|
session.sendInitiate(connection());
|
||||||
|
|
||||||
|
return outgoingFileOffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingFileRequestController requestFile(JingleFileTransferFile.RemoteFile file, FullJid from) {
|
public OutgoingFileRequestController requestFile(JingleFileTransferFile.RemoteFile file, FullJid from) {
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -42,8 +41,7 @@ import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChi
|
||||||
public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileTransferFile.RemoteFile> implements IncomingFileOfferController {
|
public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileTransferFile.RemoteFile> implements IncomingFileOfferController {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(JingleIncomingFileOffer.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(JingleIncomingFileOffer.class.getName());
|
||||||
|
private OutputStream target;
|
||||||
private File target;
|
|
||||||
|
|
||||||
public JingleIncomingFileOffer(JingleFileTransferChildElement offer) {
|
public JingleIncomingFileOffer(JingleFileTransferChildElement offer) {
|
||||||
super(new JingleFileTransferFile.RemoteFile(offer));
|
super(new JingleFileTransferFile.RemoteFile(offer));
|
||||||
|
@ -56,27 +54,21 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileT
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBytestreamReady(BytestreamSession bytestreamSession) {
|
public void onBytestreamReady(BytestreamSession bytestreamSession) {
|
||||||
LOGGER.log(Level.INFO, "Receive file to " + target.getAbsolutePath());
|
if (target == null) {
|
||||||
File mFile = target;
|
throw new IllegalStateException("Target OutputStream is null");
|
||||||
if (!mFile.exists()) {
|
|
||||||
try {
|
|
||||||
mFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Could not create new File!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGGER.log(Level.INFO, "Receive file");
|
||||||
|
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
OutputStream outputStream = null;
|
|
||||||
try {
|
try {
|
||||||
inputStream = bytestreamSession.getInputStream();
|
inputStream = bytestreamSession.getInputStream();
|
||||||
outputStream = new FileOutputStream(mFile);
|
|
||||||
|
|
||||||
int length = 0;
|
int length = 0;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
byte[] bufbuf = new byte[4096];
|
byte[] bufbuf = new byte[4096];
|
||||||
while ((length = inputStream.read(bufbuf)) >= 0) {
|
while ((length = inputStream.read(bufbuf)) >= 0) {
|
||||||
outputStream.write(bufbuf, 0, length);
|
target.write(bufbuf, 0, length);
|
||||||
read += length;
|
read += length;
|
||||||
LOGGER.log(Level.INFO, "Read " + read + " (" + length + ") of " + file.getSize() + " bytes.");
|
LOGGER.log(Level.INFO, "Read " + read + " (" + length + ") of " + file.getSize() + " bytes.");
|
||||||
if (read == (int) file.getSize()) {
|
if (read == (int) file.getSize()) {
|
||||||
|
@ -96,9 +88,9 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputStream != null) {
|
if (target != null) {
|
||||||
try {
|
try {
|
||||||
outputStream.close();
|
target.close();
|
||||||
LOGGER.log(Level.INFO, "FileOutputStream closed.");
|
LOGGER.log(Level.INFO, "FileOutputStream closed.");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Could not close OutputStream: " + e, e);
|
LOGGER.log(Level.SEVERE, "Could not close OutputStream: " + e, e);
|
||||||
|
@ -119,16 +111,32 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileT
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Future<Void> accept(XMPPConnection connection, File target)
|
public void accept(XMPPConnection connection, File target)
|
||||||
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
|
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
|
||||||
SmackException.NoResponseException {
|
SmackException.NoResponseException, IOException {
|
||||||
this.target = target;
|
|
||||||
|
if (!target.exists()) {
|
||||||
|
target.createNewFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.target = new FileOutputStream(target);
|
||||||
|
|
||||||
JingleSession session = getParent().getParent();
|
JingleSession session = getParent().getParent();
|
||||||
if (session.getSessionState() == JingleSession.SessionState.pending) {
|
if (session.getSessionState() == JingleSession.SessionState.pending) {
|
||||||
session.sendAccept(connection);
|
session.sendAccept(connection);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
@Override
|
||||||
|
public void accept(XMPPConnection connection, OutputStream stream)
|
||||||
|
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
|
target = stream;
|
||||||
|
|
||||||
|
JingleSession session = getParent().getParent();
|
||||||
|
if (session.getSessionState() == JingleSession.SessionState.pending) {
|
||||||
|
session.sendAccept(connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -36,7 +36,11 @@ public class JingleOutgoingFileOffer extends AbstractJingleFileOffer<JingleFileT
|
||||||
private static final Logger LOGGER = Logger.getLogger(JingleOutgoingFileOffer.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(JingleOutgoingFileOffer.class.getName());
|
||||||
|
|
||||||
public JingleOutgoingFileOffer(File file) {
|
public JingleOutgoingFileOffer(File file) {
|
||||||
super(new JingleFileTransferFile.LocalFile(file));
|
this(new JingleFileTransferFile.LocalFile(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public JingleOutgoingFileOffer(JingleFileTransferFile.LocalFile localFile) {
|
||||||
|
super(localFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
package org.jivesoftware.smackx.jingle_filetransfer.controller;
|
package org.jivesoftware.smackx.jingle_filetransfer.controller;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.Future;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
@ -27,5 +28,6 @@ import org.jivesoftware.smack.XMPPException;
|
||||||
* User interface for an incoming Jingle file offer.
|
* User interface for an incoming Jingle file offer.
|
||||||
*/
|
*/
|
||||||
public interface IncomingFileOfferController extends JingleFileTransferController {
|
public interface IncomingFileOfferController extends JingleFileTransferController {
|
||||||
Future<Void> accept(XMPPConnection connection, File target) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException;
|
void accept(XMPPConnection connection, File target) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, IOException;
|
||||||
|
void accept(XMPPConnection connection, OutputStream outputStream) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException, IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.util.concurrent.Future;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
@ -123,14 +123,14 @@ public class JetIntegrationTest extends AbstractOmemoIntegrationTest {
|
||||||
received.signal();
|
received.signal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Future<Void> f = offer.accept(conTwo, target);
|
offer.accept(conTwo, target);
|
||||||
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
|
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
|
||||||
received.signal(e);
|
received.signal(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ja.sendEncryptedFile(conTwo.getUser().asFullJidOrThrow(), source, oa);
|
ja.sendEncryptedFile(source, conTwo.getUser().asFullJidOrThrow(), oa);
|
||||||
|
|
||||||
received.waitForResult(60 * 1000);
|
received.waitForResult(60 * 1000);
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,8 @@ public class JingleFileTransferIntegrationTest extends AbstractSmackIntegrationT
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
receiveFuture.add(offer.accept(conTwo, target));
|
offer.accept(conTwo, target);
|
||||||
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
|
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
|
||||||
fail(e.toString());
|
fail(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
@ -95,8 +93,6 @@ public class JingleFileTransferTransportFallbackIntegrationTest extends Abstract
|
||||||
JingleFileTransferManager aftm = JingleFileTransferManager.getInstanceFor(conOne);
|
JingleFileTransferManager aftm = JingleFileTransferManager.getInstanceFor(conOne);
|
||||||
JingleFileTransferManager bftm = JingleFileTransferManager.getInstanceFor(conTwo);
|
JingleFileTransferManager bftm = JingleFileTransferManager.getInstanceFor(conTwo);
|
||||||
|
|
||||||
final ArrayList<Future<Void>> receiveFuture = new ArrayList<>(); //Uglaay
|
|
||||||
|
|
||||||
bftm.addIncomingFileOfferListener(new IncomingFileOfferListener() {
|
bftm.addIncomingFileOfferListener(new IncomingFileOfferListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onIncomingFileOffer(IncomingFileOfferController offer) {
|
public void onIncomingFileOffer(IncomingFileOfferController offer) {
|
||||||
|
@ -120,8 +116,8 @@ public class JingleFileTransferTransportFallbackIntegrationTest extends Abstract
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
receiveFuture.add(offer.accept(conTwo, target));
|
offer.accept(conTwo, target);
|
||||||
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
|
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
|
||||||
fail(e.toString());
|
fail(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue