package chatroom.parser;
import chatroom.connection.ServerConnection;
import chatroom.server.ChatroomServer;
import chatroom.server.dataclass.Room;
import chatroom.server.dataclass.User;
import java.io.IOException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/** Server parser
*
* @author peter
*/
public class ServerParser extends Parser {
/** Singleton object */
private ChatroomServer server;
/** Initialize a server parser
*
* @param con connection object
*/
public ServerParser(ServerConnection con) {
super(con);
server = ChatroomServer.getServer();
}
private static String IQ_BIND = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>%s/%s</jid></bind>";
@Override
protected void onIqBind(String id, String from, String to, String resource) {
sendIq(id, "result", to, from, String.format(IQ_BIND, to, resource));
}
@Override
protected void onIqSession(String id, String from, String to) {
sendIq(id, "result", to, from, "");
}
private static String IQ_QUERY_INFO = "<query xmlns='http://jabber.org/protocol/disco#info'>"
+ "<feature var='http://jabber.org/protocol/disco#info'/>"
+ "<feature var='http://jabber.org/protocol/disco#items'/>"
+ "<feature var='http://jabber.org/protocol/muc'/>"
+ "<feature var='http://jabber.org/protocol/xhtml-im'/>"
+ "</query>";
@Override
protected void onIqQueryInfo(String id, String from, String to) {
sendIq(id, "result", to, from, IQ_QUERY_INFO);
}
private static String IQ_QUERY_RESPONSE_BEGIN = "<query xmlns='http://jabber.org/protocol/disco#items'>";
private static String IQ_QUERY_RESPONSE_END = "</query>";
private static String IQ_QUERY_RESPONSE_ITEM = "<item jid='%s' name='%s' count='%d'/>";
private static String IQ_QUERY_RESPONSE_ITEM_NONAME = "<item jid='%s'/>";
@Override
protected void onIqQueryItem(String id, String from, String to) {
Jid jid = new Jid(to);
StringBuilder sb = new StringBuilder();
sb.append(IQ_QUERY_RESPONSE_BEGIN);
if (jid.isGlobal()) {
Set<String> rooms = server.getRoomList();
for (String room : rooms) {
Jid item = new Jid(room, null);
Room r = server.getRoom(room);
sb.append(String.format(IQ_QUERY_RESPONSE_ITEM, item.toString(), server.getRoom(room).getDescription(), r.getUserList().size()));
}
} else if (jid.isRoom()) {
Set<String> users = server.getRoom(jid.getRoom()).getUserList();
for (String user : users) {
Jid item = new Jid(jid.getRoom(), user);
sb.append(String.format(IQ_QUERY_RESPONSE_ITEM_NONAME, item.toString()));
}
}
sb.append(IQ_QUERY_RESPONSE_END);
sendIq(id, "result", to, from, sb.toString());
}
private static String IQ_QUERY_ERROR = "<error type='cancel'/>";
@Override
protected void onIqQueryError(String id, String from, String to) {
sendIq(id, "result", to, from, IQ_QUERY_ERROR);
}
@Override
protected void onIqPing(String id, String from, String to) {
sendIq(id, "result", to, from, "");
}
@Override
protected void onPresenceStatus(String from, String to, String status, String show) {
if (to != null) {
Jid jid = new Jid(to);
if (jid.isUser()) {
Room room = server.getRoom(jid.getRoom());
User user = server.getUserByConnection(connection);
if (status != null) {
user.setStatus(status);
}
user.setShow(show);
room.broadcastPresence(jid.getName(), null);
}
}
}
@Override
protected boolean onPresenceAvailable(String from, String to) {
if (to != null) {
Jid jid = new Jid(to);
if (jid.isUser()) {
Room room = server.getRoom(jid.getRoom());
User user = server.getUserByConnection(connection);
int ret = user.joinRoomWithNickname(room, jid.getName());
if (ret == 1) {
for (String other : room.getUserList()) {
if (!other.equals(jid.getName())) {
user.sendPresence(room, jid.getName(), other, null);
}
}
room.broadcastPresence(jid.getName(), null);
} else if (ret == 0) {
// The nick already existed, send a conflict.
user.sendPresenceConflict(room, to);
return false;
}
}
}
return true;
}
@Override
protected void onPresenceUnavailable(String from, String to) {
if (to != null) {
Jid jid = new Jid(to);
if (jid.isUser()) {
Room room = server.getRoom(jid.getRoom());
User user = server.getUserByConnection(connection);
room.broadcastPresence(jid.getName(), "unavailable");
user.exitRoom(room);
}
}
}
@Override
protected void onMessageGroupchat(String id, String from, String to, String msg) {
if (to != null) {
Jid jid = new Jid(to);
if (jid.isRoom()) {
Room room = server.getRoom(jid.getRoom());
User user = server.getUserByConnection(connection);
room.broadcast(msg, user.getNicknameByRoom(room));
}
}
}
public void onSendMessage(String roomName, String nickname, String sender, String type, String msg) {
sendMessage(new Jid(roomName, sender).toString(), new Jid(roomName, nickname).toString(), type, msg);
}
protected static String PRESENCE_STATUS = "<status>%s</status>";
protected static String PRESENCE_SHOW = "<show>%s</show>";
public void onSendPresence(String roomName, String nickname, String sender, String type, String status, String show) {
StringBuilder sb = new StringBuilder();
if (status != null) {
sb.append(String.format(PRESENCE_STATUS, status));
}
if (!"available".equals(show) && show != null) {
sb.append(String.format(PRESENCE_SHOW, show));
}
sendPresence(new Jid(roomName, sender).toString(), new Jid(roomName, nickname).toString(), type, sb.toString());
}
protected static String PRESENCE_CONFLICT = "<x xmlns='http://jabber.org/protocol/muc'/><error type='cancel'><conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error>";
public void onSendPresenceConflict(String roomName, String to) {
sendPresence(new Jid(roomName, null).toString(), to, "error", PRESENCE_CONFLICT);
}
public void onSendIqVCard(String id, String roomid, String sender, String vCard) {
sendIq(id, "result", new Jid(roomid, sender).toString(), null, String.format(IQ_VCARD, vCard));
}
protected static String IQ_PING_PORT = "<ping xmlns='urn:xmpp:ping' port='%d'/>";
public void onSendIqPingPort(String id, String roomid, String sender, int port) {
sendIq(id, "result", new Jid(roomid, sender).toString(), null, String.format(IQ_PING_PORT, port));
}
@Override
protected void onStream() {
serverIP = xmlParser.getAttributeValue("", "to");
sendHeader();
}
@Override
protected void onPresenceError(String from, String to, String errorType) {
logger.warning("Server parser got a presence error ...");
// Nothing to do.
}
@Override
protected void onMessagePrivate(String id, String from, String to, String msg) {
if (to != null) {
Jid jid = new Jid(to);
if (jid.isUser()) {
Jid fromJid = new Jid(from);
Room room = server.getRoom(jid.getRoom());
User user = room.getUser(jid.getName());
user.sendMessage(room, fromJid.getName(), null, msg);
}
}
if (from != null) {
Jid jid = new Jid(from);
if (jid.isUser()) {
Jid fromJid = new Jid(to);
Room room = server.getRoom(jid.getRoom());
User user = room.getUser(jid.getName());
user.sendMessage(room, jid.getName(), fromJid.getName(), null, msg);
}
}
}
private static String IQ_VCARD = "<vCard xmlns='vcard-temp'>%s</vCard>";
@Override
protected void onIqCardGet(String id, String from, String to) {
Jid jid = new Jid(to);
if (jid.isGlobal()) {
sendIq(id, "result", to, from, String.format(IQ_VCARD, ChatroomServer.getServer().getUserByConnection(connection).getVCard(null)));
} else if (jid.isUser()) {
Room room = ChatroomServer.getServer().getRoom(jid.getRoom());
if (room != null) {
User user = room.getUser(jid.getName());
if (user != null) {
onSendIqVCard(id, room.getName(), user.getNicknameByRoom(room), user.getVCard(room));
}
}
}
}
@Override
protected void onIqCardSet(String id, String from, String to) {
boolean inPhoto = false;
String profilePic = null;
String profilePicType = null;
String profilePicURL = null;
while (true) {
try {
int eventType = xmlParser.next();
String tagName = xmlParser.getName();
if (eventType == XmlPullParser.START_TAG) {
if ("PHOTO".equals(tagName)) {
inPhoto = true;
} else if ("BINVAL".equals(tagName)) {
if (inPhoto) {
profilePic = xmlParser.nextText();
}
} else if ("EXTVAL".equals(tagName)) {
if (inPhoto) {
profilePicURL = xmlParser.nextText();
}
} else if ("TYPE".equals(tagName)) {
if (inPhoto) {
profilePicType = xmlParser.nextText();
}
}
}
if (eventType == XmlPullParser.END_TAG) {
if ("PHOTO".equals(tagName)) {
inPhoto = false;
} else if ("vCard".equals(tagName)) {
break;
}
}
} catch (XmlPullParserException ex) {
Logger.getLogger(ClientParser.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ClientParser.class.getName()).log(Level.SEVERE, null, ex);
}
}
ChatroomServer.getServer().getUserByConnection(connection).setProfilePic(profilePic, profilePicType, profilePicURL);
}
@Override
protected void onIqCardResult(String id, String from, String to) {
// Nothing to do.
}
@Override
protected void onIqPingPort(String id, String from, String to, String port) {
Jid jid = new Jid(from);
if (jid.isUser()) {
Room room = server.getRoom(jid.getRoom());
int p = -1;
try {
p = room.getAudioPort();
} catch (IOException ex) {
Logger.getLogger(ServerParser.class.getName()).log(Level.SEVERE, null, ex);
}
User user = room.getUser(jid.getName());
user.sendAudioPort(room, p);
}
}
}