package uk.ac.ox.oucs.vle.proxy; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.component.api.ServerConfigurationService; import org.sakaiproject.content.api.ContentCollectionEdit; import org.sakaiproject.content.api.ContentHostingService; import org.sakaiproject.content.api.ContentResourceEdit; import org.sakaiproject.entity.api.Entity; import org.sakaiproject.entity.api.ResourceProperties; import org.sakaiproject.event.api.UsageSessionService; import org.sakaiproject.exception.*; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.SessionManager; import org.sakaiproject.util.SakaiComponentEvent; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import java.io.InputStream; /** * This attempts to automatically setup content needed for the tool to function. * This is done on Spring events so that we can be sure all the services have done init() * and are ready for use. */ public class AutoSetup implements ApplicationListener { private static final Log log = LogFactory.getLog(AutoSetup.class); private ContentHostingService contentHostingService; private SessionManager sessionManager; private UsageSessionService usageSessionService; private ServerConfigurationService serverConfigurationService; public void setServerConfigurationService(ServerConfigurationService serverConfigurationService) { this.serverConfigurationService = serverConfigurationService; } public void setContentHostingService(ContentHostingService contentHostingService) { this.contentHostingService = contentHostingService; } public void setSessionManager(SessionManager sessionManager) { this.sessionManager = sessionManager; } public void setUsageSessionService(UsageSessionService usageSessionService) { this.usageSessionService = usageSessionService; } @Override public void onApplicationEvent(ApplicationEvent event) { if (serverConfigurationService.getBoolean("ses.autosetup", true) && event instanceof SakaiComponentEvent) { try { doAsAdmin(new ImportContent()); } catch (Exception e) { log.error("Failed to setup content", e); } } } /** * Actually so the importing. */ protected class ImportContent implements Runnable { @Override public void run() { String siteId = serverConfigurationService.getString("course-signup.site-id", "course-signup"); String collection = ContentHostingService.COLLECTION_SITE + siteId; // Create folder. createFolder(ContentHostingService.COLLECTION_SITE, siteId, true); // Copy in files copyFile(collection, "departments.json"); } /** * Copy a file from the classpath to content hosting. * Don't do anything if the file already exists. * * @param collection The location to import into. * @param filename The filename */ private void copyFile(String collection, String filename) { String classPath = "/autosetup/" + filename; InputStream source = getClass().getResourceAsStream(classPath); if (source == null) { throw new NullPointerException("Couldn't find " + source); } String contentPath = collection + Entity.SEPARATOR+ filename; try { ContentResourceEdit file = contentHostingService.addResource(contentPath); file.getProperties().addProperty(ResourceProperties.PROP_DISPLAY_NAME, filename); file.setContent(source); contentHostingService.commitResource(file); } catch (PermissionException e) { throw new RuntimeException(e); } catch (IdUsedException e) { log.debug("File already exists: " + contentPath); } catch (IdInvalidException e) { throw new RuntimeException(e); } catch (InconsistentException e) { throw new RuntimeException(e); } catch (ServerOverloadException e) { throw new RuntimeException(e); } catch (OverQuotaException e) { throw new RuntimeException(e); } } /** * Create a folder in content hosting. * If the folder already exists don't do anything. * * @param base The containing folder. * @param name The name of the new folder * @param isPublic If <code>true</code> then make it public */ private void createFolder(String base, String name, boolean isPublic) { String path = base + name; try { ContentCollectionEdit collection = contentHostingService.addCollection(base, name); collection.getProperties().addProperty(ResourceProperties.PROP_DISPLAY_NAME, name); if (isPublic) { collection.setPublicAccess(); } contentHostingService.commitCollection(collection); } catch (IdUsedException e) { log.debug("Folder already exists, this is expected: " + path); } catch (IdInvalidException e) { throw new RuntimeException(e); } catch (PermissionException e) { throw new RuntimeException(e); } catch (InconsistentException e) { throw new RuntimeException(e); } catch (IdUnusedException e) { throw new RuntimeException(e); } catch (TypeException e) { throw new RuntimeException(e); } catch (IdLengthException e) { throw new RuntimeException(e); } } } /** * Runs the supplied instance as admin. * But makes sure then no matter what happens we stop running as admin at the end. * * @param runnable The thing to run as admin. */ protected void doAsAdmin(Runnable runnable) { try { Session session = sessionManager.startSession(); session.setUserId("admin"); sessionManager.setCurrentSession(session); usageSessionService.startSession("admin", null, null); runnable.run(); } finally { Session session = sessionManager.getCurrentSession(); if (session != null) { session.invalidate(); } } } }