📄 vcardmanager.java
字号:
/**
* $Revision: $
* $Date: $
*
* Copyright (C) 2006 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Lesser Public License (LGPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.sparkimpl.profile;
import org.jivesoftware.resource.Res;
import org.jivesoftware.resource.SparkRes;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.VCard;
import org.jivesoftware.smackx.provider.VCardProvider;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.util.Base64;
import org.jivesoftware.spark.util.GraphicUtils;
import org.jivesoftware.spark.util.ModelUtil;
import org.jivesoftware.spark.util.ResourceUtils;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.TaskEngine;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.plugin.manager.Enterprise;
import org.jivesoftware.sparkimpl.profile.ext.JabberAvatarExtension;
import org.jivesoftware.sparkimpl.profile.ext.VCardUpdateExtension;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
/**
* VCardManager handles all VCard loading/caching within Spark.
*
* @author Derek DeMoro
*/
public class VCardManager {
private VCard personalVCard;
private Map<String, VCard> vcards = new HashMap<String, VCard>();
private boolean vcardLoaded;
private File imageFile;
private final VCardEditor editor;
private File vcardStorageDirectory;
final MXParser parser;
private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
private File contactsDir;
private List<VCardListener> listeners = new ArrayList<VCardListener>();
/**
* Initialize VCardManager.
*/
public VCardManager() {
// Initialize parser
parser = new MXParser();
try {
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
}
catch (XmlPullParserException e) {
Log.error(e);
}
imageFile = new File(SparkManager.getUserDirectory(), "personal.png");
// Initialize vCard.
personalVCard = new VCard();
// Set VCard Storage
vcardStorageDirectory = new File(SparkManager.getUserDirectory(), "vcards");
vcardStorageDirectory.mkdirs();
// Set the current user directory.
contactsDir = new File(SparkManager.getUserDirectory(), "contacts");
contactsDir.mkdirs();
initializeUI();
// Intercept all presence packets being sent and append vcard information.
PacketFilter presenceFilter = new PacketTypeFilter(Presence.class);
SparkManager.getConnection().addPacketWriterInterceptor(new PacketInterceptor() {
public void interceptPacket(Packet packet) {
Presence newPresence = (Presence)packet;
VCardUpdateExtension update = new VCardUpdateExtension();
JabberAvatarExtension jax = new JabberAvatarExtension();
PacketExtension updateExt = newPresence.getExtension(update.getElementName(), update.getNamespace());
PacketExtension jabberExt = newPresence.getExtension(jax.getElementName(), jax.getNamespace());
if (updateExt != null) {
newPresence.removeExtension(updateExt);
}
if (jabberExt != null) {
newPresence.removeExtension(jabberExt);
}
if (personalVCard != null) {
byte[] bytes = personalVCard.getAvatar();
if (bytes != null) {
update.setPhotoHash(personalVCard.getAvatarHash());
jax.setPhotoHash(personalVCard.getAvatarHash());
newPresence.addExtension(update);
newPresence.addExtension(jax);
}
}
}
}, presenceFilter);
editor = new VCardEditor();
// Start Listener
startQueueListener();
}
/**
* Listens for new VCards to lookup in a queue.
*/
private void startQueueListener() {
final Runnable queueListener = new Runnable() {
public void run() {
while (true) {
try {
String jid = queue.take();
reloadVCard(jid);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
TaskEngine.getInstance().submit(queueListener);
}
/**
* Adds a jid to lookup vCard.
*
* @param jid the jid to lookup.
*/
public void addToQueue(String jid) {
if (!queue.contains(jid)) {
queue.add(jid);
}
}
/**
* Adds VCard capabilities to menus and other components in Spark.
*/
private void initializeUI() {
boolean enabled = Enterprise.containsFeature(Enterprise.VCARD_FEATURE);
if (!enabled) {
return;
}
// Add Actions Menu
final JMenu contactsMenu = SparkManager.getMainWindow().getMenuByName(Res.getString("menuitem.contacts"));
final JMenu communicatorMenu = SparkManager.getMainWindow().getJMenuBar().getMenu(0);
JMenuItem editProfileMenu = new JMenuItem(SparkRes.getImageIcon(SparkRes.SMALL_BUSINESS_MAN_VIEW));
ResourceUtils.resButton(editProfileMenu, Res.getString("menuitem.edit.my.profile"));
int size = contactsMenu.getMenuComponentCount();
communicatorMenu.insert(editProfileMenu, 1);
editProfileMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SwingWorker vcardLoaderWorker = new SwingWorker() {
public Object construct() {
try {
personalVCard.load(SparkManager.getConnection());
}
catch (XMPPException e) {
Log.error("Error loading vcard information.", e);
}
return true;
}
public void finished() {
editor.editProfile(personalVCard, SparkManager.getWorkspace());
}
};
vcardLoaderWorker.start();
}
});
JMenuItem viewProfileMenu = new JMenuItem("", SparkRes.getImageIcon(SparkRes.FIND_TEXT_IMAGE));
ResourceUtils.resButton(viewProfileMenu, Res.getString("menuitem.lookup.profile"));
contactsMenu.insert(viewProfileMenu, size > 0 ? size - 1 : 0);
viewProfileMenu.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String jidToView = JOptionPane.showInputDialog(SparkManager.getMainWindow(), Res.getString("message.enter.jabber.id") + ":", Res.getString("title.lookup.profile"), JOptionPane.QUESTION_MESSAGE);
if (ModelUtil.hasLength(jidToView) && jidToView.indexOf("@") != -1 && ModelUtil.hasLength(StringUtils.parseServer(jidToView))) {
viewProfile(jidToView, SparkManager.getWorkspace());
}
else if (ModelUtil.hasLength(jidToView)) {
JOptionPane.showMessageDialog(SparkManager.getMainWindow(), Res.getString("message.invalid.jabber.id"), Res.getString("title.error"), JOptionPane.ERROR_MESSAGE);
}
}
});
}
/**
* Displays <code>VCardViewer</code> for a particular JID.
*
* @param jid the jid of the user to display.
* @param parent the parent component to use for displaying dialog.
*/
public void viewProfile(final String jid, final JComponent parent) {
final SwingWorker vcardThread = new SwingWorker() {
VCard vcard = new VCard();
public Object construct() {
vcard = getVCard(jid);
return vcard;
}
public void finished() {
if (vcard.getError() != null || vcard == null) {
// Show vcard not found
JOptionPane.showMessageDialog(parent, Res.getString("message.unable.to.load.profile", jid), Res.getString("title.profile.not.found"), JOptionPane.ERROR_MESSAGE);
}
else {
editor.displayProfile(jid, vcard, parent);
}
}
};
vcardThread.start();
}
/**
* Displays the full profile for a particular JID.
*
* @param jid the jid of the user to display.
* @param parent the parent component to use for displaying dialog.
*/
public void viewFullProfile(final String jid, final JComponent parent) {
final SwingWorker vcardThread = new SwingWorker() {
VCard vcard = new VCard();
public Object construct() {
vcard = getVCard(jid);
return vcard;
}
public void finished() {
if (vcard.getError() != null || vcard == null) {
// Show vcard not found
JOptionPane.showMessageDialog(parent, Res.getString("message.unable.to.load.profile", jid), Res.getString("title.profile.not.found"), JOptionPane.ERROR_MESSAGE);
}
else {
editor.viewFullProfile(vcard, parent);
}
}
};
vcardThread.start();
}
/**
* Returns the VCard for this Spark user. This information will be cached after loading.
*
* @return this users VCard.
*/
public VCard getVCard() {
if (!vcardLoaded) {
try {
personalVCard.load(SparkManager.getConnection());
// If VCard is loaded, then save the avatar to the personal folder.
byte[] bytes = personalVCard.getAvatar();
if (bytes != null) {
ImageIcon icon = new ImageIcon(bytes);
icon = VCardManager.scale(icon);
if (icon != null && icon.getIconWidth() != -1) {
BufferedImage image = GraphicUtils.convert(icon.getImage());
ImageIO.write(image, "PNG", imageFile);
}
}
}
catch (Exception e) {
Log.error(e);
}
vcardLoaded = true;
}
return personalVCard;
}
/**
* Returns the Avatar in the form of an <code>ImageIcon</code>.
*
* @param vcard the vCard containing the avatar.
* @return the ImageIcon or null if no avatar was present.
*/
public static ImageIcon getAvatarIcon(VCard vcard) {
// Set avatar
byte[] bytes = vcard.getAvatar();
if (bytes != null) {
ImageIcon icon = new ImageIcon(bytes);
return GraphicUtils.scaleImageIcon(icon, 40, 40);
}
return null;
}
/**
* Returns the VCard. Will first look in VCard cache and only do a network
* operation if no vcard is found.
*
* @param jid the users jid.
* @return the VCard.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -