package com.blazemeter.jmeter.xmpp.actions;
import com.blazemeter.jmeter.xmpp.JMeterXMPPSampler;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smackx.filetransfer.*;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
public class SendFileXEP0096 extends AbstractXMPPAction implements FileTransferListener, ConnectionListener {
private static final Logger log = LoggingManager.getLoggerForClass();
public static final java.lang.String FILE_RECIPIENT = "file_recipient";
public static final String FILE_PATH = "file_path";
private static final long WAITING_CYCLES = 10;
private JTextField recipient;
private JTextField path;
private FileTransferManager mgr;
@Override
public String getLabel() {
return "Send File (XEP-0096)";
}
@Override
public SampleResult perform(JMeterXMPPSampler sampler, SampleResult res) throws Exception {
String recipient = sampler.getPropertyAsString(FILE_RECIPIENT);
String filePath = sampler.getPropertyAsString(FILE_PATH);
res.setSamplerData("Recipient: " + recipient + "\r\nFile: " + filePath + "\r\n");
OutgoingFileTransfer transfer = mgr.createOutgoingFileTransfer(recipient);
transfer.sendFile(new File(filePath), filePath);
waitForTransfer(transfer, sampler.getXMPPConnection().getPacketReplyTimeout());
res.setResponseData(("Bytes sent: " + transfer.getBytesSent()).getBytes());
return res;
}
private void waitForTransfer(FileTransfer transfer, long timeout) throws SmackException, InterruptedException {
double prevProgress = 0;
long counter = 0;
Thread.sleep(timeout / WAITING_CYCLES / 10); // optimistic
while (!transfer.isDone()) {
if (transfer.getStatus().equals(FileTransfer.Status.error)) {
throw new SmackException(transfer.getError().toString(), transfer.getException());
} else {
log.debug("Status: " + transfer.getStatus() + " " + transfer.getProgress());
}
if (transfer.getProgress() <= prevProgress) {
if (counter >= WAITING_CYCLES) {
throw new SmackException("File transfer timed out");
}
counter++;
Thread.sleep(timeout / WAITING_CYCLES);
} else {
counter = 0;
prevProgress = transfer.getProgress();
}
}
if (transfer.getProgress() == 0) {
throw new SmackException("No data transferred");
}
}
@Override
public void addUI(JComponent panel, GridBagConstraints labelConstraints, GridBagConstraints editConstraints) {
addToPanel(panel, labelConstraints, 0, 0, new JLabel("Recipient: ", JLabel.RIGHT));
addToPanel(panel, editConstraints, 1, 0, recipient = new JTextField(20));
addToPanel(panel, labelConstraints, 0, 1, new JLabel("File to send: ", JLabel.RIGHT));
addToPanel(panel, editConstraints, 1, 1, path = new JTextField(20));
addToPanel(panel, labelConstraints, 1, 2, new JLabel("Note: you must use full JID as recipient, like user@server/resource)", JLabel.LEFT));
}
@Override
public void clearGui() {
recipient.setText("");
path.setText("");
}
@Override
public void setSamplerProperties(JMeterXMPPSampler sampler) {
sampler.setProperty(FILE_RECIPIENT, recipient.getText());
sampler.setProperty(FILE_PATH, path.getText());
}
@Override
public void setGuiFieldsFromSampler(JMeterXMPPSampler sampler) {
recipient.setText(sampler.getPropertyAsString(FILE_RECIPIENT));
path.setText(sampler.getPropertyAsString(FILE_PATH));
}
@Override
public void fileTransferRequest(FileTransferRequest request) {
final IncomingFileTransfer transfer = request.accept();
Thread transferThread = new Thread(new Runnable() {
public void run() {
try {
OutputStream os = new NullOutputStream();
InputStream is = transfer.recieveFile();
log.debug("Reading from stream: " + is.available());
IOUtils.copy(is, os);
log.debug("Left in stream: " + is.available());
} catch (Exception e) {
log.error("Failed incoming file transfer", e);
}
}
});
transferThread.start();
}
@Override
public void connected(XMPPConnection connection) {
this.mgr = new FileTransferManager(connection);
mgr.addFileTransferListener(this);
}
@Override
public void authenticated(XMPPConnection connection) {
}
@Override
public void connectionClosed() {
}
@Override
public void connectionClosedOnError(Exception e) {
}
@Override
public void reconnectingIn(int seconds) {
}
@Override
public void reconnectionSuccessful() {
}
@Override
public void reconnectionFailed(Exception e) {
}
}