if (null == wsResult || null == webstate) {
return;
}
LOGGER.log(Level.CONFIG, "Processing the received ACL changes. WsLog [ "
+ wsResult.getLogMessage() + " ]");
GssAclChangeCollection allChanges = wsResult.getAllChanges();
GssAclChange[] changes = (null == allChanges) ? null
: allChanges.getChanges();
if (null == changes) {
return;
}
LOGGER.log(Level.CONFIG, "Total changes to be oprocessed # "
+ changes.length + " . WsLog [ " + allChanges.getLogMessage() + " ]");
// If permissions of the Web has changed due to role assignment changes
// at its first unique ancestor
boolean isWebChanged = false;
// If the Web has been reset to initiate a re-crawl due to a high level
// permission change like security policy change
boolean isWebReset = false;
// To keep track of all the lists which have been processed. This is to
// avoid re-processing of the same list due to multiple changes
Set<ListState> processedLists = Sets.newHashSet();
// All groups where there are some membership changes
// TODO: why not this is integer?
Set<String> changedGroups = new TreeSet<String>();
Set<Integer> deletedGroups = new TreeSet<Integer>();
Set<Integer> deletedUsers = new TreeSet<Integer>();
for (GssAclChange change : changes) {
if (null == change) {
continue;
}
ObjectType objType = change.getChangedObject();
SPChangeType changeType = change.getChangeType();
String changeObjectHint = change.getHint();
if (!change.isIsEffectiveInCurrentWeb()) {
LOGGER.log(Level.CONFIG, "Change changeType [ "
+ changeType
+ " ], objectType [ "
+ objType
+ " ] is not applicable to the current web. skipping tio the next change...");
continue;
}
LOGGER.log(Level.CONFIG, "Change detected changeType [ " + changeType
+ " ], objectType [ " + objType + " ]. ");
if (objType == ObjectType.SECURITY_POLICY) {
LOGGER.log(Level.INFO, "Policy Change under web [ "
+ webstate.getWebUrl() + " ]");
// With inherited ACL support no need to re-crawl entire Web.
// Web Application policy is represented by a separate document
// which will be processed by
// SharePointClient.java --> processSiteData.
if (supportsInheritedAcls) {
webstate.setWebApplicationPolicyChange(true);
} else {
LOGGER.log(Level.INFO, "Resetting all list states under web [ "
+ webstate.getWebUrl()
+ " ] because web application policy change detected.");
webstate.resetState();
isWebReset = true;
}
} else if (objType == ObjectType.WEB) {
if (changeType == SPChangeType.AssignmentDelete) {
// Typically, deletion of a role affects the ACL of only
// those entities down the hierarchy which are inheriting
// the permission. But, limited access is a special case
// where the ACL of all entities gets affected. Since, we do
// not know what permission has been deleted, we have to
// consider the worst case scenario and assume that the
// deleted role was of limited access.
LOGGER.log(Level.INFO, "Resetting all list states under web [ "
+ webstate.getWebUrl()
+ " ] because some role has been deleted and the deleted role could be Limited Access.");
webstate.resetState();
webstate.setWebApplicationPolicyChange(true);
isWebReset = true;
} else if (!isWebChanged){
// With inherited ACL support no need to re-crawl
// all inheriting Lists.
// Web Permissions are associated with Web home Page.
// just marking web home page for re-crawl.
// TODO : Need to change setWebApplicationPolicyChange
// to something like setRevisitWebHome.
webstate.setWebApplicationPolicyChange(true);
if (supportsInheritedAcls) {
LOGGER.log(Level.INFO, "Change in Web Permissions - Reseting Site home Page");
webstate.setWebApplicationPolicyChange(true);
for (ListState list : webstate.getAllListStateSet()) {
if (list.isApplyReadSecurity() && list.isInheritedSecurity()) {
LOGGER.log(Level.INFO, "Change in Web Permissions -"
+ " Resetting list state URL [ "
+ list.getListURL()
+ " ] because effective permisssions modified"
+ " for List with Read Security");
list.resetState();
}
}
} else {
isWebChanged = true;
// Since, role assignment at web have changed, we need to
// re-crawl all the list/items which are inheriting the
// changed role assignments.
for (ListState listState : webstate.getAllListStateSet()) {
if (!listState.isInheritedSecurity()) {
LOGGER.log(Level.INFO, "Skipping List [ "
+ listState
+ " ] as it does not inherit its permission");
continue;
}
if (listState.isNoCrawl()) {
LOGGER.log(Level.INFO, "Skipping List [ "
+ listState
+ " ] as it is marked for no crawl");
continue;
}
if (!processedLists.contains(listState)) {
LOGGER.log(Level.INFO, "Marking List [ "
+ listState
+ " ] as a candidate for ACL based crawl because the effective ACL at this list have been updated. All the items with inheriting permissions wil be crawled from this list.");
listState.startAclCrawl();
processedLists.add(listState);
}
}
}
}
} else if (objType == ObjectType.LIST && null != changeObjectHint) {
ListState listState = webstate.getListStateForGuid(changeObjectHint);
if (null == listState) {
LOGGER.log(Level.WARNING, "Changed List ID [ "
+ changeObjectHint
+ " ] is not found in the WebState. Skipping to the next change.");
continue;
}
if (changeType == SPChangeType.AssignmentDelete) {
// Assuming the worst case scenario of Limited Access
// deletion
LOGGER.log(Level.INFO, "Resetting list state URL [ "
+ listState
+ " ] because some role has been deleted and the deleted role"
+ " could be Limited Access.");
listState.resetState();
} else {
if (supportsInheritedAcls) {
// Revisit List home for ACL changes.
listState.markListToRevisitListHome(sharepointClientContext.getFeedType());
if (listState.isApplyReadSecurity()) {
LOGGER.log(Level.INFO, "Resetting list state URL [ "
+ listState.getListURL()
+ " ] because effective permisssions modified"
+ " for List with Read Security");
listState.resetState();
}
} else {
if (!processedLists.contains(listState)) {
LOGGER.log(Level.INFO, "Marking List [ "
+ listState
+ " ] as a candidate for ACL based crawl because the effective"
+ " ACL at this list have been updated. All the items with"
+ " inheriting permissions wil be crawled from this list.");
listState.startAclCrawl();
processedLists.add(listState);
}
}
}
} else if (objType == ObjectType.USER
// For user-related changes, we only consider deletion changes.
// Rest all are covered as part of web/list/item/group
// specific changes. Refer to the WS impl. for more details
&& changeType == SPChangeType.Delete) {
try {
deletedUsers.add(new Integer(changeObjectHint));
} catch (Exception e) {
LOGGER.log(Level.WARNING, "UserId [ " + changeObjectHint
+ " ] is invalid. skipping... ", e);
continue;
}
// TODO: Even if the user is not known to the user data store,
// we would proceed here. This is because, the user data store,
// currently, stores only those users who are member of some
// groups. A re-crawl due to user deletion can be avoided
// by storing all the SharePoint users (sent into ACLs in past)
// in the local data store.
LOGGER.log(Level.INFO, "Resetting all list states under web [ "
+ webstate.getWebUrl()
+ " ] because a user has been deleted from the SharePoint.");
webstate.resetState();
isWebReset = true;
// TODO: A re-crawl due to User deletion can be avoided
// by storing more ACL information in the local data
// store.
}
// Administrators are treated as another SPGroup
else if (objType == ObjectType.GROUP
|| objType == ObjectType.ADMINISTRATORS) {
if (changeType == SPChangeType.Delete) {
try {
deletedGroups.add(Integer.parseInt(changeObjectHint));
} catch (Exception e) {
LOGGER.log(Level.WARNING, "GroupId [ " + changeObjectHint
+ " ] is invalid. skipping... ", e);
continue;
}
// TODO: A re-crawl due to Group deletion can be avoided
// by storing more ACL information in the local data
// store.
webstate.resetState();
isWebReset = true;
} else {
changedGroups.add(changeObjectHint);
// Mark Web Application Policy Change to track Site Admin
// Change also.
if (objType == ObjectType.ADMINISTRATORS) {
webstate.setWebApplicationPolicyChange(true);
}
}
}
if (isWebReset) {
webstate.setWebApplicationPolicyChange(true);
break;
}
}
// Sync the membership of all changed groups
syncGroupMembership(deletedUsers, deletedGroups, changedGroups, wsResult.getSiteCollectionUrl());
if (null == webstate.getNextAclChangeToken()
|| webstate.getNextAclChangeToken().trim().length() == 0) {
webstate.setNextAclChangeToken(allChanges.getChangeToken());
}
}