From 312023be934399ac378bac93174f393385ae0404 Mon Sep 17 00:00:00 2001
From: uhensler <none@none>
Date: Mon, 5 Mar 2018 10:24:23 +0100
Subject: [PATCH] OO-3170: Licenses in the folder course node

---
 .../modules/bc/FileUploadController.java      |   9 -
 .../modules/bc/FolderLicenseHandler.java      |  49 ++++
 .../modules/bc/FolderRunController.java       |  10 -
 .../bc/_i18n/LocalStrings_de.properties       |   3 +-
 .../bc/_i18n/LocalStrings_en.properties       |   3 +-
 .../modules/bc/commands/CmdEditMeta.java      |  16 +-
 .../bc/components/FolderComponent.java        |  18 +-
 .../modules/bc/components/ListRenderer.java   |  17 +-
 .../commons/modules/bc/meta/MetaInfo.java     |  16 ++
 .../modules/bc/meta/MetaInfoController.java   |  94 ++++----
 .../modules/bc/meta/MetaInfoFactory.java      |  52 +++++
 .../modules/bc/meta/MetaInfoFileImpl.java     | 209 +++++++++---------
 .../bc/meta/MetaInfoFormController.java       | 142 ++++++++++--
 .../bc/meta/_i18n/LocalStrings_de.properties  |   3 +
 .../bc/meta/_i18n/LocalStrings_en.properties  |   3 +
 .../commons/services/license/License.java     |   9 +-
 .../services/license/LicenseService.java      |  38 +++-
 .../services/license/ResourceLicense.java     |  38 ++++
 .../license/manager/LicenseServiceImpl.java   |  49 +++-
 .../license/manager/LicenseTypeDAO.java       |  15 +-
 ...icenseDAO.java => ResourceLicenseDAO.java} |  24 +-
 .../services/license/model/LicenseImpl.java   | 133 +----------
 .../license/model/ResourceLicenseImpl.java    | 176 +++++++++++++++
 .../ui/LicenseQuickviewController.java        |  71 ------
 .../services/license/ui/LicenseRenderer.java  |  77 +++----
 .../license/ui/LicenseSelectionConfig.java    |   9 +-
 .../services/license/ui/LicenseUIFactory.java |   4 +-
 .../ui/_i18n/LocalStrings_de.properties       |   6 +-
 .../ui/_i18n/LocalStrings_en.properties       |   6 +-
 .../ui/author/AuthorListController.java       |  33 +--
 .../ui/author/AuthoringEntryDataSource.java   |   6 +-
 .../RepositoryEditDescriptionController.java  |   6 +-
 src/main/resources/META-INF/persistence.xml   |   2 +-
 .../modules/bc/meta/MetaInfoFactoryTest.java  | 104 +++++++++
 .../license/manager/LicenseCleaner.java       |  51 +++++
 .../manager/LicenseTypeActivationDAOTest.java |  13 +-
 .../license/manager/LicenseTypeDAOTest.java   |  40 +++-
 ...OTest.java => ResourceLicenseDAOTest.java} |  32 ++-
 .../ui/LicenseSelectionConfigTest.java        |  20 +-
 .../java/org/olat/test/AllTestsJunit4.java    |   3 +-
 40 files changed, 1023 insertions(+), 586 deletions(-)
 create mode 100644 src/main/java/org/olat/core/commons/modules/bc/FolderLicenseHandler.java
 create mode 100644 src/main/java/org/olat/core/commons/services/license/ResourceLicense.java
 rename src/main/java/org/olat/core/commons/services/license/manager/{LicenseDAO.java => ResourceLicenseDAO.java} (80%)
 create mode 100644 src/main/java/org/olat/core/commons/services/license/model/ResourceLicenseImpl.java
 delete mode 100644 src/main/java/org/olat/core/commons/services/license/ui/LicenseQuickviewController.java
 create mode 100644 src/test/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactoryTest.java
 create mode 100644 src/test/java/org/olat/core/commons/services/license/manager/LicenseCleaner.java
 rename src/test/java/org/olat/core/commons/services/license/manager/{LicenseDAOTest.java => ResourceLicenseDAOTest.java} (82%)

diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java
index 32b534fa6a7..b42279e48f0 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java
@@ -363,18 +363,12 @@ public class FileUploadController extends FormBasicController {
 		}
 	}
 	
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formCancelled(org.olat.core.gui.UserRequest)
-	 */
 	@Override	
 	protected void formCancelled(UserRequest ureq) {
 		status = FolderCommandStatus.STATUS_CANCELED;
 		fireEvent(ureq, Event.CANCELLED_EVENT);
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == overwriteDialog) {
@@ -759,9 +753,6 @@ public class FileUploadController extends FormBasicController {
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#doDispose()
-	 */
 	@Override
 	protected void doDispose() {
 		// 
diff --git a/src/main/java/org/olat/core/commons/modules/bc/FolderLicenseHandler.java b/src/main/java/org/olat/core/commons/modules/bc/FolderLicenseHandler.java
new file mode 100644
index 00000000000..9cd01ce1754
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/modules/bc/FolderLicenseHandler.java
@@ -0,0 +1,49 @@
+/**
+ * <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.bc;
+
+import java.util.Locale;
+
+import org.olat.core.commons.services.license.LicenseHandler;
+import org.olat.core.gui.translator.Translator;
+import org.olat.core.util.Util;
+import org.springframework.stereotype.Component;
+
+/**
+ * 
+ * Initial date: 02.03.2018<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+@Component
+public class FolderLicenseHandler implements LicenseHandler {
+
+	@Override
+	public String getType() {
+		return "folder";
+	}
+
+	@Override
+	public String getTitle(Locale locale) {
+		Translator translator = Util.createPackageTranslator(FolderModule.class, locale);
+		return translator.translate("license.admin.title");
+	}
+
+}
diff --git a/src/main/java/org/olat/core/commons/modules/bc/FolderRunController.java b/src/main/java/org/olat/core/commons/modules/bc/FolderRunController.java
index 216e9957eed..5524f488635 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/FolderRunController.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/FolderRunController.java
@@ -439,12 +439,6 @@ public class FolderRunController extends BasicController implements Activateable
 		}
 	}
 
-	/**
-	 * @seec org.olat removeAsListenerAndDispose(folderCommandController);
-	 *      folderCommandController = null; removeAsListenerAndDispose(cmc); cmc =
-	 *      null; .UserRequest, org.olat.core.gui.components.Component,
-	 *      org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		if (source == folderComponent || source == folderContainer || source == editQuotaButton) {
@@ -545,10 +539,6 @@ public class FolderRunController extends BasicController implements Activateable
 		return null;
 	}
 
-	/**
-	 * 
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
 	@Override
 	protected void doDispose() {		
 		//
diff --git a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties
index 841b14b2a85..b191aa18f9a 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties
@@ -68,14 +68,15 @@ eportfolio=Diese Datei als Artefakt dem ePortfolio hinzuf\u00FCgen.
 failed=Operation fehlgeschlagen
 file=Datei
 header.Info=Metadaten
+header.license=Lizenz
 header.Modified=Ge\u00E4ndert
 header.Name=Name
 header.Size=Gr\u00F6sse
 header.Status=Status
 header.Type=Typ
 header.Version=Version
-
 invalid.file.names=Folgende Dateinamen sind ung\u00FCltig, weil sie unzul\u00E4ssige Zeichen enthalten (/,\:, etc.). Bitte \u00E4ndern Sie die Namen entsprechend.
+license.admin.title=Ordner
 lock.description=Eine oder mehrere Dateien sind gesperrt.
 lock.title=Datei(en) gesperrt
 mc.copy=Objekte kopieren
diff --git a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties
index caf359feb75..23a384a182d 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties
@@ -68,14 +68,15 @@ eportfolio=Add this file as artefact to a portfolio.
 failed=Operation failed
 file=File
 header.Info=Metadata
+header.license=License
 header.Modified=Modified
 header.Name=Name
 header.Size=Size
 header.Status=Status
 header.Type=Type
 header.Version=Version
-
 invalid.file.names=The following file names are invalid since they contain special characters (/, \:, etc.). Please modify your names accordingly.
+license.admin.title=Folder
 lock.description=One or more files are locked.
 lock.title=Locked file(s)
 mc.copy=Copy object
diff --git a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdEditMeta.java b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdEditMeta.java
index e1669b743fe..9742ac28855 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdEditMeta.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdEditMeta.java
@@ -139,21 +139,11 @@ public class CmdEditMeta extends BasicController implements FolderCommand {
 		return translate("mf.metadata.title");
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.Component,
-	 *      org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		// nothing to do here
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.Controller,
-	 *      org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == metaInfoCtr && event == Event.DONE_EVENT) {
@@ -169,9 +159,7 @@ public class CmdEditMeta extends BasicController implements FolderCommand {
 						getWindowControl().setError(translator.translate("TargetNameAlreadyUsed"));
 						status = FolderCommandStatus.STATUS_FAILED;
 					} else {
-						if (meta != null) {
-							meta.rename(fileName);
-						}
+						meta.rename(fileName);
 						if(VFSConstants.NO.equals(currentItem.rename(fileName))) {
 							getWindowControl().setError(translator.translate("FileRenameFailed", new String[]{fileName}));
 							status = FolderCommandStatus.STATUS_FAILED;
@@ -198,10 +186,12 @@ public class CmdEditMeta extends BasicController implements FolderCommand {
 		fireEvent(ureq, FOLDERCOMMAND_FINISHED);
 	}
 
+	@Override
 	protected void doDispose() {
 		// metaInfoCtr should be auto-disposed
 	}
 
+	@Override
 	public boolean runsModal() {
 		return false;
 	}
diff --git a/src/main/java/org/olat/core/commons/modules/bc/components/FolderComponent.java b/src/main/java/org/olat/core/commons/modules/bc/components/FolderComponent.java
index 9f6f47d25bc..d35548768ec 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/components/FolderComponent.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/components/FolderComponent.java
@@ -140,9 +140,7 @@ public class FolderComponent extends AbstractComponent {
 		dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
 	}
 	
-	/**
-	 * @see org.olat.core.gui.components.Component#dispatchRequest(org.olat.core.gui.UserRequest)
-	 */
+	@Override
 	protected void doDispatchRequest(UserRequest ureq) {
 		if (ureq.getParameter(ListRenderer.PARAM_EDTID) != null) {
 			fireEvent(ureq, new Event(FolderCommandFactory.COMMAND_EDIT));
@@ -212,6 +210,7 @@ public class FolderComponent extends AbstractComponent {
 		currentSortOrder = col;
 		if (col.equals(SORT_NAME)) {																										// sort after file name?
 			comparator = new Comparator<VFSItem>() {
+				@Override
 				public int compare(VFSItem o1, VFSItem o2) {
 					if (sortAsc) {
 						if ((o1 instanceof VFSLeaf && o2 instanceof VFSLeaf) || (!(o1 instanceof VFSLeaf) && !(o2 instanceof VFSLeaf))) {
@@ -240,6 +239,7 @@ public class FolderComponent extends AbstractComponent {
 			};
 		} else if (col.equals(SORT_DATE)) {																							// sort after modification date (if same, then name)
 			comparator = new Comparator<VFSItem>() {
+				@Override
 				public int compare(VFSItem o1, VFSItem o2) {
 					if      (o1.getLastModified() < o2.getLastModified()) return ((sortAsc) ? -1 :  1);			
 					else if (o1.getLastModified() > o2.getLastModified()) return ((sortAsc) ?  1 : -1);
@@ -251,6 +251,7 @@ public class FolderComponent extends AbstractComponent {
 			};
 		} else	if (col.equals(SORT_SIZE)) {																						// sort after file size, folders always on top
 			comparator = new Comparator<VFSItem>() {
+				@Override
 				public int compare(VFSItem o1, VFSItem o2) {
 					VFSLeaf leaf1 = null;
 					if (o1 instanceof VFSLeaf) {
@@ -272,6 +273,7 @@ public class FolderComponent extends AbstractComponent {
 			};
 		} else if (col.equals(SORT_REV)) {																							// sort after revision number, folders always on top
 			comparator = new Comparator<VFSItem>() {
+				@Override
 				public int compare(VFSItem o1, VFSItem o2) {
 					Versionable v1 = null;
 					Versionable v2 = null;
@@ -303,16 +305,10 @@ public class FolderComponent extends AbstractComponent {
 		if (currentContainerChildren != null) updateChildren();													// if not empty the update list
 	}
 
-	/**
-	 * @return VFSContainer
-	 */
 	public VFSContainer getRootContainer() {
 		return rootContainer;
 	}
 
-	/**
-	 * @return VFSContainer
-	 */
 	public VFSContainer getCurrentContainer() {
 		return currentContainer;
 	}
@@ -374,9 +370,6 @@ public class FolderComponent extends AbstractComponent {
 		currentContainerChildren = children;
 	}
 	
-	/**
-	 * @param relPath
-	 */
 	public boolean setCurrentContainerPath(String relPath) {
 		// get the container
 		setDirty(true);
@@ -421,6 +414,7 @@ public class FolderComponent extends AbstractComponent {
 		return externContainerForCopy;
 	}
 
+	@Override
 	public ComponentRenderer getHTMLRendererSingleton() {
 		return RENDERER;
 	}
diff --git a/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java b/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java
index 6f14fc9371e..4afdaf71bcd 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/components/ListRenderer.java
@@ -35,7 +35,10 @@ import org.olat.core.commons.modules.bc.FileSelection;
 import org.olat.core.commons.modules.bc.FolderConfig;
 import org.olat.core.commons.modules.bc.FolderManager;
 import org.olat.core.commons.modules.bc.meta.MetaInfo;
+import org.olat.core.commons.modules.bc.meta.MetaInfoFactory;
 import org.olat.core.commons.modules.bc.meta.tagged.MetaTagged;
+import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.ui.LicenseRenderer;
 import org.olat.core.gui.components.form.flexible.impl.NameValuePair;
 import org.olat.core.gui.control.winmgr.AJAXFlags;
 import org.olat.core.gui.render.StringOutput;
@@ -129,8 +132,9 @@ public class ListRenderer {
 		sb.append("<table class=\"table table-condensed table-striped table-hover o_bc_table\">")
 		  .append("<thead><tr><th><a class='o_orderby ").append(sortCss,FolderComponent.SORT_NAME.equals(sortOrder)).append("' ");
 		ubu.buildHrefAndOnclick(sb, null, iframePostEnabled, false, false, new NameValuePair(PARAM_SORTID, FolderComponent.SORT_NAME))
-		   .append(">").append(translator.translate("header.Name")).append("</a>")
-		   .append("</th><th><a class='o_orderby ").append(sortCss,FolderComponent.SORT_SIZE.equals(sortOrder)).append("' ");
+		   .append(">").append(translator.translate("header.Name")).append("</a>").append("</th>");
+		sb.append("<th>").append(translator.translate("header.license")).append("</th>");
+		sb.append("<th><a class='o_orderby ").append(sortCss,FolderComponent.SORT_SIZE.equals(sortOrder)).append("' ");
 		ubu.buildHrefAndOnclick(sb, null, iframePostEnabled, false, false, new NameValuePair(PARAM_SORTID, FolderComponent.SORT_SIZE))
 		   .append(">").append(translator.translate("header.Size")).append("</a>")
 		   .append("</th><th><a class='o_orderby ").append(sortCss,FolderComponent.SORT_DATE.equals(sortOrder)).append("' ");	
@@ -339,6 +343,15 @@ public class ListRenderer {
 		}
 		sb.append("</td><td>");
 		
+		// license
+		MetaInfoFactory metaInfoFactory = CoreSpringFactory.getImpl(MetaInfoFactory.class);
+		License license = metaInfoFactory.getLicense(metaInfo);
+		if (license != null) {
+			LicenseRenderer licenseRenderer = new LicenseRenderer(translator.getLocale());
+			licenseRenderer.render(sb, license);
+		}
+		sb.append("</td><td>");
+		
 		// filesize
 		if (!isContainer) {
 			// append filesize
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java
index 112b9108a4a..7f9f31ffa02 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfo.java
@@ -205,6 +205,22 @@ public interface MetaInfo {
 
 	public void setPublicationDate(String month, String year);
 	
+	public String getLicenseTypeKey();
+	
+	public void setLicenseTypeKey(String key);
+	
+	public String getLicenseTypeName();
+	
+	public void setLicenseTypeName(String name);
+	
+	public String getLicenseText();
+	
+	public void setLicenseText(String text);
+	
+	public String getLicensor();
+	
+	public void setLicensor(String licensor);
+	
 	
 	public boolean isThumbnailAvailable();
 	
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoController.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoController.java
index 9adc03173e1..38aea3f7df0 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoController.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoController.java
@@ -24,6 +24,11 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.modules.bc.FolderLicenseHandler;
+import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.LicenseModule;
+import org.olat.core.commons.services.license.LicenseService;
+import org.olat.core.commons.services.license.ui.LicenseUIFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -57,7 +62,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 public class MetaInfoController extends FormBasicController {
 	private VFSItem item;
 	private FormLink moreMetaDataLink;
-	private StaticTextElement  publisher, creator, sourceEl, city, pages, language, url;
+	private StaticTextElement publisher, creator, sourceEl, city, pages, language, url, publicationDateEl;;
+	private StaticTextElement licenseEl;
+	private StaticTextElement licensorEl;
+	private StaticTextElement licenseFreetextEl;
 	private SingleSelection locked;
 	private Set<FormItem> metaFields;
 	private String resourceUrl;
@@ -66,6 +74,12 @@ public class MetaInfoController extends FormBasicController {
 	private UserManager userManager;
 	@Autowired
 	private VFSLockManager vfsLockManager;
+	@Autowired
+	private LicenseModule licenseModule;
+	@Autowired
+	private LicenseService licenseService;
+	@Autowired
+	private FolderLicenseHandler licenseHandler;
 
 	/**
 	 * Use this controller for editing meta data of an existing file.
@@ -80,35 +94,21 @@ public class MetaInfoController extends FormBasicController {
 		initForm(ureq);
 	}
 	
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#doDispose()
-	 */
 	@Override
 	protected void doDispose() {
 		// nothing so far
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formOK(org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void formOK(UserRequest ureq) {
 		//do nothing
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formCancelled(org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void formCancelled(UserRequest ureq) {
 		fireEvent(ureq, Event.CANCELLED_EVENT);
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formInnerEvent(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.form.flexible.FormItem,
-	 *      org.olat.core.gui.components.form.flexible.impl.FormEvent)
-	 */
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if (source == moreMetaDataLink && event.wasTriggerdBy(FormEvent.ONCLICK)) {
@@ -120,10 +120,6 @@ public class MetaInfoController extends FormBasicController {
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm(org.olat.core.gui.components.form.flexible.FormItemContainer,
-	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		setFormTitle("mf.metadata.title");
@@ -159,15 +155,10 @@ public class MetaInfoController extends FormBasicController {
 		String cityVal = StringHelper.escapeHtml(meta != null ? meta.getCity() : null);
 		city = uifactory.addStaticTextElement("mf.city", cityVal, formLayout);
 
-		// publish date
-		FormLayoutContainer publicationDate = FormLayoutContainer.createHorizontalFormLayout("publicationDateLayout", getTranslator());
-		publicationDate.setLabel("mf.publishDate", null);
-		formLayout.add(publicationDate);
-
 		String[] pubDate = (meta != null ? meta.getPublicationDate() : new String[] { "", "" });
-		uifactory.addStaticTextElement("mf.month", StringHelper.escapeHtml(pubDate[1]), publicationDate);
-		uifactory.addStaticTextElement("mf.year", StringHelper.escapeHtml(pubDate[0]), publicationDate);
-
+		String publicationDate = new StringBuilder().append(translate("mf.month")).append(pubDate[0]).append(", ")
+				.append(translate("mf.year")).append(pubDate[1]).toString();
+		publicationDateEl = uifactory.addStaticTextElement("mf.publishDate", publicationDate, formLayout);
 
 		// number of pages
 		String pageVal = StringHelper.escapeHtml(meta != null ? meta.getPages() : null);
@@ -180,6 +171,24 @@ public class MetaInfoController extends FormBasicController {
 		// url/link
 		String urlVal = StringHelper.escapeHtml(meta != null ? meta.getUrl() : null);
 		url = uifactory.addStaticTextElement("mf.url", urlVal, formLayout);
+		
+		// license
+		if (licenseModule.isEnabled(licenseHandler)) {
+			MetaInfoFactory metaInfoFactory = CoreSpringFactory.getImpl(MetaInfoFactory.class);
+			License license = metaInfoFactory.getOrCreateLicense(meta, getIdentity());
+			boolean isNoLicense = !licenseService.isNoLicense(license.getLicenseType());
+			boolean isFreetext = licenseService.isFreetext(license.getLicenseType());
+
+			licenseEl = uifactory.addStaticTextElement("mf.license",
+					LicenseUIFactory.translate(license.getLicenseType(), getLocale()), formLayout);
+			if (isNoLicense) {
+				licensorEl = uifactory.addStaticTextElement("mf.licensor", license.getLicensor(), formLayout);
+			}
+			if (isFreetext) {
+				licenseFreetextEl = uifactory.addStaticTextElement("mf.freetext",
+						LicenseUIFactory.getFormattedLicenseText(license), formLayout);
+			}
+		}
 
 		/* static fields */
 		String sizeText, typeText;
@@ -192,15 +201,24 @@ public class MetaInfoController extends FormBasicController {
 		}
 
 		// Targets to hide
-		metaFields = new HashSet<FormItem>();
+		metaFields = new HashSet<>();
 		metaFields.add(creator);
 		metaFields.add(publisher);
 		metaFields.add(sourceEl);
 		metaFields.add(city);
-		metaFields.add(publicationDate);
+		metaFields.add(publicationDateEl);
 		metaFields.add(pages);
 		metaFields.add(language);
 		metaFields.add(url);
+		if (licenseEl != null) {
+			metaFields.add(licenseEl);
+		}
+		if (licensorEl != null) {
+			metaFields.add(licensorEl);
+		}
+		if (licenseFreetextEl != null) {
+			metaFields.add(licenseFreetextEl);
+		}
 
 		if (!hasMetadata(meta)) {
 			moreMetaDataLink = uifactory.addFormLink("mf.more.meta.link", formLayout, Link.LINK_CUSTOM_CSS);
@@ -239,25 +257,22 @@ public class MetaInfoController extends FormBasicController {
 			uifactory.addStaticTextElement("mf.lockedBy", lockedDetails, formLayout);
 			
 			// username
-			String author = StringHelper.escapeHtml(meta == null ? "" : meta.getHTMLFormattedAuthor());
+			String author = StringHelper.escapeHtml(meta.getHTMLFormattedAuthor());
 			uifactory.addStaticTextElement("mf.author", author, formLayout);
 
 			// filesize
 			uifactory.addStaticTextElement("mf.size", StringHelper.escapeHtml(sizeText), formLayout);
 
 			// last modified date
-			String lastModified = meta == null ? "" : StringHelper.formatLocaleDate(meta.getLastModified(), getLocale());
+			String lastModified = StringHelper.formatLocaleDate(meta.getLastModified(), getLocale());
 			uifactory.addStaticTextElement("mf.lastModified", lastModified, formLayout);
 
 			// file type
 			uifactory.addStaticTextElement("mf.type", StringHelper.escapeHtml(typeText), formLayout);
 
-			String downloads = meta == null ? "" : String.valueOf(meta.getDownloadCount());
+			String downloads = String.valueOf(meta.getDownloadCount());
 			uifactory.addStaticTextElement("mf.downloads", downloads, formLayout);
-
-			// Don't show any meta data except title and comment if the item is
-			// a directory.
-			// Hide the metadata.
+		} else {
 			setMetaFieldsVisible(false);
 			if (moreMetaDataLink != null) {
 				moreMetaDataLink.setVisible(false);
@@ -292,8 +307,10 @@ public class MetaInfoController extends FormBasicController {
 				|| StringHelper.containsNonWhitespace(meta.getPublisher()) || StringHelper.containsNonWhitespace(meta.getSource())
 				|| StringHelper.containsNonWhitespace(meta.getCity()) || StringHelper.containsNonWhitespace(meta.getPublicationDate()[0])
 				|| StringHelper.containsNonWhitespace(meta.getPublicationDate()[1]) || StringHelper.containsNonWhitespace(meta.getPages())
-				|| StringHelper.containsNonWhitespace(meta.getLanguage()) || StringHelper.containsNonWhitespace(meta.getUrl());
-		}
+				|| StringHelper.containsNonWhitespace(meta.getLanguage()) || StringHelper.containsNonWhitespace(meta.getUrl())
+				|| StringHelper.containsNonWhitespace(meta.getLicenseTypeKey()) || StringHelper.containsNonWhitespace(meta.getLicenseTypeName())
+				|| StringHelper.containsNonWhitespace(meta.getLicenseText()) || StringHelper.containsNonWhitespace(meta.getLicensor());
+				}
 		return false;
 	}
 
@@ -307,4 +324,5 @@ public class MetaInfoController extends FormBasicController {
 			formItem.setVisible(visible);
 		}
 	}
+	
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactory.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactory.java
index b96b1b339a8..e83077d43a5 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactory.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactory.java
@@ -26,10 +26,18 @@ package org.olat.core.commons.modules.bc.meta;
 
 import java.io.File;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.modules.bc.FolderConfig;
+import org.olat.core.commons.modules.bc.FolderLicenseHandler;
+import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.LicenseHandler;
+import org.olat.core.commons.services.license.LicenseService;
+import org.olat.core.commons.services.license.LicenseType;
 import org.olat.core.commons.services.thumbnail.ThumbnailService;
+import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.OlatRelPathImpl;
 
 
@@ -91,4 +99,48 @@ public class MetaInfoFactory {
 	protected static File getOriginFile(OlatRelPathImpl olatRelPathImpl) {
 		return new File(FolderConfig.getCanonicalRoot() + olatRelPathImpl.getRelPath());
 	}
+	
+	/**
+	 * Get the license of the MetaInfo
+	 *
+	 * @param meta
+	 * @return the license or null if no license is stored in the MetaInfo
+	 */
+	public License getLicense(MetaInfo meta) {
+		LicenseService licenseService = CoreSpringFactory.getImpl(LicenseService.class);
+		License license = null;
+		boolean hasLicense = meta != null && StringHelper.containsNonWhitespace(meta.getLicenseTypeName());
+		if (hasLicense) { 
+			String licenseTypeName = meta.getLicenseTypeName();
+			LicenseType licenseType = licenseService.loadLicenseTypeByName(licenseTypeName);
+			if (licenseType == null) {
+				licenseType = licenseService.createLicenseType(licenseTypeName);
+				licenseType.setText(meta.getLicenseText());
+				licenseService.saveLicenseType(licenseType);
+			}
+			license = licenseService.createLicense(licenseType);
+			license.setLicensor(meta.getLicensor());
+			if (licenseService.isFreetext(licenseType)) {
+				license.setFreetext(meta.getLicenseText());
+			}
+		}
+		return license;
+	}
+	
+	/**
+	 * Get the license of the MetaInfo or create a new default license:
+	 *
+	 * @param meta
+	 * @param itentity the current user
+	 * @return
+	 */
+	public License getOrCreateLicense(MetaInfo meta, Identity itentity) {
+		LicenseHandler licenseHandler = CoreSpringFactory.getImpl(FolderLicenseHandler.class);
+		LicenseService licenseService = CoreSpringFactory.getImpl(LicenseService.class);
+		License license = getLicense(meta);
+		if (license == null) {
+			license = licenseService.createDefaultLicense(licenseHandler, itentity);
+		}
+		return license;
+	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java
index afb81ea0f9c..2eca8d3ea27 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFileImpl.java
@@ -103,6 +103,10 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	private Long lockedByIdentKey = null;
 	private String comment = "";
 	private String title, publisher, creator, source, city, pages, language, url, pubMonth, pubYear;
+	private String licenseTypeKey;
+	private String licenseTypeName;
+	private String licenseText;
+	private String licensor;
 	private Date lockedDate;
 	private int downloadCount;
 	private boolean locked;
@@ -112,7 +116,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	private File metaFile = null;
 	
 	private boolean cannotGenerateThumbnail = false;
-	private List<Thumbnail> thumbnails = new ArrayList<Thumbnail>();
+	private List<Thumbnail> thumbnails = new ArrayList<>();
 	private ThumbnailService thumbnailService;
 	
 
@@ -150,6 +154,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * @param meta
 	 * @param newName
 	 */
+	@Override
 	public void rename(String newName) {
 		// rename meta info file name
 		if (isDirectory()) { // rename the directory, which is the parent of the actual ".xml" file
@@ -165,6 +170,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * @param targetDir
 	 * @param move
 	 */
+	@Override
 	public void moveCopyToDir(OlatRelPathImpl target, boolean move) {
 		File fSource = metaFile;
 		File fTarget = new File(MetaInfoFactory.getCanonicalMetaPath(target));
@@ -181,7 +187,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		if (move) FileUtils.moveFileToDir(fSource, fTarget);
 		else {
 			//copy
-			 Map<String,String> pathToUuid = new HashMap<String,String>();
+			 Map<String,String> pathToUuid = new HashMap<>();
 			File mTarget = new File(fTarget, fSource.getName());
 			collectUUIDRec(mTarget, pathToUuid);
 			
@@ -242,6 +248,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * Delete all associated meta info including sub files/directories
 	 * @param meta
 	 */
+	@Override
 	public void deleteAll() {
 		if (isDirectory()) { // delete whole meta directory (where the ".xml" resides within)
 			FileUtils.deleteDirsAndFiles(metaFile.getParentFile(), true, true);
@@ -254,6 +261,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * Copy values from froMeta into this object except name.
 	 * @param fromMeta
 	 */
+	@Override
 	public void copyValues(MetaInfo fromMeta) {
 		this.setAuthor(fromMeta.getAuthor());
 		this.setComment(fromMeta.getComment());
@@ -309,6 +317,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * does not write anything.
 	 * @return True upon success.
 	 */
+	@Override
 	public boolean write() {
 		BufferedOutputStream bos = null;
 		if (metaFile == null) return false;
@@ -332,6 +341,10 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 			sw.write("<pages><![CDATA[" + filterForCData(pages) + "]]></pages>");
 			sw.write("<language><![CDATA[" + filterForCData(language) + "]]></language>");
 			sw.write("<url><![CDATA[" + filterForCData(url) + "]]></url>");
+			sw.write("<licenseTypeKey><![CDATA[" + filterForCData(licenseTypeKey) + "]]></licenseTypeKey>");
+			sw.write("<licenseTypeName><![CDATA[" + filterForCData(licenseTypeName) + "]]></licenseTypeName>");
+			sw.write("<licenseText><![CDATA[" + filterForCData(licenseText) + "]]></licenseText>");
+			sw.write("<licensor><![CDATA[" + filterForCData(licensor) + "]]></licensor>");
 			sw.write("<publicationDate><month><![CDATA[" + (pubMonth != null ? pubMonth.trim() : "") + "]]></month><year><![CDATA[" + (pubYear != null ? pubYear.trim() : "") + "]]></year></publicationDate>");
 			sw.write("<downloadCount><![CDATA[" + downloadCount + "]]></downloadCount>");
 			sw.write("<thumbnails cannotGenerateThumbnail=\"" + cannotGenerateThumbnail + "\">");
@@ -377,6 +390,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	 * 
 	 * @return True upon success.
 	 */
+	@Override
 	public boolean delete() {
 		if (metaFile == null) return false;
 		for(Thumbnail thumbnail:thumbnails) {
@@ -391,7 +405,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	/**
 	 * The parser is synchronized. Normally for such small files, this is
 	 * the quicker way. Creation of a SAXParser is really time consuming.
-	 * An other possibilty would be to use a pool of parser.
+	 * An other possibility would be to use a pool of parser.
 	 * @param fMeta
 	 * @return
 	 */
@@ -511,6 +525,14 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 			language = (n != null) ? n.getText() : "";
 			n = root.element("url");
 			url = (n != null) ? n.getText() : "";
+			n = root.element("licenseTypeKey");
+			licenseTypeKey = (n != null) ? n.getText() : "";
+			n = root.element("licenseName");
+			licenseTypeName = (n != null) ? n.getText() : "";
+			n = root.element("licenseText");
+			licenseText = (n != null) ? n.getText() : "";
+			n = root.element("licensor");
+			licensor = (n != null) ? n.getText() : "";
 			n = root.element("downloadCount");
 			downloadCount = (n != null) ? Integer.valueOf(n.getText()) : 0;
 			n = root.element("publicationDate");
@@ -532,6 +554,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 	/**
 	 * @return name of the initial author
 	 */
+	@Override
 	public String getAuthor() { 
 		if (authorIdentKey == null) {
 			return "-";
@@ -563,9 +586,6 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return authorIdentKey;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getAuthorIdentity()
-	 */
 	@Override
 	public Identity getAuthorIdentity() {
 		if (authorIdentKey == null) {
@@ -580,9 +600,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return (authorIdentKey != null);
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getHTMLFormattedAuthor()
-	 */
+	@Override
 	public String getHTMLFormattedAuthor() {
 		if (authorIdentKey == null) {
 			return "-";
@@ -596,28 +614,20 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		}	
 	}
 	
-	/**
-	 * @return comment
-	 */
+	@Override
 	public String getComment() { return comment; }
 
+	@Override
 	public String getName() { return originFile.getName(); }
-	/**
-	 * @return True if this is a directory
-	 */
+
+	@Override
 	public boolean isDirectory() { return originFile.isDirectory(); }
 
-	/**
-	 * @return Last modified timestamp
-	 */
 	@Override
 	public long getLastModified() {
 		return originFile.lastModified();
 	}
 	
-	/**
-	 * @return The last modification date of the metadata
-	 */
 	@Override
 	public Date getMetaLastModified() {
 		if(metaFile == null) return null;
@@ -625,21 +635,13 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return lastModified > 0 ? new Date(lastModified) : null;
 	}
 
-	/**
-	 * @return size of file
-	 */
+	@Override
 	public long getSize() {	return originFile.length(); }
 	
-	/**
-	 * @return formatted representation of size of file
-	 */
+	@Override
 	public String getFormattedSize() { return Formatter.formatBytes(getSize()); }
 
-	/* ------------------------- Setters ------------------------------ */
-	
-	/**
-	 * @param string
-	 */
+	@Override
 	public void setAuthor(String username) { 
 		Identity identity = BaseSecurityManager.getInstance().findIdentityByName(username);
 		if (identity == null) {
@@ -660,14 +662,9 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		authorIdentKey = identity.getKey(); 
 	}
 
-	/**
-	 * @param string
-	 */
+	@Override
 	public void setComment(String string) { comment = string; }
 
-	/**
-	 * @see java.lang.Object#toString()
-	 */
 	@Override
 	public String toString() {
 		StringBuilder sb = new StringBuilder();
@@ -680,140 +677,142 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return sb.toString();
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getCity()
-	 */
+	@Override
 	public String getCity() {
 		return city;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getLanguage()
-	 */
+	@Override
 	public String getLanguage() {
 		return language;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getPages()
-	 */
+	@Override
 	public String getPages() {
 		return pages;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getPublishDate()
-	 */
+	@Override
 	public String[] getPublicationDate() {
 		return new String[] { pubYear, pubMonth };
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getPublisher()
-	 */
+	@Override
 	public String getPublisher() {
 		return publisher;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getCreator()
-	 */
+	@Override
 	public String getCreator() {
 		return creator;
 	}
 	
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getSource()
-	 */
+	@Override
 	public String getSource() {
 		return source;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getTitle()
-	 */
+	@Override
 	public String getTitle() {
 		return title;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getUrl()
-	 */
+	@Override
 	public String getUrl() {
 		return url;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setCity(java.lang.String)
-	 */
+	@Override
 	public void setCity(String city) {
 		this.city = city;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setLanguage(java.lang.String)
-	 */
+	@Override
 	public void setLanguage(String language) {
 		this.language = language;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setPages(java.lang.String)
-	 */
+	@Override
 	public void setPages(String pages) {
 		this.pages = pages;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setPublishDate(java.lang.String)
-	 */
+	@Override
 	public void setPublicationDate(String month, String year) {
 		this.pubMonth = month;
 		this.pubYear = year;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setPublisher(java.lang.String)
-	 */
+	@Override
 	public void setPublisher(String publisher) {
 		this.publisher = publisher;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setWriter(java.lang.String)
-	 */
 	public void setWriter(String writer) {
 		this.creator = writer;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setWriter(java.lang.String)
-	 */
+	@Override
 	public void setCreator(String creator) {
 		this.creator = creator;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setSource(java.lang.String)
-	 */
+	@Override
 	public void setSource(String source) {
 		this.source = source;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setTitle(java.lang.String)
-	 */
+	@Override
 	public void setTitle(String title) {
 		this.title = title;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#setUrl(java.lang.String)
-	 */
+	@Override
 	public void setUrl(String url) {
 		this.url = url;
 	}
+
+	@Override
+	public String getLicenseTypeKey() {
+		return licenseTypeKey;
+	}
+
+	@Override
+	public void setLicenseTypeKey(String key) {
+		this.licenseTypeKey = key;
+	}
+
+	@Override
+	public String getLicenseTypeName() {
+		return licenseTypeName;
+	}
+
+	@Override
+	public void setLicenseTypeName(String name) {
+		this.licenseTypeName = name;
+	}
+
+	@Override
+	public String getLicenseText() {
+		return licenseText;
+	}
+
+	@Override
+	public void setLicenseText(String text) {
+		this.licenseText = text;
+	}
+
+	@Override
+	public String getLicensor() {
+		return licensor;
+	}
+
+	@Override
+	public void setLicensor(String licensor) {
+		this.licensor = licensor;
+	}
 	
+	@Override
 	public boolean isThumbnailAvailable() {
 		if(isDirectory()) return false;
 		if(originFile.isHidden()) return false;
@@ -824,6 +823,7 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return false;
 	}
 	
+	@Override
 	public VFSLeaf getThumbnail(int maxWidth, int maxHeight, boolean fill) {
 		if(isDirectory()) return null;
 		Thumbnail thumbnailInfo =  getThumbnailInfo(maxWidth, maxHeight, fill);
@@ -922,16 +922,12 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		return "jpg";
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#increaseDownloadCount()
-	 */
+	@Override
 	public void increaseDownloadCount() {
 		this.downloadCount++;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getDownloadCount()
-	 */
+	@Override
 	public int getDownloadCount() {
 		return downloadCount;
 	}
@@ -1025,6 +1021,14 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 			this.creator = current.toString();
 		} else if (qName.equals("url")) {
 			this.url = current.toString();
+		} else if (qName.equals("licenseTypeKey")) {
+			this.licenseTypeKey = current.toString();
+		} else if (qName.equals("licenseTypeName")) {
+			this.licenseTypeName = current.toString();
+		} else if (qName.equals("licenseText")) {
+			this.licenseText = current.toString();
+		} else if (qName.equals("licensor")) {
+			this.licensor = current.toString();
 		} else if (qName.equals("thumbnail")) {
 			String finalName = current.toString();
 			File thumbnailFile = new File(metaFile.getParentFile(), finalName);
@@ -1033,9 +1037,6 @@ public class MetaInfoFileImpl extends DefaultHandler implements MetaInfo {
 		current = null;
 	}
 
-	/**
-	 * @see org.olat.core.commons.modules.bc.meta.MetaInfo#getIconCssClass()
-	 */
 	@Override
 	public String getIconCssClass() {
 		String cssClass;
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java
index 4547083bc51..e3d7fc03f9f 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java
@@ -29,11 +29,19 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.modules.bc.FolderLicenseHandler;
+import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.LicenseModule;
+import org.olat.core.commons.services.license.LicenseService;
+import org.olat.core.commons.services.license.LicenseType;
+import org.olat.core.commons.services.license.ui.LicenseSelectionConfig;
+import org.olat.core.commons.services.license.ui.LicenseUIFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
+import org.olat.core.gui.components.form.flexible.elements.TextAreaElement;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.Form;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -72,6 +80,9 @@ public class MetaInfoFormController extends FormBasicController {
 	private FormLink moreMetaDataLink;
 	private String initialFilename;
 	private TextElement filename, title, publisher, creator, sourceEl, city, pages, language, url, comment, publicationMonth, publicationYear;
+	private SingleSelection licenseEl;
+	private TextElement licensorEl;
+	private TextAreaElement licenseFreetextEl;
 	private SingleSelection locked;
 	// Fields needed for upload dialog
 	private boolean isSubform;
@@ -86,6 +97,12 @@ public class MetaInfoFormController extends FormBasicController {
 	private VFSLockManager vfsLockManager;
 	@Autowired
 	private MetaInfoFactory metaInfoFactory;
+	@Autowired
+	private LicenseModule licenseModule;
+	@Autowired
+	private LicenseService licenseService;
+	@Autowired
+	private FolderLicenseHandler licenseHandler;
 
 	/**
 	 * Use this controller for editing meta data of an existing file.
@@ -134,36 +151,22 @@ public class MetaInfoFormController extends FormBasicController {
 		initForm(ureq);
 	}
 	
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#doDispose()
-	 */
 	@Override
 	protected void doDispose() {
 	// nothing so far
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formOK(org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void formOK(UserRequest ureq) {
 		// done, parent controller takes care of saving metadata...
 		fireEvent(ureq, Event.DONE_EVENT);
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formCancelled(org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void formCancelled(UserRequest ureq) {
 		fireEvent(ureq, Event.CANCELLED_EVENT);
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formInnerEvent(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.form.flexible.FormItem,
-	 *      org.olat.core.gui.components.form.flexible.impl.FormEvent)
-	 */
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if (source == moreMetaDataLink && event.wasTriggerdBy(FormEvent.ONCLICK)) {
@@ -172,13 +175,11 @@ public class MetaInfoFormController extends FormBasicController {
 			setMetaFieldsVisible(true);
 			flc.setDirty(true);
 			moreMetaDataLink.setVisible(false);
+		} else if (source == licenseEl) {
+			updateLicenseUI();
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm(org.olat.core.gui.components.form.flexible.FormItemContainer,
-	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		if(isSubform) {
@@ -247,6 +248,28 @@ public class MetaInfoFormController extends FormBasicController {
 		// url/link
 		String urlVal = (meta != null ? meta.getUrl() : null);
 		url = uifactory.addTextElement("url", "mf.url", -1, urlVal, formLayout);
+		
+		if (licenseModule.isEnabled(licenseHandler)) {
+			MetaInfoFactory metaInfoFactory = CoreSpringFactory.getImpl(MetaInfoFactory.class);
+			License license = metaInfoFactory.getOrCreateLicense(meta, getIdentity());
+
+			LicenseSelectionConfig licenseSelectionConfig = LicenseUIFactory
+					.createLicenseSelectionConfig(licenseHandler, license.getLicenseType());
+			licenseEl = uifactory.addDropdownSingleselect("mf.license", formLayout,
+					licenseSelectionConfig.getLicenseTypeKeys(),
+					licenseSelectionConfig.getLicenseTypeValues(getLocale()));
+			licenseEl.setMandatory(licenseSelectionConfig.isLicenseMandatory());
+			if (licenseSelectionConfig.getSelectionLicenseTypeKey() != null) {
+				licenseEl.select(licenseSelectionConfig.getSelectionLicenseTypeKey(), true);
+			}
+			licenseEl.addActionListener(FormEvent.ONCHANGE);
+			
+			licensorEl = uifactory.addTextElement("mf.licensor", 1000, license.getLicensor(), formLayout);
+
+			String freetext = licenseService.isFreetext(license.getLicenseType()) ? license.getFreetext() : "";
+			licenseFreetextEl = uifactory.addTextAreaElement("mf.freetext", 4, 72, freetext, formLayout);
+			updateLicenseUI();
+		}
 
 		/* static fields */
 		String sizeText, typeText;
@@ -259,7 +282,7 @@ public class MetaInfoFormController extends FormBasicController {
 		}
 
 		// Targets to hide
-		metaFields = new HashSet<FormItem>();
+		metaFields = new HashSet<>();
 		metaFields.add(creator);
 		metaFields.add(publisher);
 		metaFields.add(sourceEl);
@@ -268,6 +291,15 @@ public class MetaInfoFormController extends FormBasicController {
 		metaFields.add(pages);
 		metaFields.add(language);
 		metaFields.add(url);
+		if (licenseEl != null) {
+			metaFields.add(licenseEl);
+		}
+		if (licensorEl != null) {
+			metaFields.add(licensorEl);
+		}
+		if (licenseFreetextEl != null) {
+			metaFields.add(licenseFreetextEl);
+		}
 
 		if (!hasMetadata(meta)) {
 			moreMetaDataLink = uifactory.addFormLink("mf.more.meta.link", formLayout, Link.LINK_CUSTOM_CSS);
@@ -358,6 +390,23 @@ public class MetaInfoFormController extends FormBasicController {
 		}
 	}
 
+	private void updateLicenseUI() {
+		boolean licenseSelected = false;
+		boolean freetextSelected = false;
+		if (licenseEl != null && licenseEl.isOneSelected()) {
+			String selectedKey = licenseEl.getSelectedKey();
+			LicenseType licenseType = licenseService.loadLicenseTypeByKey(selectedKey);
+			licenseSelected = !licenseService.isNoLicense(licenseType);
+			freetextSelected = licenseService.isFreetext(licenseType);
+		}
+		if (licensorEl != null) {
+			licensorEl.setVisible(licenseSelected);
+		}
+		if (licenseFreetextEl != null) {
+			licenseFreetextEl.setVisible(freetextSelected);
+		}
+	}
+	
 	/**
 	 * @return True if one or more metadata fields are non-emtpy.
 	 */
@@ -366,7 +415,9 @@ public class MetaInfoFormController extends FormBasicController {
 				|| StringHelper.containsNonWhitespace(meta.getPublisher()) || StringHelper.containsNonWhitespace(meta.getSource())
 				|| StringHelper.containsNonWhitespace(meta.getCity()) || StringHelper.containsNonWhitespace(meta.getPublicationDate()[0])
 				|| StringHelper.containsNonWhitespace(meta.getPublicationDate()[1]) || StringHelper.containsNonWhitespace(meta.getPages())
-				|| StringHelper.containsNonWhitespace(meta.getLanguage()) || StringHelper.containsNonWhitespace(meta.getUrl());
+				|| StringHelper.containsNonWhitespace(meta.getLanguage()) || StringHelper.containsNonWhitespace(meta.getUrl())
+				|| StringHelper.containsNonWhitespace(meta.getLicenseTypeKey()) || StringHelper.containsNonWhitespace(meta.getLicenseTypeName())
+				|| StringHelper.containsNonWhitespace(meta.getLicenseText()) || StringHelper.containsNonWhitespace(meta.getLicensor());
 				}
 		return false;
 	}
@@ -380,6 +431,9 @@ public class MetaInfoFormController extends FormBasicController {
 		for (FormItem formItem : metaFields) {
 			formItem.setVisible(visible);
 		}
+		if (visible) {
+			updateLicenseUI();
+		}
 	}
 
 	/**
@@ -418,8 +472,37 @@ public class MetaInfoFormController extends FormBasicController {
 		meta.setSource(sourceEl.getValue());
 		meta.setUrl(url.getValue());
 		meta.setPages(pages.getValue());
+		License license = getLicenseFromFormItems();
+		meta.setLicenseTypeKey(license.getLicenseType() != null? String.valueOf(license.getLicenseType().getKey()): "");
+		meta.setLicenseTypeName(license.getLicenseType() != null? license.getLicenseType().getName(): "");
+		meta.setLicensor(license.getLicensor());
+		meta.setLicenseText(LicenseUIFactory.getLicenseText(license));
 		return meta;
 	}
+	
+	private License getLicenseFromFormItems() {
+		License license = licenseService.createLicense(null);
+		String licensor = "";
+		String freetext = "";
+		if (licenseModule.isEnabled(licenseHandler)) {
+			if (licenseEl != null && licenseEl.isOneSelected()) {
+				String licenseTypeKey = licenseEl.getSelectedKey();
+				LicenseType licneseType = licenseService.loadLicenseTypeByKey(licenseTypeKey);
+				license.setLicenseType(licneseType);
+			}
+			if (licensorEl != null && licensorEl.isVisible() && StringHelper.containsNonWhitespace(licensorEl.getValue())) {
+				licensor = licensorEl.getValue();
+			}
+			if (licenseFreetextEl != null && licenseFreetextEl.isVisible() && StringHelper.containsNonWhitespace(licenseFreetextEl.getValue())) {
+				freetext = licenseFreetextEl.getValue();
+			}
+			licensorEl.setValue(license.getLicensor());
+			licenseFreetextEl.setValue(license.getFreetext());
+		}
+		license.setLicensor(licensor);
+		license.setFreetext(freetext);
+		return license;
+	}
 
 	/**
 	 * @return The updated MeatInfo object
@@ -446,9 +529,6 @@ public class MetaInfoFormController extends FormBasicController {
 		return getMetaInfo(meta);
 	}
 
-	/**
-	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#validateFormLogic(org.olat.core.gui.UserRequest)
-	 */
 	@Override
 	protected boolean validateFormLogic(UserRequest ureq) {
 		boolean valid = true;
@@ -493,8 +573,24 @@ public class MetaInfoFormController extends FormBasicController {
 			}			
 		}
 		
+		licenseEl.clearError();
+		if (licenseEl != null && licenseEl.isMandatory() && isLicenseTypeNotSelected()) {
+			licenseEl.setErrorKey("form.legende.mandatory", null);
+			valid &= false;
+		}
+		
 		return valid;
 	}
+	
+	private boolean isLicenseTypeNotSelected() {
+		boolean isNoLicenseSelected = false;
+		if (licenseEl != null && licenseEl.isOneSelected()) {
+			String selectedKey = licenseEl.getSelectedKey();
+			LicenseType selectedLicenseType = licenseService.loadLicenseTypeByKey(selectedKey);
+			isNoLicenseSelected = licenseService.isNoLicense(selectedLicenseType);
+		}
+		return isNoLicenseSelected;
+	}
 
 	/**
 	 * Get the form item representing this form
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_de.properties
index c3f25a80628..0378d3ea66e 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_de.properties
@@ -16,9 +16,12 @@ mf.error.filename.invalidchars=Der Name des Objektes enth\u00E4lt ung\u00FCltige
 mf.file=Datei
 mf.filename=Dateiname
 mf.filename.warning=<i class\="o_icon o_icon_warn"> </i> Der Dateiname enthielt unzul\u00E4ssige Zeichen. Diese wurden entfernt.
+mf.freetext=Lizenztext
 mf.header=Metadaten Datei/Ordner
 mf.language=Sprache
 mf.lastModified=Datum letzte \u00C4nderung
+mf.license=Lizenz
+mf.licensor=Lizenzgeber
 mf.locked=Gesperrt
 mf.locked.description={0} am {1}
 mf.lockedBy=Gesperrt von
diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_en.properties
index f2efe0a5b29..7dc14d61612 100644
--- a/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/modules/bc/meta/_i18n/LocalStrings_en.properties
@@ -16,9 +16,12 @@ mf.error.filename.invalidchars=The object's name contains invalid characters.
 mf.file=File
 mf.filename=File name
 mf.filename.warning=<i class\="o_icon o_icon_warn"> </i> This file name contained invalid characters which were removed.
+mf.freetext=License text
 mf.header=Metadata file/folder
 mf.language=Language
 mf.lastModified=Last modified\:
+mf.license=License
+mf.licensor=Licensor
 mf.locked=Locked
 mf.locked.description={0} on {1}
 mf.lockedBy=Locked by
diff --git a/src/main/java/org/olat/core/commons/services/license/License.java b/src/main/java/org/olat/core/commons/services/license/License.java
index 633eb598813..2a45bc5cbb6 100644
--- a/src/main/java/org/olat/core/commons/services/license/License.java
+++ b/src/main/java/org/olat/core/commons/services/license/License.java
@@ -19,20 +19,13 @@
  */
 package org.olat.core.commons.services.license;
 
-import org.olat.core.id.CreateInfo;
-import org.olat.core.id.ModifiedInfo;
-
 /**
  * 
  * Initial date: 21.02.2018<br>
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-public interface License extends CreateInfo, ModifiedInfo {
-	
-	public String getResName();
-
-	public Long getResId();
+public interface License {
 
 	public String getLicensor();
 	
diff --git a/src/main/java/org/olat/core/commons/services/license/LicenseService.java b/src/main/java/org/olat/core/commons/services/license/LicenseService.java
index e7bd7aabcd5..1d1d1ac2a25 100644
--- a/src/main/java/org/olat/core/commons/services/license/LicenseService.java
+++ b/src/main/java/org/olat/core/commons/services/license/LicenseService.java
@@ -40,16 +40,33 @@ import org.olat.resource.OLATResource;
  */
 public interface LicenseService {
 
+	/**
+	 * Create a new license.
+	 * @param licenseType TODO
+	 *
+	 * @return
+	 */
+	public License createLicense(LicenseType licenseType);
+	
+	/**
+	 * Create a new license with the default license type.
+	 *
+	 * @param licenseHandler
+	 * @param identity
+	 */
+	public License createDefaultLicense(LicenseHandler licenseHandler, Identity identity);
+	
 	/**
 	 * Create a new license with the default license type. This method should be
-	 * used if a license is created for a new object e.g. a new learning resource.
+	 * used if a license is created for a new resourceable object e.g. a new
+	 * learning resource.
 	 *
 	 * @param ores
 	 * @param handler
 	 * @param licensor
 	 * @return
 	 */
-	public License createDefaultLicense(OLATResourceable ores, LicenseHandler handler, Identity licensor);
+	public ResourceLicense createDefaultLicense(OLATResourceable ores, LicenseHandler handler, Identity licensor);
 	
 	/**
 	 * Load the license of a resource. If no license was found, a new license with
@@ -61,7 +78,7 @@ public interface LicenseService {
 	 * @param ores
 	 * @return
 	 */
-	public License loadOrCreateLicense(OLATResourceable ores);
+	public ResourceLicense loadOrCreateLicense(OLATResourceable ores);
 
 	/**
 	 * Load the licenses for the resources.
@@ -69,7 +86,7 @@ public interface LicenseService {
 	 * @param resources
 	 * @return
 	 */
-	public List<License> loadLicenses(Collection<OLATResourceable> resources);
+	public List<ResourceLicense> loadLicenses(Collection<OLATResourceable> resources);
 
 	/**
 	 * Save the license.
@@ -77,7 +94,7 @@ public interface LicenseService {
 	 * @param license
 	 * @return
 	 */
-	public License update(License license);
+	public ResourceLicense update(ResourceLicense license);
 
 	/**
 	 * Check whether a license type with that name exists.
@@ -106,11 +123,20 @@ public interface LicenseService {
 	/**
 	 * Load a license type by its key.
 	 * 
-	 * @param licenseTypeKey the key of the license type as a String.
+	 * @param licenseTypeKey the key of the license type as a String
 	 * @return the license type or null if no license type was found for the key
 	 */
 	public LicenseType loadLicenseTypeByKey(String licenseTypeKey);
 
+
+	/**
+	 * Load a license type by its name
+	 *
+	 * @param name the name of the license type
+	 * @return the license type or null if no license type was found for the name
+	 */
+	public LicenseType loadLicenseTypeByName(String name);
+
 	/**
 	 * Load all license types. This method is primarily intended for the
 	 * administration of license types. Regular clients of the license service
diff --git a/src/main/java/org/olat/core/commons/services/license/ResourceLicense.java b/src/main/java/org/olat/core/commons/services/license/ResourceLicense.java
new file mode 100644
index 00000000000..6d8e0d6352c
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/services/license/ResourceLicense.java
@@ -0,0 +1,38 @@
+/**
+ * <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.services.license;
+
+import org.olat.core.id.CreateInfo;
+import org.olat.core.id.ModifiedInfo;
+
+/**
+ * License for a OLATResource. A ResourceLicense can be stored in the database.
+ * 
+ * Initial date: 21.02.2018<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public interface ResourceLicense extends CreateInfo, ModifiedInfo, License {
+	
+	public String getResName();
+
+	public Long getResId();
+	
+}
diff --git a/src/main/java/org/olat/core/commons/services/license/manager/LicenseServiceImpl.java b/src/main/java/org/olat/core/commons/services/license/manager/LicenseServiceImpl.java
index 3ee7672c9e0..f8a167acabf 100644
--- a/src/main/java/org/olat/core/commons/services/license/manager/LicenseServiceImpl.java
+++ b/src/main/java/org/olat/core/commons/services/license/manager/LicenseServiceImpl.java
@@ -27,6 +27,8 @@ import org.olat.core.commons.services.license.LicenseHandler;
 import org.olat.core.commons.services.license.LicenseModule;
 import org.olat.core.commons.services.license.LicenseService;
 import org.olat.core.commons.services.license.LicenseType;
+import org.olat.core.commons.services.license.ResourceLicense;
+import org.olat.core.commons.services.license.model.LicenseImpl;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,7 +47,7 @@ class LicenseServiceImpl implements LicenseService {
 	@Autowired
 	private LicenseModule licenseModule;
 	@Autowired
-	private LicenseDAO licenseDao;
+	private ResourceLicenseDAO licenseDao;
 	@Autowired
 	private LicenseTypeDAO licenseTypeDao;
 	@Autowired
@@ -54,16 +56,42 @@ class LicenseServiceImpl implements LicenseService {
 	private LicensorFactory licensorFactory;
 
 	@Override
-	public License createDefaultLicense(OLATResourceable ores, LicenseHandler handler, Identity licensor) {
-		String defaultLicenseTypeKey = licenseModule.getDefaultLicenseTypeKey(handler);
-		LicenseType defautlLicenseType = loadLicenseTypeByKey(defaultLicenseTypeKey);
+	public License createLicense(LicenseType licenseType) {
+		License license = new LicenseImpl();
+		license.setLicenseType(licenseType);
+		return license; 
+		
+	}
+
+	@Override
+	public License createDefaultLicense(LicenseHandler handler, Identity licensor) {
+		LicenseType defautlLicenseType = getDefaultLicenseType(handler);
+		String licensorName = licensorFactory.create(handler, licensor);
+		License license = new LicenseImpl();
+		license.setLicenseType(defautlLicenseType);
+		license.setLicensor(licensorName);
+		return license;
+	}
+	
+	@Override
+	public ResourceLicense createDefaultLicense(OLATResourceable ores, LicenseHandler handler, Identity licensor) {
+		LicenseType defautlLicenseType = getDefaultLicenseType(handler);
 		String licensorName = licensorFactory.create(handler, licensor);
 		return licenseDao.createAndPersist(ores, defautlLicenseType, licensorName);
 	}
+
+	private LicenseType getDefaultLicenseType(LicenseHandler handler) {
+		String defaultLicenseTypeKey = licenseModule.getDefaultLicenseTypeKey(handler);
+		LicenseType defautlLicenseType = loadLicenseTypeByKey(defaultLicenseTypeKey);
+		if (defautlLicenseType == null) {
+			defautlLicenseType = licenseTypeDao.loadNoLicenseType();
+		}
+		return defautlLicenseType;
+	}
 	
 	@Override
-	public License loadOrCreateLicense(OLATResourceable ores) {
-		License license = licenseDao.loadByResource(ores);
+	public ResourceLicense loadOrCreateLicense(OLATResourceable ores) {
+		ResourceLicense license = licenseDao.loadByResource(ores);
 		if (license == null) {
 			LicenseType licenseType = licenseTypeDao.loadNoLicenseType();
 			license = licenseDao.createAndPersist(ores, licenseType);
@@ -72,12 +100,12 @@ class LicenseServiceImpl implements LicenseService {
 	}
 
 	@Override
-	public License update(License license) {
+	public ResourceLicense update(ResourceLicense license) {
 		return licenseDao.save(license);
 	}
 
 	@Override
-	public List<License> loadLicenses(Collection<OLATResourceable> resources) {
+	public List<ResourceLicense> loadLicenses(Collection<OLATResourceable> resources) {
 		return licenseDao.loadLicenses(resources);
 	}
 
@@ -106,6 +134,11 @@ class LicenseServiceImpl implements LicenseService {
 		}
 		return licenseTypeDao.loadLicenseTypeByKey(key);
 	}
+	
+	@Override
+	public LicenseType loadLicenseTypeByName(String name) {
+		return licenseTypeDao.loadLicenseTypeByName(name);
+	}
 
 	@Override
 	public List<LicenseType> loadLicenseTypes() {
diff --git a/src/main/java/org/olat/core/commons/services/license/manager/LicenseTypeDAO.java b/src/main/java/org/olat/core/commons/services/license/manager/LicenseTypeDAO.java
index 1f88a984639..21f2b95c2d2 100644
--- a/src/main/java/org/olat/core/commons/services/license/manager/LicenseTypeDAO.java
+++ b/src/main/java/org/olat/core/commons/services/license/manager/LicenseTypeDAO.java
@@ -26,6 +26,7 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.license.LicenseHandler;
 import org.olat.core.commons.services.license.LicenseType;
 import org.olat.core.commons.services.license.model.LicenseTypeImpl;
+import org.olat.core.util.StringHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -109,6 +110,18 @@ class LicenseTypeDAO {
 		return licenseTypes == null || licenseTypes.isEmpty() ? null : licenseTypes.get(0);
 	}
 
+	LicenseType loadLicenseTypeByName(String name) {
+		if (!StringHelper.containsNonWhitespace(name)) return null;
+
+		String query = "select licensetype from licensetype licensetype where licensetype.name=:name";
+		List<LicenseType> licenseTypes = dbInstance.getCurrentEntityManager()
+				.createQuery(query, LicenseType.class)
+				.setParameter("name", name)
+				.getResultList();
+		return licenseTypes == null || licenseTypes.isEmpty() ? null : licenseTypes.get(0);
+	}
+	
+
 	List<LicenseType> loadLicenseTypes() {
 		String query = "select licensetype from licensetype licensetype";
 		return dbInstance.getCurrentEntityManager()
@@ -144,5 +157,5 @@ class LicenseTypeDAO {
 		
 		return number != null && number > 0;
 	}
-	
+
 }
diff --git a/src/main/java/org/olat/core/commons/services/license/manager/LicenseDAO.java b/src/main/java/org/olat/core/commons/services/license/manager/ResourceLicenseDAO.java
similarity index 80%
rename from src/main/java/org/olat/core/commons/services/license/manager/LicenseDAO.java
rename to src/main/java/org/olat/core/commons/services/license/manager/ResourceLicenseDAO.java
index 800167c88dd..2a0ccf2dc6b 100644
--- a/src/main/java/org/olat/core/commons/services/license/manager/LicenseDAO.java
+++ b/src/main/java/org/olat/core/commons/services/license/manager/ResourceLicenseDAO.java
@@ -27,9 +27,9 @@ import java.util.List;
 import java.util.Set;
 
 import org.olat.core.commons.persistence.DB;
-import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.ResourceLicense;
 import org.olat.core.commons.services.license.LicenseType;
-import org.olat.core.commons.services.license.model.LicenseImpl;
+import org.olat.core.commons.services.license.model.ResourceLicenseImpl;
 import org.olat.core.id.OLATResourceable;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -41,17 +41,17 @@ import org.springframework.stereotype.Service;
  *
  */
 @Service
-class LicenseDAO {
+class ResourceLicenseDAO {
 	
 	@Autowired
 	private DB dbInstance;
 
-	License createAndPersist(OLATResourceable ores, LicenseType licenseType) {
+	ResourceLicense createAndPersist(OLATResourceable ores, LicenseType licenseType) {
 		return createAndPersist(ores, licenseType, null);
 	}
 
-	License createAndPersist(OLATResourceable ores, LicenseType licenseType, String licensor) {
-		LicenseImpl license = new LicenseImpl();
+	ResourceLicense createAndPersist(OLATResourceable ores, LicenseType licenseType, String licensor) {
+		ResourceLicenseImpl license = new ResourceLicenseImpl();
 		Date now = new Date();
 		license.setCreationDate(now);
 		license.setLastModified(now);
@@ -62,13 +62,13 @@ class LicenseDAO {
 		return license;
 	}
 
-	License save(License license) {
+	ResourceLicense save(ResourceLicense license) {
 		license.setLastModified(new Date());
 		license = dbInstance.getCurrentEntityManager().merge(license);
 		return license;
 	}
 
-	License loadByResource(OLATResourceable ores) {
+	ResourceLicense loadByResource(OLATResourceable ores) {
 		if (ores == null) return null;
 		
 		String query = new StringBuilder(256)
@@ -77,15 +77,15 @@ class LicenseDAO {
 				.append("        inner join fetch license.licenseType as licenseType")
 				.append("  where license.resName=:resName and license.resId=:resId")
 				.toString();
-		List<License> licenses = dbInstance.getCurrentEntityManager()
-				.createQuery(query, License.class)
+		List<ResourceLicense> licenses = dbInstance.getCurrentEntityManager()
+				.createQuery(query, ResourceLicense.class)
 				.setParameter("resName", ores.getResourceableTypeName())
 				.setParameter("resId", ores.getResourceableId())
 				.getResultList();
 		return licenses == null || licenses.isEmpty() ? null : licenses.get(0);
 	}
 
-	List<License> loadLicenses(Collection<OLATResourceable> resources) {
+	List<ResourceLicense> loadLicenses(Collection<OLATResourceable> resources) {
 		if (resources == null || resources.isEmpty()) return new ArrayList<>();
 		
 		Set<String> resNames = new HashSet<>();
@@ -103,7 +103,7 @@ class LicenseDAO {
 				.append("    and license.resId in (:resIds)")
 				.toString();
 		return dbInstance.getCurrentEntityManager()
-				.createQuery(query, License.class)
+				.createQuery(query, ResourceLicense.class)
 				.setParameter("resNames", resNames)
 				.setParameter("resIds", resIds)
 				.getResultList();
diff --git a/src/main/java/org/olat/core/commons/services/license/model/LicenseImpl.java b/src/main/java/org/olat/core/commons/services/license/model/LicenseImpl.java
index 4a18c4b4cf2..acad760c614 100644
--- a/src/main/java/org/olat/core/commons/services/license/model/LicenseImpl.java
+++ b/src/main/java/org/olat/core/commons/services/license/model/LicenseImpl.java
@@ -19,158 +19,49 @@
  */
 package org.olat.core.commons.services.license.model;
 
-import java.util.Date;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import javax.persistence.Temporal;
-import javax.persistence.TemporalType;
-
 import org.olat.core.commons.services.license.License;
 import org.olat.core.commons.services.license.LicenseType;
-import org.olat.core.id.OLATResourceable;
-import org.olat.core.id.Persistable;
 
 /**
  * 
- * Initial date: 22.02.2018<br>
+ * Initial date: 02.03.2018<br>
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-@Entity(name="license")
-@Table(name="o_lic_license")
-public class LicenseImpl implements License, Persistable {
-
-	private static final long serialVersionUID = -2044258667835611801L;
-	
-	@Id
-	@GeneratedValue(strategy = GenerationType.IDENTITY)
-	@Column(name="id", nullable=false, unique=true, insertable=true, updatable=false)
-	private Long key;
+public class LicenseImpl implements License {
 	
-	@Temporal(TemporalType.TIMESTAMP)
-	@Column(name="creationdate", nullable=false, insertable=true, updatable=false)
-	private Date creationDate;
-	@Temporal(TemporalType.TIMESTAMP)
-	@Column(name="lastmodified", nullable=false, insertable=true, updatable=true)
-	private Date lastModified;
-	
-	@Column(name="l_resname", nullable=false, insertable=true, updatable=false)
-	private String resName;
-	@Column(name="l_resid", nullable=false, insertable=true, updatable=false)
-	private Long resId;
-	@Column(name="l_licensor", nullable=true, insertable=true, updatable=true)
+	private LicenseType licenseType;
 	private String licensor;
-	@Column(name="l_freetext", nullable=true, insertable=true, updatable=true)
 	private String freetext;
 	
-	@ManyToOne(targetEntity=LicenseTypeImpl.class, optional=false)
-	@JoinColumn(name="fk_license_type_id", nullable=false, insertable=true, updatable=true)
-	private LicenseType licenseType;
-
-	@Override
-	public Long getKey() {
-		return key;
-	};
-
-	@Override
-	public Date getCreationDate() {
-		return creationDate;
-	}
-
-	public void setCreationDate(Date creationDate) {
-		this.creationDate = creationDate;
-	}
-
-	@Override
-	public Date getLastModified() {
-		return lastModified;
-	}
-
 	@Override
-	public void setLastModified(Date lastModified) {
-		this.lastModified = lastModified;
+	public LicenseType getLicenseType() {
+		return licenseType;
 	}
 	
 	@Override
-	public String getResName() {
-		return resName;
-	}
-
-	@Override
-	public Long getResId() {
-		return resId;
-	}
-
-	public void setOLATResourceable(OLATResourceable ores) {
-		this.resName = ores.getResourceableTypeName();
-		this.resId = ores.getResourceableId();
+	public void setLicenseType(LicenseType licenseType) {
+		this.licenseType = licenseType;
 	}
-
+	
 	@Override
 	public String getLicensor() {
 		return licensor;
 	}
-
+	
 	@Override
 	public void setLicensor(String licensor) {
 		this.licensor = licensor;
 	}
-
+	
 	@Override
 	public String getFreetext() {
 		return freetext;
 	}
-
+	
 	@Override
 	public void setFreetext(String freetext) {
 		this.freetext = freetext;
 	}
-
-	@Override
-	public LicenseType getLicenseType() {
-		return licenseType;
-	}
-
-	@Override
-	public void setLicenseType(LicenseType licenseType) {
-		this.licenseType = licenseType;
-	}
-
-	@Override
-	public boolean equalsByPersistableKey(Persistable persistable) {
-		return equals(persistable);
-	}
-
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((key == null) ? 0 : key.hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		LicenseImpl other = (LicenseImpl) obj;
-		if (key == null) {
-			if (other.key != null)
-				return false;
-		} else if (!key.equals(other.key))
-			return false;
-		return true;
-	}
-
+	
 }
diff --git a/src/main/java/org/olat/core/commons/services/license/model/ResourceLicenseImpl.java b/src/main/java/org/olat/core/commons/services/license/model/ResourceLicenseImpl.java
new file mode 100644
index 00000000000..ecfd605dc14
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/services/license/model/ResourceLicenseImpl.java
@@ -0,0 +1,176 @@
+/**
+ * <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.services.license.model;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.olat.core.commons.services.license.ResourceLicense;
+import org.olat.core.commons.services.license.LicenseType;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Persistable;
+
+/**
+ * 
+ * Initial date: 22.02.2018<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+@Entity(name="license")
+@Table(name="o_lic_license")
+public class ResourceLicenseImpl implements ResourceLicense, Persistable {
+
+	private static final long serialVersionUID = -2044258667835611801L;
+	
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	@Column(name="id", nullable=false, unique=true, insertable=true, updatable=false)
+	private Long key;
+	
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name="creationdate", nullable=false, insertable=true, updatable=false)
+	private Date creationDate;
+	@Temporal(TemporalType.TIMESTAMP)
+	@Column(name="lastmodified", nullable=false, insertable=true, updatable=true)
+	private Date lastModified;
+	
+	@Column(name="l_resname", nullable=false, insertable=true, updatable=false)
+	private String resName;
+	@Column(name="l_resid", nullable=false, insertable=true, updatable=false)
+	private Long resId;
+	@Column(name="l_licensor", nullable=true, insertable=true, updatable=true)
+	private String licensor;
+	@Column(name="l_freetext", nullable=true, insertable=true, updatable=true)
+	private String freetext;
+	
+	@ManyToOne(targetEntity=LicenseTypeImpl.class, optional=false)
+	@JoinColumn(name="fk_license_type_id", nullable=false, insertable=true, updatable=true)
+	private LicenseType licenseType;
+
+	@Override
+	public Long getKey() {
+		return key;
+	};
+
+	@Override
+	public Date getCreationDate() {
+		return creationDate;
+	}
+
+	public void setCreationDate(Date creationDate) {
+		this.creationDate = creationDate;
+	}
+
+	@Override
+	public Date getLastModified() {
+		return lastModified;
+	}
+
+	@Override
+	public void setLastModified(Date lastModified) {
+		this.lastModified = lastModified;
+	}
+	
+	@Override
+	public String getResName() {
+		return resName;
+	}
+
+	@Override
+	public Long getResId() {
+		return resId;
+	}
+
+	public void setOLATResourceable(OLATResourceable ores) {
+		this.resName = ores.getResourceableTypeName();
+		this.resId = ores.getResourceableId();
+	}
+
+	@Override
+	public String getLicensor() {
+		return licensor;
+	}
+
+	@Override
+	public void setLicensor(String licensor) {
+		this.licensor = licensor;
+	}
+
+	@Override
+	public String getFreetext() {
+		return freetext;
+	}
+
+	@Override
+	public void setFreetext(String freetext) {
+		this.freetext = freetext;
+	}
+
+	@Override
+	public LicenseType getLicenseType() {
+		return licenseType;
+	}
+
+	@Override
+	public void setLicenseType(LicenseType licenseType) {
+		this.licenseType = licenseType;
+	}
+
+	@Override
+	public boolean equalsByPersistableKey(Persistable persistable) {
+		return equals(persistable);
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((key == null) ? 0 : key.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		ResourceLicenseImpl other = (ResourceLicenseImpl) obj;
+		if (key == null) {
+			if (other.key != null)
+				return false;
+		} else if (!key.equals(other.key))
+			return false;
+		return true;
+	}
+
+}
diff --git a/src/main/java/org/olat/core/commons/services/license/ui/LicenseQuickviewController.java b/src/main/java/org/olat/core/commons/services/license/ui/LicenseQuickviewController.java
deleted file mode 100644
index 2785db08d84..00000000000
--- a/src/main/java/org/olat/core/commons/services/license/ui/LicenseQuickviewController.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * <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.services.license.ui;
-
-import org.olat.core.commons.services.license.License;
-import org.olat.core.commons.services.license.LicenseType;
-import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.form.flexible.FormItemContainer;
-import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.WindowControl;
-import org.olat.core.util.StringHelper;
-
-/**
- * 
- * Initial date: 27.02.2018<br>
- * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
- *
- */
-public class LicenseQuickviewController extends FormBasicController {
-
-	private final License license;
-	private final LicenseType licenseType;
-	
-	public LicenseQuickviewController(UserRequest ureq, WindowControl wControl, License license) {
-		super(ureq, wControl, LAYOUT_VERTICAL);
-		this.license = license;
-		this.licenseType = license.getLicenseType();
-		initForm(ureq);
-	}
-
-	@Override
-	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		String type = licenseType != null? LicenseUIFactory.translate(licenseType, getLocale()): "";
-		uifactory.addStaticTextElement("license.quickview.type", type, formLayout);
-
-		String licensor = StringHelper.containsNonWhitespace(license.getLicensor())? license.getLicensor(): "";
-		uifactory.addStaticTextElement("license.quickview.licensor", licensor, formLayout);
-		
-		uifactory.addStaticTextElement("license.quickview.text", LicenseUIFactory.getFormattedLicenseText(license),
-				formLayout);
-	}
-
-	@Override
-	protected void formOK(UserRequest ureq) {
-		//
-	}
-
-	@Override
-	protected void doDispose() {
-		//
-	}
-
-}
diff --git a/src/main/java/org/olat/core/commons/services/license/ui/LicenseRenderer.java b/src/main/java/org/olat/core/commons/services/license/ui/LicenseRenderer.java
index 9f3bd5bfb67..c71bd271774 100644
--- a/src/main/java/org/olat/core/commons/services/license/ui/LicenseRenderer.java
+++ b/src/main/java/org/olat/core/commons/services/license/ui/LicenseRenderer.java
@@ -21,7 +21,6 @@ package org.olat.core.commons.services.license.ui;
 
 import java.util.Locale;
 
-import org.apache.commons.lang.StringEscapeUtils;
 import org.olat.core.commons.services.license.License;
 import org.olat.core.commons.services.license.LicenseType;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer;
@@ -30,7 +29,8 @@ import org.olat.core.gui.render.Renderer;
 import org.olat.core.gui.render.StringOutput;
 import org.olat.core.gui.render.URLBuilder;
 import org.olat.core.gui.translator.Translator;
-import org.olat.core.util.StringHelper;
+import org.olat.core.util.CodeHelper;
+import org.olat.core.util.Util;
 
 /**
  * 
@@ -40,67 +40,56 @@ import org.olat.core.util.StringHelper;
  */
 public class LicenseRenderer implements FlexiCellRenderer {
 	
-	private final String idPrefix;
 	private final Locale locale;
+	private final Translator translator;
 	
 	public LicenseRenderer(Locale locale) {
-		this(locale, null);
-	}
-	
-	public LicenseRenderer(Locale locale, String idPrefix) {
 		this.locale = locale;
-		this.idPrefix = idPrefix;
+		translator = Util.createPackageTranslator(LicenseAdminConfigController.class, locale);
 	}
 	
 	@Override
 	public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, URLBuilder ubu, Translator translator) {
 		if (cellValue instanceof License) {
 			License license = (License) cellValue;
-			LicenseType licenseType = license.getLicenseType();
 			if (renderer == null) {
 				// render for export
-				if (licenseType != null) {
-					target.append(LicenseUIFactory.translate(licenseType, locale));
-				}
+				target.append(LicenseUIFactory.translate(license.getLicenseType(), locale));
 			} else {
-				target.append("<div");
-				target.append(" style='white-space: nowrap;'");
-				String hoverText = getHoverText(licenseType);
-				if (StringHelper.containsNonWhitespace(hoverText)) {
-					target.append(" title=\"");
-					target.append(StringEscapeUtils.escapeHtml(hoverText));
-				}
-				target.append("\">");
-				target.append("<i");
-				String id = getId(row);
-				if (StringHelper.containsNonWhitespace(id)) {
-					target.append(" id='").append(id).append("'");
-				}
-				target.append(" class='").append(getCssClass(licenseType)).append("'> </i>");
-				target.append("</div>");	
+				render(target, license);	
 			}
 		}
 	}
 
-	protected String getCssClass(LicenseType licenseType) {
-		if (licenseType != null) {
-			return "o_icon o_icon-lg " + LicenseUIFactory.getCssOrDefault(licenseType);
-		}
-		return null;
-	}
-	
-	private String getHoverText(LicenseType licenseType) {
-		if (licenseType != null) {
-			return LicenseUIFactory.translate(licenseType, locale);
-		}
-		return null;
+	public void render(StringOutput sb, License license) {
+		LicenseType licenseType = license.getLicenseType();
+		long id = CodeHelper.getRAMUniqueID();
+		
+		// license icon
+		sb.append("<a id='o_lic_").append(id).append("' href='javascript:;'><i class='o_icon o_icon-lg ");
+		sb.append(LicenseUIFactory.getCssOrDefault(licenseType));
+		sb.append("'></i></a>");
+		
+		// popup with license informations
+		sb.append("<div id='o_lic_pop_").append(id).append("' style='display:none;'><div>");
+		appendStaticcontrol(sb, "license.popup.type", LicenseUIFactory.translate(licenseType, locale));
+		appendStaticcontrol(sb, "license.popup.licensor", license.getLicensor());
+		appendStaticcontrol(sb, "license.popup.text", LicenseUIFactory.getFormattedLicenseText(license));
+		sb.append("</div>");
+		
+		// JavaScript to pup up the popup
+		sb.append("<script type='text/javascript'>")
+	      .append("/* <![CDATA[ */")
+		  .append("jQuery(function() {\n")
+		  .append("  o_popover('o_lic_").append(id).append("','o_lic_pop_").append(id).append("','top');\n")
+		  .append("});")
+		  .append("/* ]]> */")
+		  .append("</script>");
 	}
 
-	private String getId(int row) {
-		if (StringHelper.containsNonWhitespace(idPrefix)) {
-			return idPrefix + String.valueOf(row);
-		}
-		return null;
+	private void appendStaticcontrol(StringOutput sb, String i18n, String text) {
+		sb.append("<label class='control-label'>").append(translator.translate(i18n)) .append("</label>");
+		sb.append("<p class='form-control-static'>").append(text).append("</p>");
 	}
 
 }
diff --git a/src/main/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfig.java b/src/main/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfig.java
index 016efc26936..6d41e286c77 100644
--- a/src/main/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfig.java
+++ b/src/main/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfig.java
@@ -24,7 +24,6 @@ import java.util.List;
 import java.util.Locale;
 
 import org.olat.core.CoreSpringFactory;
-import org.olat.core.commons.services.license.License;
 import org.olat.core.commons.services.license.LicenseHandler;
 import org.olat.core.commons.services.license.LicenseService;
 import org.olat.core.commons.services.license.LicenseType;
@@ -49,14 +48,14 @@ public class LicenseSelectionConfig {
 	
 	private final LicenseService licenseService;
 
-	public LicenseSelectionConfig(LicenseHandler licenseHandler, License license) {
-		this(CoreSpringFactory.getImpl(LicenseService.class), licenseHandler, license);
+	public LicenseSelectionConfig(LicenseHandler licenseHandler, LicenseType actualLicenseType) {
+		this(CoreSpringFactory.getImpl(LicenseService.class), licenseHandler, actualLicenseType);
 	}
 
 	// Used for testing
-	LicenseSelectionConfig(LicenseService licenseService, LicenseHandler licenseHandler, License license) {
+	LicenseSelectionConfig(LicenseService licenseService, LicenseHandler licenseHandler, LicenseType actualLicenseType) {
 		this.licenseService = licenseService;
-		this.actualLicenseType = license.getLicenseType();
+		this.actualLicenseType = actualLicenseType;
 		init(licenseHandler);
 	}
 
diff --git a/src/main/java/org/olat/core/commons/services/license/ui/LicenseUIFactory.java b/src/main/java/org/olat/core/commons/services/license/ui/LicenseUIFactory.java
index ae1b97ca91a..53ad1e4a46f 100644
--- a/src/main/java/org/olat/core/commons/services/license/ui/LicenseUIFactory.java
+++ b/src/main/java/org/olat/core/commons/services/license/ui/LicenseUIFactory.java
@@ -45,8 +45,8 @@ public class LicenseUIFactory {
 		// should not be instantiated
 	}
 	
-	public static LicenseSelectionConfig createLicenseSelectionConfig(LicenseHandler handler, License license) {
-		return new LicenseSelectionConfig(handler, license);
+	public static LicenseSelectionConfig createLicenseSelectionConfig(LicenseHandler handler, LicenseType actualLicenseType) {
+		return new LicenseSelectionConfig(handler, actualLicenseType);
 	}
 	
 	public static String translate(LicenseType licenseType, Locale locale) {
diff --git a/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_de.properties
index 886751d32c0..0411b4e3a65 100644
--- a/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_de.properties
@@ -13,9 +13,9 @@ admin.title=Lizenzen
 edit.license.type=Lizenz bearbeiten
 error.is.default.license.type=Sie k\u00f6nnen diese Lizenz nicht deaktivieren, da diese Lizenz die iniziale Lizenz ist. \u00c4ndern Sie bitte zuerst die iniziale Lizenz.
 error.license.type.name.exists=Dieser Name existiert bereits. Der Name muss eindeutig sein.
-license.quickview.text=Lizenztext
-license.quickview.licensor=Lizenzgeber
-license.quickview.type=Lizenz
+license.popup.text=Lizenztext
+license.popup.licensor=Lizenzgeber
+license.popup.type=Lizenz
 license.type.css.class=CSS Klasse
 license.type.down=Runter
 license.type.text=Lizenztext
diff --git a/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_en.properties
index c214a2d3989..487530198ab 100644
--- a/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/services/license/ui/_i18n/LocalStrings_en.properties
@@ -13,9 +13,9 @@ admin.title=Licenses
 edit.license.type=Edit license
 error.is.default.license.type=You can not deactivate this license, because it is the initial license. Please previously change the initial license.
 error.license.type.name.exists=This name already exists. The name has to be unique.
-license.quickview.text=License text
-license.quickview.licensor=Licensor
-license.quickview.type=License
+license.popup.text=License text
+license.popup.licensor=Licensor
+license.popup.type=License
 license.type.css.class=CSS class
 license.type.down=Down
 license.type.text=License text
diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java
index 23d9cb55676..059fdc19547 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java
@@ -32,9 +32,7 @@ import org.olat.basesecurity.events.MultiIdentityChosenEvent;
 import org.olat.basesecurity.events.SingleIdentityChosenEvent;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.SortKey;
-import org.olat.core.commons.services.license.License;
 import org.olat.core.commons.services.license.LicenseModule;
-import org.olat.core.commons.services.license.ui.LicenseQuickviewController;
 import org.olat.core.commons.services.license.ui.LicenseRenderer;
 import org.olat.core.commons.services.mark.Mark;
 import org.olat.core.commons.services.mark.MarkManager;
@@ -137,8 +135,6 @@ public class AuthorListController extends FormBasicController implements Activat
 	private AuthoringEntryDataSource dataSource;
 	private final SearchAuthorRepositoryEntryViewParams searchParams;
 
-	private CloseableCalloutWindowController licenseCalloutCtrl;
-	private LicenseQuickviewController licenseCtrl;
 	private ToolsController toolsCtrl;
 	protected CloseableModalController cmc;
 	private SendMailController sendMailCtrl;
@@ -299,7 +295,7 @@ public class AuthorListController extends FormBasicController implements Activat
 				true, OrderBy.authors.name()));
 		if (licenseModule.isEnabled(licenseHandler)) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.license.i18nKey(), Cols.license.ordinal(), "license",
-					 new StaticFlexiCellRenderer("license", new LicenseRenderer(getLocale(), "lic-"))));
+					 new StaticFlexiCellRenderer("license", new LicenseRenderer(getLocale()))));
 		}
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, Cols.location.i18nKey(), Cols.location.ordinal(),
 				true, OrderBy.location.name()));
@@ -529,11 +525,6 @@ public class AuthorListController extends FormBasicController implements Activat
 				toolsCalloutCtrl.deactivate();
 				cleanUp();
 			}
-		} else if(licenseCtrl == source) {
-			if(event == Event.DONE_EVENT) {
-				licenseCalloutCtrl.deactivate();
-				cleanUp();
-			}
 		} else if(referencesCtrl == source) {
 			if(event == Event.DONE_EVENT) {
 				toolsCalloutCtrl.deactivate();
@@ -569,24 +560,20 @@ public class AuthorListController extends FormBasicController implements Activat
 	}
 	
 	protected void cleanUp() {
-		removeAsListenerAndDispose(licenseCalloutCtrl);
 		removeAsListenerAndDispose(confirmDeleteCtrl);
 		removeAsListenerAndDispose(toolsCalloutCtrl);
 		removeAsListenerAndDispose(userSearchCtr);
 		removeAsListenerAndDispose(sendMailCtrl);
-		removeAsListenerAndDispose(licenseCtrl);
 		removeAsListenerAndDispose(createCtrl);
 		removeAsListenerAndDispose(importCtrl);
 		removeAsListenerAndDispose(wizardCtrl);
 		removeAsListenerAndDispose(toolsCtrl);
 		removeAsListenerAndDispose(closeCtrl);
 		removeAsListenerAndDispose(cmc);
-		licenseCalloutCtrl = null;
 		confirmDeleteCtrl = null;
 		toolsCalloutCtrl = null;
 		userSearchCtr = null;
 		sendMailCtrl = null;
-		licenseCtrl = null;
 		createCtrl = null;
 		importCtrl = null;
 		wizardCtrl = null;
@@ -660,8 +647,6 @@ public class AuthorListController extends FormBasicController implements Activat
 					launchEditor(ureq, row);
 				} else if("select".equals(cmd)) {
 					launch(ureq, row);
-				} else if("license".equals(cmd)) {
-					showLicenseDetails(ureq, row, se.getIndex());
 				}
 			} else if(event instanceof FlexiTableSearchEvent) {
 				AuthorListState stateEntry = new AuthorListState();
@@ -1097,22 +1082,6 @@ public class AuthorListController extends FormBasicController implements Activat
 		NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
 	}
 
-	private void showLicenseDetails(UserRequest ureq, AuthoringEntryRow row, int index) {
-		removeAsListenerAndDispose(licenseCtrl);
-		removeAsListenerAndDispose(licenseCalloutCtrl);
-
-		License license = row.getLicense();
-		if (license != null) {
-			licenseCtrl = new LicenseQuickviewController(ureq, getWindowControl(), license);
-			listenTo(licenseCtrl);
-	
-			licenseCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(),
-					licenseCtrl.getInitialComponent(), "lic-" + index, "", true, "");
-			listenTo(licenseCalloutCtrl);
-			licenseCalloutCtrl.activate();
-		}	
-	}
-	
 	private void launchDetails(UserRequest ureq, RepositoryEntryRef ref) {
 		String businessPath = "[RepositoryEntry:" + ref.getKey() + "][Infos:0]";
 		if(!NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl())) {
diff --git a/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java b/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java
index 504d94f7f9f..c5489f44474 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java
@@ -32,7 +32,7 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DefaultResultInfos;
 import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
-import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.ResourceLicense;
 import org.olat.core.commons.services.license.LicenseService;
 import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate;
@@ -154,7 +154,7 @@ public class AuthoringEntryDataSource implements FlexiTableDataSourceDelegate<Au
 		List<OLATResourceAccess> resourcesWithOffer = acService.filterResourceWithAC(resourcesWithAC);
 		
 		Collection<OLATResourceable> resources = repoEntries.stream().map(RepositoryEntryAuthorView::getOlatResource).collect(Collectors.toList());
-		List<License> licenses = licenseService.loadLicenses(resources);
+		List<ResourceLicense> licenses = licenseService.loadLicenses(resources);
 
 		List<AuthoringEntryRow> items = new ArrayList<>();
 		for(RepositoryEntryAuthorView entry:repoEntries) {
@@ -192,7 +192,7 @@ public class AuthoringEntryDataSource implements FlexiTableDataSourceDelegate<Au
 			}
 			
 			// license
-			for (License license: licenses) {
+			for (ResourceLicense license: licenses) {
 				OLATResource resource = entry.getOlatResource();
 				if (license.getResId().equals(resource.getResourceableId()) && license.getResName().equals(resource.getResourceableTypeName())) {
 					row.setLicense(license);
diff --git a/src/main/java/org/olat/repository/ui/author/RepositoryEditDescriptionController.java b/src/main/java/org/olat/repository/ui/author/RepositoryEditDescriptionController.java
index 9f5997a7b40..74ebb58b30a 100644
--- a/src/main/java/org/olat/repository/ui/author/RepositoryEditDescriptionController.java
+++ b/src/main/java/org/olat/repository/ui/author/RepositoryEditDescriptionController.java
@@ -36,7 +36,7 @@ import java.util.Set;
 import java.util.UUID;
 
 import org.olat.NewControllerFactory;
-import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.ResourceLicense;
 import org.olat.core.commons.services.license.LicenseModule;
 import org.olat.core.commons.services.license.LicenseService;
 import org.olat.core.commons.services.license.LicenseType;
@@ -104,7 +104,7 @@ public class RepositoryEditDescriptionController extends FormBasicController {
 	private VFSContainer mediaContainer;
 	private RepositoryEntry repositoryEntry;
 	private final String repoEntryType;
-	private License license;
+	private ResourceLicense license;
 
 	private static final int picUploadlimitKB = 5120;
 	private static final int movieUploadlimitKB = 102400;
@@ -216,7 +216,7 @@ public class RepositoryEditDescriptionController extends FormBasicController {
 			license = licenseService.loadOrCreateLicense(res);
 
 			LicenseSelectionConfig licenseSelectionConfig = LicenseUIFactory
-					.createLicenseSelectionConfig(licenseHandler, license);
+					.createLicenseSelectionConfig(licenseHandler, license.getLicenseType());
 			licenseEl = uifactory.addDropdownSingleselect("cif.license", formLayout,
 					licenseSelectionConfig.getLicenseTypeKeys(),
 					licenseSelectionConfig.getLicenseTypeValues(getLocale()));
diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml
index 400d05d469b..a7aeb12f3c5 100644
--- a/src/main/resources/META-INF/persistence.xml
+++ b/src/main/resources/META-INF/persistence.xml
@@ -80,7 +80,7 @@
 		<class>org.olat.commons.info.model.InfoMessageImpl</class>
 		<class>org.olat.core.commons.services.license.model.LicenseTypeActivation</class>
 		<class>org.olat.core.commons.services.license.model.LicenseTypeImpl</class>
-		<class>org.olat.core.commons.services.license.model.LicenseImpl</class>
+		<class>org.olat.core.commons.services.license.model.ResourceLicenseImpl</class>
 		<class>org.olat.core.commons.services.lock.pessimistic.PLockImpl</class>
 		<class>org.olat.core.commons.services.notifications.model.SubscriberImpl</class>
 		<class>org.olat.core.commons.services.notifications.model.PublisherImpl</class>
diff --git a/src/test/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactoryTest.java b/src/test/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactoryTest.java
new file mode 100644
index 00000000000..8e1e2249530
--- /dev/null
+++ b/src/test/java/org/olat/core/commons/modules/bc/meta/MetaInfoFactoryTest.java
@@ -0,0 +1,104 @@
+/**
+ * <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.bc.meta;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.commons.services.license.License;
+import org.olat.core.commons.services.license.LicenseService;
+import org.olat.core.commons.services.license.LicenseType;
+import org.olat.core.commons.services.license.manager.LicenseCleaner;
+import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 05.03.2018<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class MetaInfoFactoryTest extends OlatTestCase {
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private MetaInfoFactory metaInfoFactory;
+	@Autowired
+	private LicenseService licenseService;
+	@Autowired
+	private LicenseCleaner licenseCleaner;
+	
+	@Before
+	public void cleanUp() {
+		licenseCleaner.deleteAll();
+	}
+	
+	@Test
+	public void shouldLoadExistingLicenseType() {
+		String typeName = "name";
+		LicenseType licenseType = licenseService.createLicenseType(typeName);
+		licenseType = licenseService.saveLicenseType(licenseType);
+		dbInstance.commitAndCloseSession();
+		String licensor = "licensor";
+		String name = licenseType.getName();
+		File file = new File("");
+		MetaInfo meta = new MetaInfoFileImpl(file);
+		meta.setLicenseTypeName(name);
+		meta.setLicensor(licensor);
+		
+		License license = metaInfoFactory.getLicense(meta);
+
+		assertThat(license.getLicensor()).isEqualTo(licensor);
+		LicenseType loadedLicenseType = license.getLicenseType();
+		assertThat(loadedLicenseType).isEqualTo(licenseType);
+	}
+
+	@Test
+	public void shouldCreateNonExistingLicenseType() {
+		String typeName = "name";
+		LicenseType licenseType = licenseService.createLicenseType(typeName);
+		licenseType = licenseService.saveLicenseType(licenseType);
+		dbInstance.commitAndCloseSession();
+		String licensor = "licensor";
+		String name = "new";
+		String text = "text";
+		File file = new File("");
+		MetaInfo meta = new MetaInfoFileImpl(file);
+		meta.setLicenseTypeName(name);
+		meta.setLicensor(licensor);
+		meta.setLicenseText(text);
+		
+		License license = metaInfoFactory.getLicense(meta);
+
+		assertThat(license.getLicensor()).isEqualTo(licensor);
+		LicenseType loadedLicenseType = license.getLicenseType();
+		assertThat(loadedLicenseType.getName()).isEqualTo(name);
+		assertThat(loadedLicenseType.getText()).isEqualTo(text);
+		
+		LicenseType createdLicenseType = licenseService.loadLicenseTypeByName(name);
+		assertThat(createdLicenseType).isNotNull();
+	}
+
+}
diff --git a/src/test/java/org/olat/core/commons/services/license/manager/LicenseCleaner.java b/src/test/java/org/olat/core/commons/services/license/manager/LicenseCleaner.java
new file mode 100644
index 00000000000..4926b94b299
--- /dev/null
+++ b/src/test/java/org/olat/core/commons/services/license/manager/LicenseCleaner.java
@@ -0,0 +1,51 @@
+/**
+ * <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.services.license.manager;
+
+import org.olat.core.commons.persistence.DB;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 
+ * Initial date: 05.03.2018<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+@Component
+public class LicenseCleaner {
+
+	@Autowired
+	private DB dbInstance;
+
+	public void deleteAll() {
+		dbInstance.getCurrentEntityManager()
+				.createQuery("delete from license")
+				.executeUpdate();
+		dbInstance.getCurrentEntityManager()
+				.createQuery("delete from licensetypeactivation")
+				.executeUpdate();
+		dbInstance.getCurrentEntityManager()
+				.createQuery("delete from licensetype")
+				.executeUpdate();
+		dbInstance.commitAndCloseSession();
+	}
+	
+}
diff --git a/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeActivationDAOTest.java b/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeActivationDAOTest.java
index c8c9cd5373a..e39e19d1100 100644
--- a/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeActivationDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeActivationDAOTest.java
@@ -45,19 +45,12 @@ public class LicenseTypeActivationDAOTest extends OlatTestCase {
 	private LicenseTypeDAO licenseTypeDao;
 	@Autowired
 	private LicenseTypeActivationDAO licenseTypeActivationDao;
+	@Autowired
+	private LicenseCleaner licenseCleaner;
 	
 	@Before
 	public void cleanUp() {
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from license")
-				.executeUpdate();
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from licensetypeactivation")
-				.executeUpdate();
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from licensetype")
-				.executeUpdate();
-		dbInstance.commitAndCloseSession();
+		licenseCleaner.deleteAll();
 	}
 	
 	@Test
diff --git a/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeDAOTest.java b/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeDAOTest.java
index 9ab0bcf54ba..a296b79b925 100644
--- a/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/license/manager/LicenseTypeDAOTest.java
@@ -49,19 +49,12 @@ public class LicenseTypeDAOTest extends OlatTestCase {
 	private LicenseTypeDAO licenseTypeDao;
 	@Autowired
 	private LicenseTypeActivationDAO licenseTypeActivationDao;
+	@Autowired
+	private LicenseCleaner licenseCleaner;
 	
 	@Before
 	public void cleanUp() {
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from license")
-				.executeUpdate();
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from licensetypeactivation")
-				.executeUpdate();
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from licensetype")
-				.executeUpdate();
-		dbInstance.commitAndCloseSession();
+		licenseCleaner.deleteAll();
 	}
 	
 	@Test
@@ -147,6 +140,33 @@ public class LicenseTypeDAOTest extends OlatTestCase {
 		assertThat(noLicenseType.getName()).isEqualTo(LicenseTypeDAO.NO_LICENSE_NAME);
 	}
 
+	@Test
+	public void shouldLoadLicenseTypeByKey() {
+		LicenseType licenseType = licenseTypeDao.create(UUID.randomUUID().toString());
+		licenseType = licenseTypeDao.save(licenseType);
+		LicenseType otherLicenseType = licenseTypeDao.create(UUID.randomUUID().toString());
+		licenseTypeDao.save(otherLicenseType);
+		dbInstance.commitAndCloseSession();
+		
+		LicenseType loadedLicenseType = licenseTypeDao.loadLicenseTypeByKey(licenseType.getKey());
+		
+		assertThat(loadedLicenseType).isEqualTo(licenseType);
+	}
+	
+	@Test
+	public void shouldLoadLicenseTypeByName() {
+		LicenseType licenseType = licenseTypeDao.create(UUID.randomUUID().toString());
+		licenseType = licenseTypeDao.save(licenseType);
+		LicenseType otherLicenseType = licenseTypeDao.create(UUID.randomUUID().toString());
+		licenseTypeDao.save(otherLicenseType);
+		dbInstance.commitAndCloseSession();
+		
+		LicenseType loadedLicenseType = licenseTypeDao.loadLicenseTypeByName(licenseType.getName());
+		
+		assertThat(loadedLicenseType).isEqualTo(licenseType);
+	}
+
+
 	@Test
 	public void shouldLoadAllLicensesTypes() {
 		LicenseType licenseType1 = licenseTypeDao.create(UUID.randomUUID().toString());
diff --git a/src/test/java/org/olat/core/commons/services/license/manager/LicenseDAOTest.java b/src/test/java/org/olat/core/commons/services/license/manager/ResourceLicenseDAOTest.java
similarity index 82%
rename from src/test/java/org/olat/core/commons/services/license/manager/LicenseDAOTest.java
rename to src/test/java/org/olat/core/commons/services/license/manager/ResourceLicenseDAOTest.java
index 8a8964c4a5c..5a19851f07c 100644
--- a/src/test/java/org/olat/core/commons/services/license/manager/LicenseDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/license/manager/ResourceLicenseDAOTest.java
@@ -30,6 +30,7 @@ import org.junit.Test;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.license.License;
 import org.olat.core.commons.services.license.LicenseType;
+import org.olat.core.commons.services.license.ResourceLicense;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.test.JunitTestHelper;
@@ -43,27 +44,20 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-public class LicenseDAOTest extends OlatTestCase {
+public class ResourceLicenseDAOTest extends OlatTestCase {
 	
 	@Autowired
 	private DB dbInstance;
 	@Autowired
-	private LicenseDAO licenseDao;
+	private ResourceLicenseDAO licenseDao;
 	@Autowired
 	private LicenseTypeDAO licenseTypeDao;
+	@Autowired
+	private LicenseCleaner licenseCleaner;
 	
 	@Before
 	public void cleanUp() {
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from license")
-				.executeUpdate();
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from licensetypeactivation")
-				.executeUpdate();
-		dbInstance.getCurrentEntityManager()
-				.createQuery("delete from licensetype")
-				.executeUpdate();
-		dbInstance.commitAndCloseSession();
+		licenseCleaner.deleteAll();
 	}
 	
 	@Test
@@ -73,7 +67,7 @@ public class LicenseDAOTest extends OlatTestCase {
 		licenseType = licenseTypeDao.save(licenseType);
 		String licensor = "licensor";
 
-		License license = licenseDao.createAndPersist(ores, licenseType, licensor);
+		ResourceLicense license = licenseDao.createAndPersist(ores, licenseType, licensor);
 		dbInstance.commitAndCloseSession();
 		
 		assertThat(license.getResName()).isEqualTo(ores.getResourceableTypeName());
@@ -89,7 +83,7 @@ public class LicenseDAOTest extends OlatTestCase {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		LicenseType licenseType = licenseTypeDao.create("name");
 		licenseType = licenseTypeDao.save(licenseType);
-		License license = licenseDao.createAndPersist(ores, licenseType);
+		ResourceLicense license = licenseDao.createAndPersist(ores, licenseType);
 		dbInstance.commitAndCloseSession();
 		String freetext = "freetext";
 		license.setFreetext(freetext);
@@ -111,7 +105,7 @@ public class LicenseDAOTest extends OlatTestCase {
 		License license = licenseDao.createAndPersist(ores, licenseType);
 		dbInstance.commitAndCloseSession();
 		
-		License loadedLicense = licenseDao.loadByResource(ores);
+		ResourceLicense loadedLicense = licenseDao.loadByResource(ores);
 		
 		assertThat(loadedLicense).isEqualTo(license);
 	}
@@ -122,18 +116,18 @@ public class LicenseDAOTest extends OlatTestCase {
 		LicenseType licenseType = licenseTypeDao.create("name");
 		licenseType = licenseTypeDao.save(licenseType);
 		OLATResourceable ores1 = OresHelper.createOLATResourceableInstance(resName, (new Random()).nextLong());
-		License license1 = licenseDao.createAndPersist(ores1, licenseType);
+		ResourceLicense license1 = licenseDao.createAndPersist(ores1, licenseType);
 		OLATResourceable ores2 = OresHelper.createOLATResourceableInstance(resName, (new Random()).nextLong());
-		License license2 = licenseDao.createAndPersist(ores2, licenseType);
+		ResourceLicense license2 = licenseDao.createAndPersist(ores2, licenseType);
 		OLATResourceable ores3 = OresHelper.createOLATResourceableInstance(resName, (new Random()).nextLong());
-		License license3 = licenseDao.createAndPersist(ores3, licenseType);
+		ResourceLicense license3 = licenseDao.createAndPersist(ores3, licenseType);
 		OLATResourceable oresSameName = OresHelper.createOLATResourceableInstance(resName, (new Random()).nextLong());
 		licenseDao.createAndPersist(oresSameName, licenseType);
 		OLATResourceable oresSameId = OresHelper.createOLATResourceableInstance("other", ores1.getResourceableId());
 		licenseDao.createAndPersist(oresSameId, licenseType);
 		dbInstance.commitAndCloseSession();
 		
-		List<License> loadedLicenses = licenseDao.loadLicenses(Arrays.asList(ores1, ores2, ores3));
+		List<ResourceLicense> loadedLicenses = licenseDao.loadLicenses(Arrays.asList(ores1, ores2, ores3));
 		
 		assertThat(loadedLicenses).containsExactly(license1, license2, license3);
 	}
diff --git a/src/test/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfigTest.java b/src/test/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfigTest.java
index 563ac78e6f6..e69666843d3 100644
--- a/src/test/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfigTest.java
+++ b/src/test/java/org/olat/core/commons/services/license/ui/LicenseSelectionConfigTest.java
@@ -35,7 +35,7 @@ import org.olat.core.commons.services.license.LicenseHandler;
 import org.olat.core.commons.services.license.LicenseService;
 import org.olat.core.commons.services.license.LicenseType;
 import org.olat.core.commons.services.license.manager.TestableLicenseHandler;
-import org.olat.core.commons.services.license.model.LicenseImpl;
+import org.olat.core.commons.services.license.model.ResourceLicenseImpl;
 import org.olat.core.commons.services.license.model.LicenseTypeImpl;
 
 /**
@@ -56,7 +56,7 @@ public class LicenseSelectionConfigTest {
 	@Mock
 	private LicenseService licenseServiceMock;
 	
-	private License license = new LicenseImpl();;
+	private License license = new ResourceLicenseImpl();;
 	
 	private LicenseSelectionConfig sut;
 
@@ -72,7 +72,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(any())).thenReturn(Boolean.FALSE);
 		
 		license.setLicenseType(getActiveLicenseTypes().get(0));
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 		
 		boolean licenseMandatory = sut.isLicenseMandatory();
 		
@@ -84,7 +84,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(any())).thenReturn(Boolean.TRUE);
 		
 		license.setLicenseType(getActiveLicenseTypes().get(0));
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 		
 		boolean licenseMandatory = sut.isLicenseMandatory();
 		
@@ -94,7 +94,7 @@ public class LicenseSelectionConfigTest {
 	@Test
 	public void shouldReturnActiveLicenseTypes() {
 		license.setLicenseType(getActiveLicenseTypes().get(0));
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 		
 		String[] licenseTypeKeys = sut.getLicenseTypeKeys();
 		
@@ -106,7 +106,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(any())).thenReturn(Boolean.FALSE);
 	
 		license.setLicenseType(getInactiveLicenseType());
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 
 		String[] licenseTypeKeys = sut.getLicenseTypeKeys();
 		
@@ -118,7 +118,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(any())).thenReturn(Boolean.TRUE);
 		
 		license.setLicenseType(getInactiveLicenseType());
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 
 		String[] licenseTypeKeys = sut.getLicenseTypeKeys();
 		
@@ -130,7 +130,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(getInactiveLicenseType())).thenReturn(Boolean.FALSE);
 		
 		license.setLicenseType(getInactiveLicenseType());
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 
 		String key = sut.getSelectionLicenseTypeKey();
 		
@@ -142,7 +142,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(getActiveLicenseTypes().get(0))).thenReturn(Boolean.TRUE);
 		
 		license.setLicenseType(getActiveLicenseTypes().get(0));
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 
 		String key = sut.getSelectionLicenseTypeKey();
 		
@@ -154,7 +154,7 @@ public class LicenseSelectionConfigTest {
 		when(licenseServiceMock.isNoLicense(getInactiveLicenseType())).thenReturn(Boolean.TRUE);
 		
 		license.setLicenseType(getInactiveLicenseType());
-		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license);
+		sut = new LicenseSelectionConfig(licenseServiceMock, LICENSE_HANDLER, license.getLicenseType());
 
 		String key = sut.getSelectionLicenseTypeKey();
 		
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 2a6b13d9725..0095f54148d 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -92,11 +92,12 @@ 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.bc.meta.MetaInfoFactoryTest.class,
 	org.olat.core.commons.services.help.ConfluenceHelperTest.class,
 	org.olat.core.commons.services.help.spi.ConfluenceLinkSPITest.class,
 	org.olat.core.commons.services.license.manager.LicenseTypeActivationDAOTest.class,
 	org.olat.core.commons.services.license.manager.LicenseTypeDAOTest.class,
-	org.olat.core.commons.services.license.manager.LicenseDAOTest.class,
+	org.olat.core.commons.services.license.manager.ResourceLicenseDAOTest.class,
 	org.olat.core.commons.services.webdav.WebDAVCommandsTest.class,
 	org.olat.core.commons.services.webdav.manager.DigestAuthenticationTest.class,
 	org.olat.core.commons.services.webdav.manager.WebDAVManagerTest.class,
-- 
GitLab