/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.um.syncdata.dao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.InvalidSearchControlsException;
import javax.naming.directory.InvalidSearchFilterException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.dom4j.Document;
import org.dom4j.Element;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.util.DateUtil;
import com.jinhe.tss.core.util.EasyUtils;
import com.jinhe.tss.core.util.XMLDocUtil;
import com.jinhe.tss.um.helper.dto.GroupDTO;
import com.jinhe.tss.um.helper.dto.UserDTO;
import com.jinhe.tss.um.syncdata.SyncDataHelper;
/**
* 从LDAP数据里同步用户组织信息
*/
public class LDAPDataDao implements IOutDataDao {
public final static String DEFAULT_VALUE = "defaultValue";
/** 组需要的属性 */
public final static String APPLICATION_ID_GROUP = "applicationId";
public final static String DESCRIPTION_GROUP = "description";
public final static String GROUP_ORDER_GROUP = "groupOrder";
/** 用户需要的属性 */
public final static String APPLICATION_ID_USER = "applicationId";
public final static String LOGIN_NAME_USER = "loginName";
public final static String PASSWORD_USER = "password";
public final static String SEX_USER = "sex";
public final static String BIRTHDAY_USER = "birthday";
public final static String EMPLOYEE_NO_USER = "employeeNo";
public final static String USER_ORDER_USER = "userOrder";
private static final String GROUP_FILTER_STR = "OU=*";
private static final String USER_FILTER_STR = "CN=*";
/* otherAppUserId类似:CN=李文斌,OU=行政政法处,OU=省厅,O=GZCZ */
public UserDTO getUser(Map<String, String> paramsMap, String otherAppUserId){
List<?> list = getOtherUsers( paramsMap, paramsMap.get(SyncDataHelper.SINGLE_USER),
otherAppUserId.substring(otherAppUserId.indexOf(",") + 1),
otherAppUserId.substring(0, otherAppUserId.indexOf(",")));
if(!EasyUtils.isNullOrEmpty(list)) {
return (UserDTO)list.get(0);
}
return null;
}
private DirContext getConnection(Map<String, String> map){
// 初始化参数设置
Hashtable<String, String> env = new Hashtable<String, String> ();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.PROVIDER_URL, map.get(SyncDataHelper.URL));
env.put(Context.SECURITY_PRINCIPAL, map.get(SyncDataHelper.USERNAME));
env.put(Context.SECURITY_CREDENTIALS, map.get(SyncDataHelper.PASSWORD));
// 连接到数据源
DirContext conn = null;
try {
conn = new InitialDirContext(env);
} catch (Exception e) {
throw new BusinessException("连接LDAP失败", e);
}
return conn;
}
/*
* attributes格式如:
* <attributes>
<applicationId defaultValue="OA">applicationId</applicationId>
<id defaultValue="">id</id>
<parentGroupId defaultValue="">parentGroupId</parentGroupId>
<groupName defaultValue="">groupName</groupName>
<description defaultValue="">description</description>
<groupOrder defaultValue="">groupOrder</groupOrder>
</attributes>
* @see com.jinhe.tss.um.extend.syncdata.dao.IOutDataDao#getOtherGroups(java.lang.Object[])
*/
public List<?> getOtherGroups(Map<String, String> paramsMap, String attributes, String groupId) {
Map<String, String> attributesMap = new HashMap<String, String>();
Map<String, String> defaultValues = new HashMap<String, String>();
for (Iterator<?> it = XMLDocUtil.dataXml2Doc(attributes).getRootElement().elementIterator(); it.hasNext();) {
Element element = (Element) it.next();
attributesMap.put(element.getName(), element.getText());
defaultValues.put(element.getName(), element.attributeValue(DEFAULT_VALUE));
}
List<GroupDTO> items = new ArrayList<GroupDTO>();
try {
DirContext conn = getConnection(paramsMap);
NamingEnumeration<SearchResult> en = ldapSearch(conn, groupId, GROUP_FILTER_STR);
while (en != null && en.hasMoreElements()) {
SearchResult searchResult = en.next();
String dn = searchResult.getName();
// 组合全路径
dn = (dn != null && !"".equals(dn)) ? (dn + "," + groupId) : groupId;
if (dn.indexOf("OU=") < 0) continue;
GroupDTO group = new GroupDTO();
// 获得组的属性
group.setId(getGroupId(dn));
group.setName(getGroupName(dn));
group.setParentId(getParentGroupId(dn));
Attributes attrs = searchResult.getAttributes();
// applictionId
if (attrs.get(attributesMap.get(APPLICATION_ID_GROUP)) != null) {
group.setApplicationId(getValueFromAttribute(attrs.get(attributesMap.get(APPLICATION_ID_GROUP))));
}else{
group.setApplicationId(defaultValues.get(APPLICATION_ID_GROUP));
}
// description
if (attrs.get(attributesMap.get(DESCRIPTION_GROUP)) != null) {
group.setDescription(getValueFromAttribute(attrs.get(attributesMap.get(DESCRIPTION_GROUP))));
}
// groupOrder
if (attrs.get(attributesMap.get(GROUP_ORDER_GROUP).toString()) != null) {
group.setSeqNo(Integer.valueOf(getValueFromAttribute(attrs.get(attributesMap.get(GROUP_ORDER_GROUP)))));
}
items.add(group);
}
} catch (NamingException e) {
throw new BusinessException("获取外部用户组失败!",e);
}
return items;
}
public List<?> getOtherUsers(Map<String, String> paramsMap, String attributes, String groupId, Object...otherParams) {
String filterString = otherParams.length > 0 ? (String)otherParams[0] : USER_FILTER_STR;
Document doc = XMLDocUtil.dataXml2Doc(attributes);
Map<String, String> param = new HashMap<String, String>();
Map<String, String> defaultValues = new HashMap<String, String>();
Map<String, Integer> seqNoMap = new HashMap<String, Integer>();
for (Iterator<?> it = doc.getRootElement().elementIterator(); it.hasNext();) {
Element element = (Element) it.next();
param.put(element.getName(), element.getText());
defaultValues.put(element.getName(), element.attribute(DEFAULT_VALUE).getText());
}
List<UserDTO> items = new ArrayList<UserDTO>();
Map<String, Object> loginNameCache = new HashMap<String, Object> ();
Map<String, Object> dnCache = new HashMap<String, Object> ();
// 数据查询
try {
DirContext conn = getConnection(paramsMap);
NamingEnumeration<SearchResult> en = ldapSearch(conn, groupId, filterString);
while (en != null && en.hasMoreElements()) {
SearchResult sr = en.next();
String dn = sr.getName();
// 组合全路径
dn = dn + "," + groupId;
if(dnCache.containsKey(dn))
continue;
Attributes attrs = sr.getAttributes();
if (attrs.get("sn") == null){
continue;
}
UserDTO user = new UserDTO();
user.setId(dn);
user.setGroupId(getGroupId(dn));
if (attrs.get("sn") != null) {
user.setUserName(getNameValueFromAttribute( attrs.get("sn")));
}
// 获得用户的属性
// applictionId
if (attrs.get(param.get(APPLICATION_ID_USER).toString()) != null) {
user.setApplicationId(getValueFromAttribute(attrs.get(param.get(APPLICATION_ID_USER))));
}else{
user.setApplicationId(defaultValues.get(APPLICATION_ID_USER).toString());
}
// loginName
if (attrs.get(param.get(LOGIN_NAME_USER).toString()) != null) {
String uid_in_ldap = getNameValueFromAttribute(attrs.get(param.get(LOGIN_NAME_USER)));
// uid简称 有可能重名,重名只导入第一个
if(loginNameCache.containsKey(uid_in_ldap)) {
continue;
}
user.setLoginName(uid_in_ldap);
}else{
user.setLoginName(dn);
}
// password
if (attrs.get(param.get(PASSWORD_USER).toString()) != null) {
user.setPassword(getValueFromAttribute(attrs.get(param.get(PASSWORD_USER))));
}
// sex
if (attrs.get(param.get(SEX_USER).toString()) != null) {
user.setSex(getValueFromAttribute(attrs.get(param.get(SEX_USER))));
}
// birthday
if (attrs.get(param.get(BIRTHDAY_USER).toString()) != null) {
user.setBirthday(DateUtil.parse(getValueFromAttribute(attrs.get(param.get(BIRTHDAY_USER)))));
}
// employeeNo
if (attrs.get(param.get(EMPLOYEE_NO_USER).toString()) != null) {
user.setEmployeeNo(getValueFromAttribute(attrs.get(param.get(EMPLOYEE_NO_USER))));
}
// userOrder
if (attrs.get(param.get(USER_ORDER_USER).toString()) != null) {
user.setSeqNo(Integer.valueOf(getValueFromAttribute(attrs.get(param.get(USER_ORDER_USER)))));
} else {
Integer seqNo = (Integer)seqNoMap.get(user.getGroupId());
user.setSeqNo(seqNo == null ? new Integer(1) : new Integer(seqNo.intValue() + 1));
seqNoMap.put(user.getGroupId(), user.getSeqNo()); //将排序号放入map中以备下次保存同组的用户时可以取到 + 1
}
if(null != user){
items.add(user);
dnCache.put(dn, null);
loginNameCache.put(user.getLoginName(), null);
}
}
} catch (NamingException e) {
throw new BusinessException("获取外部用户失败!",e);
}
return items;
}
/**
* <p>
* LDAP查询
* </p>
* @param ctx
* @param searchBase
* @param filterString
* @return
*/
private NamingEnumeration<SearchResult> ldapSearch(DirContext ctx, String searchBase, String filterString) {
if (ctx == null)
return null;
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
try {
return ctx.search(searchBase, filterString, constraints);
} catch (InvalidSearchFilterException e1){
throw new BusinessException("Filter不合法", e1);
} catch (InvalidSearchControlsException e2){
throw new BusinessException("Constrains不合法", e2);
} catch (NamingException e) {
throw new BusinessException("外部组ID不合法", e);
}
}
/**
* @param dn
* 类似:CN=李文斌,OU=行政政法处,OU=省厅,O=GZCZ
* @return
* OU=行政政法处,OU=省厅,O=GZCZ
*/
private String getGroupId(String dn) {
int position = -1;
if ((position = dn.indexOf("OU=")) >= 0) {
return dn.substring(position);
}
if ((position = dn.indexOf("O=")) >= 0) {
return dn.substring(position);
}
return null;
}
/**
* @param dn
* 类似:OU=行政政法处,OU=省厅,O=GZCZ
* @return
* OU=省厅,O=GZCZ
*/
private String getParentGroupId(String dn) {
int position = dn.indexOf("OU=");
if (position >= 0) {
String selfId = dn.substring(position);
if ((position = selfId.indexOf(",OU=")) >= 0) {
return selfId.substring(position + 1);
}
//可能","号后面会多一个空格
if ((position = selfId.indexOf(", OU=")) >= 0) {
return selfId.substring(position + 2);
}
}
return null;
}
/**
* @param dn
* 类似:CN=李文斌,OU=行政政法处,OU=省厅,O=GZCZ
* @return
* 行政政法处
*/
private String getGroupName(String dn) {
int position = dn.indexOf("OU=");
if (position >= 0) {
String temp = dn.substring(position);
if ((position = temp.indexOf(",")) >= 0) {
return temp.substring(3, position); //=号和,号之间的就是groupName
}
}
return null;
}
private String getValueFromAttribute(javax.naming.directory.Attribute attr){
String attrString = attr.toString();
return attrString.substring(attrString.indexOf(":") + 1);
}
private String getNameValueFromAttribute(javax.naming.directory.Attribute attr){
String attrString = attr.toString();
return attrString.substring(attrString.indexOf(":") + 2);
}
}