/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/providers/trunk/jldap/src/java/edu/amc/sakai/user/EntryAttributeToUserTypeMapper.java $
* $Id: EntryAttributeToUserTypeMapper.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $
***********************************************************************************
*
* Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package edu.amc.sakai.user;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.novell.ldap.LDAPAttribute;
import com.novell.ldap.LDAPEntry;
/**
* Maps from a user entry's attribute to a Sakai user type. Will consider
* attribute values in the order received, returning the first non-null
* mapping. If no non-null mappings can be found, will return either a
* configurable default or the first attribute value, unmodified.
*
* TODO: could probably refactor to reduce code duplication with
* EntryContainerRdnToUserTypeMapper
*
* @author Dan McCallum, Unicon Inc
*/
public class EntryAttributeToUserTypeMapper implements UserTypeMapper {
/** Class-specific logger */
private static Log M_log = LogFactory.getLog(EntryAttributeToUserTypeMapper.class);
/** map of attribute values to Sakai user types */
private Map<String,String> attributeValueToSakaiUserTypeMap = new HashMap<String,String>();
/** A key into the current attribute map ({@link LdapAttributeMapper}) */
private String logicalAttributeName;
/** Controls behavior when no value mappings resolve. If <code>true</code>, will return
* the first attribute value encountered. Otherwise returns {@link #defaultSakaiUserType} */
private boolean returnLiteralAttributeValueIfNoMapping = false;
/** Value returned if no mappings are found and {@link #returnLiteralAttributeValueIfNoMapping}
* is <code>false</code> */
private String defaultSakaiUserType;
/**
* Maps the attribute values associated with the specified
* <code>LDAPEntry</code> to a Sakai user type.
* {@link #setLogicalAttributeName(String)} defines the
* attribute name to consult.
* {@link #setAttributeValueToSakaiUserTypeMap(Map)} controls
* the attribute value mappings.
* {@link #setReturnLiteralAttributeValueIfNoMapping(boolean)}
* controls behavior when attribute value mapping fails.
* {@link #setDefaultSakaiUserType(String)} assigns the String
* to return if attribute value mapping fails and literal value
* returns have been disabled.
*
* @see #getUserTypeAttribute(LDAPEntry, LdapAttributeMapper)
* @param ldapEntry the <code>LDAPEntry</code> to map
* @param mapper a container for attribute mapping config
* @return a Sakai user type, possibly null
*/
public String mapLdapEntryToSakaiUserType(LDAPEntry ldapEntry,
LdapAttributeMapper mapper) {
if ( M_log.isDebugEnabled() ) {
M_log.debug("mapLdapEntryToSakaiUserType(): [entry DN = " +
ldapEntry.getDN() + "]");
}
LDAPAttribute userTypeAttr =
getUserTypeAttribute(ldapEntry, mapper);
if ( userTypeAttr == null ) {
return null;
}
String[] userTypeAttrValues =
getUserTypeAttribute(ldapEntry, mapper).getStringValueArray();
String userType = mapUserTypeAttributeValues(userTypeAttrValues);
if ( M_log.isDebugEnabled() ) {
M_log.debug("mapLdapEntryToSakaiUserType(): finished mapping [user type = " +
userType + "][entry values = " + Arrays.toString(userTypeAttrValues) +
"][entry DN = " + ldapEntry.getDN() + "]");
}
return userType;
}
/**
* Extracts the <code>LDAPAttribute</code> which represents the
* <code>LDAPEntry</code>'s group membership. This is accomplished
* by querying the given {@link LdapAttributeMapper} for an
* attribute name corresponding to {@link #getLogicalAttributeName()}.
*
* @param ldapEntry the <code>LDAPEntry</code> from which to extract a
* <code>LDAPAttribute</code>
* @param mapper a container for attribute mapping config
* @return a user type <code>LDAPAttribute</code> or <code>null</code>
* if none could be found on the given <code>LDAPEntry</code>
*/
protected LDAPAttribute getUserTypeAttribute(LDAPEntry ldapEntry,
LdapAttributeMapper mapper) {
if ( M_log.isDebugEnabled() ) {
M_log.debug("getUserTypeAttribute(): [entry DN = " +
ldapEntry.getDN() + "]");
}
if ( StringUtils.isBlank(logicalAttributeName) ) {
M_log.debug("getUserTypeAttribute(): no logical attribute name specified, returning null");
return null;
}
Map<String,String> mappings = mapper.getAttributeMappings();
String attrName = mappings.get(logicalAttributeName);
if ( attrName == null ) {
if ( M_log.isDebugEnabled() ) {
M_log.debug("getUserTypeAttribute(): failed to find attribute mapping [logical attr name = " +
logicalAttributeName +
"][entry DN = " + ldapEntry.getDN() + "]");
}
return null;
}
LDAPAttribute attr = ldapEntry.getAttribute(attrName);
if ( attr == null ) {
if ( M_log.isDebugEnabled() ) {
M_log.debug("getUserTypeAttribute(): entry had no Sakai user type attr [physical attr name = " +
attrName + "][entry DN = " + ldapEntry.getDN() + "]");
}
}
return attr;
}
/**
* Maps the given list of attribute values to a single Sakai
* user type by passing each received String value, in order, to
* {@link #mapUserTypeAttributeValue(String)}. Exits with the first
* non-<code>null</code> return from that method or a value
* dependent on current value of
* {@link #isReturnLiteralAttributeValueIfNoMapping()}
*
* @param attrValues String values to test
* @return a Sakai user type, possibly null
*/
protected String mapUserTypeAttributeValues(String[] attrValues) {
for ( String value : attrValues ) {
String userType = mapUserTypeAttributeValue(value);
if ( userType != null ) {
return userType;
}
}
if ( isReturnLiteralAttributeValueIfNoMapping() ) {
return attrValues.length > 0 ? attrValues[0] : null;
}
return defaultSakaiUserType;
}
/**
* Effectively the same as
* <code>getAttributeValueToSakaiUserTypeMap().get(attrValue)</code>.
* Returns <code>null</code> if no mapping has been assigned.
*
* @param attrValue the attribute value to map
* @return the mapped value or <code>null</code> if no map or mapping
*/
protected String mapUserTypeAttributeValue(String attrValue) {
if ( attributeValueToSakaiUserTypeMap == null ) {
return null;
}
return attributeValueToSakaiUserTypeMap.get(attrValue);
}
/**
* Retrieve the current attribute value-to-Sakai user type map.
*
* @return a map of attribute values to Sakai user types
*/
public Map<String, String> getAttributeValueToSakaiUserTypeMap() {
return attributeValueToSakaiUserTypeMap;
}
/**
* Assign the attribute value-to-Sakai user type map.
*
* @param attributeValueToSakaiUserTypeMap a map of attribute
* values to Sakai user types
*/
public void setAttributeValueToSakaiUserTypeMap(
Map<String, String> attributeValueToSakaiUserTypeMap) {
this.attributeValueToSakaiUserTypeMap = attributeValueToSakaiUserTypeMap;
}
/**
* Retrieve the default Sakai user type, which will be returned from
* {@link #mapLdapEntryToSakaiUserType(LDAPEntry, LdapAttributeMapper)}
* if no mapping was found and
* {@link #isReturnLiteralAttributeValueIfNoMapping()} is <code>false</code>
*
* @return the default Sakai user type to return from
* {@link #mapLdapEntryToSakaiUserType(LDAPEntry, LdapAttributeMapper)}
*/
public String getDefaultSakaiUserType() {
return defaultSakaiUserType;
}
/**
* Assign the default Sakai user type.
*
* @see #getDefaultSakaiUserType()
*
* @param defaultSakaiUserType the default Sakai user type to return from
* {@link #mapLdapEntryToSakaiUserType(LDAPEntry, LdapAttributeMapper)}
*/
public void setDefaultSakaiUserType(String defaultSakaiUserType) {
this.defaultSakaiUserType = defaultSakaiUserType;
}
/**
* Access the key to a physical attribute name which will be used
* to resolve Sakai user types. Physical names are
* retrieved by querying the {@link LdapAttributeMapper} passed
* to {@link #mapLdapEntryToSakaiUserType(LDAPEntry, LdapAttributeMapper)}.
*
* @return a logical attribute name
*/
public String getLogicalAttributeName() {
return logicalAttributeName;
}
/**
* Assign the key to a physical attribute name which will be used
* to resolve Sakai user types.
*
* @see #getLogicalAttributeName()
*
* @param logicalAttributeName
*/
public void setLogicalAttributeName(String logicalAttributeName) {
this.logicalAttributeName = logicalAttributeName;
}
/**
* Check the behavior when attribute values cannot be mapped
* to a Sakai user type. If <code>true</code>,
* {@link #mapLdapEntryToSakaiUserType(LDAPEntry, LdapAttributeMapper)}
* will return the first attribute value encountered, otherwise will
* return the current value of {@link #getDefaultSakaiUserType()}.
* Defaults to <code>false</code>.
*
* @return <code>true</code> if failed mappings should return
* literal attribute values.
*/
public boolean isReturnLiteralAttributeValueIfNoMapping() {
return returnLiteralAttributeValueIfNoMapping;
}
/**
* Assign the behavior for calculating Sakai user types when
* attribute values fail to map.
*
* @see #isReturnLiteralAttributeValueIfNoMapping()
* @param returnLiteralAttributeValueIfNoMapping
*/
public void setReturnLiteralAttributeValueIfNoMapping(
boolean returnLiteralAttributeValueIfNoMapping) {
this.returnLiteralAttributeValueIfNoMapping = returnLiteralAttributeValueIfNoMapping;
}
}