aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl
diff options
context:
space:
mode:
authorSebastien Vincent <seb@jitsi.org>2011-03-09 09:30:54 +0000
committerSebastien Vincent <seb@jitsi.org>2011-03-09 09:30:54 +0000
commit5393fc96a763bcf0ecedf95275edc7712f2b897f (patch)
tree9dab2f9963a2aca12b6038ada01165a655141057 /src/net/java/sip/communicator/impl
parentdcb607dd8b10f297af6a590e29a7b9b6f6002aff (diff)
downloadjitsi-5393fc96a763bcf0ecedf95275edc7712f2b897f.zip
jitsi-5393fc96a763bcf0ecedf95275edc7712f2b897f.tar.gz
jitsi-5393fc96a763bcf0ecedf95275edc7712f2b897f.tar.bz2
Ongoing work on LDAP contact source support.
Diffstat (limited to 'src/net/java/sip/communicator/impl')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/MainFrame.java5
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java5
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java11
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapActivator.java101
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapDirectoryImpl.java1117
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapDirectorySetImpl.java285
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapDirectorySettingsImpl.java600
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapFactoryImpl.java79
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapPendingSearch.java66
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java383
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapQueryImpl.java77
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapSearchSettingsImpl.java88
-rw-r--r--src/net/java/sip/communicator/impl/ldap/LdapServiceImpl.java174
-rw-r--r--src/net/java/sip/communicator/impl/ldap/configform/DirectorySettingsForm.java613
-rw-r--r--src/net/java/sip/communicator/impl/ldap/configform/LdapConfigForm.java298
-rw-r--r--src/net/java/sip/communicator/impl/ldap/configform/LdapTableModel.java169
-rw-r--r--src/net/java/sip/communicator/impl/ldap/configform/Resources.java55
-rw-r--r--src/net/java/sip/communicator/impl/ldap/ldap.manifest.mf27
-rw-r--r--src/net/java/sip/communicator/impl/ldap/ldap.metadata.xml7
19 files changed, 4160 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
index 14311cb..ab55b26 100644
--- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
+++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
@@ -59,6 +59,11 @@ public class MainFrame
Skinnable
{
/**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
* The logger.
*/
private final Logger logger = Logger.getLogger(MainFrame.class);
diff --git a/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java b/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java
index 31b2aaa..e2f25f5 100644
--- a/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java
+++ b/src/net/java/sip/communicator/impl/gui/main/configforms/ConfigurationFrame.java
@@ -33,6 +33,11 @@ public class ConfigurationFrame
ServiceListener
{
/**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
* The <tt>Logger</tt> used by the <tt>ConfigurationFrame</tt> class and its
* instances for logging output.
*/
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
index f8762be..a6ed336 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
@@ -47,6 +47,11 @@ public class TreeContactList
TreeExpansionListener
{
/**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
* The logger.
*/
private static final Logger logger
@@ -1583,6 +1588,8 @@ public class TreeContactList
amap.put("main-rename", new RenameAction());
amap.put("enter", new AbstractAction()
{
+ private static final long serialVersionUID = 0L;
+
public void actionPerformed(ActionEvent e)
{
startSelectedContactChat();
@@ -1591,6 +1598,8 @@ public class TreeContactList
amap.put("openGroup", new AbstractAction()
{
+ private static final long serialVersionUID = 0L;
+
public void actionPerformed(ActionEvent e)
{
TreePath selectionPath = getSelectionPath();
@@ -1608,6 +1617,8 @@ public class TreeContactList
amap.put("closeGroup", new AbstractAction()
{
+ private static final long serialVersionUID = 0L;
+
public void actionPerformed(ActionEvent e)
{
TreePath selectionPath = getSelectionPath();
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapActivator.java b/src/net/java/sip/communicator/impl/ldap/LdapActivator.java
new file mode 100644
index 0000000..0f3e4a1
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapActivator.java
@@ -0,0 +1,101 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import java.util.*;
+
+import org.osgi.framework.*;
+
+import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.service.gui.*;
+
+/**
+ * Activates the LdapService
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapActivator
+ implements BundleActivator
+{
+ /**
+ * the logger for this class
+ */
+ private static Logger logger =
+ Logger.getLogger(LdapActivator.class);
+
+ /**
+ * instance of the service
+ */
+ private static LdapServiceImpl ldapService = null;
+
+ /**
+ * Get LDAP service.
+ *
+ * @return LDAP service
+ */
+ public static LdapService getLdapService()
+ {
+ return ldapService;
+ }
+
+ /**
+ * Starts the LDAP service
+ *
+ * @param bundleContext BundleContext
+ * @throws Exception
+ */
+ public void start(BundleContext bundleContext)
+ throws Exception
+ {
+ try
+ {
+ logger.logEntry();
+
+ /* Creates and starts the LDAP service. */
+ ldapService =
+ new LdapServiceImpl();
+
+ ldapService.start(bundleContext);
+
+ bundleContext.registerService(
+ LdapService.class.getName(), ldapService, null);
+
+ /* registers the configuration form */
+ Dictionary<String, String> properties =
+ new Hashtable<String, String>();
+ properties.put( ConfigurationForm.FORM_TYPE,
+ ConfigurationForm.ADVANCED_TYPE);
+
+ bundleContext.registerService(
+ ConfigurationForm.class.getName(),
+ new LazyConfigurationForm(
+ "net.java.sip.communicator.impl.ldap.configform.LdapConfigForm",
+ getClass().getClassLoader(),
+ "impl.ldap.PLUGIN_ICON",
+ "impl.ldap.CONFIG_FORM_TITLE",
+ 2000, true),
+ properties);
+
+ logger.trace("LDAP Service ...[REGISTERED]");
+ }
+ finally
+ {
+ logger.logExit();
+ }
+ }
+
+ /**
+ * Stops the LDAP service
+ */
+ public void stop(BundleContext bundleContext)
+ throws Exception
+ {
+ if(ldapService != null)
+ ldapService.stop(bundleContext);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapDirectoryImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapDirectoryImpl.java
new file mode 100644
index 0000000..74f27b4
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapDirectoryImpl.java
@@ -0,0 +1,1117 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+
+import net.java.sip.communicator.util.*;
+
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.service.ldap.event.*;
+
+/**
+ * An LdapDirectory stores settings for one directory server
+ * and performs ldap operations (search)
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapDirectoryImpl
+ extends DefaultLdapEventManager
+ implements LdapDirectory,
+ LdapListener,
+ LdapConstants
+{
+ /**
+ * the logger for this class
+ */
+ private final static Logger logger = Logger
+ .getLogger(LdapDirectoryImpl.class);
+
+ static
+ {
+ logger.setLevelTrace();
+ }
+
+ /**
+ * The settings for this directory
+ */
+ private LdapDirectorySettings settings;
+
+ /**
+ * Stores the pending searches
+ *
+ * @see LdapPendingSearch
+ */
+ private HashMap<LdapQuery, LdapPendingSearch> pendingSearches =
+ new HashMap<LdapQuery, LdapPendingSearch>();
+
+ /**
+ * Name of avatar attribute.
+ */
+ private final String PHOTO_ATTRIBUTE = "jpegPhoto";
+
+ /**
+ * data structure used to store the LDAP attributes that
+ * could contain our search string
+ * e.g. cn, sn, givenname, uid
+ */
+ private static final Set<String> searchableAttributes
+ = new HashSet<String>();
+
+ static
+ {
+ searchableAttributes.add("displayName");
+ searchableAttributes.add("cn");
+ searchableAttributes.add("commonname");
+ searchableAttributes.add("sn");
+ searchableAttributes.add("surname");
+ searchableAttributes.add("gn");
+ searchableAttributes.add("givenname");
+ searchableAttributes.add("uid");
+ }
+
+ /**
+ * data structure used to store the attribute whose values
+ * could be a contact address for the person found
+ * e.g. mail, telephoneNumber
+ */
+ private static final Set<String> retrievableAttributes
+ = new HashSet<String>();
+
+ static
+ {
+ retrievableAttributes.add("displayName");
+ retrievableAttributes.add("cn");
+ retrievableAttributes.add("commonname");
+ retrievableAttributes.add("sn");
+ retrievableAttributes.add("surname");
+ retrievableAttributes.add("givenName");
+ retrievableAttributes.add("givenname");
+ retrievableAttributes.add("gn");
+ retrievableAttributes.add("o");
+ retrievableAttributes.add("organizationName");
+ retrievableAttributes.add("company");
+ retrievableAttributes.add("ou");
+ retrievableAttributes.add("orgunit");
+ retrievableAttributes.add("organizationalUnitName");
+ retrievableAttributes.add("department");
+ retrievableAttributes.add("departmentNumber");
+ retrievableAttributes.add("mail");
+ retrievableAttributes.add("telephoneNumber");
+ retrievableAttributes.add("primaryPhone");
+ retrievableAttributes.add("otherTelephone");
+ retrievableAttributes.add("companyPhone");
+ retrievableAttributes.add("tel");
+ retrievableAttributes.add("mobile");
+ retrievableAttributes.add("mobileTelephoneNumber");
+ retrievableAttributes.add("cellphone");
+ retrievableAttributes.add("otherMobile");
+ retrievableAttributes.add("carPhone");
+ retrievableAttributes.add("homePhone");
+ retrievableAttributes.add("otherHomePhone");
+ }
+
+ /**
+ * the env HashTable stores the settings used to create
+ * an InitialDirContext (i.e. connect to the LDAP directory)
+ */
+ private final Hashtable<String, String> env =
+ new Hashtable<String, String>();
+
+ /**
+ * The contructor for this class.
+ * Since this element is immutable (otherwise it would be a real pain
+ * to use with a Set), it takes all the settings we could need to store
+ * This constructor will not modify the <tt>settings</tt>
+ * or save a reference to it, but may save a clone.
+ *
+ * @param settings settings for this new server
+ *
+ * @see LdapDirectorySettings
+ */
+ public LdapDirectoryImpl(LdapDirectorySettings settings)
+ {
+ String portText;
+
+ /* settings checks */
+ if(!textHasContent(settings.getName()))
+ throw new IllegalArgumentException("name has no content.");
+ if(!textHasContent(settings.getHostname()))
+ throw new IllegalArgumentException("Hostname has no content.");
+ if(settings.getAuth() != Auth.NONE && !textHasContent(
+ settings.getBindDN()))
+ throw new IllegalArgumentException("Bind DN has no content.");
+ if(settings.getAuth() != Auth.NONE && settings.getPassword() == null)
+ throw new IllegalArgumentException("password is null.");
+ if(settings.getPort() < 0 || settings.getPort() > 65535)
+ throw new IllegalArgumentException("Illegal port number.");
+ if(settings.getBaseDN() == null)
+ throw new IllegalArgumentException("Base DN has no content.");
+
+ this.settings = settings.clone();
+
+ if(this.settings.getPort() == 0)
+ portText = ":" + this.settings.getEncryption().defaultPort();
+ portText = ":" + this.settings.getPort();
+
+ /* fills environment for InitialDirContext */
+ this.env.put(Context.INITIAL_CONTEXT_FACTORY,
+ "com.sun.jndi.ldap.LdapCtxFactory");
+ this.env.put("com.sun.jndi.ldap.connect.timeout", LDAP_CONNECT_TIMEOUT);
+ this.env.put("com.sun.jndi.ldap.read.timeout", LDAP_READ_TIMEOUT);
+ this.env.put(Context.PROVIDER_URL, settings.getEncryption().
+ protocolString() + settings.getHostname() + portText +"/");
+ //connection pooling
+ this.env.put("com.sun.jndi.ldap.connect.pool", "true");
+
+ /* TODO STARTTLS */
+ switch(this.settings.getEncryption())
+ {
+ case CLEAR:
+ break;
+ case SSL:
+ this.env.put(Context.SECURITY_PROTOCOL, "ssl");
+ break;
+ }
+
+ /* TODO SASL */
+ switch(this.settings.getAuth())
+ {
+ case NONE:
+ this.env.put(Context.SECURITY_AUTHENTICATION, "none");
+ break;
+ case SIMPLE:
+ this.env.put(Context.SECURITY_AUTHENTICATION, "simple");
+ this.env.put(Context.SECURITY_PRINCIPAL,
+ this.settings.getBindDN());
+ this.env.put(Context.SECURITY_CREDENTIALS,
+ this.settings.getPassword());
+ break;
+ }
+ }
+
+ /**
+ * Returns the state of the enabled marker.
+ * Required by LdapDirectory interface.
+ *
+ * @return the state of the enabled marker
+ *
+ * @see LdapDirectory#isEnabled
+ */
+ public boolean isEnabled()
+ {
+ return this.settings.isEnabled();
+ }
+
+ /**
+ * Sets the state of the enabled marker
+ * Required by LdapDirectory interface.
+ *
+ * @param enabled whether the server is marked as enabled
+ *
+ * @see LdapDirectory#setEnabled
+ */
+ public void setEnabled(boolean enabled)
+ {
+ this.settings.setEnabled(enabled);
+ }
+
+ /**
+ * Returns an LdapDirectorySettings object containing
+ * a copy of the settings of this server
+ *
+ * @return a copy of this server settings
+ *
+ * @see LdapDirectorySettings
+ * @see LdapDirectory#getSettings
+ */
+ public LdapDirectorySettings getSettings()
+ {
+ return this.settings.clone();
+ }
+
+ /**
+ * Connects to the remote directory
+ */
+ private InitialDirContext connect()
+ throws NamingException
+ {
+ logger.trace("connecting to directory \"" + this + "\"");
+ long time0 = System.currentTimeMillis();
+ InitialDirContext dirContext =
+ new InitialDirContext(this.env);
+ long time1 = System.currentTimeMillis();
+ logger.trace("connection to directory \"" + this + "\" took " +
+ (time1-time0) + " ms");
+ return dirContext;
+ }
+
+ /**
+ * closes the ldap connection
+ */
+ private void disconnect(InitialDirContext dirContext)
+ {
+ if(dirContext == null)
+ throw new NullPointerException("dirContext is null");
+
+ try
+ {
+ dirContext.close();
+ }
+ catch(NamingException e)
+ {
+ logger.trace("disconnection from directory \"" + this +
+ "\" failed!");
+ }
+
+ logger.trace("disconnection achieved!");
+ }
+
+ /**
+ * Searches a person in the directory, based on a search string.
+ * Since that method might take time to process, it should be
+ * implemented asynchronously and send the results (LdapPersonFound)
+ * with an LdapEvent to its listeners
+ *
+ * @param query assumed name (can be partial) of the person searched
+ * e.g. "john", "doe", "john doe"
+ * @param caller the LdapListener which called the method and will
+ * receive results.
+ * @param searchSettings custom settings for this search, null if you
+ * want to stick with the defaults
+ *
+ * @see LdapDirectory#searchPerson
+ * @see LdapPersonFound
+ * @see LdapEvent
+ */
+ public void searchPerson(final LdapQuery query, final LdapListener caller,
+ LdapSearchSettings searchSettings)
+ {
+ if(query == null)
+ throw new NullPointerException("query shouldn't be null!");
+ if(caller == null)
+ throw new NullPointerException("caller shouldn't be null!");
+ if(searchSettings == null)
+ searchSettings = new LdapSearchSettingsImpl();
+
+ // if the initial query string was "john d",
+ // the intermediate query strings could be:
+ // "*john d*" and "d*john"
+ final String[] intermediateQueryStrings
+ = buildIntermediateQueryStrings(query.toString());
+
+ // the servers list contains this directory as many times as
+ // the number of intermediate query strings
+ List<LdapDirectory> serversList = new ArrayList<LdapDirectory>();
+ //for(String queryString : intermediateQueryStrings)
+ for(int i = 0 ; i < intermediateQueryStrings.length ; i++)
+ serversList.add(this);
+
+ // cancel previous queries
+ /*
+ for(Map.Entry<LdapQuery, LdapPendingSearch> entry :
+ this.pendingSearches.entrySet())
+ {
+ entry.getKey().setState(LdapQuery.State.CANCELLED);
+ }
+ */
+
+ // when the pendingSearches element will be empty,
+ // all intermediate query strings will have been searched
+ // and the search will be finished
+ this.pendingSearches.put(query, new LdapPendingSearch(serversList,
+ caller));
+
+ // really performs the search
+ for(String queryString : intermediateQueryStrings)
+ this.performSearch(query, queryString, searchSettings, this);
+ }
+
+ private void performSearch(final LdapQuery query,
+ final String realQueryString,
+ final LdapSearchSettings searchSettings,
+ final LdapListener caller)
+ {
+ Thread searchThread = new Thread()
+ {
+ int cancelState = 0;
+
+ public void run()
+ {
+ logger.trace("starting search for " + realQueryString +
+ " (initial query: \"" + query.toString() +
+ "\") on directory \"" + LdapDirectoryImpl.this + "\"");
+
+ SearchControls searchControls =
+ buildSearchControls(searchSettings);
+
+ LdapEvent endEvent = null;
+ InitialDirContext dirContext = null;
+
+ try
+ {
+ if(searchSettings.isDelaySet())
+ Thread.sleep(searchSettings.getDelay());
+
+ checkCancel();
+ dirContext = connect();
+ checkCancel();
+
+ long time0 = System.currentTimeMillis();
+
+ NamingEnumeration<?> results = dirContext.search(
+ LdapDirectoryImpl.this.settings.getBaseDN(),
+ buildSearchFilter(realQueryString),
+ searchControls
+ );
+
+ checkCancel();
+
+ while (results.hasMore())
+ {
+ checkCancel();
+
+ SearchResult searchResult =
+ (SearchResult) results.next();
+ Map<String, Set<String>> retrievedAttributes =
+ retrieveAttributes(searchResult);
+ LdapPersonFound person =
+ buildPerson(
+ query,
+ searchResult.getName(),
+ retrievedAttributes
+ );
+ LdapEvent resultEvent =
+ new LdapEvent(LdapDirectoryImpl.this,
+ LdapEvent.LdapEventCause.NEW_SEARCH_RESULT,
+ (Object) person);
+ fireLdapEvent(resultEvent, caller);
+ }
+
+ long time1 = System.currentTimeMillis();
+ logger.trace("search for real query \"" + realQueryString +
+ "\" (initial query: \"" + query.toString() +
+ "\") on directory \"" + LdapDirectoryImpl.this +
+ "\" took " + (time1-time0) + "ms");
+
+ endEvent = new LdapEvent(LdapDirectoryImpl.this,
+ LdapEvent.LdapEventCause.SEARCH_ACHIEVED, query);
+ }
+ catch(NamingException e)
+ {
+ logger.trace(
+ "an external exception was thrown during search" +
+ " for real query \"" +
+ realQueryString + "\" (initial query: \"" +
+ query.toString() + "\") on directory \"" +
+ LdapDirectoryImpl.this + "\": " + e);
+ endEvent = new LdapEvent(
+ LdapDirectoryImpl.this,
+ LdapEvent.LdapEventCause.SEARCH_ERROR,
+ query
+ );
+ }
+ catch(LdapQueryCancelledException e)
+ {
+ logger.trace("search for real query \"" + realQueryString +
+ "\" (initial query: \"" + query.toString() +
+ "\") on " + LdapDirectoryImpl.this +
+ " cancelled at state " + cancelState);
+ endEvent = new LdapEvent(
+ LdapDirectoryImpl.this,
+ LdapEvent.LdapEventCause.SEARCH_CANCELLED,
+ query
+ );
+
+ }
+ catch(InterruptedException e)
+ {
+ // whether sleep was interrupted
+ // is not that important
+ }
+ finally
+ {
+ fireLdapEvent(endEvent, caller);
+ if(dirContext != null)
+ disconnect(dirContext);
+ }
+ }
+
+ /**
+ * Checks if the query that triggered this search has
+ * been marked as cancelled. If that's the case, the
+ * search thread should be stopped and this method will
+ * send a search cancelled event to the search initiator.
+ * This method should be called by the search thread as
+ * often as possible to quickly interrupt when needed.
+ */
+ private void checkCancel()
+ throws LdapQueryCancelledException
+ {
+ if(query.getState() == LdapQuery.State.CANCELLED)
+ {
+ throw new LdapQueryCancelledException();
+ }
+ this.cancelState++;
+ }
+ };
+
+ searchThread.setDaemon(true);
+ searchThread.start();
+ }
+
+ private static String[]
+ buildIntermediateQueryStrings(String initialQueryString)
+ {
+ // search for "doe john" as well "as john doe"
+ String[] words = initialQueryString.split(" ");
+ String[] intermediateQueryStrings;
+
+ if(words.length == 2)
+ {
+ intermediateQueryStrings = new String[2];
+ intermediateQueryStrings[0] = "*" + words[0] + " " + words[1] + "*";
+ intermediateQueryStrings[1] = words[1] + "*" + words[0];
+ }
+ else
+ {
+ // one word or too many combinations
+ intermediateQueryStrings = new String[1];
+ intermediateQueryStrings[0] = "*" + initialQueryString + "*";
+ }
+
+ return intermediateQueryStrings;
+ }
+
+ /**
+ * Fills the retrievedAttributes map with
+ * "retrievable" string attributes (name, telephone number, ...)
+ *
+ * @param searchResult the results to browse for attributes
+ * @return the attributes in a Map
+ */
+ private Map<String, Set<String>>
+ retrieveAttributes(SearchResult searchResult)
+ throws NamingException
+ {
+ Attributes attributes =
+ searchResult.getAttributes();
+ Map<String, Set<String>> retrievedAttributes =
+ new HashMap<String, Set<String>>();
+ NamingEnumeration<String> ids = attributes.getIDs();
+ while(ids.hasMore())
+ {
+ String id = ids.next();
+ if(retrievableAttributes.contains(id))
+ {
+ Set<String> valuesSet = new HashSet<String>();
+ retrievedAttributes.put(id, valuesSet);
+ Attribute attribute = attributes.get(id);
+ NamingEnumeration<?> values = attribute.getAll();
+ while(values.hasMore())
+ {
+ String value = (String) values.next();
+ valuesSet.add(value);
+ }
+ }
+ }
+ return retrievedAttributes;
+ }
+
+ /**
+ * Builds an LdapPersonFound with the retrieved attributes
+ *
+ * @param query the initial query issued
+ * @param dn the distinguished name of the person in the directory
+ * @return the LdapPersonFoulnd built
+ */
+ private LdapPersonFound
+ buildPerson(
+ LdapQuery query,
+ String dn,
+ Map<String,
+ Set<String>> retrievedAttributes
+ )
+ {
+ LdapPersonFound person =
+ new LdapPersonFoundImpl(LdapDirectoryImpl.this, dn, query);
+
+ /* first name */
+ if(retrievedAttributes.get("givenname") != null)
+ {
+ String firstName =
+ retrievedAttributes.get("givenname").iterator().next();
+ person.setFirstName(firstName);
+ }
+ else if(retrievedAttributes.get("givenName") != null)
+ {
+ String firstName =
+ retrievedAttributes.get("givenName").iterator().next();
+ person.setFirstName(firstName);
+ }
+ else if(retrievedAttributes.get("gn") != null)
+ {
+ String firstName =
+ retrievedAttributes.get("gn").iterator().next();
+ person.setFirstName(firstName);
+ }
+
+ /* surname */
+ if(retrievedAttributes.get("sn") != null)
+ {
+ String surname =
+ retrievedAttributes.get("sn").iterator().next();
+ person.setSurname(surname);
+ }
+ else if(retrievedAttributes.get("surname") != null)
+ {
+ String surname =
+ retrievedAttributes.get("surname").iterator().next();
+ person.setSurname(surname);
+ }
+
+ /* displayed name */
+ if(retrievedAttributes.get("displayName") != null)
+ {
+ String displayName =
+ retrievedAttributes.get("displayName").iterator().next();
+ person.setDisplayName(displayName);
+ }
+ else if(retrievedAttributes.get("cn") != null)
+ {
+ String displayName =
+ retrievedAttributes.get("cn").iterator().next();
+ person.setDisplayName(displayName);
+ }
+ else if(retrievedAttributes.get("commonname") != null)
+ {
+ String displayName =
+ retrievedAttributes.get("commonname").iterator().next();
+ person.setDisplayName(displayName);
+ }
+ if(person.getDisplayName() == null)
+ {
+ person.setDisplayName("" + person.getFirstName() +
+ person.getSurname());
+ }
+ //should never happen
+ if(person.getDisplayName() == null)
+ {
+ throw new RuntimeException("display name is null!");
+ }
+
+ /* organization */
+ if(retrievedAttributes.get("o") != null)
+ {
+ String organization =
+ retrievedAttributes.get("o").iterator().next();
+ person.setOrganization(organization);
+ }
+ else if(retrievedAttributes.get("organizationName") != null)
+ {
+ String organization =
+ retrievedAttributes.get("organizationName").iterator()
+ .next();
+ person.setOrganization(organization);
+ }
+ else if(retrievedAttributes.get("company") != null)
+ {
+ String organization =
+ retrievedAttributes.get("company").iterator().next();
+ person.setOrganization(organization);
+ }
+
+
+ /* department */
+ if(retrievedAttributes.get("company") != null)
+ {
+ String department =
+ retrievedAttributes.get("company").iterator().next();
+ person.setDepartment(department);
+ }
+ else if(retrievedAttributes.get("ou") != null)
+ {
+ String department =
+ retrievedAttributes.get("ou").iterator().next();
+ person.setDepartment(department);
+ }
+ else if(retrievedAttributes.get("orgunit") != null)
+ {
+ String department =
+ retrievedAttributes.get("orgunit").iterator().next();
+ person.setDepartment(department);
+ }
+ else if(retrievedAttributes.get("organizationalUnitName") != null)
+ {
+ String department =
+ retrievedAttributes.get("organizationalUnitName").
+ iterator().next();
+ person.setDepartment(department);
+ }
+ else if(retrievedAttributes.get("department") != null)
+ {
+ String department =
+ retrievedAttributes.get("department").iterator().next();
+ person.setDepartment(department);
+ }
+ else if(retrievedAttributes.get("departmentNumber") != null)
+ {
+ String department =
+ retrievedAttributes.get("departmentNumber").iterator().
+ next();
+ person.setDepartment(department);
+ }
+
+ /* mail */
+ if(retrievedAttributes.get("mail") != null)
+ {
+ for(String mail : retrievedAttributes.get("mail"))
+ {
+ person.addMail(mail);
+ }
+ }
+
+ /* work phone */
+ if(retrievedAttributes.get("primaryPhone") != null)
+ {
+ String phone =
+ retrievedAttributes.get("primaryPhone").iterator().next();
+ person.addWorkPhone(phone);
+ }
+ if(retrievedAttributes.get("companyPhone") != null)
+ {
+ for(String phone : retrievedAttributes.get("companyPhone"))
+ {
+ person.addWorkPhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("telephoneNumber") != null)
+ {
+ for(String phone : retrievedAttributes.get("telephoneNumber"))
+ {
+ person.addWorkPhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("otherTelephone") != null)
+ {
+ for(String phone : retrievedAttributes.get("otherTelephone"))
+ {
+ person.addWorkPhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("tel") != null)
+ {
+ for(String phone : retrievedAttributes.get("tel"))
+ {
+ person.addWorkPhone(phone);
+ }
+ }
+
+ /* mobile phone */
+ if(retrievedAttributes.get("mobile") != null)
+ {
+ for(String phone : retrievedAttributes.get("mobile"))
+ {
+ person.addMobilePhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("mobileTelephoneNumber") != null)
+ {
+ for(String phone : retrievedAttributes.get(
+ "mobileTelephoneNumber"))
+ {
+ person.addMobilePhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("cellPhone") != null)
+ {
+ for(String phone : retrievedAttributes.get(
+ "cellPhone"))
+ {
+ person.addMobilePhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("otherMobile") != null)
+ {
+ for(String phone : retrievedAttributes.get("otherMobile"))
+ {
+ person.addMobilePhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("carPhone") != null)
+ {
+ for(String phone : retrievedAttributes.get("carPhone"))
+ {
+ person.addMobilePhone(phone);
+ }
+ }
+
+ /* home phone */
+ if(retrievedAttributes.get("homePhone") != null)
+ {
+ for(String phone : retrievedAttributes.get("homePhone"))
+ {
+ person.addHomePhone(phone);
+ }
+ }
+ if(retrievedAttributes.get("otherHomePhone") != null)
+ {
+ for(String phone : retrievedAttributes.get("otherHomePhone"))
+ {
+ person.addHomePhone(phone);
+ }
+ }
+
+ return person;
+ }
+
+ /**
+ * Turns LdapDirectoryImpl into a printable object
+ * Used for debugging purposes
+ *
+ * @return a printable string
+ *
+ */
+ public String toString()
+ {
+ return this.settings.getName();
+ }
+
+ /**
+ * An LdapDirectory is comparable in order to display LdapDirectory(s)
+ * in alphabetic order in the UI.
+ *
+ * @see java.lang.Comparable
+ */
+ public int compareTo(LdapDirectory server)
+ {
+ return this.settings.getName().compareTo(server.getSettings().
+ getName());
+ }
+
+ /**
+ * Two LdapDirectory(s) with the same displayed name
+ * should not exist in the same LdapDirectorySet,
+ * thus this function
+ */
+ public boolean equals(Object anObject)
+ {
+ if(anObject instanceof LdapDirectory)
+ {
+ LdapDirectory anLdapDirectory = (LdapDirectory) anObject;
+ return this.settings.getName().equals(anLdapDirectory.getSettings().
+ getName());
+ }
+ return false;
+ }
+
+ /**
+ * We override the equals method so we also do for
+ * hashCode to keep consistent behavior
+ */
+ public int hashCode()
+ {
+ return this.settings.getName().hashCode();
+ }
+
+ /**
+ * Used to check method input parameters
+ *
+ * @return wether the text is not empty
+ */
+ private boolean textHasContent(String aText)
+ {
+ String EMPTY_STRING = "";
+ return (aText != null) && (!aText.trim().equals(EMPTY_STRING));
+ }
+
+ /**
+ * Builds an LDAP search filter, base on the query string entered
+ * e.g. (&(|(mail=*)(telephoneNumber=*))(|(cn=*query*)(sn=*query*)(givenname=*query*)))
+ *
+ * @return an LDAP search filter
+ */
+ private String buildSearchFilter(String query)
+ {
+ StringBuffer searchFilter = new StringBuffer();
+
+ /*
+ searchFilter.append("(&(|");
+
+ for(String attribute : retrievableAttributes)
+ {
+ searchFilter.append("(");
+ searchFilter.append(attribute);
+ searchFilter.append("=*)");
+ }
+
+ searchFilter.append(")(|");
+ */
+ searchFilter.append("(|");
+
+ /* cn=*query* OR sn=*query* OR ... */
+ for(String attribute : searchableAttributes)
+ {
+ searchFilter.append("(");
+ searchFilter.append(attribute);
+ searchFilter.append("=");
+ searchFilter.append(query);
+ searchFilter.append(")");
+ }
+
+ //searchFilter.append("))");
+ searchFilter.append(")");
+ return searchFilter.toString();
+ }
+
+ /**
+ * search the children nodes of the given dn
+ *
+ * @param dn the distinguished name of the node to search for children
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapDirectory#searchChildren
+ */
+ public Collection<String> searchChildren(final String dn)
+ {
+ final Vector<String> nodes = new Vector<String>();
+ InitialDirContext dirContext = null;
+
+ if(dn.equals(""))
+ {
+ String[] returningAttributes = { "namingContexts" };
+ /* use our custom search control */
+ final SearchControls searchCtl = new SearchControls();
+ searchCtl.setSearchScope(SearchControls.OBJECT_SCOPE);
+ searchCtl.setReturningAttributes(returningAttributes);
+ searchCtl.setTimeLimit(5000);
+
+ logger.trace("starting search...");
+ try
+ {
+ dirContext = connect();
+ NamingEnumeration<?> result = dirContext.search(
+ dn, "(objectClass=*)", searchCtl);
+ while (result.hasMore())
+ {
+ SearchResult searchResult = (SearchResult) result.next();
+ Attributes attributes = searchResult.getAttributes();
+ Attribute attribute = attributes.get("namingContexts");
+ NamingEnumeration<?> values = attribute.getAll();
+ while (values.hasMore())
+ {
+ nodes.add((String) values.next());
+ }
+ }
+ }
+ catch (NamingException e)
+ {
+ logger.trace("error when performing ldap search query" + e);
+ }
+ finally
+ {
+ if(dirContext != null)
+ disconnect(dirContext);
+ }
+ }
+ else
+ {
+ /* use our custom search control */
+ final SearchControls searchCtl = new SearchControls();
+ searchCtl.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+
+ logger.trace("starting search...");
+ try
+ {
+ dirContext = connect();
+ NamingEnumeration<?> result = dirContext.search(
+ dn, "(objectClass=*)", searchCtl);
+ while (result.hasMore())
+ {
+ SearchResult sr = (SearchResult) result.next();
+ nodes.add(sr.getName());
+ logger.trace(sr.getName());
+ }
+ }
+ catch (NamingException e)
+ {
+ logger.trace("error when performing ldap search query" + e);
+ e.printStackTrace();
+ }
+ finally
+ {
+ if(dirContext != null)
+ disconnect(dirContext);
+ }
+ }
+
+ return nodes;
+ }
+
+ /**
+ * Tries to fetch the photo of the person with
+ * the given distinguished name in the directory
+ *
+ * @param dn distinguished name of the person to fetch the photo
+ * @return the bytes of the photo
+ */
+ byte[] fetchPhotoForPerson(String dn)
+ {
+ byte[] photo = null;
+ InitialDirContext dirContext = null;
+
+ /* use our custom search control */
+
+ final SearchControls searchCtl = new SearchControls();
+ searchCtl.setSearchScope(SearchControls.OBJECT_SCOPE);
+ String[] returningAttributes = { PHOTO_ATTRIBUTE };
+ searchCtl.setReturningAttributes(returningAttributes);
+
+ logger.trace("starting photo retrieval...");
+ try
+ {
+ dirContext = connect();
+ String newBaseDN;
+ if(settings.getBaseDN().equals(""))
+ newBaseDN = dn;
+ else
+ newBaseDN = dn + "," + this.settings.getBaseDN();
+ NamingEnumeration<?> result = dirContext.search(
+ newBaseDN, "(objectClass=*)", searchCtl);
+ if(result.hasMore())
+ {
+ SearchResult searchResult = (SearchResult) result.next();
+ Attributes attributes = searchResult.getAttributes();
+ Attribute attribute = attributes.get(PHOTO_ATTRIBUTE);
+ if(attribute != null)
+ {
+ NamingEnumeration<?> values = attribute.getAll();
+ if(values.hasMore())
+ {
+ photo = (byte[]) values.next();
+ }
+ }
+ }
+ }
+ catch (NamingException e)
+ {
+ logger.trace("error when performing photo retrieval" + e);
+ e.printStackTrace();
+ }
+ finally
+ {
+ if(dirContext != null)
+ disconnect(dirContext);
+ }
+
+ return photo;
+ }
+
+ private SearchControls buildSearchControls(LdapSearchSettings
+ searchSettings)
+ {
+ SearchControls searchControls = new SearchControls();
+
+ if(searchSettings.isMaxResultsSet())
+ {
+ // take value from searchSettings
+ searchControls.setCountLimit(searchSettings.getMaxResults());
+ }
+ else
+ {
+ // take default from SearchControls: no limit
+ }
+
+ if(searchSettings.isScopeSet())
+ {
+ // take value from searchSettings
+ searchControls.setSearchScope(
+ searchSettings.getScope().getConstant()
+ );
+ }
+ else
+ {
+ //take default from directory
+ searchControls.setSearchScope(
+ this.getSettings().getScope().getConstant()
+ );
+ }
+
+ searchControls.setReturningAttributes(retrievableAttributes.toArray(
+ new String[0]));
+
+ return searchControls;
+ }
+
+ /**
+ * Required by LdapListener.
+ *
+ * Dispatches event received from LdapDirectory-s to
+ * real search initiators (the search dialog for example)
+ *
+ * @param event An LdapEvent probably sent by an LdapDirectory
+ */
+ public synchronized void ldapEventReceived(LdapEvent event)
+ {
+ LdapQuery query;
+ switch(event.getCause())
+ {
+ case NEW_SEARCH_RESULT:
+ LdapPersonFound result = (LdapPersonFound) event.getContent();
+ query = result.getQuery();
+ if(this.pendingSearches.get(query) != null)
+ {
+ this.fireLdapEvent(event,
+ pendingSearches.get(query).getCaller());
+ logger.trace("result event for query \"" +
+ result.getQuery().toString() + "\" forwaded");
+ }
+ break;
+ case SEARCH_ERROR:
+ case SEARCH_CANCELLED:
+ case SEARCH_ACHIEVED:
+ query = (LdapQuery) event.getContent();
+ if(this.pendingSearches.get(query) != null)
+ {
+ this.pendingSearches.get(query).getPendingServers().
+ remove(event.getSource());
+ int sizeLeft = pendingSearches.get(query).
+ getPendingServers().size();
+ logger.trace("end event received for initial query \"" +
+ query.toString() + "\" on directory \"" +
+ event.getSource() + "\"\nthere is " + sizeLeft +
+ " search pending for this initial query on directory \"" +
+ event.getSource() + "\"");
+ if(sizeLeft == 0)
+ {
+ fireLdapEvent(event, pendingSearches.get(query).
+ getCaller());
+ event = new LdapEvent(this,
+ LdapEvent.LdapEventCause.SEARCH_ACHIEVED,
+ query);
+ pendingSearches.remove(query);
+ }
+ }
+ break;
+ }
+ }
+
+ /**
+ * A custom exception used internally by LdapDirectoryImpl
+ * to indicate that a query was cancelled
+ *
+ * @author Sebastien Mazy
+ */
+ public class LdapQueryCancelledException extends Exception
+ {
+ /**
+ * Serial version UID.
+ */
+ private final static long serialVersionUID = 0L;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapDirectorySetImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapDirectorySetImpl.java
new file mode 100644
index 0000000..3f775e8
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapDirectorySetImpl.java
@@ -0,0 +1,285 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import java.util.*;
+
+import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.service.configuration.*;
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.service.ldap.event.*;
+
+/**
+ * A thread-safe implementation of LdapDirectorySet, backed by a TreeMap
+ *
+ * @see net.java.sip.communicator.service.ldap
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapDirectorySetImpl
+ extends DefaultLdapEventManager
+ implements LdapDirectorySet,
+ LdapConstants
+{
+ /**
+ * the logger for this class
+ */
+ private static Logger logger
+ = Logger.getLogger(LdapDirectorySetImpl.class);
+
+ /**
+ * internal data structure used to store LdapDirectory(s)
+ */
+ private SortedMap<String,LdapDirectory> serverMap;
+
+ /**
+ * the configuration service
+ */
+ private ConfigurationService configService;
+
+ /**
+ * Stores the pending searches
+ *
+ * @see LdapPendingSearch
+ */
+ private HashMap<LdapQuery, LdapPendingSearch> pendingSearches =
+ new HashMap<LdapQuery, LdapPendingSearch>();
+
+ /**
+ * A simple constructor for this class
+ */
+ public LdapDirectorySetImpl()
+ {
+ this(null);
+ }
+
+ /**
+ * Use this constructor if you want every change to the LdapDirectorySet
+ * to be propagated in the user preferences files
+ *
+ * @param configService the configuration service to use
+ */
+ public LdapDirectorySetImpl(ConfigurationService configService)
+ {
+ this.serverMap = Collections.
+ synchronizedSortedMap(new TreeMap<String, LdapDirectory>());
+ this.configService = configService;
+ }
+
+ /**
+ * @return the LdapDirectory with name name or null
+ * if it isn't present in the LdapDirectorySet
+ */
+ public LdapDirectory getServerWithName(String name)
+ {
+ return this.serverMap.get(name);
+ }
+
+ /**
+ * Tries to remove an LdapDirectory from the LdapDirectorySet
+ * using the name given by the getName method.
+ *
+ * @param name name of the LdapDirectory to remove
+ *
+ * @return LdapDirectory removed LdapDirectory or null if failed
+ */
+ public LdapDirectory removeServerWithName(String name)
+ {
+ LdapDirectory removed = this.serverMap.remove(name);
+
+ if(configService != null)
+ removed.getSettings().persistentRemove();
+
+ return removed;
+ }
+
+ /**
+ * Tries to add an LdapDirectory to the LdapDirectorySet
+ *
+ * @param server the server to be added
+ *
+ * @return whether it succeeded
+ */
+ public boolean addServer(LdapDirectory server)
+ {
+ /* TODO thread-safe */
+ this.serverMap.put(server.getSettings().getName(), server);
+
+ if(configService != null)
+ server.getSettings().persistentSave();
+
+ return true;
+ }
+
+ /**
+ * @param name of the server to check presence in the LdapDirectorySet
+ *
+ * @return whether the server is in the LdapDirectorySet
+ */
+ public boolean containsServerWithName(String name)
+ {
+ /* TODO is this function useful ? */
+ return this.serverMap.containsKey(name);
+ }
+
+ /**
+ * Returns number of LdapDirectory(s) in the LdapDirectorySet.
+ *
+ * @return the number of LdapDirectory(s) in the LdapDirectorySet
+ */
+ public int size()
+ {
+ return this.serverMap.size();
+ }
+
+ /**
+ * Required by LdapDirectorySet interface.
+ * Returns a set of the marked enabled
+ * LdapDirectory(s) alphabetically sorted
+ *
+ * @return a set of the enabled LdapDirectory(s)
+ */
+ public SortedSet<LdapDirectory> getEnabledServers()
+ {
+ SortedSet<LdapDirectory> enabledServers = new TreeSet<LdapDirectory>();
+
+ for(LdapDirectory server : this)
+ {
+ if(server.isEnabled())
+ enabledServers.add(server);
+ }
+
+ return enabledServers;
+ }
+
+ /**
+ * Required by LdapDirectorySet interface.
+ * Returns a set of the marked disabled
+ * LdapDirectory(s) alphabetically sorted
+ *
+ * @return a set of the disabled LdapDirectory(s)
+ */
+ public SortedSet<LdapDirectory> getDisabledServers()
+ {
+ SortedSet<LdapDirectory> enabledServers = new TreeSet<LdapDirectory>();
+
+ for(LdapDirectory server : this)
+ {
+ if(server.isEnabled())
+ enabledServers.add(server);
+ }
+
+ return enabledServers;
+ }
+
+ /**
+ * @return an iterator on all the
+ * LdapDirectory(s) alphabeticaly sorted
+ */
+ public Iterator<LdapDirectory> iterator()
+ {
+ return this.serverMap.values().iterator();
+ }
+
+ /**
+ * Performs a search on every LdapDirectory provided
+ *
+ * @param servers a set of LdapDirectory to searchfor the person
+ * @param query the query to perform
+ * @param caller the LdapListener that will receive the results
+ * @param searchSettings the custom settings for this search,
+ * or null for the defaults
+ */
+ public synchronized void searchPerson(
+ Set<LdapDirectory> servers,
+ LdapQuery query,
+ LdapListener caller,
+ LdapSearchSettings searchSettings
+ )
+ {
+ if(servers == null)
+ throw new NullPointerException("servers shouldn't be null!");
+ if(query == null)
+ throw new NullPointerException("query shouldn't be null!");
+ if(caller == null)
+ throw new NullPointerException("caller shouldn't be null!");
+
+ this.pendingSearches.put(query, new LdapPendingSearch(servers, caller));
+ for(LdapDirectory server : servers)
+ {
+ if(server == null)
+ System.out.println("server is null");
+ server.searchPerson(query, this, searchSettings);
+ }
+ }
+
+ /**
+ * Performs a search on every enabled LdapDirectory of this set.
+ *
+ * @param query the query to perform
+ * @param caller the LdapListener that will receive the results
+ * @param searchSettings the custom settings for this search
+ */
+ public void searchPerson(
+ LdapQuery query,
+ LdapListener caller,
+ LdapSearchSettings searchSettings
+ )
+ {
+ this.searchPerson(this.getEnabledServers(), query, caller,
+ searchSettings);
+ }
+
+ /**
+ * Required by LdapListener.
+ *
+ * Dispatches event received from LdapDirectory-s to
+ * real search initiators (the search dialog for example)
+ *
+ * @param event An LdapEvent probably sent by an LdapDirectory
+ */
+ public synchronized void ldapEventReceived(LdapEvent event)
+ {
+ LdapQuery query;
+ switch(event.getCause())
+ {
+ case NEW_SEARCH_RESULT:
+ LdapPersonFound result = (LdapPersonFound) event.getContent();
+ query = result.getQuery();
+ if(this.pendingSearches.get(query) != null)
+ {
+ this.fireLdapEvent(event, pendingSearches.get(query).
+ getCaller());
+ logger.trace("result event for query \"" +
+ result.getQuery().toString() + "\" forwaded");
+ }
+ break;
+ case SEARCH_ERROR:
+ case SEARCH_CANCELLED:
+ case SEARCH_ACHIEVED:
+ query = (LdapQuery) event.getContent();
+ if(this.pendingSearches.get(query) != null)
+ {
+ this.pendingSearches.get(query).getPendingServers().remove(
+ event.getSource());
+ logger.trace("end event for query \"" + query.toString() +
+ "\" on directory \"" + event.getSource() + "\"");
+ if(pendingSearches.get(query).getPendingServers().
+ size() == 0)
+ {
+ fireLdapEvent(event, pendingSearches.get(query).
+ getCaller());
+ event = new LdapEvent(this,
+ LdapEvent.LdapEventCause.SEARCH_ACHIEVED,
+ query);
+ pendingSearches.remove(query);
+ }
+ }
+ break;
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapDirectorySettingsImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapDirectorySettingsImpl.java
new file mode 100644
index 0000000..db9707d
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapDirectorySettingsImpl.java
@@ -0,0 +1,600 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import net.java.sip.communicator.service.configuration.*;
+import net.java.sip.communicator.service.ldap.*;
+
+/**
+ * @author Sebastien Mazy
+ *
+ * Implementation of LdapDirectorySettings
+ * a wrapper around the settings needed to create an LdapDirectory
+ */
+public class LdapDirectorySettingsImpl
+ implements LdapDirectorySettings
+{
+ /**
+ * Simple constructor for this class,
+ * sets default values,
+ * note that you won't be able to create an LdapDirectory with these defaults
+ * (empty name, empty hostname forbidden by LdapDirectory)
+ */
+ public LdapDirectorySettingsImpl()
+ {
+ this.setName("");
+ this.setEnabled(true);
+ this.setHostname("");
+ this.setEncryption(Encryption.defaultValue());
+ this.setPort(0);
+ this.setAuth(Auth.defaultValue());
+ this.setBindDN("");
+ this.setPassword("");
+ this.setBaseDN("");
+ this.setScope(Scope.defaultValue());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param settings existing settings
+ */
+ public LdapDirectorySettingsImpl(LdapDirectorySettingsImpl settings)
+ {
+ this();
+ this.setName(settings.getName());
+ this.setEnabled(settings.isEnabled());
+ this.setHostname(settings.getHostname());
+ this.setEncryption(settings.getEncryption());
+ this.setPort(settings.getPort());
+ this.setAuth(settings.getAuth());
+ this.setBindDN(settings.getBindDN());
+ this.setPassword(settings.getPassword());
+ this.setBaseDN(settings.getBaseDN());
+ this.setScope(settings.getScope());
+ }
+
+ /**
+ * XML path where to store the directories settings
+ */
+ private final static String directoriesPath =
+ "net.java.sip.communicator.impl.ldap.directories";
+
+ /**
+ * name that will be displayed in the UI
+ * e.g. "My LDAP server"
+ */
+ private String name;
+
+ /**
+ * a marker
+ */
+ private boolean enabled;
+
+ /**
+ * the hostname,
+ * e.g. "example.com"
+ */
+ private String hostname;
+
+ /**
+ * the encryption protocol
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapConstants#Encryption
+ */
+ private Encryption encryption;
+
+ /**
+ * The network port number of the remote server
+ */
+ private int port;
+
+ /**
+ * the authentication method
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapConstants#Auth
+ */
+ private Auth auth;
+
+ /**
+ * the bind distinguished name if authentication is needed
+ * e.g. "cn=user,ou=People,dc=example,dc=com"
+ */
+ private String bindDN;
+
+ /**
+ * the password if authentication is needed
+ */
+ private String password;
+
+ /**
+ * distinguished name used as a base for searches
+ * e.g. "dc=example,dc=com"
+ */
+ private String baseDN;
+
+ /**
+ * the search scope: one level under the base distinguished name
+ * or all the subtree.
+ */
+ private Scope scope;
+
+ /**
+ * simple getter for name
+ *
+ * @return the name property
+ */
+ public String getName()
+ {
+ return this.name;
+ }
+
+ /**
+ * simple setter for name
+ *
+ * @param name the name property
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * Simple getter for enabled. Required by LdapDirectorySettings interface.
+ *
+ * @return whether the server is marked as enabled
+ *
+ * @see LdapDirectorySettings#isEnabled
+ */
+ public boolean isEnabled()
+ {
+ return this.enabled;
+ }
+
+ /**
+ * simple setter for enabled. Required by LdapDirectorySettings interface.
+ *
+ * @param enabled whether the server is marked as enabled
+ *
+ * @see LdapDirectorySettings#setEnabled
+ */
+ public void setEnabled(boolean enabled)
+ {
+ this.enabled = enabled;
+ }
+
+ /**
+ * simple getter for hostname
+ *
+ * @return the hostname property
+ */
+ public String getHostname()
+ {
+ return this.hostname;
+ }
+
+ /**
+ * simple setter for hostname
+ *
+ * @param hostname the hostname property
+ */
+ public void setHostname(String hostname)
+ {
+ this.hostname = hostname;
+ }
+
+ /**
+ * simple getter for encryption
+ *
+ * @return the encryption property
+ *
+ * @see LdapConstants.Encryption
+ */
+ public Encryption getEncryption()
+ {
+ return this.encryption;
+ }
+
+ /**
+ * simple setter for encryption
+ *
+ * @param encryption the encryption property
+ *
+ * @see LdapConstants.Encryption
+ */
+ public void setEncryption(Encryption encryption)
+ {
+ this.encryption = encryption;
+ }
+
+ /**
+ * simple getter for port
+ *
+ * @return the port property
+ */
+ public int getPort()
+ {
+ return this.port;
+ }
+
+ /**
+ * simple setter for port
+ *
+ * @param port the port property
+ */
+ public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+ /**
+ * simple getter for auth
+ *
+ * @return the auth property
+ *
+ * @see LdapConstants.Auth
+ */
+ public Auth getAuth()
+ {
+ return this.auth;
+ }
+
+ /**
+ * simple setter for auth
+ *
+ * @param auth the auth property
+ *
+ * @see LdapConstants.Auth
+ */
+ public void setAuth(Auth auth)
+ {
+ this.auth = auth;
+ }
+
+ /**
+ * simple getter for bindDN
+ *
+ * @return the bindDN property
+ */
+ public String getBindDN()
+ {
+ return this.bindDN;
+ }
+
+ /**
+ * simple setter for bindDN
+ *
+ * @param bindDN the bindDN property
+ */
+ public void setBindDN(String bindDN)
+ {
+ this.bindDN = bindDN;
+ }
+
+ /**
+ * simple getter for password
+ *
+ * @return the password property
+ */
+ public String getPassword()
+ {
+ return this.password;
+ }
+
+ /**
+ * simple setter for password
+ *
+ * @param password the password property
+ */
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ /**
+ * simple getter for baseDN
+ *
+ * @return the baseDN property
+ */
+ public String getBaseDN()
+ {
+ return this.baseDN;
+ }
+
+ /**
+ * simple setter for baseDN
+ *
+ * @param baseDN the baseDN property
+ */
+ public void setBaseDN(String baseDN)
+ {
+ this.baseDN = baseDN;
+ }
+
+ /**
+ * Returns the search scope: one level under the base distinguished name
+ * or all the subtree. Required by LdapDirectorySettings interface.
+ *
+ * @return the search scope
+ *
+ * @see LdapConstants.Scope
+ * @see LdapDirectorySettings#getScope
+ */
+ public Scope getScope()
+ {
+ return this.scope;
+ }
+
+ /**
+ * Sets the search scope: one level under the base distinguished name
+ * or all the subtree. Required by LdapDirectorySettings interface.
+ *
+ * @param scope the new search scope
+ *
+ * @see LdapConstants.Scope
+ * @see LdapDirectorySettings#setScope
+ */
+ public void setScope(Scope scope)
+ {
+ this.scope = scope;
+ }
+
+ /**
+ * Checks if both LdapDirectorySettings instance have the same content
+ *
+ * @return whether both LdapDirectorySettings instance have the same content
+ *
+ * @see java.lang.Object#equals
+ */
+ public boolean equals(LdapDirectorySettings other)
+ {
+ /* enabled is not in equals on purpose */
+
+ return this.getName().equals(other.getName()) &&
+ this.getHostname().equals(other.getHostname()) &&
+ this.getEncryption().equals(other.getEncryption()) &&
+ this.getPort() == other.getPort() &&
+ this.getAuth().equals(other.getAuth()) &&
+ this.getBindDN().equals(other.getBindDN()) &&
+ this.getPassword().equals(other.getPassword()) &&
+ this.getBaseDN().equals(other.getBaseDN()) &&
+ this.getScope().equals(other.getScope());
+ }
+
+ /**
+ * Returns the hash code for this instance.
+ * It has to be consistent with equals.
+ *
+ * @return the hash code dor this instance
+ *
+ * @see java.lang.Object#hashCode
+ */
+ public int hashCode()
+ {
+ /* enabled is not in the hashcode on purpose */
+
+ int hash = 7;
+ hash = 31 * hash + (null == this.getName() ? 0 :
+ this.getName().hashCode());
+ hash = 31 * hash + (null == this.getHostname() ? 0 :
+ this.getHostname().hashCode());
+ hash = 31 * hash + (null == this.getEncryption() ? 0 :
+ this.getEncryption().hashCode());
+ hash = 31 * hash + this.getPort();
+ hash = 31 * hash + (null == this.getAuth() ? 0 :
+ this.getAuth().hashCode());
+ hash = 31 * hash + (null == this.getBindDN() ? 0 :
+ this.getBindDN().hashCode());
+ hash = 31 * hash + (null == this.getPassword() ? 0 :
+ this.getPassword().hashCode());
+ hash = 31 * hash + (null == this.getScope() ? 0 :
+ this.getScope().hashCode());
+ hash = 31 * hash + (null == this.getBaseDN() ? 0 :
+ this.getBaseDN().hashCode());
+ return hash;
+ }
+
+ /**
+ * Saves these settings through the configuration service
+ *
+ * @see LdapDirectorySettings#persistentSave
+ */
+ public void persistentSave()
+ {
+ ConfigurationService configService = LdapServiceImpl.getConfigService();
+ String node = "dir" + Math.abs(this.getName().hashCode());
+
+ configService.setProperty(
+ directoriesPath + "." + node,
+ this.getName());
+ configService.setProperty(
+ directoriesPath + "." + node + ".enabled",
+ this.isEnabled());
+ configService.setProperty(
+ directoriesPath + "." + node + ".hostname",
+ this.getHostname());
+ configService.setProperty(
+ directoriesPath + "." + node + ".encryption",
+ this.getEncryption().toString());
+ configService.setProperty(
+ directoriesPath + "." + node + ".port",
+ String.valueOf(this.getPort()));
+ configService.setProperty(
+ directoriesPath + "." + node + ".auth",
+ this.getAuth().toString());
+ configService.setProperty(
+ directoriesPath + "." + node + ".bindDN",
+ this.getBindDN());
+ configService.setProperty(
+ directoriesPath + "." + node + ".password",
+ this.getPassword());
+ configService.setProperty(
+ directoriesPath + "." + node + ".scope",
+ this.getScope());
+ configService.setProperty(
+ directoriesPath + "." + node + ".baseDN",
+ this.getBaseDN());
+ }
+
+ /**
+ * Loads the settings with the given name from the config files
+ * into the LdapDirectorySetting.
+ *
+ * @param name name of the settings
+ *
+ * @see LdapDirectorySettings#persistentLoad
+ */
+ public void persistentLoad(String name)
+ {
+ ConfigurationService configService = LdapServiceImpl.getConfigService();
+ String node = "dir" + Math.abs(name.hashCode());
+
+ if(configService.getProperty(directoriesPath + "." + node) == null)
+ this.setName("");
+ else
+ this.setName( (String)
+ configService.getProperty(directoriesPath + "." + node));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".enabled")
+ == null)
+ this.setEnabled(true);
+ else
+ this.setEnabled(Boolean.parseBoolean(
+ (String)configService.getProperty(
+ directoriesPath + "." + node + ".enabled")));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".hostname")
+ == null)
+ this.setHostname("");
+ else
+ this.setHostname((String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".hostname"));
+
+ if(configService.getProperty(
+ directoriesPath + "." + node + ".encryption") == null)
+ this.setEncryption(Encryption.defaultValue());
+ else
+ this.setEncryption( Encryption.valueOf ((String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".encryption")));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".port")
+ == null)
+ this.setPort(0);
+ else
+ this.setPort( Integer.parseInt ((String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".port")));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".auth")
+ == null)
+ this.setAuth(Auth.defaultValue());
+ else
+ this.setAuth( Auth.valueOf ((String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".auth")));
+
+ if(configService.getProperty(
+ directoriesPath + "." + node + ".bindDN") == null)
+ this.setBindDN("");
+ else
+ this.setBindDN( (String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".bindDN"));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".password")
+ == null)
+ this.setPassword("");
+ else
+ this.setPassword( (String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".password"));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".scope")
+ == null)
+ this.setScope(Scope.defaultValue());
+ else
+ this.setScope( Scope.valueOf ((String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".scope")));
+
+ if(configService.getProperty(directoriesPath + "." + node + ".baseDN")
+ == null)
+ this.setBaseDN("");
+ else
+ this.setBaseDN( (String)
+ configService.getProperty(
+ directoriesPath + "." + node + ".baseDN"));
+ }
+
+ /**
+ * Removes settings with this name from the configuration files
+ * (package private)
+ *
+ * @see LdapDirectorySettings#persistentRemove
+ */
+ public void persistentRemove()
+ {
+ ConfigurationService configService = LdapServiceImpl.getConfigService();
+ String node = "dir" + Math.abs(this.getName().hashCode());
+
+ configService.setProperty(
+ directoriesPath + "." + node + ".enabled",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".hostname",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".encryption",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".port",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".auth",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".bindDN",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".password",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".baseDN",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node + ".scope",
+ null);
+ configService.setProperty(
+ directoriesPath + "." + node,
+ null);
+ }
+
+ /**
+ * meant for debugging
+ *
+ * @return a string description of this instance
+ */
+ public String toString()
+ {
+ return "LdapDirectorySettings: {\n " +
+ this.getName() + ", \n" +
+ this.getHostname() + ", \n" +
+ this.getEncryption() + ", \n" +
+ this.getPort() + ", \n" +
+ this.getAuth() + ", \n" +
+ this.getBindDN() + ", \n" +
+ this.getPassword() + ", \n" +
+ this.getBaseDN() + " \n}";
+ }
+
+ public LdapDirectorySettings clone()
+ {
+ return new LdapDirectorySettingsImpl(this);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapFactoryImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapFactoryImpl.java
new file mode 100644
index 0000000..ddc5239
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapFactoryImpl.java
@@ -0,0 +1,79 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import net.java.sip.communicator.service.ldap.*;
+
+/**
+ * Implementation of The LdapFactory, used to
+ * create LdapDirectory-s, LdapDirectorySettings, LdapQuery, ...
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapFactoryImpl
+ implements LdapFactory
+{
+ /**
+ * Required by LdapFactory interface.
+ * Creates an LdapDirectory based on the provided settings.
+ * This method will not modify the <tt>settings</tt>
+ * or save a reference to it, but may save a clone.
+ *
+ * @param settings settings for this new server
+ *
+ * @return a reference to the created LdapDirectory
+ *
+ * @see LdapDirectorySettings
+ * @see LdapFactory#createServer
+ */
+ public LdapDirectory createServer(LdapDirectorySettings settings)
+ throws IllegalArgumentException
+ {
+ return new LdapDirectoryImpl(settings);
+ }
+
+ /**
+ * Required by LdapFactory interface.
+ * Return a new instance of LdapDirectorySettings,
+ * a wrapper around a directory settings
+ *
+ * @return a new instance of LdapDirectorySettings
+ *
+ * @see LdapDirectorySettings
+ * @see LdapFactory#createServerSettings
+ */
+ public LdapDirectorySettings createServerSettings()
+ {
+ return new LdapDirectorySettingsImpl();
+ }
+
+ /**
+ * Required by LdapFactory interface.
+ * Returns an LDAP query, ready to be sent to an LdapDirectory
+ *
+ * @param query the query string, e.g. "John Doe"
+ *
+ * @return an LDAP query, ready to be sent to an LdapDirectory
+ *
+ * @see LdapQuery
+ * @see LdapFactory#createQuery
+ */
+ public LdapQuery createQuery(String query)
+ {
+ return new LdapQueryImpl(query);
+ }
+
+ /**
+ * Returns an LdapSearchSettings, to use when performing a search
+ *
+ * @return an LdapSearchSettings, to use when performing a search
+ */
+ public LdapSearchSettings createSearchSettings()
+ {
+ return new LdapSearchSettingsImpl();
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapPendingSearch.java b/src/net/java/sip/communicator/impl/ldap/LdapPendingSearch.java
new file mode 100644
index 0000000..ad320ca
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapPendingSearch.java
@@ -0,0 +1,66 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.service.ldap.event.*;
+
+/**
+ * Stores a pending search
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapPendingSearch
+{
+ /**
+ * the LdapDirectory-s which are still being searched
+ * for this search
+ */
+ private final List<LdapDirectory> pendingServers =
+ new ArrayList<LdapDirectory>();
+
+ /**
+ * the caller for this search,
+ * e.g. an LdapSearchDialog instance
+ */
+ private final LdapListener caller;
+
+ /**
+ * Simple constructor
+ *
+ * @param pendingServers pending LDAP servers
+ * @param caller callback
+ */
+ public LdapPendingSearch(Collection<LdapDirectory> pendingServers,
+ LdapListener caller)
+ {
+ this.pendingServers.addAll(pendingServers);
+ this.caller = caller;
+ }
+
+ /**
+ * Returns the LdapDirectory-s not finished searching
+ *
+ * @return the LdapDirectory-s not finished searching
+ */
+ public List<LdapDirectory> getPendingServers()
+ {
+ return this.pendingServers;
+ }
+
+ /**
+ * Returns the initiator of the search
+ *
+ * @return the initiator of the search
+ */
+ public LdapListener getCaller()
+ {
+ return this.caller;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java
new file mode 100644
index 0000000..8728861
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java
@@ -0,0 +1,383 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import java.util.*;
+
+import net.java.sip.communicator.service.ldap.*;
+
+/**
+ * Implementation of LdapPersonFound
+ * An LdapPersonFound is contained in each LdapEvent
+ * sent by an LdapDirectory after a successful LDAP search.
+ * Each instance corresponds to a person found in the
+ * LDAP directory, as well as its contact addresses.
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapPersonFoundImpl
+ implements LdapPersonFound
+{
+ /**
+ * the server on which the person was found
+ */
+ private LdapDirectoryImpl server;
+
+ /**
+ * the query which this LdapPersonFound is a result of
+ */
+ private final LdapQuery query;
+
+ /**
+ * distinguished name for this person in the directory
+ */
+ private final String dn;
+
+ /**
+ * name/pseudo found in the the directory for this person
+ */
+ private String displayName = null;
+
+ /**
+ * first name found in the the directory for this person
+ */
+ private String firstName = null;
+
+ /**
+ * surname found in the the directory for this person
+ */
+ private String surname = null;
+
+ /**
+ * organization found in the the directory for this person
+ */
+ private String organization = null;
+
+ /**
+ * department found in the the directory for this person
+ */
+ private String department = null;
+
+ /**
+ * the set storing the mail addresses
+ */
+ private final Set<String> mails = new HashSet<String>();
+
+ /**
+ * the set storing the work phone numbers
+ */
+ private final Set<String> workPhoneNumbers = new HashSet<String>();
+
+ /**
+ * the set storing the mobile phone numbers
+ */
+ private final Set<String> mobilePhoneNumbers = new HashSet<String>();
+
+ /**
+ * the set storing the home phone numbers
+ */
+ private final Set<String> homePhoneNumbers = new HashSet<String>();
+
+ /**
+ * the constructor for this class
+ *
+ * @param server the server on which this person was found
+ * @param dn distinguished name for this person in the directory
+ * @param query the search query
+ */
+ public LdapPersonFoundImpl(LdapDirectoryImpl server, String dn,
+ LdapQuery query)
+ {
+ if(server == null | query == null | dn==null)
+ throw new NullPointerException();
+ this.server = server;
+ this.query = query;
+ this.dn = dn;
+ }
+
+ /**
+ * Returns the query which this Ldapperson found is a result of
+ *
+ * @return the initial query
+ */
+ public LdapQuery getQuery()
+ {
+ return this.query;
+ }
+
+ /**
+ * Returns the server which this person was found on
+ *
+ * @return the server
+ */
+ public LdapDirectory getServer()
+ {
+ return (LdapDirectory) this.server;
+ }
+
+ /**
+ * Sets the name/pseudo found in the the directory for this person
+ *
+ * @param name the name/pseudo found in the the directory for this person
+ */
+ public void setDisplayName(String name)
+ {
+ this.displayName = name;
+ }
+
+ /**
+ * Returns the name/pseudo found in the the directory for this person
+ *
+ * @return the name/pseudo found in the the directory for this person
+ */
+ public String getDisplayName()
+ {
+ return this.displayName;
+ }
+
+ /**
+ * Tries to fetch the photo in the the directory for this person
+ *
+ * @return the photo found in the the directory for this person
+ * or null if not found
+ */
+ public byte[] fetchPhoto()
+ {
+ byte[] photo;
+ photo = this.server.fetchPhotoForPerson(this.dn);
+ return photo;
+ }
+
+ /**
+ * Sets the first name found in the the directory for this person
+ *
+ * @param firstName the name/pseudo found in the the directory for this
+ * person
+ */
+ public void setFirstName(String firstName)
+ {
+ this.firstName = firstName;
+ }
+
+ /**
+ * Returns the first name found in the the directory for this person
+ *
+ * @return the first name found in the the directory for this person
+ */
+ public String getFirstName()
+ {
+ return this.firstName;
+ }
+
+ /**
+ * Sets the surname found in the the directory for this person
+ *
+ * @param surname the surname found in the the directory for this person
+ */
+ public void setSurname(String surname)
+ {
+ this.surname = surname;
+ }
+
+ /**
+ * Returns the surname found in the the directory for this person
+ *
+ * @return the surname found in the the directory for this person
+ */
+ public String getSurname()
+ {
+ return this.surname;
+ }
+
+ /**
+ * Sets the organization found in the the directory for this person
+ *
+ * @param organization the organization found in the the directory for this
+ * person
+ */
+ public void setOrganization(String organization)
+ {
+ this.organization = organization;
+ }
+
+ /**
+ * Returns the organization found in the the directory for this person
+ *
+ * @return the organization found in the the directory for this person
+ */
+ public String getOrganization()
+ {
+ return this.organization;
+ }
+
+ /**
+ * Sets the department found in the the directory for this person
+ *
+ * @param department the department found in the the directory for this
+ * person
+ */
+ public void setDepartment(String department)
+ {
+ this.department = department;
+ }
+
+ /**
+ * Returns the department found in the the directory for this person
+ *
+ * @return the department found in the the directory for this person
+ */
+ public String getDepartment()
+ {
+ return this.department;
+ }
+
+ /**
+ * Adds a mail address to this person
+ *
+ * @param mail the mail address
+ */
+ public void addMail(String mail)
+ {
+ this.mails.add(mail);
+ }
+
+ /**
+ * Returns mail addresss from this person
+ *
+ * @return mail addresss from this person
+ */
+ public Set<String> getMail()
+ {
+ return this.mails;
+ }
+
+ /**
+ * Returns telephone numbers from this person
+ *
+ * @return telephone numbers from this person
+ */
+ public Set<String> getAllPhone()
+ {
+ Set<String> allPhone = new HashSet<String>();
+
+ allPhone.addAll(this.workPhoneNumbers);
+ allPhone.addAll(this.mobilePhoneNumbers);
+ allPhone.addAll(this.homePhoneNumbers);
+
+ return allPhone;
+ }
+
+ /**
+ * Adds a work telephone number to this person
+ *
+ * @param telephoneNumber the work telephone number
+ */
+ public void addWorkPhone(String telephoneNumber)
+ {
+ this.workPhoneNumbers.add(telephoneNumber);
+ }
+
+ /**
+ * Returns work telephone numbers from this person
+ *
+ * @return work telephone numbers from this person
+ */
+ public Set<String> getWorkPhone()
+ {
+ Set<String> workPhone = new HashSet<String>();
+
+ workPhone.addAll(this.workPhoneNumbers);
+
+ return workPhone;
+ }
+
+ /**
+ * Adds a mobile telephone number to this person
+ *
+ * @param telephoneNumber the mobile telephone number
+ */
+ public void addMobilePhone(String telephoneNumber)
+ {
+ this.mobilePhoneNumbers.add(telephoneNumber);
+ }
+
+ /**
+ * Returns mobile telephone numbers from this person
+ *
+ * @return mobile telephone numbers from this person
+ */
+ public Set<String> getMobilePhone()
+ {
+ Set<String> mobilePhone = new HashSet<String>();
+
+ mobilePhone.addAll(this.mobilePhoneNumbers);
+
+ return mobilePhone;
+ }
+
+ /**
+ * Adds a home telephone number to this person
+ *
+ * @param telephoneNumber the home telephone number
+ */
+ public void addHomePhone(String telephoneNumber)
+ {
+ this.homePhoneNumbers.add(telephoneNumber);
+ }
+
+ /**
+ * Returns home telephone numbers from this person
+ *
+ * @return home telephone numbers from this person
+ */
+ public Set<String> getHomePhone()
+ {
+ Set<String> homePhone = new HashSet<String>();
+
+ homePhone.addAll(this.homePhoneNumbers);
+
+ return homePhone;
+ }
+
+ /**
+ * Returns the distinguished name for this person
+ *
+ * @return the distinguished name for this person
+ */
+ public String getDN()
+ {
+ return this.dn;
+ }
+
+ /**
+ * A string representation of this LdapPersonFoundImpl
+ * (created for debugging purposes)
+ *
+ * @return a printable String
+ */
+ public String toString()
+ {
+ return this.getDisplayName();
+ }
+
+ public int compareTo(LdapPersonFound other)
+ {
+ if(this.toString().equals(other.toString()))
+ return this.getDN().compareTo((other).getDN());
+ else
+ return this.toString().compareTo(other.toString());
+ }
+
+ public boolean equals(Object o)
+ {
+ if(!(o instanceof LdapPersonFound) || o == null)
+ return false;
+ else
+ return this.toString().equals(o.toString()) &&
+ this.getDN().equals(((LdapPersonFound) o).getDN());
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapQueryImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapQueryImpl.java
new file mode 100644
index 0000000..ead975d
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapQueryImpl.java
@@ -0,0 +1,77 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import net.java.sip.communicator.service.ldap.*;
+
+/**
+ * Represents an LDAP search query
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapQueryImpl
+ implements LdapQuery
+{
+ /**
+ * the query
+ * e.g. "John Doe"
+ */
+ private final String query;
+
+ /**
+ * the current state
+ */
+ private volatile State state;
+
+ /**
+ * A simple constructor
+ *
+ * @param query the query
+ */
+ public LdapQueryImpl(String query)
+ {
+ if(query == null)
+ throw new RuntimeException("query is null!");
+ this.query = query;
+ this.state = State.PENDING;
+ }
+
+ /**
+ * Sets the query state to newState
+ *
+ * @param newState the query state
+ */
+ public void setState(State newState)
+ {
+ this.state = newState;
+ }
+
+ /**
+ * Returns the query state
+ *
+ * @return the query state
+ */
+ public State getState()
+ {
+ return this.state;
+ }
+
+ /**
+ * Required by LdapQuery interface
+ *
+ * Returns the query string
+ * e.g "John Doe"
+ *
+ * @return the query string
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapQuery#toString
+ */
+ public String toString()
+ {
+ return this.query;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapSearchSettingsImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapSearchSettingsImpl.java
new file mode 100644
index 0000000..8bb2aa3
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapSearchSettingsImpl.java
@@ -0,0 +1,88 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import net.java.sip.communicator.service.ldap.*;
+
+/**
+ * LDAP Settings.
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapSearchSettingsImpl
+ implements LdapSearchSettings
+{
+ private boolean isMaxResultsSet = false;
+ private int maxResults;
+ private boolean isScopeSet = false;
+ private Scope scope;
+ private boolean isDelaySet = false;
+ private int delay;
+
+ public boolean isMaxResultsSet()
+ {
+ return isMaxResultsSet;
+ }
+
+ /**
+ * Sets the maximum number of results to fetch from the
+ * directory when performing the search query.
+ *
+ * @param maxResults the maximum number of results
+ */
+ public void setMaxResults(int maxResults)
+ {
+ if(maxResults < 1)
+ throw new IllegalArgumentException(
+ "number of max results should be > 0");
+ this.maxResults = maxResults;
+ this.isMaxResultsSet = true;
+ }
+
+ /**
+ * Returns the maximum number of results to fetch from the
+ * directory when performing the search query.
+ *
+ * @return the maximum number of results
+ */
+ public int getMaxResults()
+ {
+ return this.maxResults;
+ }
+
+ public boolean isScopeSet()
+ {
+ return isScopeSet;
+ }
+
+ public void setScope(Scope scope)
+ {
+ this.scope = scope;
+ this.isScopeSet = true;
+ }
+
+ public Scope getScope()
+ {
+ return this.scope;
+ }
+
+ public boolean isDelaySet()
+ {
+ return this.isDelaySet;
+ }
+
+ public void setDelay(int delay)
+ {
+ this.delay = delay;
+ this.isDelaySet = true;
+ }
+
+ public int getDelay()
+ {
+ return this.delay;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/LdapServiceImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapServiceImpl.java
new file mode 100644
index 0000000..479eea7
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/LdapServiceImpl.java
@@ -0,0 +1,174 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap;
+
+import java.util.*;
+
+import org.osgi.framework.*;
+import net.java.sip.communicator.service.configuration.*;
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.service.resources.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ * The LDAP service allows other modules to query an LDAP server.
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapServiceImpl
+ implements LdapService
+{
+ /**
+ * All the servers registered
+ */
+ private LdapDirectorySet serverSet;
+
+ /**
+ * the LdapFactory, used to create LdapDirectory-s,
+ * LdapDirectorySettings, ...
+ */
+ private LdapFactory factory = new LdapFactoryImpl();
+
+ /**
+ * The logger for this class.
+ */
+ private static Logger logger = Logger
+ .getLogger(LdapServiceImpl.class);
+
+ /**
+ * BundleContext from the OSGI bus.
+ */
+ private static BundleContext bundleContext;
+
+ /**
+ * Reference to the configuration service
+ */
+ private static ConfigurationService configService;
+
+ /**
+ * Reference to the resource management service
+ */
+ private static ResourceManagementService resourceService;
+
+ /**
+ * Starts the service.
+ *
+ * @param bc BundleContext
+ */
+ public void start(BundleContext bc)
+ {
+ logger.trace("Starting the LDAP implementation.");
+ bundleContext = bc;
+
+ serverSet = new LdapDirectorySetImpl(getConfigService());
+ loadPersistentConfig();
+ }
+
+ /**
+ * Stops the service.
+ *
+ * @param bc BundleContext
+ */
+ public void stop(BundleContext bc)
+ {
+ logger.trace("Stopping the LDAP implementation.");
+ }
+
+ /**
+ * Returns a reference to a ConfigurationService implementation currently
+ * registered in the bundle context or null if no such implementation was
+ * found.
+ *
+ * @return a currently valid implementation of the ConfigurationService.
+ */
+ public static ConfigurationService getConfigService()
+ {
+ if(configService == null)
+ {
+ ServiceReference confReference
+ = bundleContext.getServiceReference(
+ ConfigurationService.class.getName());
+ configService
+ = (ConfigurationService) bundleContext.getService(
+ confReference);
+ }
+ return configService;
+ }
+
+ /**
+ * Returns a reference to a ConfigurationService implementation currently
+ * registered in the bundle context or null if no such implementation was
+ * found.
+ *
+ * @return a currently valid implementation of the ConfigurationService.
+ */
+ public static ResourceManagementService getResourceManagementService()
+ {
+ if(resourceService == null)
+ {
+ ServiceReference confReference
+ = bundleContext.getServiceReference(
+ ResourceManagementService.class.getName());
+ resourceService
+ = (ResourceManagementService) bundleContext.getService(
+ confReference);
+ }
+ return resourceService;
+ }
+
+ /**
+ * Returns all the LDAP directories
+ *
+ * @return the LdapDirectorySet containing all the LdapDirectory(s)
+ * registered
+ *
+ * @see net.java.sip.communicator.service.ldap#getServerSet
+ */
+ public LdapDirectorySet getServerSet()
+ {
+ return serverSet;
+ }
+
+ /**
+ * Required bu interface LdapService.
+ * Returns the LdapFactory, used to
+ * create LdapDirectory-s, LdapDirectorySettings, LdapQuery, ...
+ *
+ * @return the LdapFactory
+ *
+ * @see net.java.sip.communicator.service.ldap#getFactory
+ */
+ public LdapFactory getFactory()
+ {
+ return factory;
+ }
+
+ /**
+ * Loads config form the user preferences
+ * in the serverSet
+ */
+ private void loadPersistentConfig()
+ {
+ String name;
+ LdapDirectorySettings settings = getFactory().createServerSettings();
+ LdapDirectory server;
+ List<String> list = getConfigService().
+ getPropertyNamesByPrefix(
+ "net.java.sip.communicator.impl.ldap.directories", true);
+
+ for(Object configEntry : list)
+ {
+ name = getConfigService().getString(configEntry.toString());
+ if(name != null)
+ {
+ settings.persistentLoad(name);
+ server = this.getFactory().createServer(settings);
+ this.serverSet.addServer(server);
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/configform/DirectorySettingsForm.java b/src/net/java/sip/communicator/impl/ldap/configform/DirectorySettingsForm.java
new file mode 100644
index 0000000..73ec4bb
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/configform/DirectorySettingsForm.java
@@ -0,0 +1,613 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap.configform;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.service.ldap.LdapConstants.*;
+import net.java.sip.communicator.impl.ldap.*;
+import net.java.sip.communicator.util.swing.*;
+
+/**
+ * The page with hostname/port/encryption fields
+ *
+ * @author Sebastien Mazy
+ * @author Sebastien Vincent
+ */
+public class DirectorySettingsForm
+ extends SIPCommDialog
+ implements ActionListener
+{
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * the temporary settings
+ */
+ private LdapDirectorySettings settings;
+
+ /**
+ * component holding the name
+ */
+ private JTextField nameField;
+
+ /**
+ * component holding the hostname
+ */
+ private JTextField hostnameField;
+
+ /**
+ * component holding the connection method
+ */
+ private JCheckBox encryptionBox = new JCheckBox(
+ Resources.getString("impl.ldap.USE_SSL"));
+
+ /**
+ * component displaying the port number
+ */
+ private JSpinner portSpinner;
+
+ /**
+ * model holding the port number
+ */
+ private SpinnerNumberModel portModel;
+
+ /**
+ * the component holding the bind distinguished name
+ */
+ private JTextField bindDNField;
+
+ /**
+ * the component holding the password
+ */
+ private JPasswordField passwordField;
+
+ /**
+ * component holding the name of the server
+ *
+ * @see net.java.sip.communicator.plugin.ldaptools.components.LdapDNField
+ */
+ private JTextField baseDNField = new JTextField();
+
+ /**
+ * Strings of the authentication method combobox
+ * (must be in the same order as in enum Auth)
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapConstants#Auth
+ */
+ private final String[] authStrings =
+ {
+ Resources.getString("impl.ldap.AUTH_NONE"),
+ Resources.getString("impl.ldap.AUTH_SIMPLE")
+ };
+
+ /**
+ * Component holding the connection method
+ */
+ private JComboBox authList = new JComboBox(authStrings);
+
+ /**
+ * Strings of the connection method combobox
+ * (must be in the same order as in enum Encryption)
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapConstants#Encryption
+ */
+ private final String[] scopeStrings =
+ {
+ Resources.getString("impl.ldap.SCOPE_SUB_TREE"),
+ Resources.getString("impl.ldap.SCOPE_ONE")
+ };
+
+ /**
+ * Component holding the connection method
+ */
+ private JComboBox scopeList = new JComboBox(scopeStrings);
+
+ /**
+ * Save button.
+ */
+ private JButton saveBtn = new JButton(
+ Resources.getString("impl.ldap.SAVE"));
+
+ /**
+ * Cancel button.
+ */
+ private JButton cancelBtn = new JButton(
+ Resources.getString("impl.ldap.CANCEL"));
+
+ /**
+ * Return code.
+ */
+ private int retCode = 0;
+
+ /**
+ * Constructor.
+ */
+ public DirectorySettingsForm()
+ {
+ this.settings =
+ LdapActivator.getLdapService().getFactory().createServerSettings();
+
+ this.setTitle(Resources.getString("impl.ldap.CONFIG_FORM_TITLE"));
+ getContentPane().add(getContentPanel());
+ }
+
+ /**
+ * the panel to display in the card layout of the wizard
+ *
+ * @return this page's panel
+ */
+ public JPanel getContentPanel()
+ {
+ JPanel contentPanel = new TransparentPanel(new BorderLayout());
+ JPanel mainPanel = new TransparentPanel();
+ JPanel basePanel = new TransparentPanel(new GridBagLayout());
+ JPanel authPanel = new TransparentPanel(new GridBagLayout());
+ JPanel searchPanel = new TransparentPanel(new GridBagLayout());
+ JPanel btnPanel = new TransparentPanel(new FlowLayout(
+ FlowLayout.RIGHT));
+ BoxLayout boxLayout = new BoxLayout(mainPanel, BoxLayout.Y_AXIS);
+
+ mainPanel.setBorder(BorderFactory.createTitledBorder(
+ "LDAP settings"));
+
+ GridBagConstraints c = new GridBagConstraints();
+
+ /* name text field */
+ JLabel nameLabel = new JLabel(
+ Resources.getString("impl.ldap.SERVER_NAME"));
+ //Resources.getString("ldapNameLabel"));
+ this.nameField = new JTextField();
+ nameLabel.setLabelFor(nameField);
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 0, 5);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(nameLabel, c);
+ c.gridx = 1;
+ c.gridy = 0;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 0, 50);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_END;
+ basePanel.add(nameField, c);
+ JLabel nameExampleLabel = new JLabel("My LDAP server");
+ //Resources.getString("ldapNameExample"));
+ nameExampleLabel.setForeground(Color.GRAY);
+ nameExampleLabel.setFont(nameExampleLabel.getFont().deriveFont(8));
+ c.gridx = 1;
+ c.gridy = 1;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(0, 13, 2, 0);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(nameExampleLabel, c);
+
+ /* hostname text field */
+ JLabel hostnameLabel = new JLabel(
+ Resources.getString("impl.ldap.SERVER_HOSTNAME"));
+ //Resources.getString("ldapHostnameLabel"));
+ this.hostnameField = new JTextField();
+ hostnameLabel.setLabelFor(hostnameField);
+ c.gridx = 0;
+ c.gridy = 2;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 0, 5);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(hostnameLabel, c);
+ c.gridx = 1;
+ c.gridy = 2;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 0, 50);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_END;
+ basePanel.add(hostnameField, c);
+ JLabel hostExampleLabel = new JLabel("ldap.example.org");
+ hostExampleLabel.setForeground(Color.GRAY);
+ hostExampleLabel.setFont(hostExampleLabel.getFont().deriveFont(8));
+ c.gridx = 1;
+ c.gridy = 3;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(0, 13, 2, 0);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(hostExampleLabel, c);
+
+ /* network port number */
+ JLabel portLabel = new JLabel(
+ Resources.getString("impl.ldap.SERVER_PORT"));
+ this.portModel = new SpinnerNumberModel(389, 1, 65535, 1);
+ this.portSpinner = new JSpinner(portModel);
+ portLabel.setLabelFor(portSpinner);
+ c.gridx = 0;
+ c.gridy = 4;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 50, 2, 5);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(portLabel, c);
+ c.gridx = 1;
+ c.gridy = 4;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 2, 5);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(portSpinner, c);
+ c.gridx = 1;
+ c.gridy = 5;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 2, 5);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ basePanel.add(encryptionBox, c);
+
+ /* bind DN (Distinguished Name) */
+ authList.setSelectedIndex(0);
+ JLabel authLabel = new JLabel(
+ Resources.getString("impl.ldap.AUTHENTICATION"));
+ authLabel.setLabelFor(authList);
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 2, 5);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ authPanel.add(authLabel, c);
+ c.gridx = 1;
+ c.gridy = 0;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 5, 2, 5);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ authPanel.add(authList, c);
+
+ JLabel bindDNLabel = new JLabel(
+ Resources.getString("impl.ldap.USERNAME"));
+ this.bindDNField = new JTextField();
+ bindDNLabel.setLabelFor(this.bindDNField);
+ c.gridx = 0;
+ c.gridy = 1;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 0, 5);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ authPanel.add(bindDNLabel, c);
+ c.gridx = 1;
+ c.gridy = 1;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 0, 50);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_END;
+ authPanel.add(this.bindDNField, c);
+ JLabel bindDNExampleLabel = new JLabel("uid=user,o=example");
+ bindDNExampleLabel.setForeground(Color.GRAY);
+ bindDNExampleLabel.setFont(bindDNExampleLabel.getFont().deriveFont(8));
+ c.gridx = 1;
+ c.gridy = 2;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(0, 13, 2, 0);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ authPanel.add(bindDNExampleLabel, c);
+ /* password */
+ JLabel passwordLabel = new JLabel(
+ Resources.getString("impl.ldap.PASSWORD"));
+ this.passwordField = new JPasswordField();
+ passwordLabel.setLabelFor(this.passwordField);
+ c.gridx = 0;
+ c.gridy = 3;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 2, 5);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ authPanel.add(passwordLabel, c);
+ c.gridx = 1;
+ c.gridy = 3;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 20, 50);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_END;
+ authPanel.add(this.passwordField, c);
+
+ /* base distinguished name selection text field */
+ JLabel baseDNLabel = new JLabel(
+ Resources.getString("impl.ldap.SEARCH_BASE"));
+ baseDNLabel.setLabelFor(baseDNField);
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 0, 5);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.FIRST_LINE_START;
+ searchPanel.add(baseDNLabel, c);
+ c.gridx = 1;
+ c.gridy = 0;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(2, 5, 0, 50);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.FIRST_LINE_END;
+ searchPanel.add(baseDNField, c);
+ JLabel baseDNExampleLabel = new JLabel("o=example");
+ baseDNExampleLabel.setForeground(Color.GRAY);
+ baseDNExampleLabel.setFont(baseDNExampleLabel.getFont().deriveFont(8));
+ c.gridx = 1;
+ c.gridy = 1;
+ c.weightx = 1;
+ c.weighty = 0;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(0, 13, 2, 0);
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.LINE_START;
+ searchPanel.add(baseDNExampleLabel, c);
+
+ /* search scope */
+ scopeList.setSelectedIndex(0);
+ JLabel scopeLabel = new JLabel(
+ Resources.getString("impl.ldap.SCOPE"));
+ scopeLabel.setLabelFor(scopeList);
+ c.gridx = 0;
+ c.gridy = 2;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 50, 2, 5);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ searchPanel.add(scopeLabel, c);
+ c.gridx = 1;
+ c.gridy = 2;
+ c.weightx = 0;
+ c.weighty = 0;
+ c.gridwidth = 1;
+ c.insets = new Insets(2, 5, 2, 5);
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.LINE_START;
+ searchPanel.add(scopeList, c);
+
+ mainPanel.setLayout(boxLayout);
+ mainPanel.add(basePanel);
+ mainPanel.add(new JSeparator());
+ mainPanel.add(searchPanel);
+ mainPanel.add(new JSeparator());
+ mainPanel.add(authPanel);
+
+ /* listeners */
+ this.encryptionBox.addActionListener(this);
+ this.nameField.addActionListener(this);
+ this.hostnameField.addActionListener(this);
+ this.bindDNField.addActionListener(this);
+ this.passwordField.addActionListener(this);
+ this.saveBtn.addActionListener(this);
+ this.cancelBtn.addActionListener(this);
+
+ btnPanel.add(saveBtn);
+ btnPanel.add(cancelBtn);
+
+ contentPanel.add(mainPanel, BorderLayout.CENTER);
+ contentPanel.add(btnPanel, BorderLayout.SOUTH);
+
+ return contentPanel;
+ }
+
+ /**
+ * Loads the information from the LdapDirectorySettings instance
+ * into the UI.
+ *
+ * @param settings the LdapDirectorySettings to load
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapDirectorySettings
+ */
+ public void loadData(LdapDirectorySettings settings)
+ {
+ //load data from introduction page
+ this.nameField.setText(settings.getName());
+
+ // load data from connection page
+ this.hostnameField.setText(settings.getHostname());
+
+ this.encryptionBox.setSelected(
+ settings.getEncryption() == Encryption.SSL);
+
+ if(settings.getPort() != 0)
+ {
+ this.portModel.setValue(new Integer(settings.getPort()));
+ }
+ else
+ {
+ this.portModel.setValue(
+ new Integer(settings.getEncryption().defaultPort()));
+ }
+
+ this.bindDNField.setText(settings.getBindDN());
+ this.passwordField.setText(settings.getPassword());
+
+ // load data from search page
+ this.baseDNField.setText(settings.getBaseDN());
+
+ this.scopeList.setSelectedIndex(settings.getScope().ordinal());
+ this.authList.setSelectedIndex(settings.getAuth().ordinal());
+ }
+
+ /**
+ * Saves the information in the LdapDirectorySettings instance
+ * from the UI
+ *
+ * @param settings the LdapDirectorySettings to save the data in
+ *
+ * @see net.java.sip.communicator.service.ldap.LdapDirectorySettings
+ */
+ public void saveData(LdapDirectorySettings settings)
+ {
+ settings.setName(this.nameField.getText());
+ settings.setHostname(hostnameField.getText());
+
+ if(encryptionBox.isSelected())
+ {
+ settings.setEncryption(Encryption.SSL);
+ }
+ else
+ {
+ settings.setEncryption(Encryption.CLEAR);
+ }
+
+ // auth simple/none
+ switch(authList.getSelectedIndex())
+ {
+ case 0:
+ settings.setAuth(Auth.NONE);
+ break;
+ case 1:
+ settings.setAuth(Auth.SIMPLE);
+ break;
+ }
+
+ settings.setPort(((Integer)this.portSpinner.getValue()).intValue());
+
+ settings.setBindDN(this.bindDNField.getText());
+
+ settings.setPassword(new String(this.passwordField.getPassword()));
+
+ settings.setBaseDN(this.baseDNField.getText());
+
+ switch(scopeList.getSelectedIndex())
+ {
+ case 0:
+ settings.setScope(Scope.SUB);
+ break;
+ case 1:
+ settings.setScope(Scope.ONE);
+ break;
+ }
+ }
+
+ /**
+ * Implementation of actionPerformed.
+ *
+ * @param e the ActionEvent triggered
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ Object src = e.getSource();
+
+ if(src == encryptionBox)
+ {
+ int port = ((Integer)portSpinner.getValue()).intValue();
+
+ if(encryptionBox.isSelected())
+ {
+ if(port == LdapConstants.Encryption.CLEAR.defaultPort())
+ {
+ portSpinner.setValue(new Integer(
+ LdapConstants.Encryption.SSL.defaultPort()));
+ }
+ }
+ else
+ {
+ if(port == LdapConstants.Encryption.SSL.defaultPort())
+ {
+ portSpinner.setValue(new Integer(
+ LdapConstants.Encryption.CLEAR.defaultPort()));
+ }
+ }
+ }
+ else if(src == saveBtn)
+ {
+ this.saveData(settings);
+ retCode = 1;
+ dispose();
+ }
+ else if(src == cancelBtn)
+ {
+ retCode = 0;
+ dispose();
+ }
+ }
+
+ /**
+ * All functions implemented in this method will be invoked when user
+ * presses the Escape key.
+ *
+ * @param escaped <tt>true</tt> if this dialog has been closed by pressing
+ * the Esc key; otherwise, <tt>false</tt>
+ */
+ protected void close(boolean escaped)
+ {
+ cancelBtn.doClick();
+ }
+
+ /**
+ * Show the dialog and returns if the user has modified something (create
+ * or modify entry).
+ *
+ * @return true if the user has modified something (create
+ * or modify entry), false otherwise.
+ */
+ public int showDialog()
+ {
+ retCode = 0;
+ setVisible(true);
+
+ // this will block until user click on save/cancel/press escape/close
+ //the window
+ setVisible(false);
+ return retCode;
+ }
+
+ /**
+ * Returns LDAP settings.
+ *
+ * @return LDAP settings
+ */
+ public LdapDirectorySettings getSettings()
+ {
+ return settings;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/configform/LdapConfigForm.java b/src/net/java/sip/communicator/impl/ldap/configform/LdapConfigForm.java
new file mode 100644
index 0000000..c12d01c
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/configform/LdapConfigForm.java
@@ -0,0 +1,298 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap.configform;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import net.java.sip.communicator.util.*;
+import net.java.sip.communicator.util.swing.*;
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.impl.ldap.*;
+
+/**
+ * This ConfigurationForm shows the list of LDAP directories
+ * and allow users to manage them.
+ *
+ * @author Sebastien Mazy
+ * @author Sebastien Vincent
+ */
+public class LdapConfigForm
+ extends TransparentPanel
+ implements ConfigurationForm,
+ ActionListener,
+ ListSelectionListener
+{
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * The logger for this class.
+ */
+ private static Logger logger = Logger.getLogger(LdapConfigForm.class);
+
+ /**
+ * opens the new directory registration wizard
+ */
+ private JButton newButton = new JButton("+");
+
+ /**
+ * opens a directory modification dialog
+ */
+ private JButton modifyButton = new JButton(
+ Resources.getString("impl.ldap.EDIT"));
+
+ /**
+ * pops a directory deletion confirmation dialog
+ */
+ private JButton removeButton = new JButton("-");
+
+ /**
+ * displays the registered directories
+ */
+ private JTable directoryTable = new JTable();
+
+ /**
+ * contains the new/modify/remove buttons
+ */
+ private TransparentPanel buttonsPanel
+ = new TransparentPanel(new FlowLayout(FlowLayout.LEFT));
+
+ /**
+ * contains the directoryTable
+ */
+ private JScrollPane scrollPane = new JScrollPane();
+
+ /**
+ * contains the buttonsPanel,
+ */
+ private JPanel rightPanel = new TransparentPanel(new BorderLayout());
+
+ /**
+ * contains listPanel and rightPanel
+ */
+ private JPanel mainPanel = this;
+
+ /**
+ * model for the directoryTable
+ */
+ private LdapTableModel tableModel = new LdapTableModel();
+
+ /**
+ * Settings form.
+ */
+ private final DirectorySettingsForm settingsForm =
+ new DirectorySettingsForm();
+
+ /**
+ * Constructor
+ */
+ public LdapConfigForm()
+ {
+ super(new BorderLayout());
+ logger.trace("New LDAP configuration form.");
+ this.initComponents();
+ }
+
+ /**
+ * Inits the swing components
+ */
+ private void initComponents()
+ {
+ this.modifyButton.setEnabled(false);
+ this.removeButton.setEnabled(false);
+
+ this.newButton.setSize(newButton.getMinimumSize());
+ this.modifyButton.setSize(modifyButton.getMinimumSize());
+ this.removeButton.setSize(removeButton.getMinimumSize());
+
+ this.directoryTable.setRowHeight(22);
+ this.directoryTable.setSelectionMode(
+ ListSelectionModel.SINGLE_SELECTION);
+
+ this.directoryTable.setShowHorizontalLines(false);
+ this.directoryTable.setShowVerticalLines(false);
+ this.directoryTable.setModel(tableModel);
+ this.directoryTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+
+ settingsForm.setModal(true);
+
+ /*
+ * TODO fix: table width change when refreshing table
+ this.directoryTable.getColumnModel().getColumn(0).setPreferredWidth(10);
+ this.directoryTable.getColumnModel().getColumn(1).setPreferredWidth(100);
+ this.directoryTable.getColumnModel().getColumn(2).setPreferredWidth(100);
+ */
+
+ /* consistency with the accounts config form */
+ this.rightPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ this.rightPanel.add(this.buttonsPanel, BorderLayout.NORTH);
+
+ this.scrollPane.getViewport().add(this.directoryTable);
+ this.mainPanel.add(this.scrollPane, BorderLayout.CENTER);
+ this.mainPanel.add(this.rightPanel, BorderLayout.SOUTH);
+
+ this.mainPanel.setPreferredSize(new Dimension(500, 400));
+
+ this.buttonsPanel.add(this.newButton);
+ this.buttonsPanel.add(this.removeButton);
+ this.buttonsPanel.add(this.modifyButton);
+
+ this.directoryTable.getSelectionModel().addListSelectionListener(this);
+
+ this.newButton.setActionCommand("new");
+ this.newButton.addActionListener(this);
+ this.modifyButton.addActionListener(this);
+ this.modifyButton.setActionCommand("modify");
+ this.removeButton.addActionListener(this);
+ this.removeButton.setActionCommand("remove");
+ }
+
+ /**
+ * @see net.java.sip.communicator.service.gui.ConfigurationForm#getTitle
+ */
+ public String getTitle()
+ {
+ return Resources.getString("impl.ldap.CONFIG_FORM_TITLE");
+ }
+
+ /**
+ * @see net.java.sip.communicator.service.gui.ConfigurationForm#getIcon
+ */
+ public byte[] getIcon()
+ {
+ return Resources.getImageInBytes("LDAP_CONFIG_FORM_ICON");
+ }
+
+ /**
+ * @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 -1;
+ }
+
+ /**
+ * Processes buttons events (new, modify, remove)
+ *
+ * @see java.awt.event.ActionListener#actionPerformed
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ int row = this.directoryTable.getSelectedRow();
+
+ LdapFactory factory = LdapActivator.getLdapService().getFactory();
+ LdapDirectorySet serverSet =
+ LdapActivator.getLdapService().getServerSet();
+
+ if (e.getActionCommand().equals("new"))
+ {
+ LdapDirectorySettings settings = factory.createServerSettings();
+ settingsForm.loadData(settings);
+
+ int ret = settingsForm.showDialog();
+
+ if(ret == 1)
+ {
+ LdapDirectory server = factory.createServer(
+ settingsForm.getSettings());
+ serverSet.addServer(server);
+ refresh();
+ }
+ }
+
+ if (e.getActionCommand().equals("modify") && row != -1)
+ {
+ LdapDirectory oldServer = this.tableModel.getServerAt(row);
+ LdapDirectorySettings settings = oldServer.getSettings();
+ settingsForm.loadData(settings);
+
+ int ret = settingsForm.showDialog();
+
+ if(ret == 1)
+ {
+ LdapDirectory newServer = factory.createServer(
+ settingsForm.getSettings());
+ serverSet.removeServerWithName(oldServer.getSettings().
+ getName());
+ serverSet.addServer(newServer);
+ refresh();
+ }
+ }
+
+ if (e.getActionCommand().equals("remove") && row != -1)
+ {
+ serverSet.removeServerWithName(this.tableModel.getServerAt(row).
+ getSettings().getName());
+
+ refresh();
+ }
+ }
+
+ /**
+ * Required by ListSelectionListener. Enables the "modify"
+ * button when a server is selectionned in the table
+ *
+ * @param e event triggered
+ */
+ public void valueChanged(ListSelectionEvent e)
+ {
+ if(this.directoryTable.getSelectedRow() == -1)
+ {
+ this.modifyButton.setEnabled(false);
+ this.removeButton.setEnabled(false);
+ }
+ else if(!e.getValueIsAdjusting())
+ {
+ this.modifyButton.setEnabled(true);
+ this.removeButton.setEnabled(true);
+ }
+ }
+
+ /**
+ * refreshes the table display
+ */
+ private void refresh()
+ {
+ this.tableModel.fireTableStructureChanged();
+ }
+
+ /**
+ * 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;
+ }
+}
+
diff --git a/src/net/java/sip/communicator/impl/ldap/configform/LdapTableModel.java b/src/net/java/sip/communicator/impl/ldap/configform/LdapTableModel.java
new file mode 100644
index 0000000..f935921
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/configform/LdapTableModel.java
@@ -0,0 +1,169 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap.configform;
+
+import javax.swing.table.*;
+
+import net.java.sip.communicator.service.ldap.*;
+import net.java.sip.communicator.impl.ldap.*;
+
+/**
+ * A table model suitable for the directories list in
+ * the config form. Takes its data in an LdapDirectorySet.
+ *
+ * @author Sebastien Mazy
+ */
+public class LdapTableModel
+ extends AbstractTableModel
+{
+ /**
+ * Serial version UID.
+ */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * a reference to the LdapDirectorySet from the ldap service
+ */
+ private LdapDirectorySet serverSet =
+ LdapActivator.getLdapService().getServerSet();
+
+ /**
+ * Returns the title for this column
+ *
+ * @param column the column
+ *
+ * @return the title for this column
+ *
+ * @see javax.swing.table.AbstractTableModel#getColumnName
+ */
+ public String getColumnName(int column)
+ {
+ switch(column)
+ {
+ case 0:
+ return Resources.getString("impl.ldap.ENABLED");
+ case 1:
+ return Resources.getString("impl.ldap.SERVER_NAME");
+ case 2:
+ return Resources.getString("impl.ldap.SERVER_HOSTNAME");
+ default:
+ throw new IllegalArgumentException("column not found");
+ }
+ }
+
+ /**
+ * Returns the number of rows in the table
+ *
+ * @return the number of rows in the table
+ * @see javax.swing.table.AbstractTableModel#getRowCount
+ */
+ public int getRowCount()
+ {
+ return this.serverSet.size();
+ }
+
+ /**
+ * Returns the number of column in the table
+ *
+ * @return the number of columns in the table
+ *
+ * @see javax.swing.table.AbstractTableModel#getColumnCount
+ */
+ public int getColumnCount()
+ {
+ // 3 columns: "enable", "name" and "hostname"
+ return 3;
+ }
+
+ /**
+ * Returns the text for the given cell of the table
+ *
+ * @param row cell row
+ * @param column cell column
+ *
+ * @see javax.swing.table.AbstractTableModel#getValueAt
+ */
+ public Object getValueAt(int row, int column)
+ {
+ switch(column)
+ {
+ case 0:
+ return new Boolean(this.getServerAt(row).isEnabled());
+ case 1:
+ return this.getServerAt(row).getSettings().getName();
+ case 2:
+ return this.getServerAt(row).getSettings().getHostname();
+ default:
+ throw new IllegalArgumentException("column not found");
+ }
+ }
+
+ /**
+ * Returns the LdapDirectory at the row 'row'
+ *
+ * @param row the row on which to find the LdapDirectory
+ *
+ * @return the LdapDirectory found
+ */
+ public LdapDirectory getServerAt(int row)
+ {
+ int i = 0;
+ for(LdapDirectory server : serverSet)
+ {
+ if(i == row)
+ return server;
+ i++;
+ }
+
+ throw new IllegalArgumentException("row not found");
+ }
+
+ /**
+ * Returns whether a cell is editable. Only "enable" column (checkboxes)
+ * is editable
+ *
+ * @param row row of the cell
+ * @param col column of the cell
+ *
+ * @return whether the cell is editable
+ */
+ public boolean isCellEditable(int row, int col)
+ {
+ if(col == 0)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Overides a method that always returned Object.class
+ * Now it will return Boolean.class for the first method,
+ * letting the DefaultTableCellRenderer create checkboxes.
+ *
+ * @param columnIndex index of the column
+ * @return Column class
+ */
+ public Class<?> getColumnClass(int columnIndex)
+ {
+ return getValueAt(0, columnIndex).getClass();
+ }
+
+ /**
+ * Sets a value in an editable cell, that is to say
+ * an enable/disable chekboxin colum 0
+ */
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex)
+ {
+ if(columnIndex != 0)
+ throw new IllegalArgumentException("non editable column!");
+ LdapDirectory server = this.getServerAt(rowIndex);
+
+ /*toggle enabled marker and save */
+ server.setEnabled(!server.isEnabled());
+ server.getSettings().persistentSave();
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/configform/Resources.java b/src/net/java/sip/communicator/impl/ldap/configform/Resources.java
new file mode 100644
index 0000000..7e69c44
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/configform/Resources.java
@@ -0,0 +1,55 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.ldap.configform;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.ldap.*;
+
+/**
+ * The <tt>Resources</tt> class manages the access to the internationalization
+ * properties files and the image resources used in this plugin.
+ *
+ * @author Yana Stamcheva
+ */
+public class Resources
+{
+ /**
+ * Returns an internationalized string corresponding to the given key.
+ *
+ * @param key The key of the string.
+ * @return An internationalized string corresponding to the given key.
+ */
+ public static String getString(String key)
+ {
+ return LdapServiceImpl.getResourceManagementService()
+ .getI18NString(key);
+ }
+
+ /**
+ * Loads an image from a given image identifier.
+ *
+ * @param imageID The identifier of the image.
+ * @return The image for the given identifier.
+ */
+ public static ImageIcon getImage(String imageID)
+ {
+ return LdapServiceImpl.getResourceManagementService().getImage(imageID);
+ }
+
+ /**
+ * Loads an image from a given image identifier.
+ *
+ * @param imageID The identifier of the image.
+ * @return The image for the given identifier.
+ */
+ public static byte[] getImageInBytes(String imageID)
+ {
+ return LdapServiceImpl.getResourceManagementService().
+ getImageInBytes(imageID);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/ldap/ldap.manifest.mf b/src/net/java/sip/communicator/impl/ldap/ldap.manifest.mf
new file mode 100644
index 0000000..0c99bbd
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/ldap.manifest.mf
@@ -0,0 +1,27 @@
+Bundle-Activator: net.java.sip.communicator.impl.ldap.LdapActivator
+Bundle-Name: LDAP service provider
+Bundle-Description: A bundle that implements LDAP service.
+Bundle-Vendor: sip-communicator.org
+Bundle-Version: 0.0.1
+System-Bundle: yes
+Import-Package: org.osgi.framework,
+ javax.naming,
+ javax.naming.directory,
+ javax.naming.event,
+ javax.swing,
+ javax.swing.border,
+ javax.swing.event,
+ javax.swing.table,
+ javax.swing.tree,
+ javax.swing.text,
+ net.java.sip.communicator.util,
+ net.java.sip.communicator.util.swing,
+ net.java.sip.communicator.service.gui,
+ net.java.sip.communicator.service.configuration,
+ net.java.sip.communicator.service.resources,
+ net.java.sip.communicator.service.ldap,
+ net.java.sip.communicator.service.ldap.event,
+Export-Package: net.java.sip.communicator.service.ldap,
+ net.java.sip.communicator.service.ldap.event
+Metadata-Location: /net/java/sip/communicator/impl/ldap/ldap.metadata.xml
+
diff --git a/src/net/java/sip/communicator/impl/ldap/ldap.metadata.xml b/src/net/java/sip/communicator/impl/ldap/ldap.metadata.xml
new file mode 100644
index 0000000..ea4bca4
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/ldap/ldap.metadata.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<bundle>
+ <component class="net.java.sip.communicator.impl.ldap.LdapServiceImpl">
+ <provides service="net.java.sip.communicator.service.ldap.LdapService"/>
+ </component>
+</bundle>