androidpn的学习研究(七)Androidpn-server的添加其他xmpp相关的协议(如查看好友列表等)...

曾经有一个同学,在网上问我,如果想androidpn添加额外的xmpp协议的方法在怎么加呢?我当时很迷惑,后来经过一翻仔细研究androidpn发现,其实每一种处理xmpp协议方法,必须有一个Handler实现。具体可以参考org.androidpn.server.xmpp.handler中。

针对每一个Handler对应的xml拥有不同的命名空间,每一个命名空间在xmpp中都有定义,因为传输的xml的格式是一定的。

例如:

IQAuthHandler:命名空间 String NAMESPACE = "jabber:iq:auth";

IQRegisterHandler:命名空间 String NAMESPACE = "jabber:iq:register";

IQRosterHandler:命名空间 String NAMESPACE = "jabber:iq:roster";

同时我们从Handler的实现可以看到每一个handler最好实现对应IQHandler类,但是为辅助类型的Handler那么可以不用,例如androidpn的状态更新处理器类PresenceUpdateHandler,不必要发送相关的消息到客户端。

所以如果要实现xmpp中如查看好友,用户分组等通信协议,那么你可能要实现相关的Handler并使用xmpp协议规定的相关的命名空间。

在androidpn中主要的业务处理类XmppIoHandler可以看出最终消息解析之后分发到IQRouter中。IQRouter用于处理消息的响应的消息。

IQRouter的源代码如下:

