001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.ldap;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.PropsKeys;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.model.Contact;
026    import com.liferay.portal.model.User;
027    import com.liferay.portal.model.UserGroup;
028    import com.liferay.portal.util.PrefsPropsUtil;
029    import com.liferay.portlet.expando.model.ExpandoBridge;
030    import com.liferay.portlet.expando.util.ExpandoConverterUtil;
031    
032    import java.io.Serializable;
033    
034    import java.util.HashMap;
035    import java.util.List;
036    import java.util.Map;
037    import java.util.Properties;
038    
039    import javax.naming.directory.Attribute;
040    import javax.naming.directory.Attributes;
041    import javax.naming.directory.BasicAttribute;
042    import javax.naming.directory.BasicAttributes;
043    import javax.naming.directory.DirContext;
044    
045    import org.apache.commons.beanutils.PropertyUtils;
046    
047    /**
048     * @author Michael C. Han
049     * @author Brian Wing Shun Chan
050     * @author Marcellus Tavares
051     */
052    public class BasePortalToLDAPConverter implements PortalToLDAPConverter {
053    
054            public BasePortalToLDAPConverter() {
055                    _reservedUserFieldNames.put(
056                            UserConverterKeys.GROUP, UserConverterKeys.GROUP);
057                    _reservedUserFieldNames.put(
058                            UserConverterKeys.PASSWORD, UserConverterKeys.PASSWORD);
059                    _reservedUserFieldNames.put(
060                            UserConverterKeys.SCREEN_NAME, UserConverterKeys.SCREEN_NAME);
061            }
062    
063            public String getGroupDNName(
064                            long ldapServerId, UserGroup userGroup, Properties groupMappings)
065                    throws Exception {
066    
067                    StringBundler sb = new StringBundler(5);
068    
069                    sb.append(
070                            GetterUtil.getString(
071                                    groupMappings.getProperty(_groupDNFieldName), _DEFAULT_DN));
072                    sb.append(StringPool.EQUAL);
073                    sb.append(userGroup.getName());
074                    sb.append(StringPool.COMMA);
075                    sb.append(
076                            PortalLDAPUtil.getGroupsDN(
077                                    ldapServerId, userGroup.getCompanyId()));
078    
079                    return sb.toString();
080            }
081    
082            public Modifications getLDAPContactModifications(
083                            Contact contact, Map<String, Serializable> contactExpandoAttributes,
084                            Properties contactMappings, Properties contactExpandoMappings)
085                    throws Exception {
086    
087                    if (contactMappings.isEmpty() && contactExpandoMappings.isEmpty()) {
088                            return null;
089                    }
090    
091                    Modifications modifications = getModifications(
092                            contact, contactMappings, _reservedContactFieldNames);
093    
094                    populateCustomAttributeModifications(
095                            contact, contact.getExpandoBridge(), contactExpandoAttributes,
096                            contactExpandoMappings, modifications);
097    
098                    return modifications;
099            }
100    
101            public Attributes getLDAPGroupAttributes(
102                            long ldapServerId, UserGroup userGroup, User user,
103                            Properties groupMappings, Properties userMappings)
104                    throws Exception {
105    
106                    Attributes attributes = new BasicAttributes(true);
107    
108                    Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
109    
110                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
111    
112                    String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
113                            userGroup.getCompanyId(),
114                            PropsKeys.LDAP_GROUP_DEFAULT_OBJECT_CLASSES + postfix,
115                            StringPool.COMMA);
116    
117                    for (int i = 0; i < defaultObjectClasses.length; i++) {
118                            objectClass.add(defaultObjectClasses[i]);
119                    }
120    
121                    attributes.put(objectClass);
122    
123                    addAttributeMapping(
124                            groupMappings.getProperty(GroupConverterKeys.GROUP_NAME),
125                            userGroup.getName(), attributes);
126                    addAttributeMapping(
127                            groupMappings.getProperty(GroupConverterKeys.DESCRIPTION),
128                            userGroup.getDescription(), attributes);
129                    addAttributeMapping(
130                            groupMappings.getProperty(GroupConverterKeys.USER),
131                            getUserDNName(ldapServerId, user, userMappings), attributes);
132    
133                    return attributes;
134            }
135    
136            public Modifications getLDAPGroupModifications(
137                            long ldapServerId, UserGroup userGroup, User user,
138                            Properties groupMappings, Properties userMappings)
139                    throws Exception {
140    
141                    Modifications modifications = Modifications.getInstance();
142    
143                    String groupDN = getGroupDNName(ldapServerId, userGroup, groupMappings);
144                    String userDN = getUserDNName(ldapServerId, user, userMappings);
145    
146                    if (!PortalLDAPUtil.isGroupMember(
147                                    ldapServerId, user.getCompanyId(), groupDN, userDN)) {
148    
149                            modifications.addItem(
150                                    DirContext.ADD_ATTRIBUTE,
151                                    groupMappings.getProperty(GroupConverterKeys.USER),
152                                    getUserDNName(ldapServerId, user, userMappings));
153                    }
154    
155                    return modifications;
156            }
157    
158            public Attributes getLDAPUserAttributes(
159                            long ldapServerId, User user, Properties userMappings)
160                    throws SystemException {
161    
162                    Attributes attributes = new BasicAttributes(true);
163    
164                    Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
165    
166                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
167    
168                    String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
169                            user.getCompanyId(),
170                            PropsKeys.LDAP_USER_DEFAULT_OBJECT_CLASSES + postfix,
171                            StringPool.COMMA);
172    
173                    for (int i = 0; i < defaultObjectClasses.length; i++) {
174                            objectClass.add(defaultObjectClasses[i]);
175                    }
176    
177                    attributes.put(objectClass);
178    
179                    addAttributeMapping(
180                            userMappings.getProperty(UserConverterKeys.FIRST_NAME),
181                            user.getFirstName(), attributes);
182                    addAttributeMapping(
183                            userMappings.getProperty(UserConverterKeys.LAST_NAME),
184                            user.getLastName(), attributes);
185                    addAttributeMapping(
186                            userMappings.getProperty(UserConverterKeys.PASSWORD),
187                            user.getPasswordUnencrypted(), attributes);
188                    addAttributeMapping(
189                            userMappings.getProperty(UserConverterKeys.EMAIL_ADDRESS),
190                            user.getEmailAddress(), attributes);
191    
192                    return attributes;
193            }
194    
195            public Modifications getLDAPUserModifications(
196                            User user, Map<String, Serializable> userExpandoAttributes,
197                            Properties userMappings, Properties userExpandoMappings)
198                    throws Exception {
199    
200                    Modifications modifications = getModifications(
201                            user, userMappings, _reservedUserFieldNames);
202    
203                    if (user.isPasswordModified() &&
204                            Validator.isNotNull(user.getPasswordUnencrypted())) {
205    
206                            addModificationItem(
207                                    userMappings.getProperty(UserConverterKeys.PASSWORD),
208                                    user.getPasswordUnencrypted(), modifications);
209                    }
210    
211                    populateCustomAttributeModifications(
212                            user, user.getExpandoBridge(), userExpandoAttributes,
213                            userExpandoMappings, modifications);
214    
215                    return modifications;
216            }
217    
218            public String getUserDNName(
219                            long ldapServerId, User user, Properties userMappings)
220                    throws Exception {
221    
222                    StringBundler sb = new StringBundler(5);
223    
224                    sb.append(
225                            GetterUtil.getString(
226                                    userMappings.getProperty(_userDNFieldName), _DEFAULT_DN));
227                    sb.append(StringPool.EQUAL);
228                    sb.append(PropertyUtils.getProperty(user, _userDNFieldName));
229                    sb.append(StringPool.COMMA);
230                    sb.append(PortalLDAPUtil.getUsersDN(ldapServerId, user.getCompanyId()));
231    
232                    return sb.toString();
233            }
234    
235            public void setContactReservedFieldNames(
236                    List<String> reservedContactFieldNames) {
237    
238                    for (String reservedContactFieldName : reservedContactFieldNames) {
239                            _reservedContactFieldNames.put(
240                                    reservedContactFieldName, reservedContactFieldName);
241                    }
242            }
243    
244            public void setUserDNFieldName(String userDNFieldName) {
245                    _userDNFieldName = userDNFieldName;
246            }
247    
248            public void setUserReservedFieldNames(List<String> reservedUserFieldNames) {
249                    for (String reservedUserFieldName : reservedUserFieldNames) {
250                            _reservedUserFieldNames.put(
251                                    reservedUserFieldName, reservedUserFieldName);
252                    }
253            }
254    
255            protected void addAttributeMapping(
256                    String attributeName, String attributeValue, Attributes attributes) {
257    
258                    if (Validator.isNotNull(attributeName) &&
259                            Validator.isNotNull(attributeValue)) {
260    
261                            attributes.put(attributeName, attributeValue);
262                    }
263            }
264            protected void addModificationItem(
265                    String attributeName, String attributeValue,
266                    Modifications modifications) {
267    
268                    if (Validator.isNotNull(attributeName) &&
269                            Validator.isNotNull(attributeValue)) {
270    
271                            modifications.addItem(attributeName, attributeValue);
272                    }
273            }
274    
275            protected Modifications getModifications(
276                    Object object, Properties objectMappings,
277                    Map<String, String> reservedFieldNames) {
278    
279                    Modifications modifications = Modifications.getInstance();
280    
281                    for (Map.Entry<Object, Object> entry : objectMappings.entrySet()) {
282                            String fieldName = (String)entry.getKey();
283    
284                            if (reservedFieldNames.containsKey(fieldName)) {
285                                    continue;
286                            }
287    
288                            String ldapAttributeName = (String)entry.getValue();
289    
290                            try {
291                                    Object attributeValue = PropertyUtils.getProperty(
292                                            object, fieldName);
293    
294                                    if (attributeValue != null) {
295                                            addModificationItem(
296                                                    ldapAttributeName, attributeValue.toString(),
297                                                    modifications);
298                                    }
299                            }
300                            catch (Exception e) {
301                                    if (_log.isWarnEnabled()) {
302                                            _log.warn(
303                                                    "Unable to map field " + fieldName + " to class " +
304                                                            object.getClass(),
305                                                    e);
306                                    }
307                            }
308                    }
309    
310                    return modifications;
311            }
312    
313            protected void populateCustomAttributeModifications(
314                    Object object, ExpandoBridge expandoBridge,
315                    Map<String, Serializable> expandoAttributes,
316                    Properties expandoMappings, Modifications modifications) {
317    
318                    if ((expandoAttributes == null) || expandoAttributes.isEmpty()) {
319                            return;
320                    }
321    
322                    for (Map.Entry<Object, Object> entry : expandoMappings.entrySet()) {
323                            String fieldName = (String)entry.getKey();
324                            String ldapAttributeName = (String)entry.getValue();
325    
326                            Serializable fieldValue = expandoAttributes.get(fieldName);
327    
328                            if (fieldValue == null) {
329                                    continue;
330                            }
331    
332                            try {
333                                    int type = expandoBridge.getAttributeType(fieldName);
334    
335                                    String value = ExpandoConverterUtil.getStringFromAttribute(
336                                            type, fieldValue);
337    
338                                    addModificationItem(ldapAttributeName, value, modifications);
339                            }
340                            catch (Exception e) {
341                                    if (_log.isWarnEnabled()) {
342                                            _log.warn(
343                                                    "Unable to map field " + fieldName + " to class " +
344                                                            object.getClass(),
345                                                    e);
346                                    }
347                            }
348                    }
349            }
350    
351            private static final String _DEFAULT_DN = "cn";
352    
353            private static final String _OBJECT_CLASS = "objectclass";
354    
355            private static Log _log = LogFactoryUtil.getLog(
356                    BasePortalToLDAPConverter.class);
357    
358            private Map<String, String> _reservedContactFieldNames =
359                    new HashMap<String, String>();
360            private Map<String, String> _reservedUserFieldNames =
361                    new HashMap<String, String>();
362    
363            private String _groupDNFieldName = GroupConverterKeys.GROUP_NAME;
364            private String _userDNFieldName = UserConverterKeys.SCREEN_NAME;
365    
366    }