edu.internet2.middleware.grouper.grouperUi.serviceLogic.UiV2GroupImport Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of grouper-ui Show documentation
Show all versions of grouper-ui Show documentation
Internet2 Groups Management User Interface
The newest version!
/*******************************************************************************
* Copyright 2014 Internet2
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.internet2.middleware.grouper.grouperUi.serviceLogic;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.internet2.middleware.grouper.Group;
import edu.internet2.middleware.grouper.GroupFinder;
import edu.internet2.middleware.grouper.GrouperSession;
import edu.internet2.middleware.grouper.GrouperSourceAdapter;
import edu.internet2.middleware.grouper.Member;
import edu.internet2.middleware.grouper.Membership;
import edu.internet2.middleware.grouper.MembershipFinder;
import edu.internet2.middleware.grouper.SubjectFinder;
import edu.internet2.middleware.grouper.app.loader.GrouperLoaderConfig;
import edu.internet2.middleware.grouper.audit.AuditEntry;
import edu.internet2.middleware.grouper.audit.AuditTypeBuiltin;
import edu.internet2.middleware.grouper.exception.GrouperSessionException;
import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiGroup;
import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiSubject;
import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiPaging;
import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiResponseJs;
import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiScreenAction;
import edu.internet2.middleware.grouper.grouperUi.beans.json.GuiScreenAction.GuiMessageType;
import edu.internet2.middleware.grouper.grouperUi.beans.simpleMembershipUpdate.ImportSubjectWrapper;
import edu.internet2.middleware.grouper.grouperUi.beans.ui.GroupContainer;
import edu.internet2.middleware.grouper.grouperUi.beans.ui.GroupImportContainer;
import edu.internet2.middleware.grouper.grouperUi.beans.ui.GroupImportError;
import edu.internet2.middleware.grouper.grouperUi.beans.ui.GroupImportGroupSummary;
import edu.internet2.middleware.grouper.grouperUi.beans.ui.GrouperRequestContainer;
import edu.internet2.middleware.grouper.grouperUi.beans.ui.TextContainer;
import edu.internet2.middleware.grouper.grouperUi.serviceLogic.SimpleMembershipUpdateImportExport.GrouperImportException;
import edu.internet2.middleware.grouper.hibernate.AuditControl;
import edu.internet2.middleware.grouper.hibernate.GrouperTransactionType;
import edu.internet2.middleware.grouper.hibernate.HibernateHandler;
import edu.internet2.middleware.grouper.hibernate.HibernateHandlerBean;
import edu.internet2.middleware.grouper.hibernate.HibernateSession;
import edu.internet2.middleware.grouper.internal.dao.GrouperDAOException;
import edu.internet2.middleware.grouper.internal.dao.QueryOptions;
import edu.internet2.middleware.grouper.internal.util.GrouperUuid;
import edu.internet2.middleware.grouper.j2ee.GrouperRequestWrapper;
import edu.internet2.middleware.grouper.j2ee.GrouperUiRestServlet;
import edu.internet2.middleware.grouper.membership.MembershipType;
import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
import edu.internet2.middleware.grouper.misc.GrouperSessionHandler;
import edu.internet2.middleware.grouper.privs.AccessPrivilege;
import edu.internet2.middleware.grouper.ui.GrouperUiFilter;
import edu.internet2.middleware.grouper.ui.exceptions.ControllerDone;
import edu.internet2.middleware.grouper.ui.exceptions.NoSessionException;
import edu.internet2.middleware.grouper.ui.tags.GrouperPagingTag2;
import edu.internet2.middleware.grouper.ui.util.GrouperUiConfig;
import edu.internet2.middleware.grouper.ui.util.GrouperUiUserData;
import edu.internet2.middleware.grouper.ui.util.GrouperUiUtils;
import edu.internet2.middleware.grouper.ui.util.ProgressBean;
import edu.internet2.middleware.grouper.userData.GrouperUserDataApi;
import edu.internet2.middleware.grouper.util.GrouperCallable;
import edu.internet2.middleware.grouper.util.GrouperFuture;
import edu.internet2.middleware.grouper.util.GrouperUtil;
import edu.internet2.middleware.grouperClient.collections.MultiKey;
import edu.internet2.middleware.grouperClient.util.ExpirableCache;
import edu.internet2.middleware.subject.Subject;
import edu.internet2.middleware.subject.SubjectNotUniqueException;
import edu.internet2.middleware.subject.SubjectUtils;
/**
* operations in the group screen
* @author mchyzer
*
*/
public class UiV2GroupImport {
/** logger */
protected static final Log LOG = edu.internet2.middleware.grouper.util.GrouperUtil.getLog(UiV2GroupImport.class);
/**
* validate import list
* @param request
* @param response
*/
public void groupImportValidateList(HttpServletRequest request, HttpServletResponse response) {
final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
GrouperSession grouperSession = null;
try {
grouperSession = GrouperSession.start(loggedInSubject);
GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
String entityList = StringUtils.defaultString(request.getParameter("entityList"));
//split trim by comma, semi, or whitespace
entityList = StringUtils.replace(entityList, ",", " ");
entityList = StringUtils.replace(entityList, ";", " ");
String[] entityIdOrIdentifiers = GrouperUtil.splitTrim(entityList, null, true);
if (GrouperUtil.length(entityIdOrIdentifiers) == 0) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#entityListId",
TextContainer.retrieveFromRequest().getText().get("groupImportNoEntitiesSpecified")));
return;
}
if (GrouperUtil.length(entityIdOrIdentifiers) > 100) {
guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
TextContainer.retrieveFromRequest().getText().get("groupImportTooManyEntitiesToValidate")));
return;
}
//extra source ids and subjects ids
Set extraGuiSubjects = new LinkedHashSet();
GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupImportContainer().setGroupImportExtraGuiSubjects(extraGuiSubjects);
String source = request.getParameter("searchEntitySourceName");
List entityIdOrIdentifiersList = new ArrayList(Arrays.asList(GrouperUtil.nonNull(
entityIdOrIdentifiers, String.class)));
Map entityIdOrIdentifierMap = null;
if (StringUtils.equals("all", source)) {
entityIdOrIdentifierMap = SubjectFinder.findByIdsOrIdentifiers(entityIdOrIdentifiersList);
} else {
entityIdOrIdentifierMap = SubjectFinder.findByIdsOrIdentifiers(entityIdOrIdentifiersList, source);
}
//lets add all the subjects
for (Subject subject : GrouperUtil.nonNull(entityIdOrIdentifierMap).values()) {
extraGuiSubjects.add(new GuiSubject(subject));
}
//lets see which are missing
entityIdOrIdentifiersList.removeAll(GrouperUtil.nonNull(entityIdOrIdentifierMap).keySet());
if (entityIdOrIdentifiersList.size() > 0) {
GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupImportContainer().setEntityIdsNotFound(GrouperUtil.join(entityIdOrIdentifiersList.iterator(), ", "));
guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
TextContainer.retrieveFromRequest().getText().get("groupImportEntityIdsNotFound")));
}
//clear out combobox
guiResponseJs.addAction(GuiScreenAction.newScript(
"dijit.byId('groupAddMemberComboId').set('displayedValue', ''); " +
"dijit.byId('groupAddMemberComboId').set('value', '');"));
//select the option for enter in list
guiResponseJs.addAction(GuiScreenAction.newFormFieldValue("bulkAddOptions", "input"));
//fill in the extra subjects
guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#groupImportExtraMembersDivId",
"/WEB-INF/grouperUi2/groupImport/groupImportExtraSubjects.jsp"));
} finally {
GrouperSession.stopQuietly(grouperSession);
}
}
/**
* export a group
* @param request
* @param response
*/
public void groupExportSubmit(HttpServletRequest request, HttpServletResponse response) {
final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
GrouperSession grouperSession = null;
Group group = null;
try {
grouperSession = GrouperSession.start(loggedInSubject);
List urlStrings = GrouperUiRestServlet.extractUrlStrings(request);
//groupId=721e4e8ae6e54c4087db092f0a6372f7
String groupIdString = urlStrings.get(2);
String groupId = GrouperUtil.prefixOrSuffix(groupIdString, "=", false);
group = GroupFinder.findByUuid(grouperSession, groupId, false);
if (group == null) {
throw new RuntimeException("Cant find group by id: " + groupId);
}
GroupContainer groupContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupContainer();
GroupImportContainer groupImportContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupImportContainer();
groupContainer.setGuiGroup(new GuiGroup(group));
if (!groupContainer.isCanRead()) {
throw new RuntimeException("Cant read group: " + group.getName());
}
//ids
String groupExportOptions = urlStrings.get(3);
boolean exportAll = false;
if (StringUtils.equals("all", groupExportOptions)) {
groupImportContainer.setExportAll(true);
exportAll = true;
} else if (StringUtils.equals("ids", groupExportOptions)) {
groupImportContainer.setExportAll(false);
} else {
throw new RuntimeException("Not expecting group-export-options value: '" + groupExportOptions + "'");
}
//groupExportSubjectIds_removeAllMembers.csv
@SuppressWarnings("unused")
String fileName = urlStrings.get(4);
if (exportAll) {
String headersCommaSeparated = GrouperUiConfig.retrieveConfig().propertyValueString(
"uiV2.group.exportAllSubjectFields");
String exportAllSortField = GrouperUiConfig.retrieveConfig().propertyValueString(
"uiV2.group.exportAllSortField");
SimpleMembershipUpdateImportExport.exportGroupAllFieldsToBrowser(group, headersCommaSeparated, exportAllSortField, false);
} else {
SimpleMembershipUpdateImportExport.exportGroupSubjectIdsCsv(group, false);
}
GrouperUserDataApi.recentlyUsedGroupAdd(GrouperUiUserData.grouperUiGroupNameForUserData(),
loggedInSubject, group);
} finally {
GrouperSession.stopQuietly(grouperSession);
}
}
/**
* export group members screen
* @param request
* @param response
*/
public void groupExport(HttpServletRequest request, HttpServletResponse response) {
final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
GrouperSession grouperSession = null;
Group group = null;
try {
grouperSession = GrouperSession.start(loggedInSubject);
group = UiV2Group.retrieveGroupHelper(request, AccessPrivilege.READ).getGroup();
if (group == null) {
return;
}
GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId",
"/WEB-INF/grouperUi2/groupImport/groupExport.jsp"));
} finally {
GrouperSession.stopQuietly(grouperSession);
}
}
/**
* export group members screen change the type of export
* @param request
* @param response
*/
public void groupExportTypeChange(HttpServletRequest request, HttpServletResponse response) {
final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
GrouperSession grouperSession = null;
Group group = null;
try {
grouperSession = GrouperSession.start(loggedInSubject);
group = UiV2Group.retrieveGroupHelper(request, AccessPrivilege.READ).getGroup();
if (group == null) {
return;
}
String groupExportOptions = request.getParameter("group-export-options[]");
GroupImportContainer groupImportContainer = GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupImportContainer();
if (StringUtils.equals("all", groupExportOptions)) {
groupImportContainer.setExportAll(true);
} else if (StringUtils.equals("ids", groupExportOptions)) {
groupImportContainer.setExportAll(false);
} else {
throw new RuntimeException("Not expecting group-export-options value: '" + groupExportOptions + "'");
}
GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#formActionsDivId",
"/WEB-INF/grouperUi2/groupImport/groupExportButtons.jsp"));
} finally {
GrouperSession.stopQuietly(grouperSession);
}
}
/**
* setup the extra groups (other than combobox), and maybe move the combobox down
* @param loggedInSubject
* @param request
* @param removeGroupId if removing one
* @param includeCombobox
* @param allGroups, pass in a blank linked hash set, and all groups will be populated including combobox
* @param errorOnNullCombobox true if an error should appear if there is nothing in the combobox
* @return true if ok, false if not
*/
private boolean groupImportSetupExtraGroups(Subject loggedInSubject,
HttpServletRequest request, GuiResponseJs guiResponseJs, boolean considerRemoveGroupId, boolean includeCombobox,
Set allGroups, boolean errorOnNullCombobox) {
Set extraGuiGroups = new LinkedHashSet();
GrouperRequestContainer.retrieveFromRequestOrCreate().getGroupImportContainer().setGroupImportExtraGuiGroups(extraGuiGroups);
String removeGroupId = null;
//if removing a group id
if (considerRemoveGroupId) {
removeGroupId = request.getParameter("removeGroupId");
if (StringUtils.isBlank(removeGroupId)) {
throw new RuntimeException("Why would removeGroupId be empty????");
}
}
//if moving combobox down to extra list or getting all groups
String comboValue = request.getParameter("groupImportGroupComboName");
if (StringUtils.isBlank(comboValue)) {
//if didnt pick one from results
comboValue = request.getParameter("groupImportGroupComboNameDisplay");
}
Group theGroup = StringUtils.isBlank(comboValue) ? null : new GroupFinder()
.assignPrivileges(AccessPrivilege.UPDATE_PRIVILEGES)
.assignSubject(loggedInSubject)
.assignFindByUuidOrName(true).assignScope(comboValue).findGroup();
boolean success = true;
if (theGroup == null) {
if (includeCombobox && errorOnNullCombobox) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#groupImportGroupComboErrorId",
TextContainer.retrieveFromRequest().getText().get("groupImportGroupNotFound")));
success = false;
}
} else {
if (includeCombobox) {
extraGuiGroups.add(new GuiGroup(theGroup));
}
//always add to all groups
allGroups.add(theGroup);
}
//loop through all the hidden fields (max 100)
//TODO cant this loop and the above logic be collapsed?
for (int i=0;i<100;i++) {
String extraGroupId = request.getParameter("extraGroupId_" + i);
//we are at the end
if (StringUtils.isBlank(extraGroupId)) {
break;
}
//might be removing this one
if (considerRemoveGroupId && StringUtils.equals(removeGroupId, extraGroupId)) {
continue;
}
theGroup = new GroupFinder()
.assignPrivileges(AccessPrivilege.UPDATE_PRIVILEGES)
.assignSubject(loggedInSubject)
.assignFindByUuidOrName(true).assignScope(extraGroupId).findGroup();
extraGuiGroups.add(new GuiGroup(theGroup));
//always add to all groups
allGroups.add(theGroup);
}
return success;
}
/**
* keep an expirable cache of import progress for 5 hours (longest an import is expected). This has multikey of session id and some random uuid
* uniquely identifies this import as opposed to other imports in other tabs. This cannot have any request objects or j2ee objects
*/
private static ExpirableCache importThreadProgress = new ExpirableCache(300);
/**
* submit a group import
* @param request
* @param response
*/
public void groupImportSubmit(HttpServletRequest request, HttpServletResponse response) {
Map debugMap = new LinkedHashMap();
long startNanos = System.nanoTime();
debugMap.put("method", "groupImportSubmit");
try {
final Subject loggedInSubject = GrouperUiFilter.retrieveSubjectLoggedIn();
GrouperRequestContainer grouperRequestContainer = GrouperRequestContainer.retrieveFromRequestOrCreate();
final GroupImportContainer groupImportContainer = grouperRequestContainer.getGroupImportContainer();
String sessionId = request.getSession().getId();
debugMap.put("sessionId", GrouperUtil.abbreviate(sessionId, 8));
// uniquely identifies this import as opposed to other imports in other tabs
String uniqueImportId = GrouperUuid.getUuid();
debugMap.put("uniqueImportId", GrouperUtil.abbreviate(uniqueImportId, 8));
groupImportContainer.setUniqueImportId(uniqueImportId);
MultiKey reportMultiKey = new MultiKey(sessionId, uniqueImportId);
importThreadProgress.put(reportMultiKey, groupImportContainer);
GrouperSession grouperSession = null;
GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
final String bulkAddOption = request.getParameter("bulkAddOptions");
//TODO should this be called "groupsTheUserCanUpdate" ?
final Set groups = new LinkedHashSet();
final Set subjectSet = new LinkedHashSet();
final Map listInvalidSubjectIdsAndRow = new LinkedHashMap();
String replaceOrRemoveExistingMembers = request.getParameter("replaceOrRemoveExistingMembers");
final boolean importReplaceMembers = StringUtils.equals(replaceOrRemoveExistingMembers, "replace");
final boolean removeMembers = StringUtils.equals(replaceOrRemoveExistingMembers, "remove");
final Timestamp startDate;
try {
String startDateString = request.getParameter("startDate");
startDate = GrouperUtil.stringToTimestampTimeRequiredLocalDateTime(startDateString);
} catch (Exception e) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#member-start-date",
TextContainer.retrieveFromRequest().getText().get("groupImportFromDateInvalid")));
return;
}
final Timestamp endDate;
try {
String endDateString = request.getParameter("endDate");
endDate = GrouperUtil.stringToTimestampTimeRequiredLocalDateTime(endDateString);
} catch (Exception e) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#member-end-date",
TextContainer.retrieveFromRequest().getText().get("groupImportToDateInvalid")));
return;
}
if (startDate != null && endDate != null && !endDate.after(startDate)) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#member-end-date",
TextContainer.retrieveFromRequest().getText().get("groupImportToDateAfterFromDateError")));
return;
}
final Object[] csvEntriesObject = new Object[1];
final String[] fileName = new String[1];
try {
grouperSession = GrouperSession.start(loggedInSubject);
boolean success = groupImportSetupExtraGroups(loggedInSubject, request, guiResponseJs, false, true, groups, false);
if (!success) {
//error message already shown
return;
}
debugMap.put("groups", groups.size());
if (groups.size() == 0) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#groupImportGroupComboErrorId",
TextContainer.retrieveFromRequest().getText().get("groupImportGroupNotFound")));
return;
}
// can be import, input, list
debugMap.put("bulkAddOption", bulkAddOption);
if (StringUtils.equals(bulkAddOption, "import")) {
GrouperRequestWrapper grouperRequestWrapper = GrouperRequestWrapper.retrieveGrouperRequestWrapper(request);
FileItem importCsvFile = grouperRequestWrapper.getParameterFileItem("importCsvFile");
if (importCsvFile == null) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#importCsvFileId",
TextContainer.retrieveFromRequest().getText().get("groupImportUploadFile")));
return;
}
Reader reader = null;
reader = new InputStreamReader(importCsvFile.getInputStream());
fileName[0] = StringUtils.defaultString(importCsvFile == null ? "" : importCsvFile.getName());
try {
List csvEntries = SimpleMembershipUpdateImportExport.parseCsvImportFileToCsv(reader, fileName[0]);
debugMap.put("csvEntries", GrouperUtil.length(csvEntries));
csvEntriesObject[0] = csvEntries;
} catch (GrouperImportException gie) {
if (LOG.isDebugEnabled()) {
LOG.debug("error in import", gie);
}
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#importCsvFileId", GrouperUtil.xmlEscape(gie.getMessage())));
return;
}
} else if (StringUtils.equals(bulkAddOption, "input")) {
//combobox
success = groupImportSetupExtraSubjects(loggedInSubject, request, guiResponseJs, false, true, subjectSet, false);
if (!success) {
//error message already shown
return;
}
if (subjectSet.size() == 0) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#groupAddMemberComboErrorId",
TextContainer.retrieveFromRequest().getText().get("groupImportSubjectNotFound")));
return;
}
} else if (StringUtils.equals(bulkAddOption, "list")) {
String entityList = StringUtils.defaultString(request.getParameter("entityList"));
//split trim by comma, semi, or whitespace
entityList = StringUtils.replace(entityList, ",", " ");
entityList = StringUtils.replace(entityList, ";", " ");
String[] entityIdOrIdentifiers = GrouperUtil.splitTrim(entityList, null, true);
debugMap.put("entityIdOrIdentifiers", GrouperUtil.length(entityIdOrIdentifiers));
if (GrouperUtil.length(entityIdOrIdentifiers) == 0) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#entityListId",
TextContainer.retrieveFromRequest().getText().get("groupImportNoEntitiesSpecified")));
return;
}
String source = request.getParameter("searchEntitySourceName");
List entityIdOrIdentifiersList = new ArrayList(Arrays.asList(GrouperUtil.nonNull(
entityIdOrIdentifiers, String.class)));
Map entityIdOrIdentifierMap = null;
if (StringUtils.equals("all", source)) {
entityIdOrIdentifierMap = SubjectFinder.findByIdsOrIdentifiers(entityIdOrIdentifiersList);
} else {
entityIdOrIdentifierMap = SubjectFinder.findByIdsOrIdentifiers(entityIdOrIdentifiersList, source);
}
//lets add all the subjects
subjectSet.addAll(GrouperUtil.nonNull(entityIdOrIdentifierMap).values());
//lets see which are missing
List originalIdList = new ArrayList(entityIdOrIdentifiersList);
//lets see which are missing
entityIdOrIdentifiersList.removeAll(GrouperUtil.nonNull(entityIdOrIdentifierMap).keySet());
//keep trac of the index of the invalid ids
for (String invalidId : entityIdOrIdentifiersList) {
int index = originalIdList.indexOf(invalidId);
listInvalidSubjectIdsAndRow.put(invalidId, index == -1 ? null : index);
}
} else {
throw new RuntimeException("Not expecting bulk add option: " + bulkAddOption);
}
{
Group group = UiV2Group.retrieveGroupHelper(request, AccessPrivilege.UPDATE, false).getGroup();
if (group != null) {
groupImportContainer.setImportFromGroup(true);
groupImportContainer.setGroupId(group.getId());
}
}
{
Subject subject = UiV2Subject.retrieveSubjectHelper(request, false);
if (subject != null) {
groupImportContainer.setImportFromSubject(true);
groupImportContainer.setSubjectId(subject.getId());
groupImportContainer.setSourceId(subject.getSourceId());
}
}
if (importReplaceMembers && removeMembers) {
guiResponseJs.addAction(GuiScreenAction.newValidationMessage(GuiMessageType.error,
"#replaceExistingMembersId",
TextContainer.retrieveFromRequest().getText().get("groupImportCantReplaceAndRemove")));
return;
}
Iterator groupIterator = groups.iterator();
//TODO first off, why checking VIEW? should it be READ? or just UPDATE?
//TODO second, are groups not checked for UPDATE above in groupImportSetupExtraGroups()? or is it just groups added from gruop screen?
//lets go through the groups that were submitted
while (groupIterator.hasNext()) {
final Group group = groupIterator.next();
{
//remove groups that cannot be viewed
boolean canView = (Boolean)GrouperSession.callbackGrouperSession(
GrouperSession.staticGrouperSession().internal_getRootSession(), new GrouperSessionHandler() {
@Override
public Object callback(GrouperSession grouperSession) throws GrouperSessionException {
return group.canHavePrivilege(loggedInSubject, AccessPrivilege.VIEW.getName(), false);
}
});
if (!canView) {
guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
TextContainer.retrieveFromRequest().getText().get("groupImportGroupCantView")));
groupIterator.remove();
continue;
}
}
{
//give error if cant update
boolean canUpdate = (Boolean)GrouperSession.callbackGrouperSession(
GrouperSession.staticGrouperSession().internal_getRootSession(), new GrouperSessionHandler() {
@Override
public Object callback(GrouperSession grouperSession) throws GrouperSessionException {
return group.canHavePrivilege(loggedInSubject, AccessPrivilege.UPDATE.getName(), false);
}
});
if (!canUpdate) {
guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
TextContainer.retrieveFromRequest().getText().get("groupImportGroupCantUpdate")));
continue;
}
}
}
} catch (Exception e) {
throw new RuntimeException("error", e);
} finally {
GrouperSession.stopQuietly(grouperSession);
}
GrouperCallable grouperCallable = new GrouperCallable("groupImportMembers") {
@Override
public Void callLogic() {
try {
groupImportContainer.getProgressBean().setStartedMillis(System.currentTimeMillis());
UiV2GroupImport.this.groupImportSubmitHelper(loggedInSubject, groupImportContainer, groups, subjectSet,
listInvalidSubjectIdsAndRow, removeMembers, importReplaceMembers, bulkAddOption, fileName[0], (List)csvEntriesObject[0],
startDate, endDate);
} catch (RuntimeException re) {
groupImportContainer.getProgressBean().setHasException(true);
groupImportContainer.getProgressBean().setException(re);
// log this since the thread will just end and will never get logged
LOG.error("error", re);
} finally {
// we done
groupImportContainer.getProgressBean().setComplete(true);
}
return null;
}
};
// see if running in thread
boolean useThreads = GrouperUiConfig.retrieveConfig().propertyValueBooleanRequired("grouperUi.import.useThread");
debugMap.put("useThreads", useThreads);
if (useThreads) {
GrouperFuture grouperFuture = GrouperUtil.executorServiceSubmit(GrouperUtil.retrieveExecutorService(), grouperCallable);
Integer waitForCompleteForSeconds = GrouperUiConfig.retrieveConfig().propertyValueInt("grouperUi.import.progressStartsInSeconds");
debugMap.put("waitForCompleteForSeconds", waitForCompleteForSeconds);
GrouperFuture.waitForJob(grouperFuture, waitForCompleteForSeconds);
debugMap.put("threadAlive", !grouperFuture.isDone());
} else {
grouperCallable.callLogic();
}
guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#grouperMainContentDivId",
"/WEB-INF/grouperUi2/groupImport/groupImportReportWrapper.jsp"));
groupImportReportStatusHelper(sessionId, uniqueImportId);
} catch (RuntimeException re) {
debugMap.put("exception", GrouperUtil.getFullStackTrace(re));
throw re;
} finally {
if (LOG.isDebugEnabled()) {
debugMap.put("tookMillis", (System.nanoTime()-startNanos)/1000000);
LOG.debug(GrouperUtil.mapToString(debugMap));
}
}
}
/**
* get the status of a report
* @param request
* @param response
*/
public void groupImportReportStatus(HttpServletRequest request, HttpServletResponse response) {
String sessionId = request.getSession().getId();
String uniqueImportId = request.getParameter("uniqueImportId");
groupImportReportStatusHelper(sessionId, uniqueImportId);
}
/**
* get the status of a report
* @param request
* @param response
*/
private void groupImportReportStatusHelper(String sessionId, String uniqueImportId) {
Map debugMap = new LinkedHashMap();
debugMap.put("method", "groupImportReportStatus");
debugMap.put("sessionId", GrouperUtil.abbreviate(sessionId, 8));
debugMap.put("uniqueImportId", GrouperUtil.abbreviate(uniqueImportId, 8));
long startNanos = System.nanoTime();
try {
GuiResponseJs guiResponseJs = GuiResponseJs.retrieveGuiResponseJs();
MultiKey reportMultiKey = new MultiKey(sessionId, uniqueImportId);
GroupImportContainer groupImportContainer = importThreadProgress.get(reportMultiKey);
GrouperRequestContainer.retrieveFromRequestOrCreate().setGroupImportContainer(groupImportContainer);
//show the report screen
guiResponseJs.addAction(GuiScreenAction.newInnerHtmlFromJsp("#id_"+uniqueImportId,
"/WEB-INF/grouperUi2/groupImport/groupImportReport.jsp"));
// guiResponseJs.addAction(GuiScreenAction.newScript("guiScrollTop()"));
debugMap.put("percentComplete", groupImportContainer.getProgressBean().getPercentComplete());
debugMap.put("progressCompleteRecords", groupImportContainer.getProgressBean().getProgressCompleteRecords());
debugMap.put("progressTotalRecords", groupImportContainer.getProgressBean().getProgressTotalRecords());
if (groupImportContainer != null) {
// endless loop?
if (groupImportContainer.getProgressBean().isThisLastStatus()) {
return;
}
if (groupImportContainer.getProgressBean().isHasException()) {
guiResponseJs.addAction(GuiScreenAction.newMessage(GuiMessageType.error,
TextContainer.retrieveFromRequest().getText().get("groupImportException")));
// it has an exception, leave it be
importThreadProgress.put(reportMultiKey, null);
return;
}
// kick it off again?
debugMap.put("complete", groupImportContainer.getProgressBean().isComplete());
if (!groupImportContainer.getProgressBean().isComplete()) {
int progressRefreshSeconds = GrouperUiConfig.retrieveConfig().propertyValueInt("grouperUi.import.progressRefreshSeconds");
progressRefreshSeconds = Math.max(progressRefreshSeconds, 1);
progressRefreshSeconds *= 1000;
guiResponseJs.addAction(GuiScreenAction.newScript("setTimeout(function() {ajax('../app/UiV2GroupImport.groupImportReportStatus?uniqueImportId=" + uniqueImportId + "')}, " + progressRefreshSeconds + ")"));
} else {
// it is complete, leave it be
importThreadProgress.put(reportMultiKey, null);
if (groupImportContainer.isEndDateTooSoon()) {
int queryInterval = GrouperLoaderConfig.retrieveConfig().propertyValueInt("otherJob.enabledDisabled.queryIntervalInSeconds", 3600);
String warningMessage = TextContainer.retrieveFromRequest().getText().get("groupAddMemberMadeChangesEndDateBeforeChangeLogCanPickupWarn");
warningMessage = StringUtils.replace(warningMessage, "##minsInFuture##", String.valueOf(queryInterval/60));
guiResponseJs.addAction(GuiScreenAction.newMessageAppend(GuiMessageType.info, warningMessage));
}
}
}
} catch (RuntimeException re) {
debugMap.put("exception", GrouperUtil.getFullStackTrace(re));
throw re;
} finally {
if (LOG.isDebugEnabled()) {
debugMap.put("tookMillis", (System.nanoTime()-startNanos)/1000000);
LOG.debug(GrouperUtil.mapToString(debugMap));
}
}
}
/**
* method to do logic for import submit (note, dont use anything related to session here)
* @param loggedInSubject
* @param groupImportContainer
* @param groups
* @param subjectSet
* @param listInvalidSubjectIdsAndRow
* @param removeMembers
* @param importReplaceMembers
* @param bulkAddOption
* @param fileName
* @param startDate
* @param endDate
*/
private void groupImportSubmitHelper(final Subject loggedInSubject, final GroupImportContainer groupImportContainer,
final Set groups, final Set subjectSet, Map listInvalidSubjectIdsAndRow,
boolean removeMembers, boolean importReplaceMembers, String bulkAddOption, String fileName, List csvEntries,
Timestamp startDate, Timestamp endDate) {
Map debugMap = new LinkedHashMap();
debugMap.put("method", "groupImportSubmit");
GrouperSession grouperSession = null;
int pauseBetweenRecordsMillis = GrouperUiConfig.retrieveConfig().propertyValueIntRequired("grouperUi.import.pauseInBetweenRecordsMillis");
try {
grouperSession = GrouperSession.start(loggedInSubject);
ProgressBean progressBean = groupImportContainer.getProgressBean();
if (GrouperUtil.length(subjectSet) == 0 && csvEntries != null) {
subjectSet.addAll(SimpleMembershipUpdateImportExport.parseCsvImportFile(csvEntries, new ArrayList(),
listInvalidSubjectIdsAndRow, true));
}
Iterator groupIterator = groups.iterator();
Set guiGroups = new LinkedHashSet();
groupImportContainer.setGuiGroups(guiGroups);
progressBean.setProgressTotalRecords(GrouperUtil.length(groups) * GrouperUtil.length(subjectSet));
if (endDate != null) {
int queryInterval = GrouperLoaderConfig.retrieveConfig().propertyValueInt("otherJob.enabledDisabled.queryIntervalInSeconds", 3600);
Timestamp minAllowedInFuture = new Timestamp(System.currentTimeMillis() + queryInterval * 1000);
if (endDate.before(minAllowedInFuture)) {
groupImportContainer.setEndDateTooSoon(true);
}
}
//lets go through the groups that were submitted
while (groupIterator.hasNext()) {
final Group group = groupIterator.next();
guiGroups.add(new GuiGroup(group));
GroupImportGroupSummary groupImportGroupSummary = new GroupImportGroupSummary();
groupImportContainer.getGroupImportGroupSummaryForGroupMap().put(group, groupImportGroupSummary);
List existingMembers = new ArrayList(GrouperUtil.nonNull(group.getImmediateMembers()));
List subjectList = new ArrayList(GrouperUtil.nonNull(subjectSet));
groupImportGroupSummary.setGroupCountOriginal(GrouperUtil.length(existingMembers));
if (removeMembers) {
// if we're removing members, also include disabled memberships in the existingMembers list since we'll want to delete those as well
Set