Java tutorial
/* * Copyright 2009, OpenIAM LLC * This file is part of the OpenIAM Identity and Access Management Suite * * OpenIAM Identity and Access Management Suite is free software: * you can redistribute it and/or modify * it under the terms of the GNU General Public License * version 3 as published by the Free Software Foundation. * * OpenIAM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Lesser GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenIAM. If not, see <http://www.gnu.org/licenses/>. * */ /** * */ package org.openiam.idm.srvc.synch.service; import java.io.IOException; import java.sql.Timestamp; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.mule.module.client.MuleClient; import org.openiam.base.AttributeOperationEnum; import org.openiam.base.ws.MatchType; import org.openiam.base.ws.Response; import org.openiam.base.ws.ResponseCode; import org.openiam.base.ws.ResponseStatus; import org.openiam.base.ws.SearchParam; import org.openiam.dozer.converter.SynchConfigDozerConverter; import org.openiam.dozer.converter.SynchReviewDozerConverter; import org.openiam.dozer.converter.UserDozerConverter; import org.openiam.exception.BasicDataServiceException; import org.openiam.idm.searchbeans.AttributeMapSearchBean; import org.openiam.idm.searchbeans.UserSearchBean; import org.openiam.idm.srvc.audit.constant.AuditAction; import org.openiam.idm.srvc.audit.constant.AuditAttributeName; import org.openiam.idm.srvc.audit.dto.IdmAuditLog; import org.openiam.idm.srvc.audit.service.AuditLogService; import org.openiam.idm.srvc.auth.dto.Login; import org.openiam.idm.srvc.mngsys.domain.AttributeMapEntity; import org.openiam.idm.srvc.mngsys.service.AttributeMapDAO; import org.openiam.idm.srvc.res.dto.Resource; import org.openiam.idm.srvc.synch.domain.SynchConfigEntity; import org.openiam.idm.srvc.synch.domain.SynchReviewEntity; import org.openiam.idm.srvc.synch.dto.*; import org.openiam.idm.srvc.synch.srcadapter.AdapterFactory; import org.openiam.idm.srvc.user.service.UserDataService; import org.openiam.idm.srvc.user.dto.User; import org.openiam.idm.srvc.role.dto.Role; import org.openiam.provision.dto.ProvisionUser; import org.openiam.provision.service.ProvisionService; import org.openiam.script.ScriptIntegration; import org.openiam.util.MuleContextProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * @author suneet * */ @Service("synchService") public class IdentitySynchServiceImpl implements IdentitySynchService { @Autowired private SynchConfigDAO synchConfigDao; @Autowired protected AttributeMapDAO attributeMapDAO; @Autowired protected SynchReviewDAO synchReviewDAO; @Autowired protected SynchReviewDozerConverter synchReviewDozerConverter; @Autowired private AdapterFactory adapterFactory; @Autowired private UserDataService userManager; @Autowired @Qualifier("defaultProvision") private ProvisionService provisionService; @Autowired private UserDozerConverter userDozerConverter; @Autowired private SynchConfigDozerConverter synchConfigDozerConverter; @Value("${openiam.service_base}") private String serviceHost; @Value("${openiam.idm.ws.path}") private String serviceContext; @Autowired private AuditLogService auditLogService; @Value("${org.openiam.idm.system.user.id}") private String systemUserId; @Autowired @Qualifier("configurableGroovyScriptEngine") protected ScriptIntegration scriptRunner; private static final Log log = LogFactory.getLog(IdentitySynchServiceImpl.class); /* * The flags for the running tasks are handled by this Thread-Safe Set. * It stores the taskIds of the currently executing tasks. * This is faster and as reliable as storing the flags in the database, * if the tasks are only launched from ONE host in a clustered environment. * It is unique for each class-loader, which means unique per war-deployment. */ private static Set<String> runningTask = Collections.newSetFromMap(new ConcurrentHashMap()); /* (non-Javadoc) * @see org.openiam.idm.srvc.synch.service.IdentitySynchService#getAllConfig() */ @Transactional(readOnly = true) public List<SynchConfigEntity> getAllConfig() { List<SynchConfigEntity> configList = synchConfigDao.findAllConfig(); if (configList != null && !configList.isEmpty()) { return configList; } return null; } @Transactional(readOnly = true) public SynchConfigEntity findById(java.lang.String id) { if (id == null) { throw new IllegalArgumentException("id parameter is null"); } return synchConfigDao.findById(id); } @Transactional public SynchConfigEntity addConfig(SynchConfigEntity synchConfig) { if (synchConfig == null) { throw new IllegalArgumentException("synchConfig parameter is null"); } return synchConfigDao.add(synchConfig); } @Transactional public SynchConfigEntity mergeConfig(SynchConfigEntity synchConfig) { if (synchConfig == null) { throw new IllegalArgumentException("synchConfig parameter is null"); } if (synchConfig.getSynchReviews() == null) { // Explicitly add synch reviews to the entity synchConfig.setSynchReviews(getAllSynchReviewsBySynchConfigId(synchConfig.getSynchConfigId())); } return synchConfigDao.merge(synchConfig); } @Transactional public void removeConfig(String configId) { if (configId == null) { throw new IllegalArgumentException("id parameter is null"); } deleteAttributesMapList(getSynchConfigAttributeMaps(configId)); SynchConfigEntity config = synchConfigDao.findById(configId); synchConfigDao.remove(config); } public SyncResponse startSynchronization(SynchConfigEntity config) { return startSynchronization(config, null); } public SyncResponse startSynchReview(SynchReviewEntity synchReview) { return startSynchronization(synchReview.getSynchConfig(), synchReview); } private SyncResponse startSynchronization(final SynchConfigEntity config, SynchReviewEntity review) { SyncResponse syncResponse = new SyncResponse(ResponseStatus.SUCCESS); log.debug("-startSynchronization CALLED.^^^^^^^^"); IdmAuditLog idmAuditLog = new IdmAuditLog(); idmAuditLog.setRequestorUserId(systemUserId); idmAuditLog.setRequestorPrincipal("sysadmin"); idmAuditLog.setAction(AuditAction.SYNCHRONIZATION.value()); idmAuditLog.setSource(config.getSynchConfigId()); if ("INACTIVE".equalsIgnoreCase(config.getStatus())) { idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "WARNING: Synchronization config is in 'INACTIVE' status"); idmAuditLog = auditLogService.save(idmAuditLog); SyncResponse resp = new SyncResponse(ResponseStatus.FAILURE); resp.setErrorCode(ResponseCode.FAIL_PROCESS_INACTIVE); return resp; } SyncResponse processCheckResponse = addTask(config.getSynchConfigId()); if (processCheckResponse.getStatus() == ResponseStatus.FAILURE && processCheckResponse.getErrorCode() == ResponseCode.FAIL_PROCESS_ALREADY_RUNNING) { idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "WARNING: Previous synchronization run is not finished yet"); idmAuditLog = auditLogService.save(idmAuditLog); return processCheckResponse; } Date startDate = new Date(); SynchReviewEntity resultReview = new SynchReviewEntity(config, startDate); try { SynchConfig configDTO = synchConfigDozerConverter.convertToDTO(config, false); SynchReview reviewDTO = synchReviewDozerConverter.convertToDTO(review, false); String preScriptUrl = config.getPreSyncScript(); if (StringUtils.isNotBlank(preScriptUrl)) { log.debug("-PRE synchronization script CALLED.^^^^^^^^"); Map<String, Object> bindingMap = new HashMap<String, Object>(); bindingMap.put("config", configDTO); if (reviewDTO != null) { bindingMap.put("review", reviewDTO); } try { int ret = (Integer) scriptRunner.execute(bindingMap, preScriptUrl); if (ret == SyncConstants.FAIL) { syncResponse.setStatus(ResponseStatus.FAILURE); syncResponse.setErrorCode(ResponseCode.SYNCHRONIZATION_PRE_SRIPT_FAILURE); return syncResponse; } log.debug("-PRE synchronization script COMPLETE.^^^^^^^^"); if (ret == SyncConstants.SKIP) { return syncResponse; } else if (ret == SyncConstants.SKIP_TO_REVIEW) { resultReview.setSourceRejected(true); return syncResponse; } } catch (Exception e) { log.error(e); } } idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "Synchronization started..." + startDate); long newLastExecTime = System.currentTimeMillis(); idmAuditLog = auditLogService.save(idmAuditLog); configDTO.setParentAuditLogId(idmAuditLog.getId()); SourceAdapter adapt = adapterFactory.create(configDTO); syncResponse = adapt.startSynch(configDTO, review, resultReview); log.debug("SyncReponse updateTime value=" + newLastExecTime); idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "SyncReponse updateTime value=" + newLastExecTime); if (syncResponse.getLastRecordTime() == null) { synchConfigDao.updateExecTime(config.getSynchConfigId(), new Timestamp(newLastExecTime)); } else { synchConfigDao.updateExecTime(config.getSynchConfigId(), new Timestamp(syncResponse.getLastRecordTime().getTime())); } if (syncResponse.getLastRecProcessed() != null) { synchConfigDao.updateLastRecProcessed(config.getSynchConfigId(), syncResponse.getLastRecProcessed()); } log.debug("-startSynchronization COMPLETE.^^^^^^^^"); idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "-startSynchronization COMPLETE.^^^^^^^^"); String postScriptUrl = config.getPostSyncScript(); if (StringUtils.isNotBlank(postScriptUrl)) { log.debug("-POST synchronization script CALLED.^^^^^^^^"); Map<String, Object> bindingMap = new HashMap<String, Object>(); bindingMap.put("config", synchConfigDozerConverter.convertToDTO(config, false)); try { int ret = (Integer) scriptRunner.execute(bindingMap, postScriptUrl); if (ret == SyncConstants.FAIL) { syncResponse.setStatus(ResponseStatus.FAILURE); syncResponse.setErrorCode(ResponseCode.SYNCHRONIZATION_POST_SRIPT_FAILURE); return syncResponse; } log.debug("-POST synchronization script COMPLETE.^^^^^^^^"); } catch (Exception e) { log.error(e); } } System.out.println("IdentitySyncServiceImpl finished in => " + (System.currentTimeMillis() - newLastExecTime) + " milliseconds."); } catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); log.error(cnfe); syncResponse = new SyncResponse(ResponseStatus.FAILURE); syncResponse.setErrorCode(ResponseCode.CLASS_NOT_FOUND); syncResponse.setErrorText(cnfe.getMessage()); idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "ERROR: " + cnfe.getMessage()); } catch (Exception e) { log.error(e); e.printStackTrace(); syncResponse = new SyncResponse(ResponseStatus.FAILURE); syncResponse.setErrorText(e.getMessage()); idmAuditLog.addAttribute(AuditAttributeName.DESCRIPTION, "ERROR: " + e.getMessage()); } finally { endTask(config.getSynchConfigId()); if (resultReview.isSourceRejected() || CollectionUtils.isNotEmpty(resultReview.getReviewRecords())) { synchReviewDAO.save(resultReview); } idmAuditLog = auditLogService.save(idmAuditLog); } return syncResponse; } // manage if the task is running /** * Updates the RunningTask list to show that a process is running * @param configId * @return */ private SyncResponse addTask(String configId) { SyncResponse resp = new SyncResponse(ResponseStatus.SUCCESS); synchronized (runningTask) { if (runningTask.contains(configId)) { resp = new SyncResponse(ResponseStatus.FAILURE); resp.setErrorCode(ResponseCode.FAIL_PROCESS_ALREADY_RUNNING); return resp; } runningTask.add(configId); return resp; } } private void endTask(String configID) { runningTask.remove(configID); } public Response testConnection(SynchConfigEntity config) { try { SynchConfig configDTO = synchConfigDozerConverter.convertToDTO(config, false); SourceAdapter adapt = adapterFactory.create(configDTO); return adapt.testConnection(configDTO); } catch (ClassNotFoundException e) { Response resp = new Response(ResponseStatus.FAILURE); resp.setErrorCode(ResponseCode.CLASS_NOT_FOUND); resp.setErrorText(e.getMessage()); return resp; } catch (IOException e) { Response resp = new Response(ResponseStatus.FAILURE); resp.setErrorCode(ResponseCode.IO_EXCEPTION); resp.setErrorText(e.getMessage()); return resp; } } @Transactional public Response bulkUserMigration(BulkMigrationConfig config) { Response resp = new Response(ResponseStatus.SUCCESS); try { // select the user that we need to move UserSearchBean search = buildSearch(config); /* if (search.isEmpty()) { resp.setStatus(ResponseStatus.FAILURE); return resp; } */ List<User> searchResult = null; searchResult = userDozerConverter.convertToDTOList(userManager.findBeans(search), true); // all the provisioning service for (User user : searchResult) { log.debug("Migrating user: " + user.getId() + " " + user.getLastName()); ProvisionUser pUser = new ProvisionUser(user); if (config.getTargetRole() != null && !config.getTargetRole().isEmpty()) { Role r = parseRole(config.getTargetRole()); if (pUser.getRoles() == null) { Set<Role> roleSet = new HashSet<Role>(); pUser.setRoles(roleSet); } if ("ADD".equalsIgnoreCase(config.getOperation())) { // add to role r.setOperation(AttributeOperationEnum.ADD); pUser.getRoles().add(r); } else { // remove from role r.setOperation(AttributeOperationEnum.DELETE); pUser.getRoles().add(r); } } else if (config.getTargetResource() != null && !config.getTargetResource().isEmpty()) { Set<Resource> resourceSet = new HashSet<Resource>(); Resource resource = new Resource(); resource.setId(config.getTargetResource()); if ("ADD".equalsIgnoreCase(config.getOperation())) { // add to resourceList resource.setOperation(AttributeOperationEnum.ADD); resourceSet.add(resource); pUser.setResources(resourceSet); } else { // remove from resource List resource.setOperation(AttributeOperationEnum.DELETE); resourceSet.add(resource); pUser.setResources(resourceSet); } } // send message to provisioning service asynchronously //invokeOperation(pUser); provisionService.modifyUser(pUser); } } catch (BasicDataServiceException e) { log.error(e.getLocalizedMessage(), e); resp.setStatus(ResponseStatus.FAILURE); resp.setErrorCode(e.getCode()); } return null; } private void invokeOperation(ProvisionUser pUser) { try { Map<String, String> msgPropMap = new HashMap<String, String>(); msgPropMap.put("SERVICE_HOST", serviceHost); msgPropMap.put("SERVICE_CONTEXT", serviceContext); //Create the client with the context MuleClient client = new MuleClient(MuleContextProvider.getCtx()); client.sendAsync("vm://provisionServiceModifyMessage", pUser, msgPropMap); } catch (Exception e) { log.debug("EXCEPTION:bulkUserMigration"); log.error(e); } } private UserSearchBean buildSearch(BulkMigrationConfig config) { UserSearchBean search = new UserSearchBean(); if (config.getOrganizationId() != null && !config.getOrganizationId().isEmpty()) { search.addOrganizationId(config.getOrganizationId()); } if (config.getLastName() != null && !config.getLastName().isEmpty()) { search.setLastNameMatchToken(new SearchParam(config.getLastName(), MatchType.EXACT)); } if (config.getDeptId() != null && !config.getDeptId().isEmpty()) { search.addOrganizationId(config.getDeptId()); } if (config.getDivision() != null && !config.getDivision().isEmpty()) { search.addOrganizationId(config.getDivision()); } if (config.getAttributeName() != null && !config.getAttributeName().isEmpty()) { search.addAttribute(config.getAttributeName(), config.getAttributeValue()); } if (config.getUserStatus() != null) { search.setUserStatus(config.getUserStatus().toString()); } return search; } private Role parseRole(String roleStr) { String roleId = null; StringTokenizer st = new StringTokenizer(roleStr, "*"); if (st.hasMoreElements()) { roleId = st.nextToken(); } Role r = new Role(); r.setId(roleId); return r; } @Override @Transactional public Response resynchRole(final String roleId) { Response resp = new Response(ResponseStatus.SUCCESS); try { log.debug("Resynch Role: " + roleId); final UserSearchBean searchBean = new UserSearchBean(); searchBean.addRoleId(roleId); List<User> searchResult = null; searchResult = userDozerConverter.convertToDTOList(userManager.findBeans(searchBean), true); if (searchResult == null) { resp.setStatus(ResponseStatus.FAILURE); return resp; } // create role object to show role membership Role rl = new Role(); rl.setId(roleId); // all the provisioning service for (User user : searchResult) { log.debug("Updating the user since this role's configuration has changed.: " + user.getId() + " " + user.getLastName()); ProvisionUser pUser = new ProvisionUser(user); if (pUser.getRoles() == null) { Set<Role> roles = new HashSet<Role>(); roles.add(rl); pUser.setRoles(roles); } else { pUser.getRoles().add(rl); } provisionService.modifyUser(pUser); } } catch (BasicDataServiceException e) { log.error(e.getLocalizedMessage(), e); resp.setStatus(ResponseStatus.FAILURE); resp.setErrorCode(e.getCode()); } return resp; } @Override @Transactional(readOnly = true) public Integer getSynchConfigCountByExample(SynchConfigEntity example) { return synchConfigDao.count(example); } @Override @Transactional(readOnly = true) public List<SynchConfigEntity> getSynchConfigsByExample(SynchConfigEntity example, Integer from, Integer size) { return synchConfigDao.getByExample(example, from, size); } @Override @Transactional public void deleteAttributesMapList(List<AttributeMapEntity> attrMap) { attributeMapDAO.deleteAttributesMapList(attrMap); } @Override @Transactional public void deleteSynchReviewList(List<SynchReviewEntity> reviewList) { if (CollectionUtils.isNotEmpty(reviewList)) { for (SynchReviewEntity e : reviewList) { synchReviewDAO.delete(e); } } } @Override @Transactional(readOnly = true) public List<SynchReviewEntity> getAllSynchReviewsBySynchConfigId(String synchConfigId) { return synchReviewDAO.findAllBySynchConfigId(synchConfigId); } @Override @Transactional(readOnly = true) public List<AttributeMapEntity> getSynchConfigAttributeMaps(String synchConfigId) { return attributeMapDAO.findBySynchConfigId(synchConfigId); } @Override @Transactional(readOnly = true) public List<AttributeMapEntity> getSynchConfigAttributeMaps(AttributeMapSearchBean searchBean) { return attributeMapDAO.getByExample(searchBean); } }