LDAP: progress on EWS LDAP implementation and refactoring

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1332 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-08-09 20:15:28 +00:00
parent 19865c50b0
commit 905870f7da
6 changed files with 245 additions and 84 deletions

View File

@ -652,7 +652,7 @@ public abstract class ExchangeSession {
/**
* Test if the contact matches current condition.
*
*
* @param contact Exchange Contact
* @return true if contact matches condition
*/
@ -676,6 +676,15 @@ public abstract class ExchangeSession {
public boolean isEmpty() {
return false;
}
public String getAttributeName() {
return attributeName;
}
public String getValue() {
return value;
}
}
/**
@ -736,7 +745,7 @@ public abstract class ExchangeSession {
return false;
}
}
}
/**
@ -776,15 +785,9 @@ public abstract class ExchangeSession {
public boolean isMatch(ExchangeSession.Contact contact) {
String actualValue = contact.get(attributeName);
if (operator == Operator.IsNull) {
return actualValue == null;
} else if (operator == Operator.IsFalse) {
return "false".equals(actualValue);
} else if (operator == Operator.IsTrue) {
return "true".equals(actualValue);
} else {
return false;
}
return (operator == Operator.IsNull && actualValue == null) ||
(operator == Operator.IsFalse && "false".equals(actualValue)) ||
(operator == Operator.IsTrue && "true".equals(actualValue));
}
}
@ -1004,7 +1007,7 @@ public abstract class ExchangeSession {
Set<String> visibleRecipients = new HashSet<String>();
Address[] recipients = mimeMessage.getAllRecipients();
for (Address address : recipients) {
visibleRecipients.add(((InternetAddress)address).getAddress().toLowerCase());
visibleRecipients.add(((InternetAddress) address).getAddress().toLowerCase());
}
for (String recipient : rcptToRecipients) {
if (!visibleRecipients.contains(recipient.toLowerCase())) {
@ -1732,6 +1735,10 @@ public abstract class ExchangeSession {
return name;
}
public void setName(String name) {
this.itemName = name;
}
/**
* Compute vcard uid from name.
*
@ -2003,7 +2010,7 @@ public abstract class ExchangeSession {
// TODO: get current user attendee status, i18n
String subject = vCalendar.getFirstVeventPropertyValue("SUMMARY");
if (subject == null) {
subject = BundleMessage.format("MEETING_REQUEST");
subject = BundleMessage.format("MEETING_REQUEST");
}
writer.writeHeader("Subject", subject);
@ -2809,6 +2816,8 @@ public abstract class ExchangeSession {
return results;
}
public abstract Map<String, Contact> galFind(Condition condition) throws IOException;
/**
* Full Contact attribute list
*/

View File

@ -25,6 +25,7 @@ import davmail.exception.DavMailException;
import davmail.exception.HttpNotFoundException;
import davmail.exchange.ExchangeSession;
import davmail.exchange.VObject;
import davmail.exchange.XMLStreamUtil;
import davmail.http.DavGatewayHttpClientFacade;
import davmail.ui.tray.DavGatewayTray;
import davmail.util.IOUtil;
@ -176,6 +177,96 @@ public class DavExchangeSession extends ExchangeSession {
return !getFolderPath(folderPath).toLowerCase().startsWith(mailPath.toLowerCase());
}
/**
* LDAP to Exchange Criteria Map
*/
static final HashMap<String, String> GALFIND_CRITERIA_MAP = new HashMap<String, String>();
static {
GALFIND_CRITERIA_MAP.put("uid", "AN");
// assume mail starts with firstname
GALFIND_CRITERIA_MAP.put("smtpemail1", "FN");
GALFIND_CRITERIA_MAP.put("displayname", "DN");
GALFIND_CRITERIA_MAP.put("cn", "DN");
GALFIND_CRITERIA_MAP.put("givenname", "FN");
GALFIND_CRITERIA_MAP.put("sn", "LN");
GALFIND_CRITERIA_MAP.put("title", "TL");
GALFIND_CRITERIA_MAP.put("company", "CP");
GALFIND_CRITERIA_MAP.put("o", "CP");
GALFIND_CRITERIA_MAP.put("l", "OF");
GALFIND_CRITERIA_MAP.put("department", "DP");
GALFIND_CRITERIA_MAP.put("apple-group-realname", "DP");
}
/**
* Exchange to LDAP attribute map
*/
static final HashMap<String, String> GALFIND_ATTRIBUTE_MAP = new HashMap<String, String>();
static {
GALFIND_ATTRIBUTE_MAP.put("uid", "AN");
GALFIND_ATTRIBUTE_MAP.put("smtpemail1", "EM");
GALFIND_ATTRIBUTE_MAP.put("cn", "DN");
GALFIND_ATTRIBUTE_MAP.put("displayName", "DN");
GALFIND_ATTRIBUTE_MAP.put("telephoneNumber", "PH");
GALFIND_ATTRIBUTE_MAP.put("l", "OFFICE");
GALFIND_ATTRIBUTE_MAP.put("company", "CP");
GALFIND_ATTRIBUTE_MAP.put("title", "TL");
GALFIND_ATTRIBUTE_MAP.put("givenName", "first");
GALFIND_ATTRIBUTE_MAP.put("initials", "initials");
GALFIND_ATTRIBUTE_MAP.put("sn", "last");
GALFIND_ATTRIBUTE_MAP.put("street", "street");
GALFIND_ATTRIBUTE_MAP.put("st", "state");
GALFIND_ATTRIBUTE_MAP.put("postalCode", "zip");
GALFIND_ATTRIBUTE_MAP.put("c", "country");
GALFIND_ATTRIBUTE_MAP.put("departement", "department");
GALFIND_ATTRIBUTE_MAP.put("mobile", "mobile");
}
@Override
public Map<String, ExchangeSession.Contact> galFind(Condition condition) throws IOException {
Map<String, ExchangeSession.Contact> contacts = new HashMap<String, ExchangeSession.Contact>();
if (condition instanceof MultiCondition) {
// TODO
} else if (condition instanceof AttributeCondition) {
String searchAttribute = GALFIND_CRITERIA_MAP.get(((ExchangeSession.AttributeCondition) condition).getAttributeName());
if (searchAttribute != null) {
String searchValue = ((ExchangeSession.AttributeCondition) condition).getValue();
Map<String, Map<String, String>> results;
GetMethod getMethod = new GetMethod(URIUtil.encodePathQuery(getCmdBasePath() + "?Cmd=galfind&" + searchAttribute + '=' + searchValue));
try {
DavGatewayHttpClientFacade.executeGetMethod(httpClient, getMethod, true);
results = XMLStreamUtil.getElementContentsAsMap(getMethod.getResponseBodyAsStream(), "item", "AN");
} finally {
getMethod.releaseConnection();
}
LOGGER.debug("galfind " + searchAttribute + '=' + searchValue + ": " + results.size() + " result(s)");
for (Map<String, String> result:results.values()) {
Contact contact = buildGalfindContact(result);
if (condition.isMatch(contact)) {
contacts.put(contact.getName().toLowerCase(), contact);
}
}
}
}
return contacts;
}
protected Contact buildGalfindContact(Map<String, String> response) {
Contact contact = new Contact();
contact.setName(response.get("AN"));
contact.put("uid", response.get("AN"));
for (Map.Entry<String, String> entry : GALFIND_ATTRIBUTE_MAP.entrySet()) {
String attributeValue = response.get(entry.getValue());
if (attributeValue != null) {
contact.put(entry.getKey(), attributeValue);
}
}
return contact;
}
@Override
protected String getFreeBusyData(String attendee, String start, String end, int interval) throws IOException {
String freebusyUrl = publicFolderUrl + "/?cmd=freebusy" +
@ -460,7 +551,7 @@ public class DavExchangeSession extends ExchangeSession {
if (operator == Operator.IsEqualTo) {
return actualValue.equals(lowerCaseValue);
} else if (operator == Operator.Like) {
return actualValue.contains(lowerCaseValue);
return actualValue.contains(lowerCaseValue);
} else if (operator == Operator.StartsWith) {
return actualValue.startsWith(lowerCaseValue);
} else {
@ -619,6 +710,9 @@ public class DavExchangeSession extends ExchangeSession {
super(folderPath, itemName, properties, etag, noneMatch);
}
public Contact() {
}
protected Set<PropertyValue> buildProperties() {
Set<PropertyValue> propertyValues = new HashSet<PropertyValue>();
for (Map.Entry<String, String> entry : entrySet()) {

View File

@ -553,8 +553,6 @@ public abstract class EWSMethod extends PostMethod {
public void checkSuccess() throws EWSException {
if (errorDetail != null) {
if (!"ErrorAccessDenied".equals(errorDetail)
&& !"ErrorNameResolutionMultipleResults".equals(errorDetail)
&& !"ErrorNameResolutionNoResults".equals(errorDetail)
&& !"ErrorMailRecipientNotFound".equals(errorDetail)) {
try {
throw new EWSException(errorDetail + "\n request: " + new String(generateSoapEnvelope(), "UTF-8"));
@ -633,7 +631,11 @@ public abstract class EWSMethod extends PostMethod {
protected void handleErrors(XMLStreamReader reader) throws XMLStreamException {
String result = handleTag(reader, "ResponseCode");
if (errorDetail == null && result != null && !"NoError".equals(result)) {
if (errorDetail == null && result != null
&& !"NoError".equals(result)
&& !"ErrorNameResolutionMultipleResults".equals(result)
&& !"ErrorNameResolutionNoResults".equals(result)
) {
errorDetail = result;
}
if (isStartTag(reader, "faultstring")) {

View File

@ -361,10 +361,6 @@ public class EwsExchangeSession extends ExchangeSession {
return fieldURI;
}
protected String getValue() {
return value;
}
protected Operator getOperator() {
return operator;
}
@ -381,22 +377,24 @@ public class EwsExchangeSession extends ExchangeSession {
FieldURI fieldURI = getFieldURI();
fieldURI.appendTo(buffer);
buffer.append("<t:FieldURIOrConstant><t:Constant Value=\"");
if (operator == Operator.IsEqualTo) {
buffer.append("<t:FieldURIOrConstant>");
}
buffer.append("<t:Constant Value=\"");
// encode urlcompname
if (fieldURI instanceof ExtendedFieldURI && "0x10f3".equals(((ExtendedFieldURI) fieldURI).propertyTag)) {
buffer.append(StringUtil.xmlEncode(StringUtil.encodeUrlcompname(value)));
} else {
buffer.append(StringUtil.xmlEncode(value));
}
buffer.append("\"/></t:FieldURIOrConstant>");
buffer.append("\"/>");
if (operator == Operator.IsEqualTo) {
buffer.append("</t:FieldURIOrConstant>");
}
buffer.append("</t:").append(operator.toString()).append('>');
}
public String getAttributeName() {
return attributeName;
}
public boolean isMatch(ExchangeSession.Contact contact) {
String lowerCaseValue = value.toLowerCase();
@ -406,7 +404,7 @@ public class EwsExchangeSession extends ExchangeSession {
}
actualValue = actualValue.toLowerCase();
if (operator == Operator.IsEqualTo) {
return value.equals(actualValue);
return lowerCaseValue.equals(actualValue);
} else {
return operator == Operator.Contains && ((containmentMode.equals(ContainmentMode.Substring) && actualValue.contains(lowerCaseValue)) ||
(containmentMode.equals(ContainmentMode.Prefixed) && actualValue.startsWith(lowerCaseValue)));
@ -711,7 +709,7 @@ public class EwsExchangeSession extends ExchangeSession {
}
for (String attributeName : CONTACT_ATTRIBUTES) {
String value = response.get(Field.get(attributeName).getResponseName());
if (value != null) {
if (value != null && value.length() > 0) {
if ("bday".equals(attributeName) || "anniversary".equals(attributeName) || "lastmodified".equals(attributeName) || "datereceived".equals(attributeName)) {
value = convertDateFromExchange(value);
}
@ -852,10 +850,6 @@ public class EwsExchangeSession extends ExchangeSession {
return itemResult;
}
public void setName(String name) {
this.itemName = name;
}
}
protected class Event extends ExchangeSession.Event {
@ -1264,17 +1258,19 @@ public class EwsExchangeSession extends ExchangeSession {
protected static final HashMap<String, String> GALFIND_ATTRIBUTE_MAP = new HashMap<String, String>();
static {
GALFIND_ATTRIBUTE_MAP.put("uid", "Name");
GALFIND_ATTRIBUTE_MAP.put("cn", "DisplayName");
GALFIND_ATTRIBUTE_MAP.put("givenName", "GivenName");
GALFIND_ATTRIBUTE_MAP.put("sn", "Surname");
GALFIND_ATTRIBUTE_MAP.put("email1", "EmailAddress1");
GALFIND_ATTRIBUTE_MAP.put("email2", "EmailAddress1");
GALFIND_ATTRIBUTE_MAP.put("email3", "EmailAddress1");
GALFIND_ATTRIBUTE_MAP.put("email2", "EmailAddress2");
GALFIND_ATTRIBUTE_MAP.put("email3", "EmailAddress3");
}
protected Contact buildGalfindContact(EWSMethod.Item response) {
Contact contact = new Contact();
contact.setName(response.get("DisplayName"));
contact.setName(response.get("Name"));
contact.put("uid", response.get("Name"));
for (Map.Entry<String, String> entry : GALFIND_ATTRIBUTE_MAP.entrySet()) {
String attributeValue = response.get(entry.getValue());
if (attributeValue != null) {
@ -1284,7 +1280,7 @@ public class EwsExchangeSession extends ExchangeSession {
return contact;
}
protected Map<String, ExchangeSession.Contact> galFind(Condition condition) throws IOException {
public Map<String, ExchangeSession.Contact> galFind(Condition condition) throws IOException {
Map<String, ExchangeSession.Contact> contacts = new HashMap<String, ExchangeSession.Contact>();
if (condition instanceof MultiCondition) {
List<Condition> conditions = ((MultiCondition) condition).getConditions();
@ -1297,7 +1293,7 @@ public class EwsExchangeSession extends ExchangeSession {
Map<String, ExchangeSession.Contact> innerContacts = galFind(conditions.get(0));
for (ExchangeSession.Contact contact : innerContacts.values()) {
if (condition.isMatch(contact)) {
contacts.put(contact.getName(), contact);
contacts.put(contact.getName().toLowerCase(), contact);
}
}
}
@ -1313,13 +1309,16 @@ public class EwsExchangeSession extends ExchangeSession {
if (operator == Operator.IsEqualTo) {
searchValue = '=' + searchValue;
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("ResolveNames(" + searchValue + ')');
}
ResolveNamesMethod resolveNamesMethod = new ResolveNamesMethod(searchValue);
executeMethod(resolveNamesMethod);
List<EWSMethod.Item> responses = resolveNamesMethod.getResponseItems();
for (EWSMethod.Item response : responses) {
Contact contact = buildGalfindContact(response);
if (condition.isMatch(contact)) {
contacts.put(contact.getName(), contact);
contacts.put(contact.getName().toLowerCase(), contact);
}
}
}

View File

@ -45,24 +45,74 @@ public class ResolveNamesMethod extends EWSMethod {
Item responseItem = new Item();
responseItem.type = "Contact";
// skip to Contact
while (reader.hasNext() && !isStartTag(reader, "Contact")) {
while (reader.hasNext() && !isStartTag(reader, "Resolution")) {
reader.next();
}
while (reader.hasNext() && !isEndTag(reader, "Contact")) {
while (reader.hasNext() && !isEndTag(reader, "Resolution")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName();
if ("EmailAddresses".equals(tagLocalName)) {
handleAddresses(reader, responseItem);
} else {
responseItem.put(tagLocalName, reader.getElementText());
if ("Mailbox".equals(tagLocalName)) {
handleMailbox(reader, responseItem);
} else if ("Contact".equals(tagLocalName)) {
handleContact(reader, responseItem);
}
}
}
return responseItem;
}
protected void handleAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
protected void handleMailbox(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
while (reader.hasNext() && !isEndTag(reader, "Mailbox")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName();
if ("Name".equals(tagLocalName)) {
responseItem.put(tagLocalName, reader.getElementText());
}
}
}
}
protected void handleContact(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
while (reader.hasNext() && !isEndTag(reader, "Contact")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName();
if ("EmailAddresses".equals(tagLocalName)) {
handleEmailAddresses(reader, responseItem);
} else if ("PhysicalAddresses".equals(tagLocalName)) {
handlePhysicalAddresses(reader, responseItem);
} else if ("PhoneNumbers".equals(tagLocalName)) {
handlePhoneNumbers(reader, responseItem);
} else {
responseItem.put(tagLocalName, reader.getElementText());
}
}
}
}
protected void handlePhysicalAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
while (reader.hasNext() && !isEndTag(reader, "PhysicalAddresses")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName();
// TODO
}
}
}
protected void handlePhoneNumbers(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
while (reader.hasNext() && !isEndTag(reader, "PhoneNumbers")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {
String tagLocalName = reader.getLocalName();
// TODO
}
}
}
protected void handleEmailAddresses(XMLStreamReader reader, Item responseItem) throws XMLStreamException {
while (reader.hasNext() && !isEndTag(reader, "EmailAddresses")) {
int event = reader.next();
if (event == XMLStreamConstants.START_ELEMENT) {

View File

@ -105,8 +105,8 @@ public class LdapConnection extends AbstractConnection {
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("extensionattribute2", "custom2");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("extensionattribute3", "custom3");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("extensionattribute4", "custom4");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("email1", "mail");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("email2", "xmozillasecondemail");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("smtpemail1", "mail");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("smtpemail2", "xmozillasecondemail");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homeCountry", "mozillahomecountryname");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homeCity", "mozillahomelocalityname");
CONTACT_TO_LDAP_ATTRIBUTE_MAP.put("homePostalCode", "mozillahomepostalcode");
@ -225,7 +225,7 @@ public class LdapConnection extends AbstractConnection {
static {
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("uid", "imapUid");
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("mail", "email1");
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("mail", "smtpemail1");
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("displayname", "cn");
LDAP_TO_CONTACT_ATTRIBUTE_MAP.put("commonname", "cn");
@ -846,7 +846,7 @@ public class LdapConnection extends AbstractConnection {
static interface LdapFilter {
ExchangeSession.Condition getContactSearchFilter();
Map<String, Map<String, String>> findInGAL(ExchangeSession session) throws IOException;
Map<String, ExchangeSession.Contact> findInGAL(ExchangeSession session) throws IOException;
void add(LdapFilter filter);
@ -973,11 +973,11 @@ public class LdapConnection extends AbstractConnection {
* @return persons map
* @throws IOException on error
*/
public Map<String, Map<String, String>> findInGAL(ExchangeSession session) throws IOException {
Map<String, Map<String, String>> persons = null;
public Map<String, ExchangeSession.Contact> findInGAL(ExchangeSession session) throws IOException {
Map<String, ExchangeSession.Contact> persons = null;
for (LdapFilter child : criteria) {
Map<String, Map<String, String>> childFind = child.findInGAL(session);
Map<String, ExchangeSession.Contact> childFind = child.findInGAL(session);
if (childFind != null) {
if (persons == null) {
@ -992,10 +992,10 @@ public class LdapConnection extends AbstractConnection {
// Thus, instead of building the intersection, we check each result against
// all filters.
for (Map<String, String> result : childFind.values()) {
for (ExchangeSession.Contact result : childFind.values()) {
if (isMatch(result)) {
// This item from the child result set matches all sub-criteria, add it
persons.put(result.get("AN"), result);
persons.put(result.get("uid"), result);
}
}
}
@ -1004,7 +1004,7 @@ public class LdapConnection extends AbstractConnection {
if ((persons == null) && !isFullSearch()) {
// return an empty map (indicating no results were found)
return new HashMap<String, Map<String, String>>();
return new HashMap<String, ExchangeSession.Contact>();
}
return persons;
@ -1139,7 +1139,7 @@ public class LdapConnection extends AbstractConnection {
return false;
}
public Map<String, Map<String, String>> findInGAL(ExchangeSession session) throws IOException {
public Map<String, ExchangeSession.Contact> findInGAL(ExchangeSession session) throws IOException {
if (canIgnore) {
return null;
}
@ -1148,17 +1148,17 @@ public class LdapConnection extends AbstractConnection {
if (galFindAttributeName != null) {
// quick fix for cn=* filter
Map<String, Map<String, String>> galPersons = session.galFind(galFindAttributeName, "*".equals(value) ? "A" : value);
Map<String, ExchangeSession.Contact> galPersons = session.galFind(session.startsWith(attributeName, "*".equals(value) ? "A" : value));
if (operator == LDAP_FILTER_EQUALITY) {
// Make sure only exact matches are returned
Map<String, Map<String, String>> results = new HashMap<String, Map<String, String>>();
Map<String, ExchangeSession.Contact> results = new HashMap<String, ExchangeSession.Contact>();
for (Map<String, String> person : galPersons.values()) {
for (ExchangeSession.Contact person : galPersons.values()) {
if (isMatch(person)) {
// Found an exact match
results.put(person.get("AN"), person);
results.put(person.get("uid"), person);
}
}
@ -1213,9 +1213,9 @@ public class LdapConnection extends AbstractConnection {
protected static String getLdapAttributeName(String contactAttributeName) {
String mappedAttributeName = CONTACT_TO_LDAP_ATTRIBUTE_MAP.get(contactAttributeName);
if (mappedAttributeName != null) {
return contactAttributeName;
} else {
return mappedAttributeName;
} else {
return contactAttributeName;
}
}
@ -1265,7 +1265,7 @@ public class LdapConnection extends AbstractConnection {
if (session != null) {
// single user request
String uid = dn.substring("uid=".length(), dn.indexOf(','));
Map<String, Map<String, String>> persons = null;
Map<String, ExchangeSession.Contact> persons = null;
// first search in contact
try {
@ -1278,12 +1278,12 @@ public class LdapConnection extends AbstractConnection {
// then in GAL
if (persons == null || persons.isEmpty()) {
persons = session.galFind("AN", uid);
persons = session.galFind(session.isEqualTo("uid", uid));
Map<String, String> person = persons.get(uid.toLowerCase());
ExchangeSession.Contact person = persons.get(uid.toLowerCase());
// filter out non exact results
if (persons.size() > 1 || person == null) {
persons = new HashMap<String, Map<String, String>>();
persons = new HashMap<String, ExchangeSession.Contact>();
if (person != null) {
persons.put(uid.toLowerCase(), person);
}
@ -1303,10 +1303,10 @@ public class LdapConnection extends AbstractConnection {
sendComputerContext(currentMessageId, returningAttributes);
} else if ((BASE_CONTEXT.equalsIgnoreCase(dn) || OD_USER_CONTEXT.equalsIgnoreCase(dn))) {
if (session != null) {
Map<String, Map<String, String>> persons = new HashMap<String, Map<String, String>>();
Map<String, ExchangeSession.Contact> persons = new HashMap<String, ExchangeSession.Contact>();
if (ldapFilter.isFullSearch()) {
// append personal contacts first
for (Map<String, String> person : contactFind(null, returningAttributes, sizeLimit).values()) {
for (ExchangeSession.Contact person : contactFind(null, returningAttributes, sizeLimit).values()) {
persons.put(person.get("imapUid"), person);
if (persons.size() == sizeLimit) {
break;
@ -1315,8 +1315,8 @@ public class LdapConnection extends AbstractConnection {
// full search
for (char c = 'A'; c < 'Z'; c++) {
if (!abandon && persons.size() < sizeLimit) {
for (Map<String, String> person : session.galFind("AN", String.valueOf(c)).values()) {
persons.put(person.get("AN"), person);
for (ExchangeSession.Contact person : session.galFind(session.startsWith("uid", String.valueOf(c))).values()) {
persons.put(person.get("uid"), person);
if (persons.size() == sizeLimit) {
break;
}
@ -1333,7 +1333,7 @@ public class LdapConnection extends AbstractConnection {
// if ldapfilter is not a full search and filter is null,
// ignored all attribute filters => return empty results
if (ldapFilter.isFullSearch() || filter != null) {
for (Map<String, String> person : contactFind(filter, returningAttributes, sizeLimit).values()) {
for (ExchangeSession.Contact person : contactFind(filter, returningAttributes, sizeLimit).values()) {
persons.put(person.get("imapUid"), person);
if (persons.size() == sizeLimit) {
@ -1341,12 +1341,12 @@ public class LdapConnection extends AbstractConnection {
}
}
if (!abandon && persons.size() < sizeLimit) {
for (Map<String, String> person : ldapFilter.findInGAL(session).values()) {
for (ExchangeSession.Contact person : ldapFilter.findInGAL(session).values()) {
if (persons.size() == sizeLimit) {
break;
}
persons.put(person.get("AN"), person);
persons.put(person.get("uid"), person);
}
}
}
@ -1399,7 +1399,7 @@ public class LdapConnection extends AbstractConnection {
* @return List of users
* @throws IOException on error
*/
public Map<String, Map<String, String>> contactFind(ExchangeSession.Condition condition, Set<String> returningAttributes, int maxCount) throws IOException {
public Map<String, ExchangeSession.Contact> contactFind(ExchangeSession.Condition condition, Set<String> returningAttributes, int maxCount) throws IOException {
Set<String> contactReturningAttributes;
if (returningAttributes != null && !returningAttributes.isEmpty()) {
contactReturningAttributes = new HashSet<String>();
@ -1415,13 +1415,17 @@ public class LdapConnection extends AbstractConnection {
contactReturningAttributes = ExchangeSession.CONTACT_ATTRIBUTES;
}
Map<String, Map<String, String>> results = new HashMap<String, Map<String, String>>();
Map<String, ExchangeSession.Contact> results = new HashMap<String, ExchangeSession.Contact>();
List<ExchangeSession.Contact> contacts = session.searchContacts(ExchangeSession.CONTACTS, contactReturningAttributes, condition, maxCount);
for (ExchangeSession.Contact contact : contacts) {
if (contact.get("imapUid") != null) {
results.put(contact.get("imapUid"), contact);
// use imapUid as uid
String imapUid = contact.get("imapUid");
if (imapUid != null) {
contact.put("uid", imapUid);
contact.remove("imapUid");
results.put(imapUid, contact);
}
}
@ -1438,7 +1442,7 @@ public class LdapConnection extends AbstractConnection {
* @param returningAttributes returning attributes
* @throws IOException on error
*/
protected void sendPersons(int currentMessageId, String baseContext, Map<String, Map<String, String>> persons, Set<String> returningAttributes) throws IOException {
protected void sendPersons(int currentMessageId, String baseContext, Map<String, ExchangeSession.Contact> persons, Set<String> returningAttributes) throws IOException {
boolean needObjectClasses = returningAttributes.contains("objectclass") || returningAttributes.isEmpty();
boolean iCalSearch = returningAttributes.contains("apple-serviceslocator");
boolean returnAllAttributes = returningAttributes.isEmpty();
@ -1456,16 +1460,16 @@ public class LdapConnection extends AbstractConnection {
needDetails = false;
}
for (Map<String, String> person : persons.values()) {
for (ExchangeSession.Contact person : persons.values()) {
if (abandon) {
break;
}
returningAttributes.add("uid");
Map<String, Object> ldapPerson = new HashMap<String, Object>();
// convert GAL entries
if (person.get("AN") != null) {
/*if (person.get("uid") != null) {
// TODO: move to galFind
// add detailed information, only for GAL entries
if (needDetails) {
session.galLookup(person);
@ -1484,13 +1488,14 @@ public class LdapConnection extends AbstractConnection {
ldapPerson.put(ldapAttribute, value);
}
}
// TODO
// iCal fix to suit both iCal 3 and 4: move cn to sn, remove cn
if (iCalSearch && ldapPerson.get("cn") != null && returningAttributes.contains("sn")) {
ldapPerson.put("sn", ldapPerson.get("cn"));
ldapPerson.remove("cn");
}
} else {
} else {*/
// convert Contact entries
if (returnAllAttributes) {
// just convert contact attributes to default ldap names
@ -1502,6 +1507,8 @@ public class LdapConnection extends AbstractConnection {
}
}
} else {
// always map uid
ldapPerson.put("uid", person.get("uid"));
// iterate over requested attributes
for (String ldapAttribute : returningAttributes) {
String contactAttribute = getContactAttributeName(ldapAttribute);
@ -1528,7 +1535,7 @@ public class LdapConnection extends AbstractConnection {
}
}
}
//}
// Process all attributes which have static mappings
for (Map.Entry<String, String> entry : STATIC_ATTRIBUTE_MAP.entrySet()) {