/**********************************************************************************
* $URL$
* $Id$
***********************************************************************************
*
* Copyright (c) 2009 The Sakai Foundation.
*
* Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
*
* 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 org.theospi.portfolio.worksite.mgt.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.authz.api.AuthzGroupService;
import org.sakaiproject.authz.api.GroupProvider;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.entity.api.EntityManager;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.event.api.Event;
import org.sakaiproject.event.cover.EventTrackingService;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.siteassociation.api.SiteAssocManager;
/**
* This class listens for several events and will create/remove groups in sites as needed, marking them as provided.
* @author chrismaurer
*
*/
public class SiteGroupProviderListener implements Observer {
protected final transient Log logger = LogFactory.getLog(getClass());
private EntityManager entityManager;
private GroupProvider groupProvider;
private SiteAssocManager siteAssocManager;
private SiteService siteService;
private AuthzGroupService authzGroupService;
private boolean enableListener = true;
private static final String MANAGED_GROUP_PROPERTY = "MANAGED_GROUP_PROPERTY";
public void init() {
logger.info("init()");
if (isEnableListener()) {
logger.info("Enabling listener");
EventTrackingService.addObserver(this);
}
}
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
* method.
*/
public void update(Observable o, Object arg) {
if (arg instanceof Event) {
String eventStr = ((Event)arg).getEvent();
if (eventStr.equals(SiteService.SECURE_UPDATE_SITE_MEMBERSHIP) || eventStr.equals(AuthzGroupService.SECURE_UPDATE_AUTHZ_GROUP)) {
processEvent((Event)arg, o);
}
}
}
protected void processEvent(Event event, Observable arg) {
String eventStr = event.getEvent();
Reference ref = getEntityManager().newReference(event.getResource());
try {
if (eventStr.equals(AuthzGroupService.SECURE_UPDATE_AUTHZ_GROUP)) {
// This was a realm update (likely coming from the roster sync job)
// so the ref is a realm ref rather than just a site ref
ref = getEntityManager().newReference(ref.getId());
}
// When adding in the listening for realm.upd, it picks up group updates now and we want to ignore them
if (!ref.getSubType().equals("group")) {
Site siteFromId = getSiteService().getSite(ref.getId());
// check out the update
processUpdate(siteFromId);
}
} catch (IdUnusedException e) {
logger.error("error getting site object", e);
}
}
protected void processUpdate(Site site) {
List<String> siteIds = getSiteAssocManager().getAssociatedFrom(site.getId());
//String[] siteIds = getProviderGroupIds(site);
for (String siteId : siteIds) {
try {
Site eachSite = getSiteService().getSite(siteId);
//only process site if it is set to sync
String[] unpackedIds = getGroupProvider().unpackId(eachSite.getProviderGroupId());
List<String> unpackedList = new ArrayList<String>(Arrays.asList(unpackedIds));
if(unpackedList.contains(site.getId())){
processUpdateSiteGroup(site.getId(), eachSite);
}
} catch (IdUnusedException e) {
logger.error("error getting site object", e);
}
}
}
/**
* @param rootSite
* @param changingSite
* @param add
*/
protected void processUpdateSiteGroup(String siteToSync, Site changingSite) {
//changingSite.loadAll();
Collection<Group> groups = changingSite.getGroups();
boolean needSave = false;
Group groupToSave = null;
for(Group group : groups) {
//Find the group that came from the original site
String property = group.getProperties().getProperty(MANAGED_GROUP_PROPERTY);
if(siteToSync.equals(property)) {
needSave = true;
group.setProviderGroupId(siteToSync);
groupToSave = group;
break;
}
}
if (needSave) {
try {
logger.debug("BEGIN Saving group: '" + groupToSave.getTitle() + "' in site '" + changingSite.getTitle() + "'");
getSiteService().save(changingSite);
logger.debug("END Saving group: '" + groupToSave.getTitle() + "' in site '" + changingSite.getTitle() + "'");
} catch (IdUnusedException e) {
logger.error(e);
} catch (PermissionException e) {
logger.error(e);
}
}
}
private String[] getProviderGroupIds(Site site){
return getGroupProvider().unpackId(site.getProviderGroupId());
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public EntityManager getEntityManager() {
return entityManager;
}
public GroupProvider getGroupProvider() {
if(groupProvider == null){
groupProvider = (org.sakaiproject.authz.api.GroupProvider) ComponentManager.get(GroupProvider.class);
}
return groupProvider;
}
public void setEnableListener(boolean enableListener) {
this.enableListener = enableListener;
}
public boolean isEnableListener() {
return enableListener;
}
public void setSiteAssocManager(SiteAssocManager siteAssocManager) {
this.siteAssocManager = siteAssocManager;
}
public SiteAssocManager getSiteAssocManager() {
return siteAssocManager;
}
public void setSiteService(SiteService siteService) {
this.siteService = siteService;
}
public SiteService getSiteService() {
return siteService;
}
public void setAuthzGroupService(AuthzGroupService authzGroupService) {
this.authzGroupService = authzGroupService;
}
public AuthzGroupService getAuthzGroupService() {
return authzGroupService;
}
}