Add ContactSource plugin for Thunderbird

cusax-fix
Ingo Bauersachs 13 years ago
parent 7cb8b28211
commit e65b7c8f54

@ -1,91 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/felix.jar">
<attributes>
<attribute name="javadoc_location" value="http://www.osgi.org/javadoc/r4v42/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/jdic-all.jar"/>
<classpathentry kind="lib" path="lib/bundle/junit.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/aclibico-2.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/apache-ant-1.7.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/cglib-nodep.osgi-2.1_3.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/dhcp4java-1.00.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/dict4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/dnsjava.jar">
<attributes>
<attribute name="javadoc_location" value="http://www.dnsjava.org/dnsjava-current/doc/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/installer-exclude/easymock-3.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/fmj.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/forms-1.2.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-client-1.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-client-meta-1.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-contacts-3.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-contacts-meta-3.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-core-1.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/google-collect-1.0-rc1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/hexdump-0.2.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/httpclient-osgi-4.2.3.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/httpcore-osgi-4.2.3.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/ice4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jain-sdp.jar">
<attributes>
<attribute name="javadoc_location" value="https://hudson.jboss.org/jenkins/job/jain-sip/lastStableBuild/artifact/javadoc/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/installer-exclude/jain-sip-api.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jain-sip-ri.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jdic_misc.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jdom.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jfontchooser-1.0.5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jmdns.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jml-1.0b5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jmyspell-core.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jna.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jnsapi.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/joscar-client.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/joscar-common.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/joscar-protocol.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jsch-0.1.36.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jsocks-klea.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/json-simple-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/junit.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/laf-widget.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/lcrypto-jdk16-143.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/libdbus-java-2.7.jar">
<attributes>
<attribute name="javadoc_location" value="http://dbus.freedesktop.org/doc/dbus-java/api/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/installer-exclude/libjitsi.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/log4j-1.2.8.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/mac_widgets-0.9.5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/objenesis-1.2.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/otr4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/pircbot.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/profiler4j-1.0-beta3-SC.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/rome-0.9.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/sdes4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/smack.jar" sourcepath="lib/installer-exclude/smack-src.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/smackx.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/swing-worker-1.2.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jna-platform.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/unix-0.5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/ymsg_network_v0_67.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/zrtp4j-light.jar"/>
<classpathentry kind="lib" path="lib/os-specific/linux/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/os-specific/mac/growl4j.jar"/>
<classpathentry kind="lib" path="lib/os-specific/mac/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/os-specific/mac/OrangeExtensions.jar"/>
<classpathentry kind="lib" path="lib/os-specific/solaris/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/os-specific/windows/jdic_stub.jar"/>
<classpathentry kind="output" path="classes"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/felix.jar">
<attributes>
<attribute name="javadoc_location" value="http://www.osgi.org/javadoc/r4v42/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/jdic-all.jar"/>
<classpathentry kind="lib" path="lib/bundle/junit.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/aclibico-2.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/apache-ant-1.7.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/cglib-nodep.osgi-2.1_3.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/commons-logging-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/dhcp4java-1.00.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/dict4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/dnsjava.jar">
<attributes>
<attribute name="javadoc_location" value="http://www.dnsjava.org/dnsjava-current/doc/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/installer-exclude/easymock-3.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/fmj.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/forms-1.2.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-client-1.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-client-meta-1.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-contacts-3.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-contacts-meta-3.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/gdata-core-1.0.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/google-collect-1.0-rc1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/hexdump-0.2.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/httpclient-osgi-4.2.3.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/httpcore-osgi-4.2.3.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/ice4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jain-sdp.jar">
<attributes>
<attribute name="javadoc_location" value="https://hudson.jboss.org/jenkins/job/jain-sip/lastStableBuild/artifact/javadoc/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/installer-exclude/jain-sip-api.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jain-sip-ri.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jdic_misc.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jdom.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jfontchooser-1.0.5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jmdns.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jml-1.0b5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jmyspell-core.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jna.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jnsapi.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/joscar-client.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/joscar-common.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/joscar-protocol.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jsch-0.1.36.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jsocks-klea.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/json-simple-1.1.1.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/junit.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/laf-widget.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/lcrypto-jdk16-143.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/libdbus-java-2.7.jar">
<attributes>
<attribute name="javadoc_location" value="http://dbus.freedesktop.org/doc/dbus-java/api/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/installer-exclude/libjitsi.jar" sourcepath="/libjitsi"/>
<classpathentry kind="lib" path="lib/installer-exclude/log4j-1.2.8.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/mac_widgets-0.9.5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/objenesis-1.2.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/otr4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/pircbot.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/profiler4j-1.0-beta3-SC.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/rome-0.9.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/sdes4j.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/smack.jar" sourcepath="lib/installer-exclude/smack-src.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/smackx.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/swing-worker-1.2.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jna-platform.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/unix-0.5.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/ymsg_network_v0_67.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/zrtp4j-light.jar"/>
<classpathentry kind="lib" path="lib/os-specific/linux/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/os-specific/mac/growl4j.jar"/>
<classpathentry kind="lib" path="lib/os-specific/mac/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/os-specific/mac/OrangeExtensions.jar"/>
<classpathentry kind="lib" path="lib/os-specific/solaris/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/os-specific/windows/jdic_stub.jar"/>
<classpathentry kind="lib" path="lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar" sourcepath="/jmork"/>
<classpathentry kind="output" path="classes"/>
</classpath>

