package de.uni_passau.fim.pkjab.model.xmpp;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import de.uni_passau.fim.pkjab.model.messages.Message;
import de.uni_passau.fim.pkjab.util.Base64;
import de.uni_passau.fim.pkjab.util.UserState;
public class XMPPWriter {
private static final String CLOSE_EMPTY_TAG = "/>";
private static final String CONNECTION_INIT = "<?xml version='1.0' ?><stream:stream to='%s' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>";
private static final String CONNECTION_CLOSE = "</stream:stream>";
private static final String AUTH_START = "<auth mechanism='%s' xmlns='urn:ietf:params:xml:ns:xmpp-sasl'";
private static final String AUTH_RESPONSE = "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'";
private static final String BIND = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'";
private static final String BIND_RESOURCE = "><resource>%s</resource></bind>";
private static final String SESSION_INIT = "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>";
private static final String PRESENCE = "<presence";
private static final String PRESENCE_TYPE = PRESENCE + " type='%s'";
private static final String PRESENCE_SHOW = PRESENCE + "><show>%s</show";
private static final String PRESENCE_STATUS = "><status>%s</status";
private static final String PRESENCE_CLOSE = "></presence>";
private final BufferedWriter writer;
private int myId = 0;
public XMPPWriter(OutputStream outputStream) throws IllegalArgumentException, IOException {
if (outputStream == null) {
throw new IllegalArgumentException("Socket required.");
}
writer = new BufferedWriter(new OutputStreamWriter(outputStream));
}
public synchronized void sendInit(String domain) throws IOException {
writer.write(String.format(CONNECTION_INIT, domain));
writer.flush();
}
public synchronized void sendAuthInit(String mechanism, byte[] initialResponse) throws IOException {
writer.write(String.format(AUTH_START, mechanism));
if (initialResponse == null) {
writer.write(CLOSE_EMPTY_TAG);
} else {
writer.write(">");
writer.write(Base64.encodeBytes(initialResponse));
writer.write("</auth>");
}
writer.flush();
}
public synchronized void sendAuthResponse(byte[] response) throws IOException {
writer.write(AUTH_RESPONSE);
if (response == null) {
writer.write(CLOSE_EMPTY_TAG);
} else {
writer.write(">");
writer.write(Base64.encodeBytes(response));
writer.write("</response>");
}
writer.flush();
}
public synchronized void sendBind(String resource) throws IOException {
if (resource == null || resource.equals("")) {
sendIq("set", BIND + CLOSE_EMPTY_TAG, null, null, null);
} else {
sendIq("set", BIND + String.format(BIND_RESOURCE, resource), null, null, null);
}
}
public synchronized void sendSessionInit() throws IOException {
sendIq("set", SESSION_INIT, null, null, null);
}
public synchronized void getRoster() throws IOException {
sendIqQuery("get", "jabber:iq:roster", "", null, null, null);
}
public synchronized void sendPresence(UserState state, String text) throws IOException {
if (state == UserState.OFFLINE) {
writer.write(String.format(PRESENCE_TYPE, state.toXML()));
} else if (state == UserState.ONLINE) {
writer.write(PRESENCE);
} else {
writer.write(String.format(PRESENCE_SHOW, state.toXML()));
}
if (text != null) {
writer.write(String.format(PRESENCE_STATUS, text));
}
writer.write(PRESENCE_CLOSE);
writer.flush();
}
public synchronized void sendQuit() throws IOException {
// close tags, send quit
writer.write(CONNECTION_CLOSE);
writer.flush();
}
public synchronized void writeRaw(String text) throws IOException {
writer.write(text);
writer.flush();
}
public synchronized void sendIq(String type, String content, String id,
String to, String from) throws IOException {
StringBuffer sb = new StringBuffer("<iq id='");
if (id == null)
sb.append(myId++);
else
sb.append(id);
sb.append("'");
if (to != null) {
sb.append(" to='"); sb.append(to); sb.append('\'');
}
if (from != null) {
sb.append(" from='"); sb.append(from); sb.append('\'');
}
sb.append(" type='"); sb.append(type); sb.append("'>");
sb.append(content);
sb.append("</iq>");
writer.write(sb.toString());
writer.flush();
}
public synchronized void sendMessage(Message msg) throws IOException {
writer.write(msg.toXML());
writer.flush();
}
public synchronized void sendIqQuery(String type, String namespace,
String content, String id, String to, String from) throws IOException {
sendIq(type, String.format("<query xmlns='%s'>%s</query>", namespace, content), id, to, from);
}
}