Java代码 收藏代码
  1. packageorg.androidpn.server.xmpp.router;
  2. importjava.util.ArrayList;
  3. importjava.util.List;
  4. importjava.util.Map;
  5. importjava.util.concurrent.ConcurrentHashMap;
  6. importorg.androidpn.server.xmpp.handler.IQAuthHandler;
  7. importorg.androidpn.server.xmpp.handler.IQHandler;
  8. importorg.androidpn.server.xmpp.handler.IQRegisterHandler;
  9. importorg.androidpn.server.xmpp.handler.IQRosterHandler;
  10. importorg.androidpn.server.xmpp.session.ClientSession;
  11. importorg.androidpn.server.xmpp.session.Session;
  12. importorg.androidpn.server.xmpp.session.SessionManager;
  13. importorg.apache.commons.logging.Log;
  14. importorg.apache.commons.logging.LogFactory;
  15. importorg.dom4j.Element;
  16. importorg.xmpp.packet.IQ;
  17. importorg.xmpp.packet.JID;
  18. importorg.xmpp.packet.PacketError;
  19. /**
  20. *ThisclassistorouteIQpacketstotheircorrespondinghandler.
  21. *
  22. *@authorSehwanNoh(devnoh@gmail.com)
  23. */
  24. publicclassIQRouter{
  25. privatefinalLoglog=LogFactory.getLog(getClass());
  26. privateSessionManagersessionManager;
  27. privateList<IQHandler>iqHandlers=newArrayList<IQHandler>();
  28. privateMap<String,IQHandler>namespace2Handlers=newConcurrentHashMap<String,IQHandler>();
  29. /**
  30. *ConstuctsapacketrouterregisteringnewIQhandlers.
  31. */
  32. publicIQRouter(){
  33. sessionManager=SessionManager.getInstance();
  34. iqHandlers.add(newIQAuthHandler());
  35. iqHandlers.add(newIQRegisterHandler());
  36. iqHandlers.add(newIQRosterHandler());
  37. }
  38. /**
  39. *RoutestheIQpacketbasedonitsnamespace.
  40. *
  41. *@parampacketthepackettoroute
  42. */
  43. publicvoidroute(IQpacket){
  44. if(packet==null){
  45. thrownewNullPointerException();
  46. }
  47. JIDsender=packet.getFrom();
  48. ClientSessionsession=sessionManager.getSession(sender);
  49. if(session==null
  50. ||session.getStatus()==Session.STATUS_AUTHENTICATED
  51. ||("jabber:iq:auth".equals(packet.getChildElement()
  52. .getNamespaceURI())
  53. ||"jabber:iq:register".equals(packet.getChildElement()
  54. .getNamespaceURI())||"urn:ietf:params:xml:ns:xmpp-bind"
  55. .equals(packet.getChildElement().getNamespaceURI()))){
  56. handle(packet);
  57. }else{
  58. IQreply=IQ.createResultIQ(packet);
  59. reply.setChildElement(packet.getChildElement().createCopy());
  60. reply.setError(PacketError.Condition.not_authorized);
  61. session.process(reply);
  62. }
  63. }
  64. privatevoidhandle(IQpacket){
  65. try{
  66. ElementchildElement=packet.getChildElement();
  67. Stringnamespace=null;
  68. if(childElement!=null){
  69. namespace=childElement.getNamespaceURI();
  70. }
  71. if(namespace==null){
  72. if(packet.getType()!=IQ.Type.result
  73. &&packet.getType()!=IQ.Type.error){
  74. log.warn("Unknownpacket"+packet);
  75. }
  76. }else{
  77. IQHandlerhandler=getHandler(namespace);
  78. if(handler==null){
  79. sendErrorPacket(packet,
  80. PacketError.Condition.service_unavailable);
  81. }else{
  82. handler.process(packet);
  83. }
  84. }
  85. }catch(Exceptione){
  86. log.error("Couldnotroutepacket",e);
  87. Sessionsession=sessionManager.getSession(packet.getFrom());
  88. if(session!=null){
  89. IQreply=IQ.createResultIQ(packet);
  90. reply.setError(PacketError.Condition.internal_server_error);
  91. session.process(reply);
  92. }
  93. }
  94. }
  95. /**
  96. *Sendatheerrorpackettotheoriginalsender
  97. */
  98. privatevoidsendErrorPacket(IQoriginalPacket,
  99. PacketError.Conditioncondition){
  100. if(IQ.Type.error==originalPacket.getType()){
  101. log.error("CannotreplyanIQerrortoanotherIQerror:"
  102. +originalPacket);
  103. return;
  104. }
  105. IQreply=IQ.createResultIQ(originalPacket);
  106. reply.setChildElement(originalPacket.getChildElement().createCopy());
  107. reply.setError(condition);
  108. try{
  109. PacketDeliverer.deliver(reply);
  110. }catch(Exceptione){
  111. //Ignore
  112. }
  113. }
  114. /**
  115. *AddsanewIQHandlertothelistofregisteredhandler.
  116. *
  117. *@paramhandlertheIQHandler
  118. */
  119. publicvoidaddHandler(IQHandlerhandler){
  120. if(iqHandlers.contains(handler)){
  121. thrownewIllegalArgumentException(
  122. "IQHandleralreadyprovidedbytheserver");
  123. }
  124. namespace2Handlers.put(handler.getNamespace(),handler);
  125. }
  126. /**
  127. *RemovesanIQHandlerfromthelistofregisteredhandler.
  128. *
  129. *@paramhandlertheIQHandler
  130. */
  131. publicvoidremoveHandler(IQHandlerhandler){
  132. if(iqHandlers.contains(handler)){
  133. thrownewIllegalArgumentException(
  134. "CannotremoveanIQHandlerprovidedbytheserver");
  135. }
  136. namespace2Handlers.remove(handler.getNamespace());
  137. }
  138. /**
  139. *ReturnsanIQHandlerwiththegivennamespace.
  140. */
  141. privateIQHandlergetHandler(Stringnamespace){
  142. IQHandlerhandler=namespace2Handlers.get(namespace);
  143. if(handler==null){
  144. for(IQHandlerhandlerCandidate:iqHandlers){
  145. if(namespace.equalsIgnoreCase(handlerCandidate.getNamespace())){
  146. handler=handlerCandidate;
  147. namespace2Handlers.put(namespace,handler);
  148. break;
  149. }
  150. }
  151. }
  152. returnhandler;
  153. }
  154. }

由以上的源代码可以看出,IQRouter在加载时候将各种处理器添加到回话管理器中,当消息分发到IQRouter中时候,根据命名空间的不同使用不同的处理处置即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值