diff options
author | Sebastien Vincent <seb@jitsi.org> | 2011-03-09 09:30:54 +0000 |
---|---|---|
committer | Sebastien Vincent <seb@jitsi.org> | 2011-03-09 09:30:54 +0000 |
commit | 5393fc96a763bcf0ecedf95275edc7712f2b897f (patch) | |
tree | 9dab2f9963a2aca12b6038ada01165a655141057 /src/net/java/sip/communicator/impl | |
parent | dcb607dd8b10f297af6a590e29a7b9b6f6002aff (diff) | |
download | jitsi-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')
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> |