001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.contentio.synchronize.impl; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.component.Component; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.commons.lang.StringUtils; 027import org.slf4j.Logger; 028 029import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection; 030import org.ametys.plugins.contentio.synchronize.impl.LDAPCollectionHelper.LDAPCollectionHelperSearchResult; 031import org.ametys.runtime.i18n.I18nizableText; 032 033/** 034 * Implementation of {@link SynchronizableContentsCollection} to be synchronized with a LDAP data source 035 */ 036public class LDAPSynchronizableContentsCollection extends AbstractDataSourceSynchronizableContentsCollection implements Component 037{ 038 private static final String __PARAM_LDAP_SCOPE = "scope"; 039 private static final String __PARAM_LDAP_RELATIVE_DN = "peopleDN"; 040 private static final String __PARAM_LDAP_FILTER = "baseFilter"; 041 042 /** The helper for LDAP connection */ 043 protected LDAPCollectionHelper _ldapHelper; 044 045 @Override 046 public void service(ServiceManager serviceManager) throws ServiceException 047 { 048 super.service(serviceManager); 049 _ldapHelper = (LDAPCollectionHelper) serviceManager.lookup(LDAPCollectionHelper.ROLE); 050 } 051 052 @Override 053 protected Map<String, Map<String, Object>> internalSearch(Map<String, Object> searchParameters, int offset, int limit, List<Object> sort, Logger logger) 054 { 055 // Sort is ignored in LDAP request 056 057 Map<String, List<String>> mapping = getMapping(); 058 Map<String, Map<String, Object>> searchResults = new HashMap<>(); 059 060 String idField = getIdField(); 061 List<String> remoteKeys = mapping.get(idField); 062 if (remoteKeys != null && remoteKeys.size() > 0) 063 { 064 // Filter from search parameters 065 String filter = getFilter(); 066 List<String> filters = new ArrayList<>(); 067 if (StringUtils.isNotEmpty(filter)) 068 { 069 filters.add(filter); 070 } 071 if (searchParameters != null) 072 { 073 for (String parameterName : searchParameters.keySet()) 074 { 075 filters.add(parameterName + "=" + searchParameters.get(parameterName)); 076 } 077 } 078 String filtersReduced = filters.stream().filter(StringUtils::isNotEmpty).map(s -> "(" + s + ")").reduce("", (s1, s2) -> s1 + s2); 079 if (!filtersReduced.isEmpty()) 080 { 081 filtersReduced = "(&" + filtersReduced + ")"; 082 } 083 084 try 085 { 086 LDAPCollectionHelperSearchResult results = _ldapHelper.search(getId(), getRelativeDN(), filtersReduced, getSearchScope(), offset, limit, mapping, remoteKeys.get(0), logger, getDataSourceId()); 087 088 searchResults = results.searchResults(); 089 for (Map<String, Object> result : searchResults.values()) 090 { 091 Object sccValues = result.get(remoteKeys.get(0)); 092 result.put(SCC_UNIQUE_ID, sccValues instanceof List<?> ? ((List<?>) sccValues).get(0) : sccValues); 093 } 094 095 _nbError = results.nbErrors(); 096 _hasGlobalError = results.hasGlobalError(); 097 } 098 catch (Exception e) 099 { 100 throw new RuntimeException("An error occured when importing from LDAP UserDirectory", e); 101 } 102 } 103 else 104 { 105 _nbError = 1; 106 logger.error("Missing LDAP attribute in mapping for field '{}' holding the unique identifier", idField); 107 } 108 109 return searchResults; 110 } 111 112 /** 113 * Get the scope for LDAP search 114 * @return The scope 115 */ 116 protected String getSearchScope() 117 { 118 return (String) getParameterValues().get(__PARAM_LDAP_SCOPE); 119 } 120 121 /** 122 * Get the LDAP filter 123 * @return the filter 124 */ 125 protected String getFilter() 126 { 127 return (String) getParameterValues().get(__PARAM_LDAP_FILTER); 128 } 129 130 /** 131 * Get the LDAP relative DN 132 * @return the relative DN 133 */ 134 protected String getRelativeDN() 135 { 136 return (String) getParameterValues().get(__PARAM_LDAP_RELATIVE_DN); 137 } 138 139 @Override 140 protected void configureSearchModel() 141 { 142 for (String columnOrCriteria : _columnsAndCriteria) 143 { 144 _searchModelConfiguration.addCriterion(columnOrCriteria); 145 _searchModelConfiguration.addColumn(columnOrCriteria, new I18nizableText(columnOrCriteria), false); 146 } 147 } 148 149 @Override 150 protected Map<String, Map<String, List<Object>>> getRemoteValues(Map<String, Object> searchParameters, Logger logger) 151 { 152 Map<String, Map<String, List<Object>>> organizedResults = super.getRemoteValues(searchParameters, logger); 153 _ldapHelper.transformTypedAttributes(organizedResults, getContentType(), getMapping().keySet()); 154 return organizedResults; 155 } 156}