@ -946,6 +946,7 @@
bundle-plugin-loggingutils,
bundle-provdisc,bundle-provdisc-dhcp,bundle-provdisc-mdns,
bundle-provisioning,bundle-addrbook,bundle-plugin-ldap,
bundle-thunderbird,
bundle-plugin-contactsourceconfig,bundle-plugin-certconfig,
bundle-globalshortcut,bundle-plugin-msofficecomm,bundle-libjitsi,
bundle-customcontactactions, bundle-phonenumbercontactsource,
@ -2641,6 +2642,17 @@ javax.swing.event, javax.swing.border"/>
</jar>
</target>
<!-- BUNDLE-PLUGIN-THUNDERBIRD -->
<target name="bundle-thunderbird">
<!-- Creates a bundle which provides support for the thunderbird Address Book. -->
<jar compress="false" destfile="${bundles.dest}/thunderbook.jar"
manifest="${src}/net/java/sip/communicator/plugin/thunderbird/thunderbird.manifest.mf">
<zipfileset dir="${dest}/net/java/sip/communicator/plugin/thunderbird"
prefix="net/java/sip/communicator/plugin/thunderbird" />
</jar>
<copy file="${lib.noinst}/jmork-1.0.5-SNAPSHOT.jar" tofile="${bundles.dest}/jmork.jar"/>
</target>
<target name="bundle-certificate">
<jar compress="false" destfile="${bundles.dest}/certificate.jar"
manifest="${src}/net/java/sip/communicator/impl/certificate/certificate.manifest.mf">

@ -129,7 +129,8 @@ felix.auto.start.66= \
reference:file:sc-bundles/swingnotification.jar \
reference:file:sc-bundles/osdependent.jar \
reference:file:sc-bundles/ldap.jar \
reference:file:sc-bundles/replacement.jar
reference:file:sc-bundles/replacement.jar \
reference:file:sc-bundles/jmork.jar
felix.auto.start.67= \
reference:file:sc-bundles/globalshortcut.jar \
@ -170,6 +171,7 @@ felix.auto.start.67= \
reference:file:sc-bundles/plugin-nimbuzzavatars.jar \
reference:file:sc-bundles/chatconfig.jar \
reference:file:sc-bundles/addrbook.jar \
reference:file:sc-bundles/thunderbook.jar \
reference:file:sc-bundles/plugin-msofficecomm.jar \
reference:file:sc-bundles/plugin-ldap.jar \
reference:file:sc-bundles/plugin-contactsourceconfig.jar \

