The JEP pointed out by Anlumo would likely be a good one to use.
I do have some similar code currently. Though, the message is built as a string so I am not sure if it will fit your purposes, but it is in the direction of what I believe you are looking for and could be likely generalized in some manner. The code I wrote allows you to transfer files over the XMPP stream, this is done transparently to the client using the API though as all they see is an output stream that handles the work of building the packets and sending.
Here is the code I currently have, it is available in Smack in IBBTransferNegotiator:
private class IBBOutputStream extends OutputStream {
protected byte[] buffer;
protected int count = 0;
protected int seq = 0;
final String userID;
final private IQ closePacket;
private String messageID;
private String sid;
IBBOutputStream(String userID, String sid, int blockSize) {
if (blockSize <= 0) {
throw new IllegalArgumentException(“Buffer size <= 0”);
}
buffer = new byte[blockSize];
this.userID = userID;
Message template = new Message(userID);
messageID = template.getPacketID();
this.sid = sid;
closePacket = createClosePacket(userID, sid);
}
private IQ createClosePacket(String userID, String sid) {
IQ packet = new IBBExtensions.Close(sid);
packet.setTo(userID);
packet.setType(IQ.Type.SET);
return packet;
}
public void write(int b) throws IOException {
if (count >= buffer.length) {
flushBuffer();
}
buffer[count++] = (byte) b;
}
public synchronized void write(byte b[], int off, int len)
throws IOException {
if (len >= buffer.length) {
// “byte” off the first chunck to write out
writeOut(b, off, buffer.length);
// recursivly call this method again with the lesser amount subtracted.
write(b, off + buffer.length, len - buffer.length);
} else {
writeOut(b, off, len);
}
}
private void writeOut(byte b[], int off, int len) {
if (len > buffer.length - count) {
flushBuffer();
}
System.arraycopy(b, off, buffer, count, len);
count += len;
}
private void flushBuffer() {
writeToXML(buffer, 0, count);
count = 0;
}
private synchronized void writeToXML(byte[] buffer, int offset, int len) {
Message template = createTemplate(messageID + “_” + seq);
IBBExtensions.Data ext = new IBBExtensions.Data(sid);
template.addExtension(ext);
String enc = StringUtils.encodeBase64(buffer, offset, len, false);
ext.setData(enc);
ext.setSeq(seq);
synchronized (this) {
try {
this.wait(100);
}
catch (InterruptedException e) {
/* Do Nothing */
}
}
connection.sendPacket(template);
seq = (seq + 1 == 65535 ? 0 : seq + 1);
}
public void close() throws IOException {
connection.sendPacket(closePacket);
}
public void flush() throws IOException {
flushBuffer();
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public Message createTemplate(String messageID) {
Message template = new Message(userID);
template.setPacketID(messageID);
return template;
}
}
/code
Let me know what you think,
Alex