Java 在OpenFire中刷新vCard
我为OpenFireXMPP服务器开发了一个VCard插件,主要目的是通过HTTP请求创建/更新和检索用户的化身。不幸的是,插件没有按预期工作-VCard更改被分发到数据库(Java 在OpenFire中刷新vCard,java,xmpp,openfire,vcf-vcard,Java,Xmpp,Openfire,Vcf Vcard,我为OpenFireXMPP服务器开发了一个VCard插件,主要目的是通过HTTP请求创建/更新和检索用户的化身。不幸的是,插件没有按预期工作-VCard更改被分发到数据库(ofVcardtable),但是用户pic被更新的用户和他的伙伴都看不到刷新的图像。以下是我如何创建/更新vCard: ... XMPPServer server = XMPPServer.getInstance(); VCardManager vcardManager = server.getVCardM
ofVcard
table),但是用户pic被更新的用户和他的伙伴都看不到刷新的图像。以下是我如何创建/更新vCard:
...
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);
但它们似乎没有任何效果
我无法找出从
IQvCardHandler
中的handleIQ(IQ数据包)
调用setVcard
方法的方式与我自己的代码之间的区别。我遗漏了什么?好的,我会自己回答我的问题-也许有人会觉得这些信息很有用
事实证明,这并不像仅仅将一张图片存储到数据库中那么简单。预计相关方之间会发生消息交换。此交换的关键部分是,有一个状态更新,由客户端发送,该更新将通知服务器,从而通知其所有好友有关其新的配置文件映像。有关详细信息,请参阅。这是一段“模拟”状态更新的代码,将发送给用户的所有好友:
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问题,我强烈建议在调试模式下本地运行它-请参阅此处的说明:。请注意,较新的eclipse版本没有从现有源代码创建项目,但是您必须单击New->Java project,取消选中Use default location复选框并浏览到项目位置。好的,我会自己回答我的问题-也许有人会觉得这些信息很有用 事实证明,这并不像仅仅将一张图片存储到数据库中那么简单。预计相关方之间会发生消息交换。此交换的关键部分是,有一个状态更新,由客户端发送,该更新将通知服务器,从而通知其所有好友有关其新的配置文件映像。有关详细信息,请参阅。这是一段“模拟”状态更新的代码,将发送给用户的所有好友:
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问题,我强烈建议在调试模式下本地运行它-请参阅此处的说明:。请注意,较新的eclipse版本没有从现有源创建项目,但是您必须单击New->Java project,取消选中Use default location复选框并浏览到项目位置