@ -1687,3 +1687,8 @@ plugin.certconfig.REVOCATION_OCSP_ENABLED=OCSP (Online Certificate Status Protoc
# Phone number contact source plugin
plugin.phonenumbercontactsource.DISPLAY_NAME=Phone numbers
#Thunderbird address book plugin
plugin.thunderbird.CONFIG_FORM_TITLE=Thunderbird
plugin.thunderbird.ENABLED=Enabled
plugin.thunderbird.PHONE_PREFIX=Phone prefix:

@ -160,7 +160,7 @@ private void addConfigForm(ConfigurationForm form)
{
int cIndex = form.getIndex();
if (cIndex >= contactSourceComboBox.getItemCount())
if (cIndex >= contactSourceComboBox.getItemCount() || cIndex == -1)
contactSourceComboBox.addItem(form);
else
contactSourceComboBox.insertItemAt(form, cIndex);

@ -0,0 +1,149 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.thunderbird;
import java.util.*;
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.util.*;
import org.jitsi.service.configuration.*;
import org.jitsi.service.resources.*;
import org.osgi.framework.*;
/**
* Bundle-Activator for the Thunderbird address book contact source plug-in.
*
* @author Ingo Bauersachs
*/
public class ThunderbirdActivator
implements BundleActivator
{
/** OSGi context. */
private static BundleContext bundleContext;
/** Active address book registrations. */
private static Map<ThunderbirdContactSourceService, ServiceRegistration>
registrations;
/**
* Gets the configuration service.
* @return the configuration service.
*/
static ConfigurationService getConfigService()
{
return ServiceUtils.getService(bundleContext,
ConfigurationService.class);
}
/**
* Gets the resource service.
* @return the resource service.
*/
static ResourceManagementService getResources()
{
return ServiceUtils.getService(bundleContext,
ResourceManagementService.class);
}
/**
* Gets all registered Thunderbird address book services.
* @return all registered Thunderbird address book services.
*/
static List<ThunderbirdContactSourceService> getActiveServices()
{
return new LinkedList<ThunderbirdContactSourceService>(
registrations.keySet());
}
/**
* Loads and registers an address book service.
* @param config the name of the base property of the service to load.
*/
static void add(String config)
{
ThunderbirdContactSourceService service
= new ThunderbirdContactSourceService(config);
registrations.put(service,
bundleContext.registerService(
ContactSourceService.class.getName(), service, null));
}
/**
* Stops an address book service and deletes the corresponding configuration
* data.
*
* @param service the address book instance to remove.
*/
static void remove(ThunderbirdContactSourceService service)
{
registrations.get(service).unregister();
registrations.remove(service);
ConfigurationService config = getConfigService();
for (String prop : config.getPropertyNamesByPrefix(
service.getBaseConfigProperty(), false))
{
config.removeProperty(prop);
}
}
/**
* Searches the configuration for Thunderbird address books and registers a
* {@link ContactSourceService} for each found config.
*/
public void start(BundleContext bundleContext) throws Exception
{
ThunderbirdActivator.bundleContext = bundleContext;
ConfigurationService config = getConfigService();
List<String> configs =
config.getPropertyNamesByPrefix(
ThunderbirdContactSourceService.PNAME_BASE_THUNDERBIRD_CONFIG,
false);
registrations = new HashMap
<ThunderbirdContactSourceService, ServiceRegistration>();
for (String cfg : configs)
{
if (cfg.endsWith(config.getString(cfg)))
{
add(cfg);
}
}
/* registers the configuration form */
Dictionary<String, String> properties
= new Hashtable<String, String>();
properties.put(
ConfigurationForm.FORM_TYPE,
ConfigurationForm.CONTACT_SOURCE_TYPE);
bundleContext.registerService(
ConfigurationForm.class.getName(),
new LazyConfigurationForm(
ThunderbirdConfigForm.class.getName(),
getClass().getClassLoader(),
null,
"plugin.thunderbird.CONFIG_FORM_TITLE"),
properties);
}
/**
* Unregisters all {@link ContactSourceService}s that were registered by
* this activator.
*/
public void stop(BundleContext bundleContext) throws Exception
{
for (ServiceRegistration sr : registrations.values())
{
sr.unregister();
}
registrations = null;
}
}

@ -0,0 +1,338 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.thunderbird;
import static net.java.sip.communicator.plugin.thunderbird
.ThunderbirdContactSourceService.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
import org.jitsi.service.configuration.*;
import org.jitsi.service.resources.*;
import org.jitsi.util.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.plugin.desktoputil.*;
/**
* This ConfigurationForm shows the list of Thunderbird address books
* and allow users to manage them.
*
* @author Ingo Bauersachs
*/
public class ThunderbirdConfigForm
extends TransparentPanel
implements ConfigurationForm,
ActionListener,
DocumentListener
{
/** Serial version UID. */
private static final long serialVersionUID = 0L;
/** Resource service */
private ResourceManagementService R = ThunderbirdActivator.getResources();
private JTextField txtFilename;
private JTextField txtPrefix;
private JButton cmdBrowse;
private JCheckBox chkEnabled;
/**
* Creates a new instance of this class.
*/
public ThunderbirdConfigForm()
{
super(new BorderLayout());
this.initComponents();
}
/**
* Inits the swing components
*/
private void initComponents()
{
JPanel pnl = new TransparentPanel();
pnl.setLayout(new GridLayout(0, 2));
add(pnl, BorderLayout.NORTH);
chkEnabled = new SIPCommCheckBox(
R.getI18NString("plugin.thunderbird.ENABLED"));
pnl.add(chkEnabled);
pnl.add(new JLabel("")); //empty to wrap the grid to the next line
txtFilename = new JTextField();
txtFilename.setEditable(false);
pnl.add(txtFilename);
cmdBrowse = new JButton(R.getI18NString("service.gui.BROWSE") + "...");
pnl.add(cmdBrowse);
JLabel lblPrefix = new JLabel(
R.getI18NString("plugin.thunderbird.PHONE_PREFIX"));
pnl.add(lblPrefix);
txtPrefix = new JTextField();
pnl.add(txtPrefix);
List<ThunderbirdContactSourceService> activeServices
= ThunderbirdActivator.getActiveServices();
if (activeServices.size() > 0)
{
chkEnabled.setSelected(true);
ThunderbirdContactSourceService service = activeServices.get(0);
txtFilename.setText(service.getFilename());
txtPrefix.setText(service.getPhoneNumberPrefix());
}
else
{
chkEnabled.setSelected(false);
}
updateStates();
chkEnabled.addActionListener(this);
txtFilename.getDocument().addDocumentListener(this);
cmdBrowse.addActionListener(this);
}
/**
* @see net.java.sip.communicator.service.gui.ConfigurationForm#getTitle
*/
public String getTitle()
{
return R.getI18NString("plugin.thunderbird.CONFIG_FORM_TITLE");
}
/**
* @see net.java.sip.communicator.service.gui.ConfigurationForm#getIcon
*/
public byte[] getIcon()
{
return null;
}
/**
* @see net.java.sip.communicator.service.gui.ConfigurationForm#getForm
*/
public Object getForm()
{
return this;
}
/**
* Required by ConfirgurationForm interface
*
* Returns the index of this configuration form in the configuration window.
* This index is used to put configuration forms in the desired order.
* <p>
* 0 is the first position
* -1 means that the form will be put at the end
* </p>
* @return the index of this configuration form in the configuration window.
*
* @see net.java.sip.communicator.service.gui.ConfigurationForm#getIndex
*/
public int getIndex()
{
return 3;
}
/**
* Processes buttons events (new, modify, remove)
*
* @see java.awt.event.ActionListener#actionPerformed
*/
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == cmdBrowse)
{
browseForMab();
ThunderbirdActivator.getActiveServices().get(0)
.setFilename(txtFilename.getText());
}
else if (e.getSource() == chkEnabled)
{
if (chkEnabled.isSelected())
{
browseForMab();
if (txtFilename.getText() != null)
{
String bprop = PNAME_BASE_THUNDERBIRD_CONFIG + ".1";
ConfigurationService config
= ThunderbirdActivator.getConfigService();
config.setProperty(bprop, "1");
config.setProperty(bprop + "." + PNAME_INDEX, 1);
config.setProperty(bprop + "." + PNAME_FILENAME,
txtFilename.getText());
config.setProperty(bprop + "." + PNAME_DISPLAYNAME,
"Thunderbird");
config.setProperty(bprop + "." + PNAME_PREFIX,
txtPrefix.getText());
ThunderbirdActivator.add(bprop);
}
}
else
{
for (ThunderbirdContactSourceService svc
: ThunderbirdActivator.getActiveServices())
{
ThunderbirdActivator.remove(svc);
}
txtFilename.setText(null);
txtPrefix.setText(null);
}
updateStates();
}
}
/**
* Opens a file browser dialog to select a Thunderbird .mab file. If the
* user has chosen an existing file, the name is set to the filename
* textbox.
*/
private void browseForMab()
{
FilenameFilter ff = new FilenameFilter()
{
public boolean accept(File dir, String name)
{
String extension = "";
int i = name.lastIndexOf('.');
if (i > 0)
{
extension = name.substring(i + 1);
}
return "mab".equals(extension);
}
};
FileDialog fd = new FileDialog((Frame)null);
fd.setFilenameFilter(ff);
fd.setMultipleMode(false);
if (OSUtils.IS_WINDOWS)
{
File f = new File(
new File(
System.getenv("APPDATA"), "Thunderbird"),
"Profiles");
if (f.exists())
{
fd.setDirectory(f.getAbsolutePath());
}
}
else if (OSUtils.IS_LINUX)
{
File f = new File(
System.getProperty("user.home"),
".thunderbird");
if (!f.exists())
{
f = new File(
System.getProperty("user.home"),
".mozilla-thunderbird");
}
if (f.exists())
{
fd.setDirectory(f.getAbsolutePath());
}
}
else if (OSUtils.IS_MAC)
{
File f = new File(
System.getProperty("user.home"),
"/Library/Profiles");
if (!f.exists())
{
f = new File(
System.getProperty("user.home"),
"Application Support/Thunderbird/Profiles");
}
if (f.exists())
{
fd.setDirectory(f.getAbsolutePath());
}
}
fd.setVisible(true);
if (fd.getFile() != null)
{
File f = new File(fd.getDirectory(), fd.getFile());
if (f.exists())
{
txtFilename.setText(f.getAbsolutePath());
}
}
}
/**
* Enables or disables the controls enabled state based on the enabled
* checkbox.
*/
private void updateStates()
{
txtFilename.setEnabled(chkEnabled.isSelected());
txtPrefix.setEnabled(chkEnabled.isSelected());
cmdBrowse.setEnabled(chkEnabled.isSelected());
}
/**
* Indicates if this is an advanced configuration form.
* @return <tt>true</tt> if this is an advanced configuration form,
* otherwise it returns <tt>false</tt>
*/
public boolean isAdvanced()
{
return true;
}
/*
* (non-Javadoc)
*
* @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.
* DocumentEvent)
*/
public void insertUpdate(DocumentEvent e)
{}
/*
* (non-Javadoc)
*
* @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.
* DocumentEvent)
*/
public void removeUpdate(DocumentEvent e)
{}
/*
* (non-Javadoc)
*
* @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.
* DocumentEvent)
*/
public void changedUpdate(DocumentEvent e)
{
if (e.getDocument() == txtPrefix.getDocument())
{
ThunderbirdActivator.getActiveServices().get(0)
.setPhoneNumberPrefix(txtPrefix.getText());
}
}
}

