Improve JFT API

This commit is contained in:
vanitasvitae 2017-08-15 17:43:06 +02:00
parent d7df408661
commit e53165a96c
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
8 changed files with 112 additions and 40 deletions

View File

@ -78,7 +78,11 @@ public final class JetManager extends Manager implements JingleDescriptionManage
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()) {
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);
JingleOutgoingFileOffer offer = new JingleOutgoingFileOffer(file);
if (filename != null) {
offer.getFile().setName(filename);
}
content.setDescription(offer);
JingleTransportManager transportManager = jingleManager.getBestAvailableTransportManager(recipient);

View File

@ -17,7 +17,9 @@
package org.jivesoftware.smackx.jingle_filetransfer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -29,6 +31,7 @@ import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
import org.jivesoftware.smackx.jingle.JingleManager;
@ -64,6 +67,7 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
private final List<IncomingFileOfferListener> offerListeners =
Collections.synchronizedList(new ArrayList<IncomingFileOfferListener>());
private final List<IncomingFileRequestListener> requestListeners =
Collections.synchronizedList(new ArrayList<IncomingFileRequestListener>());
@ -93,7 +97,7 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
public OutgoingFileOfferController sendFile(File file, FullJid to)
throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException,
SmackException.NoResponseException, SmackException.FeatureNotSupportedException {
return sendFile(file, null, to);
return sendFile(file, null, to);
}
public OutgoingFileOfferController sendFile(File file, String alternativeFilename, FullJid to)
@ -127,9 +131,60 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
return offer;
}
public OutgoingFileOfferController sendStream(InputStream stream, String filename, FullJid to) {
//TODO: Implement
return null;
public OutgoingFileOfferController sendStream(final InputStream stream, JingleFileTransferFile.LocalFile file, FullJid recipient) throws SmackException.FeatureNotSupportedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
if (!ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(recipient, getNamespace())) {
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) {

View File

@ -21,7 +21,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Future;
import java.util.logging.Level;
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 {
private static final Logger LOGGER = Logger.getLogger(JingleIncomingFileOffer.class.getName());
private File target;
private OutputStream target;
public JingleIncomingFileOffer(JingleFileTransferChildElement offer) {
super(new JingleFileTransferFile.RemoteFile(offer));
@ -56,27 +54,21 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileT
@Override
public void onBytestreamReady(BytestreamSession bytestreamSession) {
LOGGER.log(Level.INFO, "Receive file to " + target.getAbsolutePath());
File mFile = target;
if (!mFile.exists()) {
try {
mFile.createNewFile();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not create new File!");
}
if (target == null) {
throw new IllegalStateException("Target OutputStream is null");
}
LOGGER.log(Level.INFO, "Receive file");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = bytestreamSession.getInputStream();
outputStream = new FileOutputStream(mFile);
int length = 0;
int read = 0;
byte[] bufbuf = new byte[4096];
while ((length = inputStream.read(bufbuf)) >= 0) {
outputStream.write(bufbuf, 0, length);
target.write(bufbuf, 0, length);
read += length;
LOGGER.log(Level.INFO, "Read " + read + " (" + length + ") of " + file.getSize() + " bytes.");
if (read == (int) file.getSize()) {
@ -96,9 +88,9 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileT
}
}
if (outputStream != null) {
if (target != null) {
try {
outputStream.close();
target.close();
LOGGER.log(Level.INFO, "FileOutputStream closed.");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not close OutputStream: " + e, e);
@ -119,16 +111,32 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<JingleFileT
}
@Override
public Future<Void> accept(XMPPConnection connection, File target)
public void accept(XMPPConnection connection, File target)
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
SmackException.NoResponseException {
this.target = target;
SmackException.NoResponseException, IOException {
if (!target.exists()) {
target.createNewFile();
}
this.target = new FileOutputStream(target);
JingleSession session = getParent().getParent();
if (session.getSessionState() == JingleSession.SessionState.pending) {
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

View File

@ -36,7 +36,11 @@ public class JingleOutgoingFileOffer extends AbstractJingleFileOffer<JingleFileT
private static final Logger LOGGER = Logger.getLogger(JingleOutgoingFileOffer.class.getName());
public JingleOutgoingFileOffer(File file) {
super(new JingleFileTransferFile.LocalFile(file));
this(new JingleFileTransferFile.LocalFile(file));
}
public JingleOutgoingFileOffer(JingleFileTransferFile.LocalFile localFile) {
super(localFile);
}
@Override

View File

@ -17,7 +17,8 @@
package org.jivesoftware.smackx.jingle_filetransfer.controller;
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.XMPPConnection;
@ -27,5 +28,6 @@ import org.jivesoftware.smack.XMPPException;
* User interface for an incoming Jingle file offer.
*/
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;
}

View File

@ -25,7 +25,7 @@ import static org.junit.Assert.assertArrayEquals;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.Future;
import java.io.IOException;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
@ -123,14 +123,14 @@ public class JetIntegrationTest extends AbstractOmemoIntegrationTest {
received.signal();
}
});
Future<Void> f = offer.accept(conTwo, target);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
offer.accept(conTwo, target);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
received.signal(e);
}
}
});
ja.sendEncryptedFile(conTwo.getUser().asFullJidOrThrow(), source, oa);
ja.sendEncryptedFile(source, conTwo.getUser().asFullJidOrThrow(), oa);
received.waitForResult(60 * 1000);

View File

@ -107,8 +107,8 @@ public class JingleFileTransferIntegrationTest extends AbstractSmackIntegrationT
});
try {
receiveFuture.add(offer.accept(conTwo, target));
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
offer.accept(conTwo, target);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
fail(e.toString());
}
}

View File

@ -23,8 +23,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.Future;
import java.util.logging.Level;
import org.jivesoftware.smack.SmackException;
@ -95,8 +93,6 @@ public class JingleFileTransferTransportFallbackIntegrationTest extends Abstract
JingleFileTransferManager aftm = JingleFileTransferManager.getInstanceFor(conOne);
JingleFileTransferManager bftm = JingleFileTransferManager.getInstanceFor(conTwo);
final ArrayList<Future<Void>> receiveFuture = new ArrayList<>(); //Uglaay
bftm.addIncomingFileOfferListener(new IncomingFileOfferListener() {
@Override
public void onIncomingFileOffer(IncomingFileOfferController offer) {
@ -120,8 +116,8 @@ public class JingleFileTransferTransportFallbackIntegrationTest extends Abstract
});
try {
receiveFuture.add(offer.accept(conTwo, target));
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
offer.accept(conTwo, target);
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | IOException e) {
fail(e.toString());
}
}