package org.sakaiproject.component.app.scheduler.jobs; import java.util.Calendar; import java.util.Date; import java.util.List; import lombok.Setter; import lombok.extern.apachecommons.CommonsLog; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.sakaiproject.authz.api.SecurityAdvisor; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.authz.api.SecurityAdvisor.SecurityAdvice; import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.site.api.SiteService.SelectionType; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.SessionManager; /** * <p> * This job finds all sites that have been softly deleted and checks their * deletion time. If it is older than site.soft.deletion.gracetime, they are * then really deleted. The value is in days and defaults to 30 if not set. * </p> * * <p> * This does not take into account whether or not site.soft.deletion is enabled * since there may be sites which have been softly deleted but then the param is * disabled, leaving them in limbo. * </p> * * @author Steve Swinsburg (steve.swinsburg@gmail.com) * */ @CommonsLog public class SoftSiteDeletionJob implements Job { private final int GRACETIME_DEFAULT = 30; private SecurityAdvisor securityAdvisor; public void init() { // Create our security advisor. securityAdvisor = new SecurityAdvisor() { public SecurityAdvice isAllowed(String userId, String function, String reference) { return SecurityAdvice.ALLOWED; } }; } public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { log.info("SoftSiteDeletionJob started."); Date graceDate = getGraceDate(); // get sites List<Site> sites = siteService.getSites(SelectionType.ANY_DELETED, null, null, null, null, null); log.info(sites.size() + " softly deleted site(s) will be processed"); // foreach site, check soft deletion time // Note: we could do this in the SQL so we only get a list of sites that // all need to be deleted. // but this would no doubt be db specific so would add extra complexity // to the SQL layer // for now, just do it in code. There won't be many sites to process at // once. for (Site s : sites) { log.debug("Looking at : " + s.getTitle() + " (" + s.getId() + ")"); if (!s.isSoftlyDeleted()) { log.warn("Site was in returned list but isn't deleted: " + s.getId()); continue; } // get calendar for the softly deleted date Date deletedDate = s.getSoftlyDeletedDate(); if (deletedDate == null) { log.warn("Site doesn't have a deleted date: " + s.getId()); continue; } // if this deleted date is before the gracetime, delete the site. if (deletedDate.before(graceDate)) { log.info("Site: " + s.getId() + " is due for deletion"); try { enableSecurityAdvisor(); siteService.removeSite(s); log.info("Removed site: " + s.getId()); } catch (PermissionException e) { log.error("Error removing site: " + s.getId() + ", " + e.getMessage()); } catch (IdUnusedException e) { log.error("Error removing site: " + s.getId() + ", " + e.getMessage()); } finally { disableSecurityAdvisor(); } } else { log.info("Site: " + s.getId() + " has not passed the gracetime yet and will be skipped."); } } log.info("SoftSiteDeletionJob completed."); } /** * Time in the past which sites deleted before can be deleted. * * @return */ private Date getGraceDate() { // get the gracetime config param in days. int gracetime = serverConfigurationService.getInt( "site.soft.deletion.gracetime", GRACETIME_DEFAULT); // get calendar for gracetime Calendar grace = Calendar.getInstance(); grace.add(Calendar.DATE, -gracetime); Date graceDate = grace.getTime(); log.debug("Grace set to: " + graceDate); return graceDate; } /** * Setup a security advisor for this transaction */ private void enableSecurityAdvisor() { securityService.pushAdvisor(securityAdvisor); } /** * Remove security advisor */ private void disableSecurityAdvisor() { securityService.popAdvisor(); } @Setter private ServerConfigurationService serverConfigurationService; @Setter private SiteService siteService; @Setter private SecurityService securityService; }