@ -0,0 +1,260 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.thunderbird;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.*;
import org.jitsi.util.StringUtils;
import mork.*;
import net.java.sip.communicator.service.contactsource.*;
import net.java.sip.communicator.service.contactsource.ContactDetail.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
* Queries a Thunderbird address book for contacts matching the given pattern.
*
* @author Ingo Bauersachs
*/
public class ThunderbirdContactQuery
extends AsyncContactQuery<ThunderbirdContactSourceService>
{
/** Class logger */
private final static Logger logger = Logger
.getLogger(ThunderbirdContactQuery.class);
/**
* Creates a new instance of this class.
*
* @param owner The contact source that created this query.
* @param query The pattern to match against the contacts database.
*/
public ThunderbirdContactQuery(ThunderbirdContactSourceService owner,
Pattern query)
{
super(owner, query);
start();
}
/**
* Starts the query against the address book database.
*/
@Override
protected void run()
{
String file = super.getContactSource().getFilename();
try
{
// parse the Thunderbird Mork database
InputStreamReader sr =
new InputStreamReader(new FileInputStream(file));
MorkDocument md = new MorkDocument(sr);
sr.close();
// We now have rows in their tables and additional rows at
// transaction level. Put the to a better format:
// DB -> Tables -> Rows
Map<String, Map<String, Row>> db =
new HashMap<String, Map<String, Row>>();
for (Table t : md.getTables())
{
String tableId = t.getTableId() + "/" + t.getScopeName();
Map<String, Row> table = db.get(tableId);
if (table == null)
{
table = new HashMap<String, Row>();
db.put(tableId, table);
}
for (Row r : t.getRows())
{
String scope = r.getScopeName();
if (scope == null)
{
scope = t.getScopeName();
}
table.put(r.getRowId() + "/" + scope, r);
}
}
// The additional rows at the root-level update/replace the ones in
// the tables. There's usually neither a table nor a scope defined,
// so lets just use the default.
String defaultScope = md.getDicts().get(0).dereference("^80");
for (Row r : md.getRows())
{
String scope = r.getScopeName();
if (scope == null)
{
scope = defaultScope;
}
String tableId = "1/" + scope;
Map<String, Row> table = db.get(tableId);
if (table == null)
{
table = new HashMap<String, Row>();
db.put(tableId, table);
}
String rowId = r.getRowId() + "/" + scope;
if (rowId.startsWith("-"))
{
rowId = rowId.substring(1);
}
table.put(rowId, r);
}
// okay, "transactions" are applied, now perform the search
for (Entry<String, Map<String, Row>> table : db.entrySet())
{
for (Map.Entry<String, Row> e : table.getValue().entrySet())
{
if (e.getKey().endsWith(defaultScope))
{
readEntry(e.getValue());
}
}
}
super.stopped(true);
}
catch (FileNotFoundException e)
{
logger.warn("Could not open address book", e);
}
catch (Exception e)
{
logger.warn("Could not parse " + file, e);
}
}
/**
* Processes a database row by matching it against the query and adding it
* to the result set if it matched.
*
* @param r The database row representing a contact.
*/
private void readEntry(Row r)
{
// match the pattern against this contact
boolean hadMatch = false;
for (Alias value : r.getAliases().values())
{
if (value != null
&& (super.query.matcher(value.getValue()).find() || super
.phoneNumberMatches(value.getValue())))
{
hadMatch = true;
break;
}
}
// nope, didn't match, ignore
if (!hadMatch)
{
return;
}
List<ContactDetail> details = new LinkedList<ContactDetail>();
// e-mail(s)
for (String email : getPropertySet(r, "PrimaryEmail", "SecondEmail",
"DefaultEmail"))
{
ContactDetail detail = new ContactDetail(email, Category.Email);
detail.addSupportedOpSet(OperationSetPersistentPresence.class);
details.add(detail);
}
// phone number(s)
this.addPhoneDetail(details, r, "HomePhone", SubCategory.Home);
this.addPhoneDetail(details, r, "WorkPhone", SubCategory.Work);
this.addPhoneDetail(details, r, "CellularNumber", SubCategory.Mobile);
// and the dispaly name
String displayName = r.getValue("DisplayName");
if (StringUtils.isNullOrEmpty(displayName, true))
{
displayName = r.getValue("LastName");
if (displayName != null)
{
displayName = displayName.trim();
}
String firstName = r.getValue("FirstName");
if (!StringUtils.isNullOrEmpty(firstName, true))
{
displayName = firstName + " " + displayName;
}
}
// create the contact and add it to the results
GenericSourceContact sc =
new GenericSourceContact(super.getContactSource(), displayName,
details);
addQueryResult(sc);
}
/**
* Adds a "Phone" {@link ContactDetail} to a query contact.
*
* @param details The {@link List} of {@link ContactDetail}s to which the
* details is added.
* @param r The source database row of the contact.
* @param property The source database property name to add as a detail.
* @param category The Phone-{@link SubCategory} for the phone number to
* add.
*/
private void addPhoneDetail(List<ContactDetail> details, Row r,
String property, SubCategory category)
{
String phone = r.getValue(property);
if (StringUtils.isNullOrEmpty(phone, true))
{
return;
}
phone = PhoneNumberI18nService.normalize(phone);
ContactDetail detail =
new ContactDetail(phone, ContactDetail.Category.Phone,
new ContactDetail.SubCategory[]
{ category });
detail.addSupportedOpSet(OperationSetBasicTelephony.class);
detail.addSupportedOpSet(OperationSetPersistentPresence.class);
details.add(detail);
}
/**
* Gets a set of non-empty properties from the source database row.
*
* @param r The source database row to process.
* @param properties The property-names to extract.
* @return A set of non-empty properties from the source database row.
*/
private Set<String> getPropertySet(Row r, String... properties)
{
Set<String> validValues = new HashSet<String>(properties.length);
for (String prop : properties)
{
String value = r.getValue(prop);
if (!StringUtils.isNullOrEmpty(value, true))
{
validValues.add(value);
}
}
return validValues;
}
}

