刷新OpenFire中的VCards

我为OpenFire XMPP服务器开发了一个VCard插件,其主要目的是通过HTTP请求创建/更新和检索用户的头像。 不幸的是,插件没有按预期工作 – VCard更改被传播到数据库( ofVcard表),但是userpic更新的用户和他的伙伴都没有看到刷新的图像。 以下是我创建/更新VCards的方法:

  ... XMPPServer server = XMPPServer.getInstance(); VCardManager vcardManager = server.getVCardManager(); public void createOrUpdateVcard(String username, String vcard) throws Exception { SAXReader reader = new SAXReader(); reader.setValidation(false); // convert String into InputStream InputStream is = new ByteArrayInputStream(vcard.getBytes()); // read it with BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(is)); try { // Reading malformed XML will lead to DocumentException Document document = reader.read(is); Element vCardElement = document.getRootElement(); log.info("Username: " + username); vcardManager.setVCard(username, vCardElement); } catch (DocumentException e) { throw new MalformedXmlException(e); } } ... 

当我直接从客户端更改头像(我们使用的是Jitsi)时,更改不仅会立即存储在数据库中,而且所有好友都会获得刷新后的图像。 我看到我使用的VCardManager内部调度事件:

 VCardEventDispatcher.dispatchVCardUpdated(username, newvCard); 

但他们似乎没有任何影响。

我无法弄清楚从setVcardhandleIQ(IQ packet)和我自己的代码中调用setVcard方法的方式有什么区别。 我错过了什么?

好的,我会自己回答我的问题 – 也许有人会发现此信息有用。

事实certificate,并不像将图片存储到数据库那么简单。 预计将在相关各方之间进行消息交换。 这种交换的关键部分是客户端发送的状态更新,通知服务器及其所有好友他的新配置文件图像。 有关更多详细信息,请参阅XEP-0153:基于vCard的Avatars 。 这是一段代码,它“模拟”将发送给所有用户的好友的状态更新:

  public void createOrUpdateVcard(String username, String vcard) throws MalformedXmlException, UserNotFoundException, SetVcardException { SAXReader reader = new SAXReader(); reader.setValidation(false); InputStream is = new ByteArrayInputStream(vcard.getBytes()); try { // Reading malformed XML will lead to DocumentException Document document = reader.read(is); Element vCardElement = document.getRootElement(); //Checking that the user exists User user = userManager.getUser(username); //This might be redundant String userUsername = user.getUsername(); log.debug("Setting VCard for " + userUsername); //Storing vCard into the database VCardManager.getInstance().setVCard(userUsername, vCardElement); Presence presence = new Presence(); JID userJID = server.createJID(username, null); presence.setFrom(userJID); presence.setStatus(""); presence.setPriority(30); Element xElement = presence.addChildElement("x", "vcard-temp:x:update"); Element photoElement = xElement.addElement("photo"); SecureRandom random = new SecureRandom(); //We do not care about the actual hash - just push updates every time String fakeHash = new BigInteger(130, random).toString(32); photoElement.setText(fakeHash); Element cElement = presence.addChildElement("c", "http://jabber.org/protocol/caps"); cElement.addAttribute( "ext", "voice-v1 video-v1 camera-v1" ) .addAttribute("hash", "sha-1"); System.out.println("SENDING PRESENCE UPDATE:\n" + presence.toXML()); broadcastUpdate(presence); } catch (DocumentException e) { throw new MalformedXmlException(e); }catch (UserNotFoundException e){ throw new UserNotFoundException(); } catch (Exception e){ //Unfortunately setVCard method above just throws Exception. //This catch block is for wrapping it up throw new SetVcardException(); } } 

这是PresenceUpdateHandler类中稍微调整过的方法:

 private void broadcastUpdate(Presence update) { if (update.getFrom() == null) { return; } if (localServer.isLocal(update.getFrom())) { // Do nothing if roster service is disabled if (!RosterManager.isRosterServiceEnabled()) { return; } // Local updates can simply run through the roster of the local user String name = update.getFrom().getNode(); try { if (name != null && !"".equals(name)) { Roster roster = rosterManager.getRoster(name); roster.broadcastPresence(update); } } catch (UserNotFoundException e) { log.warn("Presence being sent from unknown user " + name, e); } catch (PacketException e) { log.error(LocaleUtils.getLocalizedString("admin.error"), e); } } else { // Foreign updates will do a reverse lookup of entries in rosters // on the server log.warn("Presence requested from server " + localServer.getServerInfo().getXMPPDomain() + " by unknown user: " + update.getFrom()); } } 

为了调试OpenFire问题,我强烈建议在调试模式下本地运行它 – 请参阅此处的说明: 2 。 请注意,较新的eclipse版本没有来自现有源的Create项目,但您必须单击New – > Java Project,取消选中Use default location复选框并浏览到项目位置。