openfire服务端采用http://blog.csdn.net/yangzl2008/article/details/16991175#t4提到的方法解决会议室中人员持久化问题。
smack端,首先获取服务器所有会议服务:
/**
* 初始化会议室列表 <br>
* 该列表数据为会议服务列表,一个会议服务包含N个会议室
*/
public List<HostedRoom> getHostRooms() {
if (getConnection() == null)
return null;
Collection<HostedRoom> hostrooms = null;
List<HostedRoom> roominfos = new ArrayList<HostedRoom>();
try {
ServiceDiscoveryManager.getInstanceFor(getConnection());
hostrooms = MultiUserChat.getHostedRooms(getConnection(),
getConnection().getServiceName());
for (HostedRoom entry : hostrooms) {
roominfos.add(entry);
Log.i("room", "name:" + entry.getName() + " - ID:" + entry.getJid());
}
Log.i("room", "服务会议数量:" + roominfos.size());
} catch (XMPPException e) {
e.printStackTrace();
}
return roominfos;
}
然后根据选定的会议服务jid,发送自定义请求来获取该会议服务下当前用户所在的群组:
public List<MyJoinedRoomIQ.Room> getMyRoomItems(){
//构建自定义协议,查询我加入的房间
MyJoinedRoomRequestIQ iq = new MyJoinedRoomRequestIQ(getConferenceHostRooms().getJid());
// Create a packet collector to listen for a response.
PacketCollector collector =
getXmppConnection().createPacketCollector(new PacketIDFilter(iq.getPacketID()));
getXmppConnection().sendPacket(iq);
// Wait up to 5 seconds for a result.
MyJoinedRoomIQ result = (MyJoinedRoomIQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Stop queuing results
collector.cancel();
/*<iq type="result" id="41V6J-7" to="libai@127.0.0.1/Smack">
* <rooms xmlns="myjoinedroom">
* <room>
* <serviceId>1</serviceId>
* <name>新群3</name>
* <roomid>8</roomid>
* <nickName>libai</nickName>
* <memberJID>huaqiang@127.0.0.1</memberJID>
* </room>
* </rooms>
*</iq>*/
return (result==null?new ArrayList<MyJoinedRoomIQ.Room>(0):result.getRooms());
}
自定义请求类MyJoinedRoomRequestIQ如下:
public class MyJoinedRoomRequestIQ extends IQ{
public MyJoinedRoomRequestIQ(String toJID) {
super();
setTo(toJID);
setType(IQ.Type.GET);
setPacketID(Packet.nextID());
}
@Override
public String getChildElementXML() {
return "<query xmlns=\""+MyJoinedRoomIQ.nameSpace+"\" />";
}
}
接收服务端响应类MyJoinedRoomIQ如下:
public class MyJoinedRoomIQ extends IQ {
public static final String elementName="rooms";
public static final String nameSpace="myjoinedroom";
private final List<Room> rooms = new CopyOnWriteArrayList<Room>();
@Override
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<room xmlns=\"").append(MyJoinedRoomIQ.nameSpace).append("\"").append(">");
synchronized (rooms) {
for (Room r:rooms) {
buf.append(r.toXml());
}
}
buf.append("</room>");
return buf.toString();
}
public static class Room implements Serializable{
private static final long serialVersionUID = 2488520282455672273L;
String serviceId;
String name;
String roomid;
String nickName;
String memberJID;
public String toXml() {
StringBuilder buf = new StringBuilder();
buf.append("<room>")
.append("<serviceId>").append(serviceId==null?"":StringUtils.escapeForXML(serviceId)).append("</serviceId>")
.append("<name>").append(name==null?"":StringUtils.escapeForXML(name)).append("</name>")
.append("<roomid>").append(roomid==null?"":StringUtils.escapeForXML(roomid)).append("</roomid>")
.append("<nickName>").append(nickName==null?"":StringUtils.escapeForXML(nickName)).append("</nickName>")
.append("<memberJID>").append(memberJID==null?"":StringUtils.escapeForXML(memberJID)).append("</memberJID>")
.append("</room>");
return buf.toString();
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRoomid() {
return roomid;
}
public void setRoomid(String roomid) {
this.roomid = roomid;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getMemberJID() {
return memberJID;
}
public void setMemberJID(String memberJID) {
this.memberJID = memberJID;
}
}
public List<Room> getRooms() {
return rooms;
}
public void addRooms(List<Room> rooms){
rooms.addAll(rooms);
}
public void addRoom(Room room){
rooms.add(room);
}
}
在smack的连接配置中,必须配置以下Provider
ProviderManager.getInstance().addIQProvider(MyJoinedRoomIQ.elementName, MyJoinedRoomIQ.nameSpace, new MyJoinedRoomProvider());
MyJoinedRoomProvider的定义如下:
public class MyJoinedRoomProvider implements IQProvider{
public IQ parseIQ(XmlPullParser parser) throws Exception {
MyJoinedRoomIQ rooms = new MyJoinedRoomIQ();
boolean done = false;
MyJoinedRoomIQ.Room room=null;
String serviceId="",name="",roomid="",nickName="",memberJID="";
while (!done) {
int eventType = parser.next();
switch (eventType) {
case XmlPullParser.START_TAG:
if(parser.getName().equals("serviceId")){
serviceId=parser.nextText();
}
if(parser.getName().equals("name")){
name=parser.nextText();
}
if(parser.getName().equals("roomid")){
roomid=parser.nextText();
}
if(parser.getName().equals("nickName")){
nickName=parser.nextText();
}
if(parser.getName().equals("memberJID")){
memberJID=parser.nextText();
}
break;
case XmlPullParser.END_TAG:
if("room".equals(parser.getName())){
room = new MyJoinedRoomIQ.Room();
room.setServiceId(serviceId);
room.setName(name);
room.setNickName(nickName);
room.setRoomid(roomid);
room.setMemberJID(memberJID);
rooms.addRoom(room);
}else if("rooms".equals(parser.getName())){
done=true;
}
break;
}
}
return rooms;
}
}
客户端配置完毕。
服务端需要插件来对接收到的请求做处理并响应给客户端,插件如下:
public class MUCExpand implements Plugin,PacketInterceptor{
private static final Logger log = LoggerFactory.getLogger(MUCExpand.class);
private XMPPServer server;
@Override
public void initializePlugin(PluginManager manager, File pluginDirectory) {
InterceptorManager.getInstance().addInterceptor(this);
server = XMPPServer.getInstance();
}
@Override
public void interceptPacket(Packet packet, Session session,
boolean incoming, boolean processed) throws PacketRejectedException {
if (incoming && processed && packet instanceof IQ) {
JID fromJID = packet.getFrom();
if (fromJID == null)return;
JID jid=null;
if((jid=packet.getTo())==null)return;
if(jid.getDomain()==null || !jid.getDomain().startsWith("conference"))return;
IQ iq = (IQ) packet;
if(!iq.getType().equals(org.xmpp.packet.IQ.Type.get))return;
Element iqele = iq.getElement();
Iterator<Node> iter = iqele.nodeIterator();
boolean flag = false;
while(iter.hasNext()){
Node node = iter.next();
flag = node.asXML().contains("<query xmlns=\"myjoinedroom\"");
if(flag)break;
}
if(!flag)return;
//获取该用户的所有群组返回
/*<iq from='macbeth.shakespeare.lit' id='disco2' to='hag66@shakespeare.lit/pda' type='result'>
<rooms xmlns='myjoinedroom'>
<room>
<jid>1</jid>
<name>sadfsad@sdf.sdf</name>
........
</room>
</rooms>
</iq>
*/
IQ responseIQ = new IQ(org.xmpp.packet.IQ.Type.result,iq.getID());
responseIQ.setTo(fromJID);
Element queryEle = responseIQ.setChildElement("rooms", "myjoinedroom");
List<Map<String, String>> mucs = getMUCInfo(fromJID.toBareJID());
if(mucs!=null && mucs.size()>0){
Element itemEle = null;
for (Map<String, String> map : mucs) {
itemEle=queryEle.addElement("room");
itemEle.addElement("serviceId").setText(map.get("serviceId"));
itemEle.addElement("name").setText(map.get("roomName"));
itemEle.addElement("roomid").setText( map.get("roomid"));
itemEle.addElement("nickName").setText( map.get("nickName"));
itemEle.addElement("memberJID").setText( map.get("memberJID"));
}
}
server.getRoutingTable().routePacket(fromJID, responseIQ, true);
System.out.println("响应给["+fromJID.toString()+"]群组:"+responseIQ.toXML());
}
}
public List<Map<String, String>> getMUCInfo(String jid) {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
String sql = "select ofmucroom.serviceID, ofmucroom.name, ofmucroom.roomid ,ofmucmember.nickname,ofmucmember.jid from ofmucroom join ofmucmember on ofmucroom.roomID = ofmucmember.roomID and ofmucmember.jid = ?";
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
Map<String, String> map = null;
try {
connection = DbConnectionManager.getConnection();
statement = connection.prepareStatement(sql);
statement.setString(1, jid);
resultSet = statement.executeQuery();
while (resultSet.next()) {
map = new HashMap<String, String>();
map.put("serviceId", resultSet.getString(1)==null?"":resultSet.getString(1));
map.put("roomName", resultSet.getString(2)==null?"":resultSet.getString(2));
map.put("roomid", resultSet.getString(3)==null?"":resultSet.getString(3));
map.put("nickName", resultSet.getString(4)==null?"":resultSet.getString(4));
map.put("memberJID", resultSet.getString(5)==null?"":resultSet.getString(5));
list.add(map);
}
} catch (Exception e1) {
e1.printStackTrace();
log.error(e1.getMessage());
} finally {
DbConnectionManager.closeConnection(resultSet, statement,
connection);
}
return list;
}
@Override
public void destroyPlugin() {
// TODO Auto-generated method stub
}
}
至此,smack通过自定义协议获取当前用户的群代码完毕。