@ -0,0 +1,216 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.thunderbird;
import java.util.regex.*;
import org.jitsi.service.configuration.*;
import net.java.sip.communicator.service.contactsource.*;
/**
* Query creator for an instance of a Thunderbird address book.
*
* @author Ingo Bauersachs
*/
public class ThunderbirdContactSourceService
implements ExtendedContactSourceService
{
/**
* Name of the base-property for a Thunderbird address book configuration.
*/
public final static String PNAME_BASE_THUNDERBIRD_CONFIG =
"net.java.sip.communicator.plugin.thunderbird.source";
/**
* Property-name, appended to
* {@link ThunderbirdContactSourceService#PNAME_BASE_THUNDERBIRD_CONFIG} ,
* that indicates the address-book database filename.
*/
public final static String PNAME_FILENAME = "FILENAME";
/**
* Property-name, appended to
* {@link ThunderbirdContactSourceService#PNAME_BASE_THUNDERBIRD_CONFIG} ,
* that indicates the display-name shown as the contact group.
*/
public final static String PNAME_DISPLAYNAME = "DISPLAYNAME";
/**
* Property-name, appended to
* {@link ThunderbirdContactSourceService#PNAME_BASE_THUNDERBIRD_CONFIG} ,
* that indicates the priority in the search results.
*/
public final static String PNAME_INDEX = "INDEX";
/**
* Property-name, appended to
* {@link ThunderbirdContactSourceService#PNAME_BASE_THUNDERBIRD_CONFIG} ,
* that indicates the telephone-number prefix.
*/
public final static String PNAME_PREFIX = "PREFIX";
/** Reference to the configuration service */
ConfigurationService config = ThunderbirdActivator.getConfigService();
/** The base property name to which the other PNAME_ will be appended */
private final String baseConfigProperty;
/** Value of property {@link #PNAME_FILENAME} */
private String fileName;
/** Value of property {@link #PNAME_DISPLAYNAME} */
private final String displayName;
/** Value of property {@link #PNAME_INDEX} */
private final int index;
/** Value of property {@link #PNAME_PREFIX} */
private String prefix;
/**
* Creates a new instance of this class.
*
* @param baseConfigProperty The base property name of the config for this
* instance
*/
public ThunderbirdContactSourceService(String baseConfigProperty)
{
this.baseConfigProperty = baseConfigProperty;
this.fileName =
config.getString(baseConfigProperty + "." + PNAME_FILENAME);
this.displayName =
config.getString(baseConfigProperty + "." + PNAME_DISPLAYNAME);
this.index = config.getInt(baseConfigProperty + "." + PNAME_INDEX, 0);
this.prefix = config.getString(baseConfigProperty + "." + PNAME_PREFIX);
}
/**
* Gets the base property name to which the other PNAME_ will be appended.
* @return the base property name.
*/
String getBaseConfigProperty()
{
return this.baseConfigProperty;
}
/*
* (non-Javadoc)
*
* @see net.java.sip.communicator.service.contactsource
* .ContactSourceService#getType()
*/
public int getType()
{
return DEFAULT_TYPE;
}
/*
* (non-Javadoc)
*
* @see net.java.sip.communicator.service.contactsource
* .ContactSourceService#getDisplayName()
*/
public String getDisplayName()
{
return this.displayName;
}
/*
* (non-Javadoc)
*
* @see net.java.sip.communicator.service.contactsource
* .ContactSourceService#queryContactSource(java.lang.String)
*/
public ContactQuery queryContactSource(String queryString)
{
return new ThunderbirdContactQuery(this, Pattern.compile(queryString,
Pattern.CASE_INSENSITIVE));
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.contactsource.ContactSourceService#
* queryContactSource(java.lang.String, int)
*/
public ContactQuery queryContactSource(String queryString, int contactCount)
{
return new ThunderbirdContactQuery(this, Pattern.compile(queryString,
Pattern.CASE_INSENSITIVE));
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.contactsource.ExtendedContactSourceService
* #queryContactSource(java.util.regex.Pattern)
*/
public ContactQuery queryContactSource(Pattern queryPattern)
{
return new ThunderbirdContactQuery(this, queryPattern);
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.contactsource.ContactSourceService#
* getIndex()
*/
public int getIndex()
{
return this.index;
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.contactsource.ExtendedContactSourceService
* #getPhoneNumberPrefix()
*/
public String getPhoneNumberPrefix()
{
return this.prefix;
}
/**
* Sets a new phone number prefix to use from now on.
* @param prefix the new prefix.
*/
void setPhoneNumberPrefix(String prefix)
{
this.prefix = prefix;
config.setProperty(this.baseConfigProperty + "." + PNAME_PREFIX,
prefix);
}
/**
* Gets the filename to the address book database processed by this
* ContactSource.
*
* @return The filename to the address book database.
*/
String getFilename()
{
return this.fileName;
}
/**
* Sets a new database file name to use from now on.
* @param filename the new file name.
*/
void setFilename(String filename)
{
this.fileName = filename;
config.setProperty(this.baseConfigProperty + "." + PNAME_FILENAME,
filename);
}
}

@ -0,0 +1,20 @@
Bundle-Activator: net.java.sip.communicator.plugin.thunderbird.ThunderbirdActivator
Bundle-Description: Thunderbird address source
Bundle-Name: thunderbird
Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1
Import-Package: javax.swing,
javax.swing.event,
javax.swing.text,
org.jitsi.service.configuration,
org.jitsi.util,
net.java.sip.communicator.service.contactsource,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.service.protocol,
org.jitsi.service.resources,
net.java.sip.communicator.service.resources,
net.java.sip.communicator.util,
net.java.sip.communicator.plugin.desktoputil,
org.osgi.framework,
mork
System-Bundle: no
Loading…
Cancel
Save