/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.repository.handlers;
import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import org.olat.core.CoreSpringFactory;
import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.stack.TooledStackedPanel;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.layout.MainLayoutController;
import org.olat.core.gui.control.generic.wizard.Step;
import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.gui.media.CleanupAfterDeliveryFileMediaResource;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.gui.translator.Translator;
import org.olat.core.helpers.Settings;
import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.Roles;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.FileUtils;
import org.olat.core.util.Formatter;
import org.olat.core.util.PathUtils;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.core.util.WebappHelper;
import org.olat.core.util.ZipUtil;
import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.coordinate.LockResult;
import org.olat.core.util.mail.MailHelper;
import org.olat.core.util.mail.MailerResult;
import org.olat.core.util.nodes.INode;
import org.olat.core.util.resource.OLATResourceableJustBeforeDeletedEvent;
import org.olat.core.util.vfs.LocalFileImpl;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.core.util.vfs.VFSItem;
import org.olat.course.CorruptedCourseException;
import org.olat.course.CourseFactory;
import org.olat.course.CourseModule;
import org.olat.course.ICourse;
import org.olat.course.PersistingCourseImpl;
import org.olat.course.Structure;
import org.olat.course.assessment.AssessmentMode;
import org.olat.course.config.CourseConfig;
import org.olat.course.export.CourseEnvironmentMapper;
import org.olat.course.groupsandrights.CourseGroupManager;
import org.olat.course.groupsandrights.PersistingCourseGroupManager;
import org.olat.course.run.CourseRuntimeController;
import org.olat.course.run.RunMainController;
import org.olat.course.tree.CourseEditorTreeNode;
import org.olat.fileresource.types.GlossaryResource;
import org.olat.fileresource.types.ResourceEvaluation;
import org.olat.fileresource.types.SharedFolderFileResource;
import org.olat.modules.glossary.GlossaryManager;
import org.olat.modules.reminder.Reminder;
import org.olat.modules.reminder.ReminderModule;
import org.olat.modules.reminder.ReminderRule;
import org.olat.modules.reminder.ReminderService;
import org.olat.modules.reminder.RuleSPI;
import org.olat.modules.reminder.model.ReminderRules;
import org.olat.modules.sharedfolder.SharedFolderManager;
import org.olat.repository.ErrorList;
import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryImportExport;
import org.olat.repository.RepositoryEntryImportExport.RepositoryEntryImport;
import org.olat.repository.RepositoryManager;
import org.olat.repository.RepositoryService;
import org.olat.repository.model.RepositoryEntrySecurity;
import org.olat.repository.ui.RepositoryEntryRuntimeController.RuntimeControllerCreator;
import org.olat.resource.OLATResource;
import org.olat.resource.OLATResourceManager;
import org.olat.resource.references.ReferenceManager;
import org.olat.user.UserManager;
import de.tuchemnitz.wizard.workflows.coursecreation.CourseCreationHelper;
import de.tuchemnitz.wizard.workflows.coursecreation.CourseCreationMailHelper;
import de.tuchemnitz.wizard.workflows.coursecreation.model.CourseCreationConfiguration;
import de.tuchemnitz.wizard.workflows.coursecreation.steps.CcStep00;
/**
* Initial Date: Apr 15, 2004
*
* @author
*
* Comment: Mike Stock
*
*/
public class CourseHandler implements RepositoryHandler {
public static final String EDITOR_XML = "editortreemodel.xml";
private static final OLog log = Tracing.createLoggerFor(CourseHandler.class);
@Override
public boolean isCreate() {
return true;
}
@Override
public RepositoryEntry createResource(Identity initialAuthor, String displayname, String description, Object createObject, Locale locale) {
RepositoryService repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
OLATResource resource = OLATResourceManager.getInstance().createOLATResourceInstance(CourseModule.class);
RepositoryEntry re = repositoryService.create(initialAuthor, null, "", displayname, description, resource, RepositoryEntry.ACC_OWNERS);
DBFactory.getInstance().commit();
String shortDisplayname = Formatter.truncateOnly(displayname, 25);
ICourse course = CourseFactory.createCourse(re, shortDisplayname, displayname, "");
log.audit("Course created: " + course.getCourseTitle());
return re;
}
@Override
public boolean isPostCreateWizardAvailable() {
return true;
}
@Override
public String getCreateLabelI18nKey() {
return "new.course";
}
@Override
public ResourceEvaluation acceptImport(File file, String filename) {
ResourceEvaluation eval = new ResourceEvaluation();
try {
IndexFileFilter visitor = new IndexFileFilter();
Path fPath = PathUtils.visit(file, filename, visitor);
if(visitor.isValid()) {
Path repoXml = fPath.resolve("export/repo.xml");
if(repoXml != null) {
eval.setValid(true);
RepositoryEntryImport re = RepositoryEntryImportExport.getConfiguration(repoXml);
if(re != null) {
eval.setDisplayname(re.getDisplayname());
eval.setDescription(re.getDescription());
}
eval.setReferences(hasReferences(fPath));
}
}
eval.setValid(visitor.isValid());
} catch (IOException | IllegalArgumentException e) {
log.error("", e);
}
return eval;
}
/**
* Find references in the export folder with the repo.xml.
* @param fPath
* @return
*/
private boolean hasReferences(Path fPath) {
boolean hasReferences = false;
Path export = fPath.resolve("export");
if(Files.isDirectory(export)) {
try(DirectoryStream<Path> directory = Files.newDirectoryStream(export)) {
for (Path p : directory) {
Path repoXml = p.resolve("repo.xml");
if(Files.exists(repoXml)) {
hasReferences = true;
break;
}
}
} catch (IOException e) {
log.error("", e);
}
}
return hasReferences;
}
@Override
public RepositoryEntry importResource(Identity initialAuthor, String initialAuthorAlt, String displayname,
String description, boolean withReferences, Locale locale, File file, String filename) {
OLATResource newCourseResource = OLATResourceManager.getInstance().createOLATResourceInstance(CourseModule.class);
ICourse course = CourseFactory.importCourseFromZip(newCourseResource, file);
// cfc.release();
if (course == null) {
return null;
}
RepositoryService repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
RepositoryEntry re = repositoryService
.create(initialAuthor, null, "", displayname, description, newCourseResource, RepositoryEntry.ACC_OWNERS);
DBFactory.getInstance().commit();
// create empty run structure
course = CourseFactory.openCourseEditSession(course.getResourceableId());
Structure runStructure = course.getRunStructure();
runStructure.getRootNode().removeAllChildren();
CourseFactory.saveCourse(course.getResourceableId());
//import references
CourseEditorTreeNode rootNode = (CourseEditorTreeNode)course.getEditorTreeModel().getRootNode();
importReferences(rootNode, course, initialAuthor, locale, withReferences);
if(withReferences && course.getCourseConfig().hasCustomSharedFolder()) {
importSharedFolder(course, initialAuthor);
}
if(withReferences && course.getCourseConfig().hasGlossary()) {
importGlossary(course, initialAuthor);
}
// create group management / import groups
CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
File fImportBaseDirectory = course.getCourseExportDataDir().getBasefile();
CourseEnvironmentMapper envMapper = cgm.importCourseBusinessGroups(fImportBaseDirectory);
envMapper.setAuthor(initialAuthor);
//upgrade course
course = CourseFactory.loadCourse(cgm.getCourseResource());
course.postImport(fImportBaseDirectory, envMapper);
//rename root nodes
course.getRunStructure().getRootNode().setShortTitle(Formatter.truncateOnly(displayname, 25)); //do not use truncate!
course.getRunStructure().getRootNode().setLongTitle(displayname);
//course.saveRunStructure();
CourseEditorTreeNode editorRootNode = ((CourseEditorTreeNode)course.getEditorTreeModel().getRootNode());
editorRootNode.getCourseNode().setShortTitle(Formatter.truncateOnly(displayname, 25)); //do not use truncate!
editorRootNode.getCourseNode().setLongTitle(displayname);
// mark entire structure as dirty/new so the user can re-publish
markDirtyNewRecursively(editorRootNode);
// root has already been created during export. Unmark it.
editorRootNode.setNewnode(false);
//save and close edit session
CourseFactory.saveCourse(course.getResourceableId());
CourseFactory.closeCourseEditSession(course.getResourceableId(), true);
RepositoryEntryImportExport imp = new RepositoryEntryImportExport(fImportBaseDirectory);
if(imp.anyExportedPropertiesAvailable()) {
re = imp.importContent(re, getMediaContainer(re));
}
//import reminders
importReminders(re, fImportBaseDirectory, envMapper, initialAuthor);
//clean up export folder
cleanExportAfterImport(fImportBaseDirectory);
return re;
}
private void cleanExportAfterImport(File fImportBaseDirectory) {
try {
Path exportDir = fImportBaseDirectory.toPath();
FileUtils.deleteDirsAndFiles(exportDir);
} catch (Exception e) {
log.error("", e);
}
}
private void importSharedFolder(ICourse course, Identity owner) {
SharedFolderManager sfm = SharedFolderManager.getInstance();
RepositoryEntryImportExport importExport = sfm.getRepositoryImportExport(course.getCourseExportDataDir().getBasefile());
SharedFolderFileResource resource = sfm.createSharedFolder();
if (resource == null) {
log.error("Error adding file resource during repository reference import: " + importExport.getDisplayName());
}
// unzip contents
VFSContainer sfContainer = sfm.getSharedFolder(resource);
File fExportedFile = importExport.importGetExportedFile();
if (fExportedFile.exists()) {
ZipUtil.unzip(new LocalFileImpl(fExportedFile), sfContainer);
} else {
log.warn("The actual contents of the shared folder were not found in the export.");
}
// create repository entry
RepositoryService repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
OLATResource ores = OLATResourceManager.getInstance().findOrPersistResourceable(resource);
RepositoryEntry importedRepositoryEntry = repositoryService.create(owner, null,
importExport.getResourceName(), importExport.getDisplayName(), importExport.getDescription(), ores, 0);
// set the new shared folder reference
CourseConfig courseConfig = course.getCourseEnvironment().getCourseConfig();
courseConfig.setSharedFolderSoftkey(importedRepositoryEntry.getSoftkey());
CoreSpringFactory.getImpl(ReferenceManager.class)
.addReference(importedRepositoryEntry.getOlatResource(), course, SharedFolderManager.SHAREDFOLDERREF);
CourseFactory.setCourseConfig(course.getResourceableId(), courseConfig);
}
private void importGlossary(ICourse course, Identity owner) {
GlossaryManager gm = GlossaryManager.getInstance();
RepositoryEntryImportExport importExport = gm.getRepositoryImportExport(course.getCourseExportDataDir().getBasefile());
GlossaryResource resource = gm.createGlossary();
if (resource == null) {
log.error("Error adding glossary directry during repository reference import: " + importExport.getDisplayName());
return;
}
// unzip contents
VFSContainer glossaryContainer = gm.getGlossaryRootFolder(resource);
File fExportedFile = importExport.importGetExportedFile();
if (fExportedFile.exists()) {
ZipUtil.unzip(new LocalFileImpl(fExportedFile), glossaryContainer);
} else {
log.warn("The actual contents of the glossary were not found in the export.");
}
// create repository entry
RepositoryService repositoryService = CoreSpringFactory.getImpl(RepositoryService.class);
OLATResource ores = OLATResourceManager.getInstance().findOrPersistResourceable(resource);
RepositoryEntry importedRepositoryEntry = repositoryService.create(owner,
null, importExport.getResourceName(), importExport.getDisplayName(), importExport.getDescription(), ores, 0);
// set the new glossary reference
CourseConfig courseConfig = course.getCourseEnvironment().getCourseConfig();
courseConfig.setGlossarySoftKey(importedRepositoryEntry.getSoftkey());
CoreSpringFactory.getImpl(ReferenceManager.class).addReference(course, importedRepositoryEntry.getOlatResource(), GlossaryManager.GLOSSARY_REPO_REF_IDENTIFYER);
CourseFactory.setCourseConfig(course.getResourceableId(), courseConfig);
}
private void importReferences(CourseEditorTreeNode node, ICourse course, Identity owner, Locale locale, boolean withReferences) {
node.getCourseNode().importNode(course.getCourseExportDataDir().getBasefile(), course, owner, locale, withReferences);
for (int i = 0; i<node.getChildCount(); i++) {
INode child = node.getChildAt(i);
if(child instanceof CourseEditorTreeNode) {
importReferences((CourseEditorTreeNode)child, course, owner, locale, withReferences);
}
}
}
private void importReminders(RepositoryEntry re, File fImportBaseDirectory, CourseEnvironmentMapper envMapper, Identity initialAuthor) {
ReminderModule reminderModule = CoreSpringFactory.getImpl(ReminderModule.class);
ReminderService reminderService = CoreSpringFactory.getImpl(ReminderService.class);
List<Reminder> reminders = reminderService.importRawReminders(initialAuthor, re, fImportBaseDirectory);
if(reminders.size() > 0) {
for(Reminder reminder:reminders) {
ReminderRules clonedRules = new ReminderRules();
String configuration = reminder.getConfiguration();
ReminderRules rules = reminderService.toRules(configuration);
for(ReminderRule rule:rules.getRules()) {
RuleSPI ruleSpi = reminderModule.getRuleSPIByType(rule.getType());
if(ruleSpi != null) {
ReminderRule clonedRule = ruleSpi.clone(rule, envMapper);
clonedRules.getRules().add(clonedRule);
}
}
String convertedConfiguration = reminderService.toXML(clonedRules);
reminder.setConfiguration(convertedConfiguration);
reminderService.save(reminder);
}
}
}
private void markDirtyNewRecursively(CourseEditorTreeNode editorRootNode) {
editorRootNode.setDirty(true);
editorRootNode.setNewnode(true);
if (editorRootNode.getChildCount() > 0) {
for (int i = 0; i < editorRootNode.getChildCount(); i++) {
markDirtyNewRecursively((CourseEditorTreeNode)editorRootNode.getChildAt(i));
}
}
}
@Override
public RepositoryEntry copy(Identity author, RepositoryEntry source, RepositoryEntry target) {
final OLATResource sourceResource = source.getOlatResource();
final OLATResource targetResource = target.getOlatResource();
CourseFactory.copyCourse(sourceResource, targetResource);
//transaction copied
ICourse sourceCourse = CourseFactory.loadCourse(source);
CourseGroupManager sourceCgm = sourceCourse.getCourseEnvironment().getCourseGroupManager();
CourseEnvironmentMapper env = PersistingCourseGroupManager.getInstance(sourceResource).getBusinessGroupEnvironment();
File fExportDir = new File(WebappHelper.getTmpDir(), UUID.randomUUID().toString());
fExportDir.mkdirs();
sourceCgm.exportCourseBusinessGroups(fExportDir, env, false, false);
ICourse course = CourseFactory.loadCourse(target);
CourseGroupManager cgm = course.getCourseEnvironment().getCourseGroupManager();
// import groups
CourseEnvironmentMapper envMapper = cgm.importCourseBusinessGroups(fExportDir);
envMapper.setAuthor(author);
//upgrade to the current version of the course
course = CourseFactory.loadCourse(cgm.getCourseResource());
course.postCopy(envMapper, sourceCourse);
cloneReminders(author, envMapper, source, target);
return target;
}
private void cloneReminders(Identity author, CourseEnvironmentMapper envMapper, RepositoryEntry source, RepositoryEntry target) {
ReminderModule reminderModule = CoreSpringFactory.getImpl(ReminderModule.class);
ReminderService reminderService = CoreSpringFactory.getImpl(ReminderService.class);
List<Reminder> reminders = reminderService.getReminders(source);
for(Reminder reminder:reminders) {
String configuration = reminder.getConfiguration();
ReminderRules rules = reminderService.toRules(configuration);
ReminderRules clonedRules = new ReminderRules();
for(ReminderRule rule:rules.getRules()) {
RuleSPI ruleSpi = reminderModule.getRuleSPIByType(rule.getType());
if(ruleSpi != null) {
ReminderRule clonedRule = ruleSpi.clone(rule, envMapper);
if (clonedRule != null)
clonedRules.getRules().add(clonedRule);
}
}
Reminder clonedReminder = reminderService.createReminder(target, author);
clonedReminder.setDescription(reminder.getDescription());
clonedReminder.setEmailBody(reminder.getEmailBody());
clonedReminder.setConfiguration(reminderService.toXML(clonedRules));
reminderService.save(clonedReminder);
}
}
@Override
public String getSupportedType() {
return CourseModule.getCourseTypeName();
}
@Override
public boolean supportsDownload() {
return true;
}
@Override
public EditionSupport supportsEdit(OLATResourceable resource) {
return EditionSupport.yes;
}
@Override
public boolean supportsAssessmentDetails() {
return false;
}
@Override
public MainLayoutController createLaunchController(RepositoryEntry re, RepositoryEntrySecurity reSecurity, UserRequest ureq, WindowControl wControl) {
return new CourseRuntimeController(ureq, wControl, re, reSecurity,
new RuntimeControllerCreator() {
@Override
public Controller create(UserRequest uureq, WindowControl wwControl, TooledStackedPanel toolbarPanel,
RepositoryEntry entry, RepositoryEntrySecurity security, AssessmentMode assessmentMode) {
ICourse course = CourseFactory.loadCourse(entry);
return new RunMainController(uureq, wwControl, toolbarPanel, course, entry, security, assessmentMode);
}
}, true, true);
}
@Override
public Controller createAssessmentDetailsController(RepositoryEntry re, UserRequest ureq, WindowControl wControl, TooledStackedPanel toolbar, Identity assessedIdentity) {
return null;
}
@Override
public MediaResource getAsMediaResource(OLATResourceable res, boolean backwardsCompatible) {
RepositoryEntry re = RepositoryManager.getInstance().lookupRepositoryEntry(res, true);
String exportFileName = StringHelper.transformDisplayNameToFileSystemName(re.getDisplayname()) + ".zip";
File fExportZIP = new File(WebappHelper.getTmpDir(), exportFileName);
CourseFactory.exportCourseToZIP(res, fExportZIP, false, backwardsCompatible);
return new CleanupAfterDeliveryFileMediaResource(fExportZIP);
}
@Override
public VFSContainer getMediaContainer(RepositoryEntry repoEntry) {
OLATResource resource = repoEntry.getOlatResource();
String relPath = File.separator + PersistingCourseImpl.COURSE_ROOT_DIR_NAME + File.separator + resource.getResourceableId();
VFSContainer rootFolder = new OlatRootFolderImpl(relPath, null);
VFSItem item = rootFolder.resolve("media");
VFSContainer mediaContainer;
if(item == null) {
mediaContainer = rootFolder.createChildContainer("media");
} else if(item instanceof VFSContainer) {
mediaContainer = (VFSContainer)item;
} else {
log.error("media folder is not a container", null);
mediaContainer = null;
}
return mediaContainer;
}
@Override
public Controller createEditorController(RepositoryEntry re, UserRequest ureq, WindowControl wControl, TooledStackedPanel toolbar) {
return CourseFactory.createEditorController(ureq, wControl, toolbar, re, null);
}
@Override
public StepsMainRunController createWizardController(OLATResourceable res, UserRequest ureq, WindowControl wControl) {
// load the course structure
final RepositoryEntry repoEntry = (RepositoryEntry) res;
ICourse course = CourseFactory.loadCourse(repoEntry);
Translator cceTranslator = Util.createPackageTranslator(CourseCreationHelper.class, ureq.getLocale());
final CourseCreationConfiguration courseConfig = new CourseCreationConfiguration(course.getCourseTitle(), Settings.getServerContextPathURI() + "/url/RepositoryEntry/" + repoEntry.getKey());
// wizard finish callback called after "finish" is called
final CourseCreationHelper ccHelper = new CourseCreationHelper(ureq.getLocale(), repoEntry, courseConfig , course);
StepRunnerCallback finishCallback = new StepRunnerCallback() {
public Step execute(UserRequest uureq, WindowControl control, StepsRunContext runContext) {
// here goes the code which reads out the wizards data from the runContext and then does some wizardry
ccHelper.finalizeWorkflow(uureq);
control.setInfo(CourseCreationMailHelper.getSuccessMessageString(uureq));
// send notification mail
final MailerResult mr = CourseCreationMailHelper.sentNotificationMail(uureq, ccHelper.getConfiguration());
MailHelper.printErrorsAndWarnings(mr, control, uureq.getLocale());
return StepsMainRunController.DONE_MODIFIED;
}
};
Step start = new CcStep00(ureq, courseConfig, repoEntry);
StepsMainRunController ccSMRC = new StepsMainRunController(ureq, wControl, start, finishCallback, null, cceTranslator.translate("coursecreation.title"), "o_sel_course_create_wizard");
return ccSMRC;
}
@Override
public boolean cleanupOnDelete(RepositoryEntry entry, OLATResourceable res) {
// notify all current users of this resource (course) that it will be deleted now.
CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new OLATResourceableJustBeforeDeletedEvent(res), res);
//archiving is done within readyToDelete
OLATResourceManager rm = OLATResourceManager.getInstance();
OLATResource resource = rm.findResourceable(res);
CourseFactory.deleteCourse(entry, resource);
return true;
}
@Override
public boolean readyToDelete(RepositoryEntry entry, Identity identity, Roles roles, Locale locale, ErrorList errors) {
ReferenceManager refM = CoreSpringFactory.getImpl(ReferenceManager.class);
String referencesSummary = refM.getReferencesToSummary(entry.getOlatResource(), locale);
if (referencesSummary != null) {
Translator translator = Util.createPackageTranslator(RepositoryManager.class, locale);
errors.setError(translator.translate("details.delete.error.references",
new String[] { referencesSummary, entry.getDisplayname() }));
return false;
}
/*
* make an archive of the course nodes with valuable data
*/
UserManager um = UserManager.getInstance();
String charset = um.getUserCharset(identity);
try {
CourseFactory.archiveCourse(entry.getOlatResource(),charset, locale, identity, roles);
} catch (CorruptedCourseException e) {
log.error("The course is corrupted, cannot archive it: " + entry, e);
}
return true;
}
@Override
public LockResult acquireLock(OLATResourceable ores, Identity identity) {
return CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(ores, identity, CourseFactory.COURSE_EDITOR_LOCK);
}
@Override
public void releaseLock(LockResult lockResult) {
if(lockResult!=null) {
CoordinatorManager.getInstance().getCoordinator().getLocker().releaseLock(lockResult);
}
}
@Override
public boolean isLocked(OLATResourceable ores) {
return CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(ores, CourseFactory.COURSE_EDITOR_LOCK);
}
private static class IndexFileFilter extends SimpleFileVisitor<Path> {
private boolean editorFile;
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
String filename = file.getFileName().toString();
if(EDITOR_XML.equals(filename)) {
editorFile = true;
}
return editorFile ? FileVisitResult.TERMINATE : FileVisitResult.CONTINUE;
}
public boolean isValid() {
return editorFile;
}
}
}