package org.chartsy.chatsy.chatimpl.profile;
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.chartsy.chatsy.chat.ChatsyManager;
import org.chartsy.chatsy.chat.ui.ContactItem;
import org.chartsy.chatsy.chat.util.Base64;
import org.chartsy.chatsy.chat.util.GraphicUtils;
import org.chartsy.chatsy.chat.util.ModelUtil;
import org.chartsy.chatsy.chat.util.SwingWorker;
import org.chartsy.chatsy.chat.util.TaskEngine;
import org.chartsy.chatsy.chat.util.log.Log;
import org.chartsy.chatsy.chatimpl.plugin.manager.Enterprise;
import org.chartsy.chatsy.chatimpl.profile.ext.JabberAvatarExtension;
import org.chartsy.chatsy.chatimpl.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.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
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 java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
public class VCardManager
{
private static final Logger LOG = Logger.getLogger(VCardManager.class.getName());
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>();
public VCardManager()
{
parser = new MXParser();
try
{
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
}
catch (XmlPullParserException e)
{
LOG.log(Level.SEVERE, "", e);
}
imageFile = new File(ChatsyManager.getUserDirectory(), "personal.png");
personalVCard = new VCard();
vcardStorageDirectory = new File(ChatsyManager.getUserDirectory(), "vcards");
if (!vcardStorageDirectory.exists())
vcardStorageDirectory.mkdirs();
contactsDir = new File(ChatsyManager.getUserDirectory(), "contacts");
if (!contactsDir.exists())
contactsDir.mkdirs();
initializeUI();
PacketFilter presenceFilter = new PacketTypeFilter(Presence.class);
ChatsyManager.getConnection().addPacketInterceptor(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 && bytes.length > 0)
{
update.setPhotoHash(personalVCard.getAvatarHash());
jax.setPhotoHash(personalVCard.getAvatarHash());
newPresence.addExtension(update);
newPresence.addExtension(jax);
}
}
}
}, presenceFilter);
editor = new VCardEditor();
startQueueListener();
}
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();
break;
}
}
}
};
TaskEngine.getInstance().submit(queueListener);
}
public void addToQueue(String jid)
{
if (!queue.contains(jid))
queue.add(jid);
}
private void initializeUI()
{
boolean enabled = Enterprise.containsFeature(Enterprise.VCARD_FEATURE);
if (!enabled)
return;
}
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)
editor.displayProfile(jid, vcard, parent);
}
};
vcardThread.start();
}
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)
editor.viewFullProfile(vcard, parent);
}
};
vcardThread.start();
}
public VCard getVCard()
{
if (!vcardLoaded)
{
try
{
personalVCard.load(ChatsyManager.getConnection());
byte[] bytes = personalVCard.getAvatar();
if (bytes != null && bytes.length > 0)
{
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;
}
public static ImageIcon getAvatarIcon(VCard vcard)
{
byte[] bytes = vcard.getAvatar();
if (bytes != null && bytes.length > 0)
{
ImageIcon icon = new ImageIcon(bytes);
return GraphicUtils.scaleImageIcon(icon, 40, 40);
}
return null;
}
public VCard getVCard(String jid)
{
return getVCard(jid, true);
}
public VCard getVCardFromMemory(String jid)
{
if (vcards.containsKey(jid))
return vcards.get(jid);
VCard vcard = loadFromFileSystem(jid);
if (vcard == null)
{
addToQueue(jid);
vcard = new VCard();
vcard.setJabberId(jid);
}
return vcard;
}
public VCard getVCard(String jid, boolean useCache)
{
jid = StringUtils.parseBareAddress(jid);
if (!vcards.containsKey(jid) || !useCache)
{
VCard vcard = new VCard();
try
{
VCard localVCard = loadFromFileSystem(jid);
if (localVCard != null)
{
localVCard.setJabberId(jid);
vcards.put(jid, localVCard);
return localVCard;
}
vcard.load(ChatsyManager.getConnection(), jid);
vcard.setJabberId(jid);
if (vcard.getNickName() != null && vcard.getNickName().length() > 0)
{
ContactItem item = ChatsyManager.getWorkspace().getContactList().getContactItemByJID(jid);
if (item != null)
item.setNickname(vcard.getNickName());
}
vcards.put(jid, vcard);
}
catch (XMPPException e)
{
vcard.setJabberId(jid);
vcard.setError(new XMPPError(XMPPError.Condition.conflict));
vcards.put(jid, vcard);
}
}
return vcards.get(jid);
}
public VCard reloadVCard(String jid)
{
jid = StringUtils.parseBareAddress(jid);
VCard vcard = new VCard();
try
{
vcard.load(ChatsyManager.getConnection(), jid);
vcard.setJabberId(jid);
if (vcard.getNickName() != null && vcard.getNickName().length() > 0)
{
ContactItem item = ChatsyManager.getWorkspace().getContactList().getContactItemByJID(jid);
item.setNickname(vcard.getNickName());
}
vcards.put(jid, vcard);
}
catch (XMPPException e)
{
vcard.setError(new XMPPError(XMPPError.Condition.conflict));
vcards.put(jid, vcard);
}
return vcards.get(jid);
}
public void addVCard(String jid, VCard vcard)
{
vcard.setJabberId(jid);
vcards.put(jid, vcard);
}
public static ImageIcon scale(ImageIcon icon)
{
Image avatarImage = icon.getImage();
if (icon.getIconHeight() > 64 || icon.getIconWidth() > 64)
avatarImage = avatarImage.getScaledInstance(-1, 64, Image.SCALE_SMOOTH);
return new ImageIcon(avatarImage);
}
public URL getAvatar(String jid)
{
if (jid != null && StringUtils.parseBareAddress(ChatsyManager.getSessionManager().getJID()).equals(StringUtils.parseBareAddress(jid)))
{
if (imageFile.exists())
{
try
{
return imageFile.toURI().toURL();
}
catch (MalformedURLException e)
{
Log.error(e);
}
}
else
{
return getClass().getResource("/org/chartsy/chatsy/resources/default-avatar-64.png");
}
}
ContactItem item = ChatsyManager.getWorkspace().getContactList().getContactItemByJID(jid);
URL avatarURL = null;
if (item != null)
{
try
{
avatarURL = item.getAvatarURL();
}
catch (MalformedURLException e)
{
Log.error(e);
}
}
if (avatarURL == null)
{
return getClass().getResource("/org/chartsy/chatsy/resources/default-avatar-64.png");
}
return avatarURL;
}
public VCard searchPhoneNumber(String phoneNumber)
{
for (VCard vcard : vcards.values())
{
String homePhone = getNumbersFromPhone(vcard.getPhoneHome("VOICE"));
String workPhone = getNumbersFromPhone(vcard.getPhoneWork("VOICE"));
String cellPhone = getNumbersFromPhone(vcard.getPhoneWork("CELL"));
String query = getNumbersFromPhone(phoneNumber);
if ((homePhone != null && homePhone.contains(query)) ||
(workPhone != null && workPhone.contains(query)) ||
(cellPhone != null && cellPhone.contains(query)))
return vcard;
}
return null;
}
public static String getNumbersFromPhone(String number)
{
if (number == null)
return null;
number = number.replace("-", "");
number = number.replace("(", "");
number = number.replace(")", "");
number = number.replace(" ", "");
if (number.startsWith("1"))
number = number.substring(1);
return number;
}
public void setPersonalVCard(VCard vcard)
{
this.personalVCard = vcard;
}
public URL getAvatarURL(String jid)
{
VCard vcard = getVCard(jid, true);
if (vcard != null)
{
String hash = vcard.getAvatarHash();
if (!ModelUtil.hasLength(hash))
return null;
final File avatarFile = new File(contactsDir, hash);
try
{
return avatarFile.toURI().toURL();
}
catch (MalformedURLException e)
{
Log.error(e);
}
}
return null;
}
private VCard loadFromFileSystem(String jid)
{
String fileName = Base64.encodeBytes(jid.getBytes());
final File vcardFile = new File(vcardStorageDirectory, fileName);
if (!vcardFile.exists())
return null;
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(vcardFile), "UTF-8"));
VCardProvider provider = new VCardProvider();
parser.setInput(in);
VCard vcard = (VCard)provider.parseIQ(parser);
String timestamp = vcard.getField("timestamp");
if (timestamp != null)
{
long time = Long.parseLong(timestamp);
long now = System.currentTimeMillis();
long hour = (1000 * 60) * 60;
if (now - time > hour)
addToQueue(jid);
}
vcard.setJabberId(jid);
vcards.put(jid, vcard);
return vcard;
}
catch (Exception e)
{
Log.warning("Unable to load vCard for " + jid, e);
}
return null;
}
public void addVCardListener(VCardListener listener)
{
listeners.add(listener);
}
public void removeVCardListener(VCardListener listener)
{
listeners.remove(listener);
}
protected void notifyVCardListeners()
{
for (VCardListener listener : listeners)
{
listener.vcardChanged(personalVCard);
}
}
}