private void migrateUser( final long fromDirectoryId, final long toDirectoryId, final String remoteUser, final User user, final AtomicLong migratedCount) throws Exception { if (!user.getName().equalsIgnoreCase(remoteUser)) { UserWithAttributes userWithAttributes = directoryManager.findUserWithAttributesByName(fromDirectoryId, user.getName()); try { final UserTemplate newUser = new UserTemplate(user); newUser.setDirectoryId(toDirectoryId); directoryManager.addUser( toDirectoryId, newUser, new PasswordCredential(generatePassword())); } catch (InvalidUserException e) { // That's fine just go on to the next user. Don't copy the groups. return; } // Migrate attributes Set<String> keys = userWithAttributes.getKeys(); Map<String, Set<String>> attributes = new HashMap<String, Set<String>>(); for (String key : keys) { Set<String> values = userWithAttributes.getValues(key); attributes.put(key, values); } directoryManager.storeUserAttributes(toDirectoryId, user.getName(), attributes); MembershipQuery<Group> groupQuery = QueryBuilder.queryFor(Group.class, EntityDescriptor.group()) .parentsOf(EntityDescriptor.user()) .withName(user.getName()) .returningAtMost(EntityQuery.ALL_RESULTS); List<Group> groups = directoryManager.searchDirectGroupRelationships(fromDirectoryId, groupQuery); for (Group group : groups) { // We may need to add the group first try { directoryManager.findGroupByName(toDirectoryId, group.getName()); } catch (GroupNotFoundException ex) { final GroupTemplate newGroup = new GroupTemplate(group); newGroup.setDirectoryId(toDirectoryId); directoryManager.addGroup(toDirectoryId, newGroup); } directoryManager.addUserToGroup(toDirectoryId, user.getName(), group.getName()); directoryManager.removeUserFromGroup(fromDirectoryId, user.getName(), group.getName()); } directoryManager.removeUser(fromDirectoryId, user.getName()); migratedCount.addAndGet(1); } }
private void migrateUsers( final long fromDirectoryId, final long toDirectoryId, final String remoteUser, final MigrateDirectoryUsersCommand migrateUsersCommand, final BindException errors) { // Check the to & from directories Directory from = validateDirectory(fromDirectoryId, errors, "fromDirectoryId"); Directory to = validateDirectory(toDirectoryId, errors, "toDirectoryId"); if (to != null && to.equals(from)) { errors.addError( new FieldError( "migration", "toDirectoryId", i18nResolver.getText("embedded.crowd.directory.migrate.users.field.directory.same"))); } if (errors.hasErrors()) { return; } setDirectoryEnabled(from, false); setDirectoryEnabled(to, false); // Copy SearchRestriction restriction = NullRestrictionImpl.INSTANCE; UserQuery<User> query = new UserQuery<User>(User.class, restriction, 0, -1); try { // TODO: Sucking all users in like this may be problematic for Confluence. If planning to // enable this // TODO: feature for other products make sure the performance impacts are understood. List<User> users = directoryManager.searchUsers(fromDirectoryId, query); final AtomicLong migratedCount = new AtomicLong(0); for (Iterator<User> iter = users.iterator(); iter.hasNext(); ) { final User user = iter.next(); transactionTemplate.execute( new TransactionCallback() { public Object doInTransaction() { try { migrateUser(fromDirectoryId, toDirectoryId, remoteUser, user, migratedCount); } catch (Exception e) { throw new RuntimeException(e); } return null; } }); } migrateUsersCommand.setTestSuccessful(true); migrateUsersCommand.setTotalCount(users.size()); migrateUsersCommand.setMigratedCount(migratedCount.get()); } catch (Exception e) { log.error("User migration failed", e); errors.addError( new ObjectError( "migration", i18nResolver.getText( "embedded.crowd.directory.migrate.users.error", htmlEncoder.encode(e.getMessage())))); } // Enable both directories setDirectoryEnabled(from, true); setDirectoryEnabled(to, true); }