CVE-2021-39181 (published 2021-09-01T20:15Z)

OpenOlat is a web-based learning management system (LMS). Prior to version 15.3.18, 15.5.3, and 16.0.0, using a prepared import XML file (e.g. a course) any class on the Java classpath can be instantiated, including spring AOP bean factories. This can be used to execute code arbitrary code by the attacker. The attack requires an OpenOlat user account with the authoring role. It can not be exploited by unregistered users. The problem is fixed in versions 15.3.18, 15.5.3, and 16.0.0. There are no known workarounds aside from upgrading.

Severity: MEDIUM
CVSS v2 base score: 6.5 (AV:N/AC:L/Au:S/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-91
cwe_name: XML Injection (aka Blind XPath Injection)
description: The product does not properly neutralize special elements that are used in XML, allowing attackers to modify the syntax, content, or commands of the XML before it is processed by an end system.
extended_description: Within XML, special elements could include reserved words or characters such as "<", ">", """, and "&", which could then be used to add new data or modify XML syntax.
         

Fix information:
repo_url: https://github.com/OpenOLAT/OpenOLAT
commit_details: repo_url: https://github.com/OpenOLAT/OpenOLAT
author: srosse
author_date: 2021-06-21 11:13:50+02:00
msg: OO-5548: setup security of XStream by default
repository: repo_url: https://github.com/OpenOLAT/OpenOLAT
repo_name: OpenOLAT/OpenOLAT
description: Learning Management System OpenOlat
repo_language: Java
owner: OpenOLAT
file_changes: filename: ChecklistCourseNode.java
change_type: ModificationType.MODIFY
diff: @@ -309,6 +309,7 @@ public class ChecklistCourseNode extends AbstractAccessableCourseNode {
 	@Override
 	public void exportNode(File exportDirectory, ICourse course) {
 		XStream xstream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xstream);
 		ChecklistManager cm = ChecklistManager.getInstance();
 		Checklist checklist = loadOrCreateChecklist(course.getCourseEnvironment().getCoursePropertyManager());
 		Checklist copy = cm.copyChecklistInRAM(checklist);
@@ -328,13 +329,14 @@ public class ChecklistCourseNode extends AbstractAccessableCourseNode {
 		}
 		
 		XStream xstream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xstream);
 		Checklist checklist = (Checklist) xstream.fromXML(importContent);
 		if(checklist != null) {
 			checklist = ChecklistManager.getInstance().copyChecklist(checklist);
 			setChecklistKey(cpm, checklist.getKey());
 		}
 	}
-	
+
 	@Override
 	public boolean archiveNodeData(Locale locale, ICourse course, ArchiveOptions options,
 			ZipOutputStream exportStream, String archivePath, String charset) {
@@ -344,7 +346,9 @@ public class ChecklistCourseNode extends AbstractAccessableCourseNode {
 		filename = ZipUtil.concat(archivePath, filename);
 		
 		Checklist checklist = loadOrCreateChecklist(course.getCourseEnvironment().getCoursePropertyManager());
-		String exportContent = XStreamHelper.createXStreamInstance().toXML(checklist);
+		XStream xstream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xstream);
+		String exportContent = xstream.toXML(checklist);
 		try {
 			exportStream.putNextEntry(new ZipEntry(filename));
 			IOUtils.write(exportContent, exportStream, "UTF-8");

programming_language: Java
filename: LinksPortlet.java
change_type: ModificationType.MODIFY
diff: @@ -79,6 +79,15 @@ public class LinksPortlet extends AbstractPortlet {
 	private static final String ELEM_LINK_TARGET = "Target";
 	private static final String ELEM_LINK_LANG = "Language";
 	
+	private static final XStream xstream = XStreamHelper.createXStreamInstance();
+	static {
+		XStreamHelper.allowDefaultPackage(xstream);
+		xstream.alias("LinksPortlet", Map.class);
+		xstream.alias(ELEM_LINK, PortletLink.class);
+		xstream.alias(ELEM_INSTITUTION, PortletInstitution.class);
+		xstream.aliasAttribute(PortletInstitution.class, ATTR_INSTITUTION_NAME, ATTR_INSTITUTION_NAME);
+	}
+	
 	private static HashMap<String, PortletInstitution> content;
 
 	private static File fxConfXStreamFile;
@@ -155,24 +164,13 @@ public class LinksPortlet extends AbstractPortlet {
 			saveLinkList(content);
 			FileUtils.copyFileToFile(fxConfFile, new File(fxConfFile + ".bak"), true);
 		} else {
-			XStream xstream = XStreamHelper.createXStreamInstance();
-			xstream.alias("LinksPortlet", Map.class);
-			xstream.alias(ELEM_LINK, PortletLink.class);
-			xstream.alias(ELEM_INSTITUTION, PortletInstitution.class);
-			xstream.aliasAttribute(PortletInstitution.class, ATTR_INSTITUTION_NAME, ATTR_INSTITUTION_NAME);
 			content = (HashMap<String, PortletInstitution>) XStreamHelper.readObject(xstream, fxConfXStreamFile);
 		}		
 	}
 	
-	public static boolean saveLinkList(HashMap<String, PortletInstitution> portletMap){
-		XStream xstream = XStreamHelper.createXStreamInstance();
-		xstream.alias("LinksPortlet", Map.class);
-		xstream.alias(ELEM_LINK, PortletLink.class);
-		xstream.alias(ELEM_INSTITUTION, PortletInstitution.class);
-		xstream.aliasAttribute(PortletInstitution.class, ATTR_INSTITUTION_NAME, ATTR_INSTITUTION_NAME);
-		String output = xstream.toXML(portletMap);
+	public static boolean saveLinkList(Map<String, PortletInstitution> portletMap){
 		XStreamHelper.writeObject(xstream, fxConfXStreamFile, portletMap);
-		return (output.length() != 0);		
+		return true;		
 	}
 	
 	public static PortletLink getLinkByIdentifier(String identifier){

programming_language: Java
filename: ChangeEMailExecuteController.java
change_type: ModificationType.MODIFY
diff: @@ -108,6 +108,7 @@ public class ChangeEMailExecuteController extends ChangeEMailController implemen
 	 */
 	public boolean changeEMail(WindowControl wControl) {
 		XStream xml = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xml);
 		@SuppressWarnings("unchecked")
 		HashMap<String, String> mails = (HashMap<String, String>) xml.fromXML(tempKey.getEmailAddress());
 		

programming_language: Java
filename: LandingPagesModule.java
change_type: ModificationType.MODIFY
diff: @@ -44,6 +44,7 @@ public class LandingPagesModule extends AbstractSpringModule {
 	private static final XStream rulesXStream;
 	static {
 		rulesXStream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(rulesXStream);
 		rulesXStream.alias("rules", Rules.class);
 		rulesXStream.alias("rule", Rule.class);
 	}

programming_language: Java
filename: GlossaryItemManager.java
change_type: ModificationType.MODIFY
diff: @@ -79,6 +79,7 @@ public class GlossaryItemManager {
 	
 	private static final XStream xstreamReader = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(xstreamReader);
 		xstreamReader.alias(XML_GLOSSARY_ITEM_NAME, GlossaryItem.class);
 		xstreamReader.alias(XML_REVISION_NAME, Revision.class);
 	}
@@ -102,6 +103,7 @@ public class GlossaryItemManager {
 	});
 	
 	static {
+		XStreamHelper.allowDefaultPackage(xstreamReader);
 		xstreamWriter.alias(XML_GLOSSARY_ITEM_NAME, GlossaryItem.class);
 		xstreamWriter.alias(XML_REVISION_NAME, Revision.class);
 	}
@@ -229,7 +231,7 @@ public class GlossaryItemManager {
 	 * @param glossaryFile
 	 * @param glossaryItemArr
 	 */
-	private void saveToFile(VFSLeaf glossaryFile, List<GlossaryItem> glossaryItemArr) {
+	protected final void saveToFile(VFSLeaf glossaryFile, List<GlossaryItem> glossaryItemArr) {
 		// cdata-tags should be used instead of strings, overwrite writer.
 		glossaryItemArr = removeEmptyGlossaryItems(glossaryItemArr);
 		XStreamHelper.writeObject(xstreamWriter, glossaryFile, glossaryItemArr);
@@ -274,7 +276,7 @@ public class GlossaryItemManager {
 	 * @return list with GlossaryItem's
 	 */
 	@SuppressWarnings("unchecked")
-	private List<GlossaryItem> loadGlossaryItemListFromFile(VFSLeaf glossaryFile) {
+	protected final List<GlossaryItem> loadGlossaryItemListFromFile(VFSLeaf glossaryFile) {
 		List<GlossaryItem> glossaryItemList = new ArrayList<>();
 		if (glossaryFile == null) { return new ArrayList<>(); }
 		

programming_language: Java
filename: DiscoveryXStream.java
change_type: ModificationType.MODIFY
diff: @@ -39,7 +39,6 @@ class DiscoveryXStream {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				DiscoveryImpl.class, NetZoneImpl.class, AppImpl.class, ActionImpl.class, ProofKeyImpl.class
 		};

programming_language: Java
filename: LicenseXStreamHelper.java
change_type: ModificationType.MODIFY
diff: @@ -44,6 +44,7 @@ class LicenseXStreamHelper {
 	
 	private static final XStream licenseXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(licenseXStream);
 		licenseXStream.alias("license", LicenseImpl.class);
 		licenseXStream.alias("license", ResourceLicenseImpl.class);
 		licenseXStream.alias("licenseType", LicenseTypeImpl.class);

programming_language: Java
filename: PersistentTaskDAO.java
change_type: ModificationType.MODIFY
diff: @@ -50,6 +50,9 @@ import com.thoughtworks.xstream.XStream;
 public class PersistentTaskDAO {
 	
 	private static XStream xstream = XStreamHelper.createXStreamInstance();
+	static {
+		XStreamHelper.allowDefaultPackage(xstream);
+	}
 	
 	@Autowired
 	private DB dbInstance;
@@ -61,7 +64,7 @@ public class PersistentTaskDAO {
 		ptask.setLastModified(currentDate);
 		ptask.setName(name);
 		ptask.setStatus(TaskStatus.newTask);
-		ptask.setTask(xstream.toXML(task));
+		ptask.setTask(toXML(task));
 		dbInstance.getCurrentEntityManager().persist(ptask);
 		return ptask;
 	}
@@ -78,7 +81,7 @@ public class PersistentTaskDAO {
 		ptask.setResource(resource);
 		ptask.setResSubPath(resSubPath);
 		ptask.setStatus(TaskStatus.newTask);
-		ptask.setTask(xstream.toXML(task));
+		ptask.setTask(toXML(task));
 		dbInstance.getCurrentEntityManager().persist(ptask);
 		return ptask;
 	}
@@ -189,7 +192,7 @@ public class PersistentTaskDAO {
 			ptask.setScheduledDate(scheduledDate);
 			ptask.setStatus(TaskStatus.newTask);
 			ptask.setStatusBeforeEditStr(null);
-			ptask.setTask(xstream.toXML(runnableTask));
+			ptask.setTask(toXML(runnableTask));
 
 			ptask = dbInstance.getCurrentEntityManager().merge(ptask);
 			if(modifier != null) {
@@ -249,6 +252,11 @@ public class PersistentTaskDAO {
 		dbInstance.commit();
 	}
 	
+	
+	protected static String toXML(Serializable task) {
+		return xstream.toXML(task);
+	}
+	
 	public Runnable deserializeTask(PersistentTask task) {
 		return (Runnable)xstream.fromXML(task.getTask());
 	}

programming_language: Java
filename: VFSXStream.java
change_type: ModificationType.MODIFY
diff: @@ -53,7 +53,6 @@ public class VFSXStream {
 	private static XStream mystream;
 	static {
 		mystream = XStreamHelper.createXStreamInstance();
-		XStream.setupDefaultSecurity(mystream);
 		Class<?>[] types = new Class[] {
 				VersionsFileImpl.class, RevisionFileImpl.class, VFSRevision.class,
 				VFSMetadata.class, VFSMetadataImpl.class, Identity.class, IdentityImpl.class,

programming_language: Java
filename: MapperDAO.java
change_type: ModificationType.MODIFY
diff: @@ -34,6 +34,8 @@ import org.olat.core.util.xml.XStreamHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import com.thoughtworks.xstream.XStream;
+
 /**
  * 
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
@@ -41,6 +43,11 @@ import org.springframework.stereotype.Service;
 @Service("mapperDao")
 public class MapperDAO {
 	
+	private static final XStream xstream = XStreamHelper.createXStreamInstance();
+	static {
+		XStreamHelper.allowDefaultPackage(xstream);
+	}
+	
 	@Autowired
 	private DB dbInstance;
 	
@@ -66,13 +73,21 @@ public class MapperDAO {
 		}
 		m.setOriginalSessionId(sessionId);
 		
-		String configuration = XStreamHelper.createXStreamInstance().toXML(mapper);
+		String configuration = xstream.toXML(mapper);
 		m.setXmlConfiguration(configuration);
 		
 		dbInstance.getCurrentEntityManager().persist(m);
 		return m;
 	}
 	
+	protected static String toXml(Object mapper) {
+		return xstream.toXML(mapper);
+	}
+	
+	public static Object fromXML(String configuration) {
+		return xstream.fromXML(configuration);
+	}
+	
 	/**
 	 * Update a persisted mapper.
 	 * 
@@ -82,7 +97,7 @@ public class MapperDAO {
 	 * @return
 	 */
 	public boolean updateConfiguration(String mapperId, Serializable mapper, int expirationTime) {
-		String configuration = XStreamHelper.createXStreamInstance().toXML(mapper);
+		String configuration = xstream.toXML(mapper);
 		Date currentDate = new Date();
 		Date expirationDate = null;
 		if(expirationTime > 0) {
@@ -120,7 +135,7 @@ public class MapperDAO {
 		if(pm != null && StringHelper.containsNonWhitespace(pm.getXmlConfiguration())) {
 			String configuration = pm.getXmlConfiguration();
 			
-			Object obj = XStreamHelper.createXStreamInstance().fromXML(configuration);
+			Object obj = xstream.fromXML(configuration);
 			if(obj instanceof Mapper) {
 				return (Mapper)obj;
 			}

programming_language: Java
filename: SiteDefinitions.java
change_type: ModificationType.MODIFY
diff: @@ -77,6 +77,7 @@ public class SiteDefinitions extends AbstractSpringModule {
 	
 	private static final XStream xStream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(xStream);
 		xStream.alias("coursesite", CourseSiteConfiguration.class);
 		xStream.alias("languageConfig", LanguageConfiguration.class);
 		xStream.alias("siteconfig", SiteConfiguration.class);

programming_language: Java
filename: HistoryManager.java
change_type: ModificationType.MODIFY
diff: @@ -57,6 +57,9 @@ public class HistoryManager {
 	private static XStream historyReadStream = XStreamHelper.createXStreamInstance();
 	private static XStream historyWriteStream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(historyReadStream);
+		XStreamHelper.allowDefaultPackage(historyWriteStream);
+		
 		//xstream config
 		historyReadStream.omitField(BusinessGroup.class, "type");
 		historyReadStream.omitField(BusinessGroup.class, "ownerGroup");

programming_language: Java
filename: DbStorage.java
change_type: ModificationType.MODIFY
diff: @@ -57,6 +57,7 @@ public class DbStorage implements PreferencesStorage {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(xstream);
 		xstream.ignoreUnknownElements();
 	}
 

programming_language: Java
filename: EnhancedXStream.java
change_type: ModificationType.MODIFY
diff: @@ -43,9 +43,9 @@ import com.thoughtworks.xstream.mapper.MapperWrapper;
  * 
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
-public class EnhancedXStream extends XStream {
+class EnhancedXStream extends XStream {
 
-	public EnhancedXStream(boolean export) {
+	EnhancedXStream(boolean export) {
 		super();
 
 		if (export) {

programming_language: Java
filename: XStreamHelper.java
change_type: ModificationType.MODIFY
diff: @@ -36,6 +36,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
@@ -82,10 +83,22 @@ import com.thoughtworks.xstream.XStream;
  * @author Felix Jost, Florian Gnaegi
  */
 public class XStreamHelper {
-	private static final String ENCODING = "UTF-8";
 
-	private static XStream unconfiguredXStream = new XStream();
+	private static final String[] DEFAULT_PACKAGES = new String[] {
+			"org.olat.**",
+			"de.bps.**",
+			"at.ac.uibk.**",
+			"org.hibernate.**"
+		};
+	private static final XStream unconfiguredXStream = new XStream();
+	static {
+		XStream.setupDefaultSecurity(unconfiguredXStream);
+		allowDefaultPackage(unconfiguredXStream);
+	}
 	
+	public static final void allowDefaultPackage(XStream xstream) {
+		xstream.allowTypesByWildcard(DEFAULT_PACKAGES);
+	}
 
 	/**
 	 * Write a an object to an XML file. UTF-8 is used as encoding
@@ -228,7 +241,9 @@ public class XStreamHelper {
 	 * writing to a configured XML mapping
 	 */
 	public static XStream createXStreamInstance() {
-		return new EnhancedXStream(false);
+		XStream xstream = new EnhancedXStream(false);
+		XStream.setupDefaultSecurity(xstream);
+		return xstream;
 	}
 	
 	/**
@@ -238,7 +253,9 @@ public class XStreamHelper {
 	 * @return
 	 */
 	public static XStream createXStreamInstanceForDBObjects() {
-		return new EnhancedXStream(true);
+		XStream xstream = new EnhancedXStream(true);
+		XStream.setupDefaultSecurity(xstream);
+		return xstream;
 	}
 
 	/**
@@ -302,7 +319,7 @@ public class XStreamHelper {
 	 * @return
 	 */
 	public static Object readObject(XStream xStream, InputStream is) {
-		try(InputStreamReader isr = new InputStreamReader(is, ENCODING);) {
+		try(InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);) {
 			return xStream.fromXML(isr);
 		} catch (Exception e) {
 			throw new OLATRuntimeException(XStreamHelper.class,
@@ -318,7 +335,7 @@ public class XStreamHelper {
 	 * @return
 	 */
 	public static Object readObject(XStream xStream, String xml) {
-		try(InputStream is = new ByteArrayInputStream(xml.getBytes(ENCODING))) {
+		try(InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
 			return readObject(xStream, is);
 		} catch (Exception e) {
 			throw new OLATRuntimeException(XStreamHelper.class,
@@ -377,9 +394,9 @@ public class XStreamHelper {
 	 *            the object to be serialized
 	 */
 	public static void writeObject(XStream xStream, OutputStream os, Object obj) {
-		try(OutputStreamWriter osw = new OutputStreamWriter(os, ENCODING)) {
+		try(OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
 			String data = xStream.toXML(obj);
-			data = "<?xml version=\"1.0\" encoding=\"" + ENCODING + "\"?>\n"
+			data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 					+ data; // give a decent header with the encoding used
 			osw.write(data);
 			osw.flush();

programming_language: Java
filename: CourseXStreamAliases.java
change_type: ModificationType.MODIFY
diff: @@ -95,6 +95,9 @@ public class CourseXStreamAliases {
 	 * @return
 	 */
 	static {
+		XStreamHelper.allowDefaultPackage(readXstream);
+		XStreamHelper.allowDefaultPackage(writeXstream);
+		
 		//write XStream
 		writeXstream.alias("com.frentix.olat.course.nodes.ViteroCourseNode", ViteroCourseNode.class);
 		writeXstream.alias("BookSection", BookSectionImpl.class);

programming_language: Java
filename: FormatConfigHelper.java
change_type: ModificationType.MODIFY
diff: @@ -42,7 +42,6 @@ public class FormatConfigHelper {
 	
 	private static final XStream configXstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(configXstream);
 		Class<?>[] types = new Class[] { ExportFormat.class };
 		configXstream.addPermission(new ExplicitTypePermission(types));
 		configXstream.alias(QTI_EXPORT_ITEM_FORMAT_CONFIG, ExportFormat.class);

programming_language: Java
filename: EfficiencyStatementManager.java
change_type: ModificationType.MODIFY
diff: @@ -103,7 +103,18 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx
 	@Autowired
 	private UserManager userManager;
 	
-	private final XStream xstream = XStreamHelper.createXStreamInstance();
+	private static final XStream xstream = XStreamHelper.createXStreamInstance();
+	static {
+		XStreamHelper.allowDefaultPackage(xstream);
+	}
+	
+	public static EfficiencyStatement fromXML(String xml) {
+		return (EfficiencyStatement)xstream.fromXML(xml);
+	}
+	
+	public static String toXML(EfficiencyStatement statement) {
+		return xstream.toXML(statement);
+	}
 
 	/**
 	 * Updates the users efficiency statement for this course. <p>
@@ -341,7 +352,7 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx
 		}
 
 		efficiencyProperty.setLastModified(new Date());
-		efficiencyProperty.setStatementXml(xstream.toXML(efficiencyStatement));
+		efficiencyProperty.setStatementXml(toXML(efficiencyStatement));
 	}
 	
 	/**
@@ -377,7 +388,7 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx
 		if(s == null || s.getStatementXml() == null) {
 			return null;
 		}
-		return (EfficiencyStatement)xstream.fromXML(s.getStatementXml());
+		return fromXML(s.getStatementXml());
 	}
 	
 	public EfficiencyStatement getUserEfficiencyStatementByResourceKey(Long resourceKey, Identity identity){
@@ -393,7 +404,7 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx
 		if(statement.isEmpty() || statement.get(0).getStatementXml() == null) {
 			return null;
 		}
-		return (EfficiencyStatement)xstream.fromXML(statement.get(0).getStatementXml());
+		return fromXML(statement.get(0).getStatementXml());
 	}
 	
 
@@ -532,7 +543,7 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx
 		if(statement.isEmpty() || !StringHelper.containsNonWhitespace(statement.get(0).getStatementXml())) {
 			return null;
 		}
-		return (EfficiencyStatement)xstream.fromXML(statement.get(0).getStatementXml());
+		return fromXML(statement.get(0).getStatementXml());
 	}
 	
 	public UserEfficiencyStatementLight getUserEfficiencyStatementLightByKey(Long key) {
@@ -648,7 +659,7 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx
 				.getResultList();
 		for(UserEfficiencyStatementImpl statement:statements) {
 			if(StringHelper.containsNonWhitespace(statement.getStatementXml())) {
-				EfficiencyStatement s = (EfficiencyStatement)xstream.fromXML(statement.getStatementXml());
+				EfficiencyStatement s = fromXML(statement.getStatementXml());
 				efficiencyStatements.add(s);
 			}
 		}

programming_language: Java
filename: EfficiencyStatementMediaHandler.java
change_type: ModificationType.MODIFY
diff: @@ -37,9 +37,9 @@ import org.olat.core.logging.Tracing;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.VFSLeaf;
-import org.olat.core.util.xml.XStreamHelper;
 import org.olat.course.assessment.AssessmentHelper;
 import org.olat.course.assessment.EfficiencyStatement;
+import org.olat.course.assessment.manager.EfficiencyStatementManager;
 import org.olat.course.assessment.model.AssessmentNodeData;
 import org.olat.course.assessment.ui.tool.IdentityAssessmentOverviewController;
 import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController;
@@ -57,8 +57,6 @@ import org.olat.util.logging.activity.LoggingResourceable;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import com.thoughtworks.xstream.XStream;
-
 /**
  * 
  * Initial date: 24.06.2016<br>
@@ -69,8 +67,7 @@ import com.thoughtworks.xstream.XStream;
 public class EfficiencyStatementMediaHandler extends AbstractMediaHandler {
 	
 	private static final Logger log = Tracing.createLoggerFor(EfficiencyStatementMediaHandler.class);
-	private static final XStream myXStream = XStreamHelper.createXStreamInstance();
-	
+
 	public static final String EFF_MEDIA = "EfficiencyStatement";
 	
 	@Autowired
@@ -114,7 +111,7 @@ public class EfficiencyStatementMediaHandler extends AbstractMediaHandler {
 		Media media = null;
 		if (mediaObject instanceof EfficiencyStatement) {
 			EfficiencyStatement statement = (EfficiencyStatement) mediaObject;
-			String xml = myXStream.toXML(statement); 
+			String xml = EfficiencyStatementManager.toXML(statement); 
 			media = mediaDao.createMedia(title, description, xml, EFF_MEDIA, businessPath, null, 90, author);
 			ThreadLocalUserActivityLogger.log(PortfolioLoggingAction.PORTFOLIO_MEDIA_ADDED, getClass(),
 					LoggingResourceable.wrap(media));
@@ -128,7 +125,7 @@ public class EfficiencyStatementMediaHandler extends AbstractMediaHandler {
 		EfficiencyStatement statement = null;
 		if(StringHelper.containsNonWhitespace(statementXml)) {
 			try {
-				statement = (EfficiencyStatement)myXStream.fromXML(statementXml);
+				statement = EfficiencyStatementManager.fromXML(statementXml);
 			} catch (Exception e) {
 				log.error("Cannot load efficiency statement from artefact", e);
 			}
@@ -148,7 +145,7 @@ public class EfficiencyStatementMediaHandler extends AbstractMediaHandler {
 		EfficiencyStatement statement = null;
 		if(StringHelper.containsNonWhitespace(media.getContent())) {
 			try {
-				statement = (EfficiencyStatement)myXStream.fromXML(media.getContent());
+				statement = EfficiencyStatementManager.fromXML(media.getContent());
 			} catch (Exception e) {
 				log.error("Cannot load efficiency statement from artefact", e);
 			}

programming_language: Java
filename: CourseConfigManagerImpl.java
change_type: ModificationType.MODIFY
diff: @@ -57,7 +57,6 @@ public class CourseConfigManagerImpl implements CourseConfigManager {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				CourseConfig.class, Hashtable.class, HashMap.class
 		};

programming_language: Java
filename: CustomConfigManager.java
change_type: ModificationType.MODIFY
diff: @@ -57,6 +57,10 @@ import com.thoughtworks.xstream.XStream;
 public class CustomConfigManager {
 	
 	private static final Logger log = Tracing.createLoggerFor(CustomConfigManager.class);
+	private static final XStream xstream = XStreamHelper.createXStreamInstance();
+	static {
+		XStreamHelper.allowDefaultPackage(xstream);
+	}
 	
 	private static final String IFRAME_CSS = "iframe.css";
 	private static final String MAIN_CSS = "main.css";
@@ -91,8 +95,7 @@ public class CustomConfigManager {
 			configTarget = themeBase.createChildLeaf(CUSTOM_CONFIG_XML);
 		} 
 		
-		XStream xStream = XStreamHelper.createXStreamInstance();
-		xStream.toXML(customConfig, configTarget.getOutputStream(false));
+		xstream.toXML(customConfig, configTarget.getOutputStream(false));
 		
 		// compile the css-files
 		StringBuilder sbMain = new StringBuilder();
@@ -187,9 +190,8 @@ public class CustomConfigManager {
 		if (configTarget == null) {
 			return defaultConf;
 		}
-		XStream xStream = XStreamHelper.createXStreamInstance();
 		try(InputStream in=configTarget.getInputStream()) {
-			return (Map<String, Map<String, Object>>) xStream.fromXML(in);
+			return (Map<String, Map<String, Object>>) xstream.fromXML(in);
 		} catch(IOException e) {
 			log.error("", e);
 			return defaultConf;

programming_language: Java
filename: ProjectBrokerCourseNode.java
change_type: ModificationType.MODIFY
diff: @@ -430,6 +430,7 @@ public class ProjectBrokerCourseNode extends AbstractAccessableCourseNode {
 			File projectBrokerFile = new File(folderNodeData, "projectbroker.xml");
 			if (projectBrokerFile.exists()) {
 				XStream xstream = XStreamHelper.createXStreamInstance();
+				XStreamHelper.allowDefaultPackage(xstream);
 				ProjectGroupManager projectGroupManager = CoreSpringFactory.getImpl(ProjectGroupManager.class);
 				ProjectBrokerConfig brokerConfig = (ProjectBrokerConfig) XStreamHelper.readObject(xstream,
 						projectBrokerFile);
@@ -456,6 +457,7 @@ public class ProjectBrokerCourseNode extends AbstractAccessableCourseNode {
 	private void importProject(File projectDir, File projectFile, ProjectBroker projectBroker, ICourse course,
 			CourseEnvironmentMapper envMapper) {
 		XStream xstream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xstream);
 		BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
 		CoursePropertyManager cpm = course.getCourseEnvironment().getCoursePropertyManager();
 		ProjectGroupManager projectGroupManager = CoreSpringFactory.getImpl(ProjectGroupManager.class);
@@ -536,6 +538,7 @@ public class ProjectBrokerCourseNode extends AbstractAccessableCourseNode {
 		ProjectBroker pb = projectBrokerManager.getProjectBroker(projectBrokerManager.getProjectBrokerId(cpm, this));
 		ProjectGroupManager projectGroupManager = CoreSpringFactory.getImpl(ProjectGroupManager.class);
 		XStream xstream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xstream);
 
 		// folder for the pb node
 		File pbNodeFolder = new File(exportDirectory, getIdent());

programming_language: Java
filename: GTAManagerImpl.java
change_type: ModificationType.MODIFY
diff: @@ -130,6 +130,9 @@ public class GTAManagerImpl implements GTAManager, DeletableGroupData {
 	private static final Logger log = Tracing.createLoggerFor(GTAManagerImpl.class);
 	
 	private static final XStream taskDefinitionsXstream = XStreamHelper.createXStreamInstance();
+	static {
+		XStreamHelper.allowDefaultPackage(taskDefinitionsXstream);
+	}
 	
 	@Autowired
 	private DB dbInstance;

programming_language: Java
filename: GroupXStream.java
change_type: ModificationType.MODIFY
diff: @@ -46,8 +46,6 @@ public class GroupXStream {
 	
 	public GroupXStream() {
 		xstream = XStreamHelper.createXStreamInstance();
-		
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				CollabTools.class, Group.class, Area.class, AreaCollection.class, GroupCollection.class,
 				OLATGroupExport.class, ArrayList.class

programming_language: Java
filename: CPManagerImpl.java
change_type: ModificationType.MODIFY
diff: @@ -81,7 +81,6 @@ public class CPManagerImpl implements CPManager {
 
 	private static XStream configXstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(configXstream);
 		Class<?>[] types = new Class[] {
 				CPPackageConfig.class, DeliveryOptions.class
 			};

programming_language: Java
filename: QTI21ServiceImpl.java
change_type: ModificationType.MODIFY
diff: @@ -194,7 +194,6 @@ public class QTI21ServiceImpl implements QTI21Service, UserDataDeletable, Initia
 	
 	private static XStream configXstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(configXstream);
 		Class<?>[] types = new Class[] {
 				QTI21DeliveryOptions.class, QTI21AssessmentResultsOptions.class
 		};

programming_language: Java
filename: ChatLogHelper.java
change_type: ModificationType.MODIFY
diff: @@ -32,7 +32,6 @@ import java.util.Locale;
 import javax.annotation.PostConstruct;
 
 import org.apache.logging.log4j.Logger;
-import org.apache.pdfbox.io.IOUtils;
 import org.olat.basesecurity.IdentityImpl;
 import org.olat.core.gui.media.MediaResource;
 import org.olat.core.gui.translator.Translator;
@@ -72,18 +71,16 @@ public class ChatLogHelper {
 	@PostConstruct 
 	public void init() {
 		logXStream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(logXStream);
 		logXStream.alias("message", InstantMessageImpl.class);
 		logXStream.alias("identity", IdentityImpl.class);
 		logXStream.omitField(IdentityImpl.class, "user");
 	}
 	
 	public void archive(OLATResourceable ores, File exportDirectory) {
-		ObjectOutputStream out = null;
-		try {
-			File file = new File(exportDirectory, "chat.xml");
-			Writer writer = new FileWriter(file);
-			out = logXStream.createObjectOutputStream(writer);
-			
+		File file = new File(exportDirectory, "chat.xml");
+		try(Writer writer = new FileWriter(file);
+			ObjectOutputStream out = logXStream.createObjectOutputStream(writer)) {		
 			int counter = 0;
 			List<InstantMessage> messages;
 			do {
@@ -95,8 +92,6 @@ public class ChatLogHelper {
 			} while(messages.size() == BATCH_SIZE);
 		} catch (IOException e) {
 			log.error("", e);
-		} finally {
-			IOUtils.closeQuietly(out);
 		}
 	}
 	

programming_language: Java
filename: ContentEditorXStream.java
change_type: ModificationType.MODIFY
diff: @@ -47,7 +47,6 @@ public class ContentEditorXStream {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				ImageSettings.class, ImageHorizontalAlignment.class, ImageTitlePosition.class, ImageSize.class,
 				TextSettings.class, ContainerSettings.class, ContainerColumn.class,

programming_language: Java
filename: CurriculumXStream.java
change_type: ModificationType.MODIFY
diff: @@ -63,7 +63,6 @@ public class CurriculumXStream {
 	private static final XStream xstream = XStreamHelper.createXStreamInstanceForDBObjects();
 	
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				Curriculum.class, CurriculumImpl.class, CurriculumElement.class, CurriculumElementImpl.class,
 				CurriculumElementType.class, CurriculumElementTypeImpl.class, CurriculumElementTypeManagedFlag.class,

programming_language: Java
filename: DisadvantageCompensationAuditLogDAO.java
change_type: ModificationType.MODIFY
diff: @@ -48,6 +48,7 @@ public class DisadvantageCompensationAuditLogDAO {
 	
 	private static final XStream disadvantageCompensationXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(disadvantageCompensationXStream);
 		disadvantageCompensationXStream.alias("disadvantageCompensation", DisadvantageCompensationImpl.class);
 		disadvantageCompensationXStream.ignoreUnknownElements();
 		

programming_language: Java
filename: FormXStream.java
change_type: ModificationType.MODIFY
diff: @@ -37,7 +37,6 @@ public class FormXStream {
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] { Choice.class,
 				Choices.class, Container.class, Disclaimer.class, FileStoredData.class, FileUpload.class, Form.class,
 				HTMLParagraph.class, HTMLRaw.class, Image.class, ImageSettings.class, InformationType.class,

programming_language: Java
filename: LectureBlockAuditLogDAO.java
change_type: ModificationType.MODIFY
diff: @@ -69,6 +69,7 @@ public class LectureBlockAuditLogDAO {
 	
 	private static final XStream lectureBlockXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(lectureBlockXStream);
 		lectureBlockXStream.ignoreUnknownElements();
 		
 		lectureBlockXStream.alias("lectureBlock", LectureBlockImpl.class);
@@ -85,6 +86,7 @@ public class LectureBlockAuditLogDAO {
 
 	private static final XStream rollCallXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(rollCallXStream);
 		rollCallXStream.alias("rollcall", LectureBlockRollCallImpl.class);
 		rollCallXStream.ignoreUnknownElements();
 		rollCallXStream.omitField(LectureBlockRollCallImpl.class, "identity");
@@ -94,6 +96,7 @@ public class LectureBlockAuditLogDAO {
 	
 	private static final XStream summaryXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(summaryXStream);
 		summaryXStream.alias("summary", LectureParticipantSummaryImpl.class);
 		summaryXStream.ignoreUnknownElements();
 		summaryXStream.omitField(LectureParticipantSummaryImpl.class, "identity");
@@ -102,6 +105,7 @@ public class LectureBlockAuditLogDAO {
 	
 	private static final XStream absenceNoticeXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(absenceNoticeXStream);
 		absenceNoticeXStream.alias("absenceNotice", AbsenceNoticeImpl.class);
 		absenceNoticeXStream.ignoreUnknownElements();
 		absenceNoticeXStream.omitField(LectureParticipantSummaryImpl.class, "identity");
@@ -113,6 +117,7 @@ public class LectureBlockAuditLogDAO {
 	
 	private static final XStream absenceNoticeRelationsXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(absenceNoticeRelationsXStream);
 		absenceNoticeRelationsXStream.alias("absenceNoticeRelations", AbsenceNoticeRelationsAuditImpl.class);
 		absenceNoticeRelationsXStream.ignoreUnknownElements();
 		

programming_language: Java
filename: OpenMeetingsDAO.java
change_type: ModificationType.MODIFY
diff: @@ -54,6 +54,7 @@ public class OpenMeetingsDAO {
 	@PostConstruct
 	public void init() {
 		xStream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xStream);
 		xStream.alias("room", OpenMeetingsRoom.class);
 		xStream.omitField(OpenMeetingsRoom.class, "property");
 		xStream.omitField(OpenMeetingsRoom.class, "numOfUsers");

programming_language: Java
filename: BinderXStream.java
change_type: ModificationType.MODIFY
diff: @@ -44,6 +44,9 @@ public class BinderXStream {
 	
 	private static final Logger log = Tracing.createLoggerFor(BinderXStream.class);
 	private static final XStream myStream = XStreamHelper.createXStreamInstanceForDBObjects();
+	static {
+		XStreamHelper.allowDefaultPackage(myStream);
+	}
 	
 	public static final Binder copy(Binder binder) {
 		String stringuified = myStream.toXML(binder);
@@ -55,7 +58,7 @@ public class BinderXStream {
 		try(InputStream inStream = Files.newInputStream(path)) {
 			return (Binder)myStream.fromXML(inStream);
 		} catch (Exception e) {
-			log.error("Cannot import this map: " + path, e);
+			log.error("Cannot import this map: {}", path, e);
 			return null;
 		}
 	}
@@ -65,7 +68,7 @@ public class BinderXStream {
 		try(OutputStream out=new ShieldOutputStream(zout)) {
 			myStream.toXML(binder, out);
 		} catch (Exception e) {
-			log.error("Cannot export this map: " + binder, e);
+			log.error("Cannot export this map: {}", binder, e);
 		}
 	}
 }

programming_language: Java
filename: MetadataXStream.java
change_type: ModificationType.MODIFY
diff: @@ -34,6 +34,7 @@ public class MetadataXStream {
 
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(xstream);
 		xstream.alias("citation", org.olat.modules.portfolio.model.CitationXml.class);
 		xstream.aliasType("citation", org.olat.modules.portfolio.model.CitationXml.class);
 	}

programming_language: Java
filename: PortfolioServiceImpl.java
change_type: ModificationType.MODIFY
diff: @@ -145,7 +145,6 @@ public class PortfolioServiceImpl implements PortfolioService {
 	private static XStream configXstream = XStreamHelper.createXStreamInstance();
 	static {
 		configXstream.alias("deliveryOptions", BinderDeliveryOptions.class);
-		XStream.setupDefaultSecurity(configXstream);
 		Class<?>[] types = new Class[] {
 				BinderDeliveryOptions.class
 		};

programming_language: Java
filename: MetadataConverterHelper.java
change_type: ModificationType.MODIFY
diff: @@ -43,7 +43,7 @@ public class MetadataConverterHelper {
 	
 	private static XStream metadatXstream = XStreamHelper.createXStreamInstance();
 	static {
-		
+		XStreamHelper.allowDefaultPackage(metadatXstream);
 		metadatXstream.alias("item", QuestionItemImpl.class);
 		metadatXstream.alias("educationalContext", QEducationalContext.class);
 		metadatXstream.alias("itemType", QItemType.class);

programming_language: Java
filename: QuestionItemAuditLogDAO.java
change_type: ModificationType.MODIFY
diff: @@ -52,6 +52,7 @@ public class QuestionItemAuditLogDAO {
 	
 	private static final XStream qitemXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(qitemXStream);
 		qitemXStream.alias("questionItem", QuestionItemImpl.class);
 		qitemXStream.alias("taxonomyLevel", TaxonomyLevelImpl.class);
 		qitemXStream.alias("educationalContext", QEducationalContext.class);

programming_language: Java
filename: AnalysisPresentationXStream.java
change_type: ModificationType.MODIFY
diff: @@ -50,7 +50,6 @@ public class AnalysisPresentationXStream {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				MultiGroupBy.class, GroupBy.class, AnalysisSearchParameter.class, QualityDataCollectionRefImpl.class,
 				RepositoryEntryRefImpl.class, IdentityRefImpl.class, OrganisationRefImpl.class, CurriculumRefImpl.class,

programming_language: Java
filename: ReminderRulesXStream.java
change_type: ModificationType.MODIFY
diff: @@ -38,6 +38,7 @@ public class ReminderRulesXStream {
 	
 	private static final XStream ruleXStream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(ruleXStream);
 		ruleXStream.alias("rule", org.olat.modules.reminder.model.ReminderRuleImpl.class);
 		ruleXStream.alias("rules", org.olat.modules.reminder.model.ReminderRules.class);
 		ruleXStream.alias("reminders", org.olat.modules.reminder.model.ImportExportReminders.class);

programming_language: Java
filename: ScormMainManager.java
change_type: ModificationType.MODIFY
diff: @@ -56,7 +56,6 @@ public class ScormMainManager {
 	private static final Logger log = Tracing.createLoggerFor(ScormMainManager.class);
 	private static XStream configXstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(configXstream);
 		Class<?>[] types = new Class[] {
 				ScormPackageConfig.class, DeliveryOptions.class
 			};

programming_language: Java
filename: TaxonomyCompetenceAuditLogDAO.java
change_type: ModificationType.MODIFY
diff: @@ -46,6 +46,7 @@ public class TaxonomyCompetenceAuditLogDAO {
 	
 	private static final XStream competenceXStream = XStreamHelper.createXStreamInstanceForDBObjects();
 	static {
+		XStreamHelper.allowDefaultPackage(competenceXStream);
 		competenceXStream.alias("competence", TaxonomyCompetenceImpl.class);
 		competenceXStream.alias("taxonomyLevel", TaxonomyLevelImpl.class);
 		competenceXStream.ignoreUnknownElements();

programming_language: Java
filename: VideoManager.java
change_type: ModificationType.MODIFY
diff: @@ -119,13 +119,6 @@ public interface VideoManager {
 	 */
 	public boolean getFrame(VFSLeaf video, int frameNumber, VFSLeaf frame) throws IOException;
 
-	/**
-	 * Read the the metdatadata-xml in the videoresource folder
-	 * @param videoResource
-	 * @return
-	 */
-	public VideoMetadata readVideoMetadataFile(OLATResource videoResource);
-
 	/**
 	 * Trigger the transcoding process to generate versions of the video
 	 * 
@@ -489,14 +482,6 @@ public interface VideoManager {
 	 */
 	public VideoTranscoding retranscodeFailedVideoTranscoding(VideoTranscoding videoTranscoding);
 
-	/**
-	 * Checks if is metadata file valid.
-	 *
-	 * @param videoResource
-	 * @return true, if is metadata file valid
-	 */
-	public boolean isMetadataFileValid(OLATResource videoResource);
-
 	/**
 	 * Checks for master container.
 	 *

programming_language: Java
filename: VideoManagerImpl.java
change_type: ModificationType.MODIFY
diff: @@ -78,14 +78,12 @@ import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSManager;
 import org.olat.core.util.vfs.VFSStatus;
 import org.olat.core.util.vfs.filters.VFSItemFilter;
-import org.olat.core.util.xml.XStreamHelper;
 import org.olat.fileresource.FileResourceManager;
 import org.olat.fileresource.types.ResourceEvaluation;
 import org.olat.modules.video.VideoFormat;
 import org.olat.modules.video.VideoManager;
 import org.olat.modules.video.VideoMarkers;
 import org.olat.modules.video.VideoMeta;
-import org.olat.modules.video.VideoMetadata;
 import org.olat.modules.video.VideoMetadataSearchParams;
 import org.olat.modules.video.VideoModule;
 import org.olat.modules.video.VideoQuestion;
@@ -94,7 +92,6 @@ import org.olat.modules.video.VideoTranscoding;
 import org.olat.modules.video.model.TranscodingCount;
 import org.olat.modules.video.model.VideoMarkersImpl;
 import org.olat.modules.video.model.VideoMetaImpl;
-import org.olat.modules.video.model.VideoMetadataImpl;
 import org.olat.modules.video.model.VideoQuestionsImpl;
 import org.olat.modules.video.spi.youtube.YoutubeProvider;
 import org.olat.modules.video.spi.youtube.model.YoutubeMetadata;
@@ -396,34 +393,6 @@ public class VideoManagerImpl implements VideoManager {
 		}
 	}
 
-	@Override
-	public boolean isMetadataFileValid(OLATResource videoResource) {
-		VFSContainer baseContainer = FileResourceManager.getInstance().getFileResourceRootImpl(videoResource);
-		VFSLeaf metaDataFile = (VFSLeaf) baseContainer.resolve(FILENAME_VIDEO_METADATA_XML);
-		try {
-			VideoMetadata meta = (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
-			return meta != null;
-		} catch (Exception e) {
-			return false;
-		}
-	}
-
-	@Override
-	public VideoMetadata readVideoMetadataFile(OLATResource videoResource){
-		VFSContainer baseContainer= FileResourceManager.getInstance().getFileResourceRootImpl(videoResource);
-		VFSLeaf metaDataFile = (VFSLeaf) baseContainer.resolve(FILENAME_VIDEO_METADATA_XML);
-		try {
-			return (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
-		} catch (Exception e) {
-			log.error("Error while parsing XStream file for videoResource::{}", videoResource, e);
-			// return an empty, so at least it displays something and not an error
-			VideoMetadata meta =  new VideoMetadataImpl();
-			meta.setWidth(800);
-			meta.setHeight(600);
-			return meta;
-		}
-	}
-
 	@Override
 	public String toPodcastVideoUrl(String url) {
 		try {

programming_language: Java
filename: VideoMetaXStream.java
change_type: ModificationType.MODIFY
diff: @@ -25,7 +25,9 @@ import java.io.OutputStream;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.xml.XStreamHelper;
 import org.olat.modules.video.VideoMeta;
+import org.olat.modules.video.VideoMetadata;
 import org.olat.modules.video.model.VideoMetaImpl;
+import org.olat.modules.video.model.VideoMetadataImpl;
 
 import com.thoughtworks.xstream.XStream;
 import com.thoughtworks.xstream.security.ExplicitTypePermission;
@@ -40,9 +42,9 @@ public class VideoMetaXStream {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
-				VideoMeta.class, VideoMetaImpl.class
+				VideoMeta.class, VideoMetaImpl.class,
+				VideoMetadata.class, VideoMetadataImpl.class
 		};
 		xstream.addPermission(new ExplicitTypePermission(types));
 		xstream.ignoreUnknownElements();

programming_language: Java
filename: VideoXStream.java
change_type: ModificationType.MODIFY
diff: @@ -47,7 +47,6 @@ public class VideoXStream {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xstream);
 		Class<?>[] types = new Class[] {
 				VideoMarker.class, VideoMarkerImpl.class, VideoMarkers.class, VideoMarkersImpl.class,
 				VideoQuestion.class, VideoQuestionImpl.class, VideoQuestions.class, VideoQuestionsImpl.class

programming_language: Java
filename: VideoQualityTableFormController.java
change_type: ModificationType.MODIFY
diff: @@ -204,7 +204,6 @@ public class VideoQualityTableFormController extends FormBasicController {
 			VideoTranscoding videoTranscoding = (VideoTranscoding) link.getUserObject();
 			if (videoTranscoding == null) {
 				// this is the master video
-//				VideoMetadata videoMetadata = videoManager.readVideoMetadataFile(videoResource);
 				VideoMeta videoMetadata = videoManager.getVideoMetadata(videoResource);
 				previewVC.contextPut("width", videoMetadata.getWidth());
 				previewVC.contextPut("height", videoMetadata.getHeight());

programming_language: Java
filename: ViteroManager.java
change_type: ModificationType.MODIFY
diff: @@ -186,6 +186,7 @@ public class ViteroManager implements UserDataDeletable {
 	@PostConstruct
 	public void init() {
 		xStream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xStream);
 		xStream.alias("vBooking", ViteroBooking.class);
 		xStream.omitField(ViteroBooking.class, "property");
 	}

programming_language: Java
filename: FeedFileStorge.java
change_type: ModificationType.MODIFY
diff: @@ -100,6 +100,7 @@ public class FeedFileStorge {
 	public FeedFileStorge() {
 		fileResourceManager = FileResourceManager.getInstance();
 		xstream = XStreamHelper.createXStreamInstance();
+		XStreamHelper.allowDefaultPackage(xstream);
 		xstream.alias("feed", FeedImpl.class);
 		xstream.aliasField("type", FeedImpl.class, "resourceableType");
 		xstream.omitField(FeedImpl.class, "id");

programming_language: Java
filename: BlogEntryMediaController.java
change_type: ModificationType.MODIFY
diff: @@ -60,6 +60,7 @@ public class BlogEntryMediaController extends BasicController {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(xstream);
 		xstream.alias("item", ItemImpl.class);
 	}
 	

programming_language: Java
filename: RegistrationManager.java
change_type: ModificationType.MODIFY
diff: @@ -33,6 +33,7 @@ import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -79,6 +80,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.security.ExplicitTypePermission;
 
 /**
  * Description:
@@ -92,7 +94,10 @@ public class RegistrationManager implements UserDataDeletable, UserDataExportabl
 	
 	private static final XStream xmlXStream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(xmlXStream);
+		Class<?>[] types = new Class[] {
+				HashMap.class
+			};
+		xmlXStream.addPermission(new ExplicitTypePermission(types));
 	}
 
 	private static final int VALID_UNTIL_30_DAYS = 30*24;

programming_language: Java
filename: RepositoryEntryImportExport.java
change_type: ModificationType.MODIFY
diff: @@ -88,6 +88,7 @@ public class RepositoryEntryImportExport {
 	
 	private static final XStream xstream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(xstream);
 		xstream.alias(PROP_ROOT, RepositoryEntryImport.class);
 		xstream.aliasField(PROP_SOFTKEY, RepositoryEntryImport.class, "softkey");
 		xstream.aliasField(PROP_RESOURCENAME, RepositoryEntryImport.class, "resourcename");

programming_language: Java
filename: CourseWebService.java
change_type: ModificationType.MODIFY
diff: @@ -131,7 +131,9 @@ public class CourseWebService {
 
 	private static final Logger log = Tracing.createLoggerFor(CourseWebService.class);
 	private static final XStream myXStream = XStreamHelper.createXStreamInstance();
-
+	static {
+		XStreamHelper.allowDefaultPackage(myXStream);
+	}
 	
 	public static final CacheControl cc = new CacheControl();
 	static {
@@ -695,6 +697,7 @@ public class CourseWebService {
 		Date lastModified = new Date(runStructureItem.getLastModified());
 		Response.ResponseBuilder response = request.evaluatePreconditions(lastModified);
 		if(response == null) {
+			//TODO xstream
 			return Response.ok(myXStream.toXML(course.getRunStructure())).build();
 		}
 		return response.build();	

programming_language: Java
filename: OLATUpgrade_11_3_0.java
change_type: ModificationType.MODIFY
diff: @@ -33,11 +33,14 @@ import org.olat.core.util.vfs.VFSContainer;
 import org.olat.core.util.vfs.VFSItem;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.vfs.VFSManager;
+import org.olat.core.util.xml.XStreamHelper;
+import org.olat.fileresource.FileResourceManager;
 import org.olat.fileresource.types.VideoFileResource;
 import org.olat.modules.video.VideoManager;
 import org.olat.modules.video.VideoMetadata;
 import org.olat.modules.video.manager.VideoManagerImpl;
 import org.olat.modules.video.model.VideoMetaImpl;
+import org.olat.modules.video.model.VideoMetadataImpl;
 import org.olat.repository.RepositoryEntry;
 import org.olat.resource.OLATResource;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -51,6 +54,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 public class OLATUpgrade_11_3_0 extends OLATUpgrade {
 
 	private static final Logger log = Tracing.createLoggerFor(OLATUpgrade_11_3_0.class);
+
+	private static final String FILENAME_VIDEO_METADATA_XML = "video_metadata.xml";
 	
 	private static final String VIDEO_XML = "VIDEO XML";
 	private static final String VERSION = "OLAT_11.3.0";
@@ -120,8 +125,8 @@ public class OLATUpgrade_11_3_0 extends OLATUpgrade {
 			}
 			// update track files on file system
 			VFSContainer masterContainer = videoManager.getMasterContainer(videoResource);
-			if (videoManager.isMetadataFileValid(videoResource)) {
-				VideoMetadata metafromXML = videoManager.readVideoMetadataFile(videoResource);
+			if (isMetadataFileValid(videoResource)) {
+				VideoMetadata metafromXML = readVideoMetadataFile(videoResource);
 				for (Entry<String, String> track : metafromXML.getAllTracks().entrySet()) {
 					VFSItem item = masterContainer.resolve(track.getValue());
 					if (item != null && item instanceof VFSLeaf) {
@@ -165,4 +170,30 @@ public class OLATUpgrade_11_3_0 extends OLATUpgrade {
 			return false;
 		}
 	}
+	
+	private boolean isMetadataFileValid(OLATResource videoResource) {
+		VFSContainer baseContainer = FileResourceManager.getInstance().getFileResourceRootImpl(videoResource);
+		VFSLeaf metaDataFile = (VFSLeaf) baseContainer.resolve(FILENAME_VIDEO_METADATA_XML);
+		try {
+			VideoMetadata meta = (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
+			return meta != null;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+	
+	private VideoMetadata readVideoMetadataFile(OLATResource videoResource){
+		VFSContainer baseContainer= FileResourceManager.getInstance().getFileResourceRootImpl(videoResource);
+		VFSLeaf metaDataFile = (VFSLeaf) baseContainer.resolve(FILENAME_VIDEO_METADATA_XML);
+		try {
+			return (VideoMetadata) XStreamHelper.readObject(XStreamHelper.createXStreamInstance(), metaDataFile);
+		} catch (Exception e) {
+			log.error("Error while parsing XStream file for videoResource::{}", videoResource, e);
+			// return an empty, so at least it displays something and not an error
+			VideoMetadata meta =  new VideoMetadataImpl();
+			meta.setWidth(800);
+			meta.setHeight(600);
+			return meta;
+		}
+	}
 }

programming_language: Java
filename: OLATUpgrade_12_3_0.java
change_type: ModificationType.MODIFY
diff: @@ -237,7 +237,7 @@ public class OLATUpgrade_12_3_0 extends OLATUpgrade {
 			Item xmlItem = QTIEditHelper.readItemXml(leaf);
 			return xmlItem.getTitle();
 		} catch (NullPointerException e) {
-			log.warn("Cannot read files from dir: " + item.getDirectory());
+			log.warn("Cannot read files from dir: {}", item.getDirectory());
 		}
 		return null;
 	}
@@ -247,6 +247,7 @@ public class OLATUpgrade_12_3_0 extends OLATUpgrade {
 		if (!uhd.getBooleanDataValue(MIGRATE_DIALOG)) {
 			try {
 				XStream xstream = XStreamHelper.createXStreamInstance();
+				XStreamHelper.allowDefaultPackage(xstream);
 				xstream.alias("org.olat.modules.dialog.DialogPropertyElements", DialogPropertyElements.class);
 				xstream.alias("org.olat.modules.dialog.DialogElement", DialogElement.class);
 

programming_language: Java
filename: OLATUpgrade_15_3_18.java
change_type: ModificationType.ADD
diff: @@ -0,0 +1,137 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <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 the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <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>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.upgrade;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.olat.core.commons.modules.bc.FolderConfig;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.commons.persistence.QueryBuilder;
+import org.olat.core.logging.Tracing;
+import org.olat.core.util.xml.XStreamHelper;
+import org.olat.course.CourseXStreamAliases;
+import org.olat.course.PersistingCourseImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.thoughtworks.xstream.XStream;
+
+/**
+ * 
+ * Initial date: 18 juin 2021<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class OLATUpgrade_15_3_18 extends OLATUpgrade {
+
+	private static final Logger log = Tracing.createLoggerFor(OLATUpgrade_15_3_18.class);
+
+	private static final String VERSION = "OLAT_15.3.18";
+	private static final String OPEN_COURSES = "OPEN COURSES";
+
+	@Autowired
+	private DB dbInstance;
+
+	public OLATUpgrade_15_3_18() {
+		super();
+	}
+	
+	@Override
+	public String getVersion() {
+		return VERSION;
+	}
+	
+	@Override
+	public boolean doPostSystemInitUpgrade(UpgradeManager upgradeManager) {
+		UpgradeHistoryData uhd = upgradeManager.getUpgradesHistory(VERSION);
+		if (uhd == null) {
+			// has never been called, initialize
+			uhd = new UpgradeHistoryData();
+		} else if (uhd.isInstallationComplete()) {
+			return false;
+		}
+		
+		boolean allOk = true;
+		allOk &= openCourse(upgradeManager, uhd);
+
+		uhd.setInstallationComplete(allOk);
+		upgradeManager.setUpgradesHistory(uhd, VERSION);
+		if(allOk) {
+			log.info(Tracing.M_AUDIT, "Finished OLATUpgrade_15_3_18 successfully!");
+		} else {
+			log.info(Tracing.M_AUDIT, "OLATUpgrade_15_3_18 not finished, try to restart OpenOlat!");
+		}
+		return allOk;
+	}
+	
+	private boolean openCourse(UpgradeManager upgradeManager, UpgradeHistoryData uhd) {
+		boolean allOk = true;
+		if (!uhd.getBooleanDataValue(OPEN_COURSES)) {
+			try {
+				Path coursesPath = Paths.get(FolderConfig.getCanonicalRoot(), PersistingCourseImpl.COURSE_ROOT_DIR_NAME);
+				List<Long> resourceIds = getCourseKeys();
+				for(Long resourceId:resourceIds)  {
+					checkCourse(coursesPath, resourceId);
+				}
+			} catch (Exception e) {
+				log.error("", e);
+				allOk = false;
+			}
+			
+			uhd.setBooleanDataValue(OPEN_COURSES, allOk);
+			upgradeManager.setUpgradesHistory(uhd, VERSION);
+		}
+		return allOk;
+	}
+	
+	private void checkCourse(Path coursesPath, Long resourceId) {
+		try {
+			Path coursePath =  coursesPath.resolve(resourceId.toString());
+			Path runStructure = coursePath.resolve(PersistingCourseImpl.RUNSTRUCTURE_XML);
+			Path editorTree = coursePath.resolve(PersistingCourseImpl.EDITORTREEMODEL_XML);
+
+			XStream xstream = CourseXStreamAliases.getReadCourseXStream();
+			if(Files.exists(runStructure)) {
+				XStreamHelper.readObject(xstream, runStructure.toFile());
+			}
+			if(Files.exists(editorTree)) {
+				XStreamHelper.readObject(xstream, editorTree.toFile());
+			}
+		} catch (Exception e) {
+			log.error("Error with course: {}", resourceId, e);
+		}
+	}
+	
+	private List<Long> getCourseKeys() {
+		QueryBuilder sb = new QueryBuilder();
+		sb.append("select ores.resId from repositoryentry v")
+		  .append(" inner join v.olatResource as ores")
+		  .and().append(" ores.resName = 'CourseModule'");
+		
+		List<Long> courseKeys = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Long.class)
+				.getResultList();
+		dbInstance.commitAndCloseSession();
+		return courseKeys;
+	}
+}

programming_language: Java
filename: UpgradeManager.java
change_type: ModificationType.MODIFY
diff: @@ -31,11 +31,11 @@ import java.util.Map;
 
 import javax.sql.DataSource;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.configuration.Initializable;
 import org.olat.core.gui.control.Event;
 import org.olat.core.logging.AssertException;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.StartupException;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.WebappHelper;
@@ -45,6 +45,7 @@ import org.olat.core.util.event.GenericEventListener;
 import org.olat.core.util.xml.XStreamHelper;
 
 import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.security.ExplicitTypePermission;
 
 /**
  * 
@@ -62,7 +63,13 @@ import com.thoughtworks.xstream.XStream;
 
 public abstract class UpgradeManager implements Initializable, GenericEventListener {
 	
-	protected final XStream upgradesXStream = XStreamHelper.createXStreamInstance();
+	protected static final XStream upgradesXStream = XStreamHelper.createXStreamInstance();
+	static {
+		Class<?>[] types = new Class[] {
+				UpgradeHistoryData.class
+			};
+		upgradesXStream.addPermission(new ExplicitTypePermission(types));
+	}
 	
 	private static final Logger log = Tracing.createLoggerFor(UpgradeManager.class);
 	
@@ -154,12 +161,11 @@ public abstract class UpgradeManager implements Initializable, GenericEventListe
 	/**
 	 * Load all persisted UpgradeHistoryData objects from the fileSystem
 	 */
-	@SuppressWarnings("unchecked")
 	protected void initUpgradesHistories() {
 		File upgradesDir = new File(WebappHelper.getUserDataRoot(), SYSTEM_DIR);
 		File upgradesHistoriesFile = new File(upgradesDir, INSTALLED_UPGRADES_XML);
 		if (upgradesHistoriesFile.exists()) {
-			upgradesHistories = (Map<String, UpgradeHistoryData>)upgradesXStream.fromXML(upgradesHistoriesFile);
+			upgradesHistories = read(upgradesHistoriesFile);
 		} else {
 			if (upgradesHistories == null) {
 				upgradesHistories = new HashMap<>();
@@ -169,6 +175,11 @@ public abstract class UpgradeManager implements Initializable, GenericEventListe
 			createUpgradeData();
 		}
 	}
+
+	@SuppressWarnings("unchecked")
+	protected static Map<String, UpgradeHistoryData> read(File file) {
+		return (Map<String, UpgradeHistoryData>)upgradesXStream.fromXML(file);
+	}
 	
 	/**
 	 * create fake upgrade data as this is a new installation

programming_language: Java
filename: upgradeContext.xml
change_type: ModificationType.MODIFY
diff: @@ -69,6 +69,7 @@
 				<bean id="upgrade_15_2_6" class="org.olat.upgrade.OLATUpgrade_15_2_6"/>
 				<bean id="upgrade_15_3_0" class="org.olat.upgrade.OLATUpgrade_15_3_0"/>
 				<bean id="upgrade_15_3_12" class="org.olat.upgrade.OLATUpgrade_15_3_12"/>
+				<bean id="upgrade_15_3_18" class="org.olat.upgrade.OLATUpgrade_15_3_18"/>
 			</list>
 		</property>
 	</bean>

programming_language: Scala
filename: HomePageConfigManagerImpl.java
change_type: ModificationType.MODIFY
diff: @@ -54,7 +54,6 @@ public class HomePageConfigManagerImpl implements HomePageConfigManager {
 	
 	private static XStream homeConfigXStream = XStreamHelper.createXStreamInstance();
 	static {
-		XStream.setupDefaultSecurity(homeConfigXStream);
 		Class<?>[] types = new Class[] {
 				HomePageConfig.class
 		};
@@ -85,8 +84,8 @@ public class HomePageConfigManagerImpl implements HomePageConfigManager {
 					}
 				}
 			} catch (Exception e) {
-				log.error("Error while loading homepage config from path::" + configFile.getAbsolutePath() + ", fallback to default configuration",
-						e);
+				log.error("Error while loading homepage config from path::{}, fallback to default configuration",
+						configFile.getAbsolutePath(), e);
 				FileUtils.deleteFile(configFile);
 				retVal = loadAndSaveDefaults(identity);
 				// show message to user

programming_language: Java
filename: UserInterestsPropertyHandler.java
change_type: ModificationType.MODIFY
diff: @@ -64,6 +64,7 @@ public class UserInterestsPropertyHandler extends AbstractUserPropertyHandler {
 	
 	private static final XStream interestsXStream = XStreamHelper.createXStreamInstance();
 	static {
+		XStreamHelper.allowDefaultPackage(interestsXStream);
 		interestsXStream.alias("category", UserInterestsCategory.class);
 		interestsXStream.alias("categories", List.class);
 		interestsXStream.addImplicitCollection(UserInterestsCategory.class, "subcategories");

programming_language: Java
filename: GlossaryItemManagerTest.java
change_type: ModificationType.ADD
diff: @@ -0,0 +1,94 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <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 the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <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>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.core.commons.modules.glossary;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+import org.olat.core.logging.Tracing;
+import org.olat.core.util.WebappHelper;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.test.OlatTestCase;
+import org.olat.test.VFSJavaIOFile;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 21 juin 2021<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class GlossaryItemManagerTest extends OlatTestCase {
+	
+	private static final Logger log = Tracing.createLoggerFor(GlossaryItemManagerTest.class);
+	
+	@Autowired
+	private GlossaryItemManager glossaryItemManager;
+	
+	@Test
+	public void loadGlossaryItemListFromFile() throws URISyntaxException {
+		URL glossaryUrl = GlossaryItemManagerTest.class.getResource("glossary.xml");
+		VFSLeaf glossaryLeaf = new VFSJavaIOFile(glossaryUrl.toURI());
+		List<GlossaryItem> items = glossaryItemManager.loadGlossaryItemListFromFile(glossaryLeaf);
+		Assert.assertNotNull(items);
+	}
+	
+	@Test
+	public void saveToFile() throws URISyntaxException, MalformedURLException{
+		GlossaryItem item = new GlossaryItem("Definition", "This is a definition.");
+		List<String> flexions = new ArrayList<>();
+		flexions.add("Add");
+		flexions.add("Flex");
+		item.setGlossFlexions(flexions);
+		List<URI> uris = new ArrayList<>();
+		uris.add(new URL("https://www.frentix.com").toURI());
+		item.setGlossLinks(uris);
+		List<String> synonyms = new ArrayList<>();
+		synonyms.add("Synonym");
+		item.setGlossSynonyms(synonyms);
+		
+		List<GlossaryItem> items = new ArrayList<>();
+		items.add(item);
+		
+		File glossaryFile = new File(WebappHelper.getTmpDir(), "glossary" + UUID.randomUUID() + ".xml");
+		glossaryFile.getParentFile().mkdirs();
+		VFSLeaf glossaryLeaf = new VFSJavaIOFile(glossaryFile);
+		glossaryItemManager.saveToFile(glossaryLeaf, items);
+		
+		// read the files
+		List<GlossaryItem> savedItems = glossaryItemManager.loadGlossaryItemListFromFile(glossaryLeaf);
+		Assert.assertNotNull(items);
+		Assert.assertEquals(1, savedItems.size());
+		Assert.assertEquals("Definition", savedItems.get(0).getGlossTerm());
+		
+		if(!glossaryFile.delete()) {
+			log.error("Cannot delete: {}", glossaryFile);
+		}
+	}
+}

programming_language: Java
filename: glossary.xml
change_type: ModificationType.ADD
diff: @@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<list>
+  <glossentry>
+    <glossTerm>Forsythie</glossTerm>
+    <glossDef><![CDATA[<p>Die Forsythie, auch Garten-Forsythie, Goldflieder oder Goldglöckchen genannt, ist ein häufig gepflanzter Zierstrauch. Es handelt sich um eine Hybride zweier Arten aus der Gattung der Forsythien. Diese gehört zur Familie der Ölbaumgewächse.</p>]]></glossDef>
+    <glossSynonyms/>
+    <revHistory>
+      <revision>
+        <author>
+          <firstname>Jeremery</firstname>
+          <surname>Johns</surname>
+          <link>[Identity:66027520]</link>
+        </author>
+        <revisionflag>added</revisionflag>
+        <date>22 Mar 2021</date>
+      </revision>
+      <revision>
+        <author>
+          <firstname>Jeremery</firstname>
+          <surname>Johns</surname>
+          <link>[Identity:66027520]</link>
+        </author>
+        <revisionflag>added</revisionflag>
+        <date>22 Mar 2021</date>
+      </revision>
+      <revision>
+        <author>
+          <firstname>Jeremery</firstname>
+          <surname>Johns</surname>
+          <link>[Identity:66027520]</link>
+        </author>
+        <revisionflag>changed</revisionflag>
+        <date>22 Mar 2021</date>
+      </revision>
+    </revHistory>
+  </glossentry>
+  <glossentry>
+    <glossTerm>Kraut- und Braunfäule</glossTerm>
+    <glossDef><![CDATA[<p><img src="https://www.gesal.ch/.imaging/focus/dam/global/pests-diseases/Kraut-Braunfaeule_Tomate.jpg0/jcr:content.jpeg?x&#61;53&amp;y&#61;41&amp;lastModified&#61;Mon&#43;Dec&#43;02&#43;13%3A31%3A13&#43;CET&#43;2019&amp;width&#61;472&amp;height&#61;354" alt=" herb and brown rot - Kraut- und Braunfaeule" width="117" height="88" /></p>
+<p>Kraut- und Braunfäule ist eine Pilzerkrankung, die vor allem im Sommer bei feuchten Witterungsbedingungen auftritt. Bei Tomatenpflanzen erscheinen auf den Blättern graugrüne später braune Flecken, die sich schnell ausbreiten. Die Früchte zeigen schmutzig braune Flecken. Das Fruchtfleisch ist unter den Flecken verhärtet und fault. Die Dauerformen dieses Schadpilzes überdauern im Boden und befallen bei geeigneten Bedingungen (feuchtwarm über 15°C) ab Ende Juni zunächst die bodennahen Blätter.</p>]]></glossDef>
+    <glossSynonyms/>
+    <revHistory>
+      <revision>
+        <author>
+          <firstname>Jeremery</firstname>
+          <surname>Johns</surname>
+          <link>[Identity:66027520]</link>
+        </author>
+        <revisionflag>added</revisionflag>
+        <date>23 Mar 2021</date>
+      </revision>
+    </revHistory>
+  </glossentry>
+  <glossentry>
+    <glossTerm>Test</glossTerm>
+    <glossDef></glossDef>
+    <glossSynonyms/>
+    <revHistory>
+      <revision>
+        <author>
+          <firstname>Jeremery</firstname>
+          <surname>Johns</surname>
+          <link>[Identity:66027520]</link>
+        </author>
+        <revisionflag>added</revisionflag>
+        <date>23 Mar 2021</date>
+      </revision>
+    </revHistory>
+  </glossentry>
+  <glossentry>
+    <glossTerm>Tomatenhaus</glossTerm>
+    <glossDef><![CDATA[<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>]]></glossDef>
+    <glossSynonyms/>
+    <revHistory>
+      <revision>
+        <author>
+          <firstname>Jeremery</firstname>
+          <surname>Johns</surname>
+          <link>[Identity:66027520]</link>
+        </author>
+        <revisionflag>added</revisionflag>
+        <date>24 Mar 2021</date>
+      </revision>
+    </revHistory>
+  </glossentry>
+</list>
\ No newline at end of file

programming_language: Markdown
filename: PersistentTaskDAOTest.java
change_type: ModificationType.MODIFY
diff: @@ -36,7 +36,6 @@ import org.olat.core.commons.services.taskexecutor.model.PersistentTask;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.WebappHelper;
-import org.olat.core.util.xml.XStreamHelper;
 import org.olat.repository.RepositoryEntry;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
@@ -192,7 +191,7 @@ public class PersistentTaskDAOTest extends OlatTestCase  {
 		ptask.setStatus(TaskStatus.inWork);
 		ptask.setExecutorBootId(UUID.randomUUID().toString());
 		ptask.setExecutorNode(Integer.toString(WebappHelper.getNodeId()));
-		ptask.setTask(XStreamHelper.createXStreamInstance().toXML(new DummyTask()));
+		ptask.setTask(PersistentTaskDAO.toXML(new DummyTask()));
 		dbInstance.getCurrentEntityManager().persist(ptask);
 
 		//simulate a task from an other node
@@ -203,7 +202,7 @@ public class PersistentTaskDAOTest extends OlatTestCase  {
 		alienTask.setStatus(TaskStatus.inWork);
 		alienTask.setExecutorBootId(UUID.randomUUID().toString());
 		alienTask.setExecutorNode(Integer.toString(WebappHelper.getNodeId() + 1));
-		alienTask.setTask(XStreamHelper.createXStreamInstance().toXML(new DummyTask()));
+		alienTask.setTask(PersistentTaskDAO.toXML(new DummyTask()));
 		dbInstance.getCurrentEntityManager().persist(alienTask);
 
 		dbInstance.commitAndCloseSession();

programming_language: Java
filename: MapperDAOTest.java
change_type: ModificationType.MODIFY
diff: @@ -27,7 +27,6 @@ import org.junit.Test;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.dispatcher.mapper.manager.MapperDAO;
 import org.olat.core.dispatcher.mapper.model.PersistedMapper;
-import org.olat.core.util.xml.XStreamHelper;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -37,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class MapperDAOTest extends OlatTestCase {
 	
+	
 	@Autowired
 	private MapperDAO mapperDao;
 	@Autowired
@@ -92,7 +92,7 @@ public class MapperDAOTest extends OlatTestCase {
 		Assert.assertEquals(pMapper, loadedMapper);
 		Assert.assertEquals(mapperId, loadedMapper.getMapperId());
 
-		Object objReloaded = XStreamHelper.createXStreamInstance().fromXML(pMapper.getXmlConfiguration());
+		Object objReloaded = MapperDAO.fromXML(pMapper.getXmlConfiguration());
 		Assert.assertTrue(objReloaded instanceof PersistentMapper);
 		PersistentMapper sMapperReloaded = (PersistentMapper)objReloaded;
 		Assert.assertEquals("mapper-to-persist", sMapperReloaded.getKey());
@@ -111,7 +111,7 @@ public class MapperDAOTest extends OlatTestCase {
 		//load the mapper
 		PersistedMapper loadedMapper = mapperDao.loadByMapperId(mapperId);
 		Assert.assertNotNull(loadedMapper);
-		Object objReloaded = XStreamHelper.createXStreamInstance().fromXML(pMapper.getXmlConfiguration());
+		Object objReloaded = MapperDAO.fromXML(pMapper.getXmlConfiguration());
 		Assert.assertTrue(objReloaded instanceof PersistentMapper);
 		PersistentMapper sMapperReloaded = (PersistentMapper)objReloaded;
 		Assert.assertEquals("mapper-to-persist-bis", sMapperReloaded.getKey());
@@ -125,7 +125,7 @@ public class MapperDAOTest extends OlatTestCase {
 		//load the updated mapper
 		PersistedMapper loadedMapper2 = mapperDao.loadByMapperId(mapperId);
 		Assert.assertNotNull(loadedMapper2);
-		Object objReloaded2 = XStreamHelper.createXStreamInstance().fromXML(loadedMapper2.getXmlConfiguration());
+		Object objReloaded2 = MapperDAO.fromXML(loadedMapper2.getXmlConfiguration());
 		Assert.assertTrue(objReloaded2 instanceof PersistentMapper);
 		PersistentMapper sMapperReloaded2 = (PersistentMapper)objReloaded2;
 		Assert.assertEquals("mapper-to-update", sMapperReloaded2.getKey());
@@ -144,7 +144,7 @@ public class MapperDAOTest extends OlatTestCase {
 		//load the mapper
 		PersistedMapper loadedMapper = mapperDao.loadByMapperId(mapperId);
 		Assert.assertNotNull(loadedMapper);
-		Object objReloaded = XStreamHelper.createXStreamInstance().fromXML(pMapper.getXmlConfiguration());
+		Object objReloaded = MapperDAO.fromXML(pMapper.getXmlConfiguration());
 		Assert.assertTrue(objReloaded instanceof PersistentMapper);
 		PersistentMapper sMapperReloaded = (PersistentMapper)objReloaded;
 		Assert.assertEquals("mapper-to-persist-until", sMapperReloaded.getKey());
@@ -159,7 +159,7 @@ public class MapperDAOTest extends OlatTestCase {
 		//load the updated mapper
 		PersistedMapper loadedMapper2 = mapperDao.loadByMapperId(mapperId);
 		Assert.assertNotNull(loadedMapper2);
-		Object objReloaded2 = XStreamHelper.createXStreamInstance().fromXML(loadedMapper2.getXmlConfiguration());
+		Object objReloaded2 = MapperDAO.fromXML(loadedMapper2.getXmlConfiguration());
 		Assert.assertTrue(objReloaded2 instanceof PersistentMapper);
 		PersistentMapper sMapperReloaded2 = (PersistentMapper)objReloaded2;
 		Assert.assertEquals("mapper-to-update-until", sMapperReloaded2.getKey());

programming_language: Java
filename: XMLDigitalSignatureUtilTest.java
change_type: ModificationType.MODIFY
diff: @@ -48,7 +48,7 @@ public class XMLDigitalSignatureUtilTest {
 	@BeforeClass
 	public static void loadBouncyCastle() {
 		new PersistedProperties(event -> {
-			//
+			// do nothing
 		});
 	}
 	

programming_language: Java
filename: XStreamHelperTest.java
change_type: ModificationType.ADD
diff: @@ -0,0 +1,84 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <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 the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <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>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.core.util.xml;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.olat.core.logging.OLATRuntimeException;
+
+import com.thoughtworks.xstream.converters.ConversionException;
+
+/**
+ * 
+ * Initial date: 18 juin 2021<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class XStreamHelperTest {
+	
+	@Test
+	public void readXmlMapAllowed() throws URISyntaxException {
+		URL url = XStreamHelperTest.class.getResource("xstream_map_strings.xml");
+		File file = new File(url.toURI());
+		Object obj = XStreamHelper.createXStreamInstance().fromXML(file);
+		Assert.assertNotNull(obj);
+	}
+	
+	@Test
+	public void readXmlMapDbObjectsAllowed() throws URISyntaxException {
+		URL url = XStreamHelperTest.class.getResource("xstream_map_strings.xml");
+		File file = new File(url.toURI());
+		Object obj = XStreamHelper.createXStreamInstanceForDBObjects().fromXML(file);
+		Assert.assertNotNull(obj);
+	}
+	
+	@Test
+	public void readXmlMapUnconfiguredAllowed() throws URISyntaxException {
+		URL url = XStreamHelperTest.class.getResource("xstream_map_strings.xml");
+		File file = new File(url.toURI());
+		Object obj = XStreamHelper.readObject(file);
+		Assert.assertNotNull(obj);
+	}
+
+	@Test(expected = ConversionException.class)
+	public void readXmlMapNotAllowed() throws URISyntaxException {
+		URL url = XStreamHelperTest.class.getResource("xstream_map_alien.xml");
+		File file = new File(url.toURI());
+		XStreamHelper.createXStreamInstance().fromXML(file);
+	}
+	
+	@Test(expected = ConversionException.class)
+	public void readXmlMapDbObjectsNotAllowed() throws URISyntaxException {
+		URL url = XStreamHelperTest.class.getResource("xstream_map_alien.xml");
+		File file = new File(url.toURI());
+		XStreamHelper.createXStreamInstanceForDBObjects().fromXML(file);
+	}
+	
+	@Test(expected = OLATRuntimeException.class)
+	public void readXmlMapUnconfiguredNotAllowed() throws URISyntaxException {
+		URL url = XStreamHelperTest.class.getResource("xstream_map_alien.xml");
+		File file = new File(url.toURI());
+		XStreamHelper.readObject(file);
+	}
+}

programming_language: Java
filename: xstream_map_alien.xml
change_type: ModificationType.ADD
diff: @@ -0,0 +1,8 @@
+<java.util.HashMap>
+  <entry>
+    <string>Hello</string>
+    <org.springframework.scheduling.quartz.JobDetailFactoryBean>
+    	<name>World</name>
+    </org.springframework.scheduling.quartz.JobDetailFactoryBean>
+  </entry>
+</java.util.HashMap>
\ No newline at end of file

programming_language: Scala
filename: xstream_map_strings.xml
change_type: ModificationType.ADD
diff: @@ -0,0 +1,6 @@
+<java.util.HashMap>
+  <entry>
+    <string>Hello</string>
+    <string>World</string>
+  </entry>
+</java.util.HashMap>
\ No newline at end of file

programming_language: Markdown
filename: AllTestsJunit4.java
change_type: ModificationType.MODIFY
diff: @@ -81,6 +81,7 @@ import org.junit.runners.Suite;
 	org.olat.core.util.openxml.OpenXMLDocumentTest.class,
 	org.olat.core.util.pdf.PdfDocumentTest.class,
 	org.olat.core.util.xml.XMLDigitalSignatureUtilTest.class,
+	org.olat.core.util.xml.XStreamHelperTest.class,
 	org.olat.core.configuration.EDConfigurationTest.class,
 	org.olat.core.id.context.BusinessControlFactoryTest.class,
 	org.olat.core.id.context.HistoryManagerTest.class,
@@ -100,6 +101,7 @@ import org.junit.runners.Suite;
 	org.olat.commons.coordinate.cluster.jms.JMSTest.class,
 	org.olat.commons.coordinate.cluster.lock.LockTest.class,
 	org.olat.commons.coordinate.CoordinatorTest.class,
+	org.olat.core.commons.modules.glossary.GlossaryItemManagerTest.class,
 	org.olat.core.commons.services.csp.manager.CSPManagerTest.class,
 	org.olat.core.commons.services.doceditor.manager.DocEditorIdentityServiceTest.class,
 	org.olat.core.commons.services.doceditor.manager.AccessDAOTest.class,
@@ -575,7 +577,8 @@ import org.junit.runners.Suite;
 	 * tree is not available
 	 */
 	org.olat.core.commons.services.scheduler.SchedulerTest.class,
-	org.olat.upgrade.UpgradeDefinitionTest.class
+	org.olat.upgrade.UpgradeDefinitionTest.class,
+	org.olat.upgrade.UpgradeManagerTest.class
 })
 public class AllTestsJunit4 {
 	//

programming_language: Java
filename: VFSJavaIOFile.java
change_type: ModificationType.MODIFY
diff: @@ -22,12 +22,16 @@ package org.olat.test;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.URI;
 import java.nio.file.Path;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.commons.modules.bc.FolderConfig;
 import org.olat.core.commons.services.vfs.VFSMetadata;
+import org.olat.core.logging.Tracing;
 import org.olat.core.util.vfs.JavaIOItem;
 import org.olat.core.util.vfs.VFSConstants;
 import org.olat.core.util.vfs.VFSContainer;
@@ -44,10 +48,16 @@ import org.olat.core.util.vfs.callbacks.VFSSecurityCallback;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
 public class VFSJavaIOFile implements VFSLeaf, JavaIOItem {
+	
+	private static final Logger log = Tracing.createLoggerFor(VFSJavaIOFile.class);
 
 	private final String name;
 	private final File file;
 	
+	public VFSJavaIOFile(URI uri) {
+		this(new File(uri));
+	}
+	
 	public VFSJavaIOFile(File file) {
 		this(file.getName(), file);
 	}
@@ -189,6 +199,11 @@ public class VFSJavaIOFile implements VFSLeaf, JavaIOItem {
 
 	@Override
 	public OutputStream getOutputStream(boolean append) {
-		return null;
+		try {
+			return new FileOutputStream(file);
+		} catch (FileNotFoundException e) {
+			log.error("", e);
+			return null;
+		}
 	}
 }
\ No newline at end of file

programming_language: Java
filename: UpgradeManagerTest.java
change_type: ModificationType.ADD
diff: @@ -0,0 +1,76 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <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 the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <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>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.upgrade;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+import org.olat.core.logging.Tracing;
+import org.olat.core.util.WebappHelper;
+import org.olat.core.util.xml.XStreamHelper;
+
+/**
+ * 
+ * Initial date: 18 juin 2021<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class UpgradeManagerTest {
+	
+	private static final Logger log = Tracing.createLoggerFor(UpgradeManagerTest.class);
+	
+	@Test
+	public void readUpgradesXml() throws Exception {
+		URL upgradeUrl = UpgradeManagerTest.class.getResource("installed_upgrades.xml");
+		File upgradeFile = new File(upgradeUrl.toURI());
+		Map<String, UpgradeHistoryData> upgrades = UpgradeManager.read(upgradeFile);
+		Assert.assertNotNull(upgrades);
+		Assert.assertFalse(upgrades.isEmpty());
+	}
+	
+	@Test
+	public void readDatabaseUpgradesXml() throws Exception {
+		URL upgradeUrl = UpgradeManagerTest.class.getResource("installed_database_upgrades.xml");
+		File upgradeFile = new File(upgradeUrl.toURI());
+		Map<String, UpgradeHistoryData> upgrades = UpgradeManager.read(upgradeFile);
+		Assert.assertNotNull(upgrades);
+		Assert.assertFalse(upgrades.isEmpty());
+	}
+	
+	@Test
+	public void writeDatabaseUpgradesXml() throws Exception {
+		URL upgradeUrl = UpgradeManagerTest.class.getResource("installed_database_upgrades.xml");
+		File upgradeFile = new File(upgradeUrl.toURI());
+		Map<String, UpgradeHistoryData> upgrades = UpgradeManager.read(upgradeFile);
+		Assert.assertNotNull(upgrades);
+		Assert.assertFalse(upgrades.isEmpty());
+
+		File savedFile = new File(WebappHelper.getTmpDir(), "upgradeDB-" + UUID.randomUUID() + ".xml");
+		XStreamHelper.writeObject(UpgradeManager.upgradesXStream, savedFile, upgrades);
+		if(!savedFile.delete()) {
+			log.error("Cannot delete: {}", savedFile);
+		}
+	}
+}

programming_language: Java
filename: installed_database_upgrades.xml
change_type: ModificationType.ADD
diff: @@ -0,0 +1,1179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map>
+  <entry>
+    <string>OLAT_11.0.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.16</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.17</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_9.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.13</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.1.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.1.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.1.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.1.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.5.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.5.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.5.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_9.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.1.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.3.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.0.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.0.0-user</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLATfx_8.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.3.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.2.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.0.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.8</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.4.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_9.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.5.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.5.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_9.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLATfx_8.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.1.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.1.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.1.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta10</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta4</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.8</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta8</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.4</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta9</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.5.24</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.0.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.0.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.4.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.4.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.5.8</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.5.7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.5.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.5.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.5.14</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.0.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+</map>
\ No newline at end of file

programming_language: TypeScript
filename: installed_upgrades.xml
change_type: ModificationType.ADD
diff: @@ -0,0 +1,954 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map>
+  <entry>
+    <string>OLAT_11.0.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>RECERTIFICATION DATE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_9.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>ADD BIG BLUE BUTTON URL TO CALENDAR</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE USER LIFECYCLE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>ASSESSMENT PROPERTY TABLE</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>EFFICIENCY STATEMENT TABLE</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>PORTFOLIO SETTINGS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>RESET FAILED THUMBNAILS</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE ONLYOFFICE CONFIGS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.0.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>PORTFOLIO v2 USER TOOL</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.5.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>ADD MISSING ENTRY TECHNICAL TYPE</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>COPY PORTFOLIO PAGE EDITABLE FLAG</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>GROUP INFO MESSAGE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.2.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>STATUS OLD TASK ELEMENT</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>SET MS ORES TYPE NAME</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.8.fx</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>RESET FAILED PDF THUMBNAILS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_9.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.10</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>VIDEO VFS METADATA</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Calendar user configurations</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>Imported calendars</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>Calendar tokens</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>Imported calendars url</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.0.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CLEAN META PATH ERRORS</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META FORUM</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META HOMEPAGES</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META TMP</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META RESOURCES</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META CTS</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META COURSES</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>CLEAN META HOMES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.1.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE TEMP KEY VALID UNTIL</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE QUALITY DATA COLLECTION TO ORGANISATION</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta10</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE BOOKABLE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.8</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>DELETE PORTFOLIO V1</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE FILE METADATA</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE LIBRARY CONFIGURATION</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MOVE REPO IMAGES</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE CURRICULUM ROLES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CATALOG ORDER INDEX</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE SURVEY SERIES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE QPOOL TITLE</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE DIALOG ELEMENTS</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MOVE DOC POOL INFOS PAGE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.4</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CATALOG ORDER INDEX</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0.beta9</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE BOOKABLE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CATALOG ORDER INDEX</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>INIT ASESSMENT ENTRY ROOT</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.5.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE WEB FEED</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.hammed</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CLEANUP CERTIFICATES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE USER PROPERTY</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE USER NAME</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE CATALOG SORTING</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>INIT VFS MODIFIED BY</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>INIT ENTRY TECHNICAL TYPE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.0.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>ASSESSMENT LAST ATTEMPTS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CLEAN UP REPOSITORY ENTRY TO GROUP RELATION</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.2.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CLEAN UP APPOINTMENT ORGANIZERS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_11.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>VIDEO XML</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.pre.6.ae</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>CONDITION COURSES COMPLETION</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.12</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>DELETE APPOINTMENT USER RESTRICTIONS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE FILE METADATA</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE LIBRARY CONFIGURATION</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MOVE REPO IMAGES</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE CURRICULUM ROLES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.1.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.5.17</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>UPDATE COURSE STATS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.0.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>UPDATE UNKOWN VIDEO FORMAT</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.0.3</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>PASSWORD SYNTAX CHECK TYPO</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>TRANSFER INFOS NOTIFICATIONS NOT DESIRED</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>DATA COLLECTION ORGANISATIONS</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>LIVE STREAM LAUNCHES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.7</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>BIGBLUEBUTTON SERVER TO DB</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_14.2.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>DELETE COURSE EXPORT DIRECTORY</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>DELETE DOWNLOAD ZIP</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_10.3.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Clean export folder</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>PORTFOLIO EVALUATION FORM</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE ROLE</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>LECTURES SEND APPEAL DATES</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE ADMIN SITE SECURITY CALLBACK</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE REPO ENTRY TO DEF ORG</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE LUCENE 7.5</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE INVITEE</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE REPO ENTRY ACCESS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>UPDATE CURRICULUM CHILDREN</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.0.2</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData/>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_7.0.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.2.8</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>GUEST COURSE NODES PASSWORDS</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_13.2.4</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>ORPHAN IDENTITIES</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.4.5</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE QPOOL TAXONOMY</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MAIL CONFIG SPLITTING</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>KEEP INTERNAL MAIL DISABLED</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_15.3.6</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE BIGBLUEBUTTON JOIN FLAG</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.0.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>LAST USER MODIFICATION</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>USER PROPERTY CONTEXT RENAME</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>FEED XML TO DB</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_8.2.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>Database update</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.4.1</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE PASSWORD HISTORY</string>
+          <boolean>true</boolean>
+        </entry>
+        <entry>
+          <string>MIGRATE CHANGE PASSWORD</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+  <entry>
+    <string>OLAT_12.4.0</string>
+    <org.olat.upgrade.UpgradeHistoryData>
+      <upgradeData>
+        <entry>
+          <string>MIGRATE QPOOL LICENSE</string>
+          <boolean>true</boolean>
+        </entry>
+      </upgradeData>
+      <installationComplete>true</installationComplete>
+    </org.olat.upgrade.UpgradeHistoryData>
+  </entry>
+</map>
\ No newline at end of file

programming_language: HTML