diff --git a/.hgtags b/.hgtags
index 3b652c907c799e49b6a1ec4b2cd506d2da0b6349..6fcc5e089583587d4bb0f6d3d266c94d8d0b242e 100644
--- a/.hgtags
+++ b/.hgtags
@@ -36,3 +36,6 @@ be1c6b822eb317f3a48d392eb27055e7d4d52cc3 OpenOLAT 8.2.0
 4e8dde0bdfecb7d408237cfcac5c24a8337cc21e OpenOLAT 8.3.1
 0db1cf58d37858b5096cc6fe97b0a9159d626c37 OpenOLAT 8.3.2
 c04c6d0e5c4eb486f95c62846c8f16869752497d OpenOLAT 8.3.3
+c705216e80316b862757515d1a9f0f772393fbc8 OpenOLAT 8.3.4
+c705216e80316b862757515d1a9f0f772393fbc8 OpenOLAT 8.3.4
+138f584995d4a899f812e5a921ba079aed8d9e48 OpenOLAT 8.3.4
diff --git a/INSTALL.README.HEAD b/INSTALL.README.HEAD
index 4419c0cb5d21575ab5d0f1510201852682c6e30b..86b8f1115e17999f9fe8f00566825a2cb8e3c1ad 100644
--- a/INSTALL.README.HEAD
+++ b/INSTALL.README.HEAD
@@ -60,7 +60,9 @@ Preconditions:
   7.6 Open the generated server.xml file and manually set the following parameters: 
       In the "Context" element set parameter reloadable="false" 
       In all "Connector" elements set paramter URIEncoding="UTF-8"
-
+  7.7 Option: to use the application server database connection pool configure a jdbc data resource in the the 
+      "Context" element, set db.source=jndi in the olat.local.properties and  db.jndi to the name of the data soruce
+      If unsure, set db.source=local to use the bundled data connection pool (not recommendet for production)
 8. In Eclipse: start the server
 
 9. In your browser open URL http://localhost:8080/olat
@@ -100,4 +102,4 @@ Background (optional for further interest)
 o There is only one spring context for the whole OpenOLAT which you can access via CoreSpringFactory. The context 
   is configured with the files serviceconfig/olat.properies and can be overwritten with olat.local.properties. 
   changes in olat.local.properties are reflected upon each restart of Tomcat.
-
+  
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 359e39ed828ff910954a4cf6eaedb922856dcae7..89c61ea7967f0d383c7f207f76a8bdb3b04a7f3b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,13 +64,13 @@
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<targetJdk>1.6</targetJdk>
-		<org.springframework.version>3.2.0.RELEASE</org.springframework.version>
-		<org.hibernate.version>4.1.9.Final</org.hibernate.version>
+		<org.springframework.version>3.2.1.RELEASE</org.springframework.version>
+		<org.hibernate.version>4.1.10.Final</org.hibernate.version>
 		<com.sun.jersey.version>1.15</com.sun.jersey.version>
 		<jackson.version>1.9.2</jackson.version>
-		<org.mysql.version>5.1.21</org.mysql.version>
+		<org.mysql.version>5.1.23</org.mysql.version>
 		<org.postgresql.version>9.1-901.jdbc4</org.postgresql.version>
-		<org.infinispan.version>5.1.6.FINAL</org.infinispan.version>
+		<org.infinispan.version>5.2.1.Final</org.infinispan.version>
 
 	    <!-- properties for testing and Q&A -->
 	    <!-- by default no tests are executed so far (April 2011). Use appropriate profiles and properties on the command line -->
@@ -1884,7 +1884,7 @@
 		<dependency>
 			<groupId>com.thoughtworks.xstream</groupId>
 			<artifactId>xstream</artifactId>
-			<version>1.4.3</version>
+			<version>1.4.4</version>
 		</dependency>
 		<dependency>
 			<groupId>cos</groupId>
diff --git a/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java b/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java
index bc894cef2e353f997f14e0a41241c496a6a4de02..022e1c8c3d4dd19c1e3ce2d061d7c73f136d3059 100644
--- a/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java
+++ b/src/main/java/de/bps/course/nodes/ChecklistCourseNode.java
@@ -197,7 +197,7 @@ public class ChecklistCourseNode extends AbstractAccessableCourseNode {
 	public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
 		oneClickStatusCache = null;
 		String translatorStr = Util.getPackageName(ConditionEditController.class);
-		List statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(statusDescs);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/de/bps/course/nodes/DENCourseNode.java b/src/main/java/de/bps/course/nodes/DENCourseNode.java
index 4e536645285d214d376318a104059403f3f3ad19..5252a5401a41b6f78398f28dada3189f9ba455d1 100644
--- a/src/main/java/de/bps/course/nodes/DENCourseNode.java
+++ b/src/main/java/de/bps/course/nodes/DENCourseNode.java
@@ -22,6 +22,7 @@ package de.bps.course.nodes;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.olat.commons.calendar.model.KalendarEvent;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.stack.StackedController;
 import org.olat.core.gui.control.Controller;
@@ -118,7 +119,7 @@ public class DENCourseNode extends AbstractAccessableCourseNode {
 	@Override
 	public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
 		String translatorStr = Util.getPackageName(ConditionEditController.class);
-		List statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		return StatusDescriptionHelper.sort(statusDescs);
 	}
 
@@ -155,7 +156,7 @@ public class DENCourseNode extends AbstractAccessableCourseNode {
 		cpm.deleteNodeProperties(this, CONF_CANCEL_ENROLL_ENABLED);
 		DENManager denManager = DENManager.getInstance();
 		//empty List as first argument, so all dates for this course node are going to delete
-		denManager.persistDENSettings(new ArrayList(), course, this);
+		denManager.persistDENSettings(new ArrayList<KalendarEvent>(), course, this);
 	}
 
 }
diff --git a/src/main/java/org/olat/admin/securitygroup/gui/GroupController.java b/src/main/java/org/olat/admin/securitygroup/gui/GroupController.java
index fd7d8a77e0025e7f003dd0a7ab9603354f0d2973..722f9abb1a90064bbbf634745c8f884af8a99fa3 100644
--- a/src/main/java/org/olat/admin/securitygroup/gui/GroupController.java
+++ b/src/main/java/org/olat/admin/securitygroup/gui/GroupController.java
@@ -28,6 +28,7 @@ package org.olat.admin.securitygroup.gui;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 
 import org.olat.admin.securitygroup.gui.multi.UsersToGroupWizardController;
 import org.olat.admin.user.UserSearchController;
@@ -502,8 +503,9 @@ public class GroupController extends BasicController {
 				ccIdentities = null;	
 			}
 			//fxdiff VCRP-16: intern mail system
+			String metaId = UUID.randomUUID().toString();
 			MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString());
-			MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, toBeRemoved, ccIdentities, mailTemplate, sender);
+			MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, toBeRemoved, ccIdentities, mailTemplate, sender, metaId);
 			MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), ureq.getLocale());
 		}
 	}
@@ -556,8 +558,9 @@ public class GroupController extends BasicController {
 				ccIdentities = null;	
 			}
 			//fxdiff VCRP-16: intern mail system
+			String metaId = UUID.randomUUID().toString();
 			MailContext context = new MailContextImpl(getWindowControl().getBusinessControl().getAsString());
-			MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, identitiesAddedEvent.getAddedIdentities(), ccIdentities, mailTemplate, sender);
+			MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, identitiesAddedEvent.getAddedIdentities(), ccIdentities, mailTemplate, sender, metaId);
 			MailHelper.appendErrorsAndWarnings(mailerResult, errorMessage, infoMessage, ureq.getLocale());
 		}
 		// report any errors on screen
diff --git a/src/main/java/org/olat/admin/site/AdminSite.java b/src/main/java/org/olat/admin/site/AdminSite.java
index e3fc51a75002e3d9c0b56b4e051c0840b36c0f28..acdf82abc68a0d4f25a615f4c433a7a0184ae206 100644
--- a/src/main/java/org/olat/admin/site/AdminSite.java
+++ b/src/main/java/org/olat/admin/site/AdminSite.java
@@ -40,8 +40,10 @@ import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.BusinessControlFactory;
 import org.olat.core.id.context.StateSite;
+import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.Util;
 import org.olat.core.util.resource.OresHelper;
+import org.olat.util.logging.activity.LoggingResourceable;
 /**
  * Description:<br>
  * TODO: Felix Jost Class Description for HomeSite
@@ -77,6 +79,7 @@ public class AdminSite implements SiteInstance {
 	public MainLayoutController createController(UserRequest ureq, WindowControl wControl) {
 		//fxdiff BAKS-7 Resume function
 		OLATResourceable ores = OresHelper.createOLATResourceableInstance(AdminSite.class, 0l);
+		ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
 		WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ureq, ores, new StateSite(this), wControl, true);
 		MainLayoutController c = ControllerFactory.createLaunchController(ORES_OLATADMINS, ureq, bwControl, true);
 		return c;
diff --git a/src/main/java/org/olat/admin/user/groups/GroupLeaveDialogBoxController.java b/src/main/java/org/olat/admin/user/groups/GroupLeaveDialogBoxController.java
index 7fd704e006ed2fcdb96cb611c028027645545230..a1f0063eaffb0ccb7295025c576792f4bc134fd2 100644
--- a/src/main/java/org/olat/admin/user/groups/GroupLeaveDialogBoxController.java
+++ b/src/main/java/org/olat/admin/user/groups/GroupLeaveDialogBoxController.java
@@ -88,7 +88,7 @@ public class GroupLeaveDialogBoxController extends FormBasicController {
 			groupDeleteEl.select(keys[0], true);
 		}
 		
-		;FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
 		buttonsContainer.setRootForm(mainForm);
 		formLayout.add(buttonsContainer);
 		uifactory.addFormSubmitButton("deleteButton", "ok", buttonsContainer);
diff --git a/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java b/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java
index cbef349ce723c6bd14c9921dab918aadc7e28e6a..c4a8b5d646eef2d7565c471c82163d8e4c44c3ba 100644
--- a/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java
+++ b/src/main/java/org/olat/admin/user/groups/GroupOverviewController.java
@@ -49,12 +49,15 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
+import org.olat.core.gui.control.generic.modal.DialogBoxController;
+import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.id.Identity;
 import org.olat.core.util.Util;
 import org.olat.core.util.mail.MailHelper;
 import org.olat.core.util.mail.MailPackage;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupMembership;
+import org.olat.group.BusinessGroupModule;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.model.AddToGroupsEvent;
 import org.olat.group.model.BusinessGroupMembershipChange;
@@ -83,11 +86,13 @@ public class GroupOverviewController extends BasicController {
 	private BusinessGroupTableModelWithType tableDataModel;
 	
 	private Link addGroups;
+	private DialogBoxController confirmSendMailBox;
 	private CloseableModalController cmc;
 	private GroupSearchController groupsCtrl;
 	private GroupLeaveDialogBoxController removeFromGrpDlg;
 
 	private final BaseSecurity securityManager;
+	private final BusinessGroupModule groupModule;
 	private final BusinessGroupService businessGroupService;
 	
 	private final Identity identity;
@@ -97,6 +102,7 @@ public class GroupOverviewController extends BasicController {
 		
 		this.identity = identity;
 		securityManager = BaseSecurityManager.getInstance();
+		groupModule = CoreSpringFactory.getImpl(BusinessGroupModule.class);
 		businessGroupService = CoreSpringFactory.getImpl(BusinessGroupService.class);
 
 		vc = createVelocityContainer("groupoverview");
@@ -216,17 +222,29 @@ public class GroupOverviewController extends BasicController {
 			}
 		}	else if (source == groupsCtrl && event instanceof AddToGroupsEvent){
 			AddToGroupsEvent groupsEv = (AddToGroupsEvent) event;
-			if (groupsEv.getOwnerGroupKeys().isEmpty() && groupsEv.getParticipantGroupKeys().isEmpty()) {
+			if (groupsEv.isEmpty()) {
 				// no groups selected
 				showWarning("group.add.result.none");
 			} else {
 				if (cmc != null) {
 					cmc.deactivate();				
 				}
-				doAddToGroups(groupsEv);
-				updateModel(ureq);
+				
+				boolean mailMandatory = groupModule.isMandatoryEnrolmentEmail(ureq.getUserSession().getRoles());
+				if(mailMandatory) {
+					doAddToGroups(groupsEv, true);
+					updateModel(ureq);
+				} else {
+					confirmSendMailBox = activateYesNoDialog(ureq, null, translate("dialog.modal.bg.send.mail"), confirmSendMailBox);
+					confirmSendMailBox.setUserObject(groupsEv);
+				}
 			}
 			cleanUpPopups();
+		} else if(source == confirmSendMailBox) {
+			boolean sendMail = DialogBoxUIFactory.isYesEvent(event) || DialogBoxUIFactory.isOkEvent(event);
+			AddToGroupsEvent groupsEv = (AddToGroupsEvent)confirmSendMailBox.getUserObject();
+			doAddToGroups(groupsEv, sendMail);
+			updateModel(ureq);
 		} else if (source == removeFromGrpDlg){
 			if(event == Event.DONE_EVENT) {
 				boolean sendMail = removeFromGrpDlg.isSendMail();
@@ -250,7 +268,7 @@ public class GroupOverviewController extends BasicController {
 		removeFromGrpDlg = null;
 	}
 	
-	private void doAddToGroups(AddToGroupsEvent e) {
+	private void doAddToGroups(AddToGroupsEvent e, boolean sendMail) {
 		List<BusinessGroupMembershipChange> changes = new ArrayList<BusinessGroupMembershipChange>();
 		if(e.getOwnerGroupKeys() != null && !e.getOwnerGroupKeys().isEmpty()) {
 			for(Long tutorGroupKey:e.getOwnerGroupKeys()) {
@@ -267,9 +285,8 @@ public class GroupOverviewController extends BasicController {
 			}
 		}
 		
-		MailPackage mailing = new MailPackage();
+		MailPackage mailing = new MailPackage(sendMail);
 		businessGroupService.updateMemberships(getIdentity(), changes, mailing);
-		DBFactory.getInstance().commit();
 	}
 	
 	private void doLeave(UserRequest ureq, List<BusinessGroup> groupsToLeave) {
diff --git a/src/main/java/org/olat/admin/user/groups/GroupSearchController.java b/src/main/java/org/olat/admin/user/groups/GroupSearchController.java
index 8e471b57bb82e1c0c2e7a3ab01b419effbf5992e..bee65b41739d2e4b93c88aa8b8dadfe4bb192524 100644
--- a/src/main/java/org/olat/admin/user/groups/GroupSearchController.java
+++ b/src/main/java/org/olat/admin/user/groups/GroupSearchController.java
@@ -130,7 +130,6 @@ public class GroupSearchController extends StepFormBasicController {
 		tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.courses.i18n(), Cols.courses.ordinal()));
 		tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.tutor.i18n(), Cols.tutor.ordinal()));
 		tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.participant.i18n(), Cols.participant.ordinal()));
-		tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Cols.mail.i18n(), Cols.mail.ordinal()));
 		
 		tableDataModel = new GroupTableDataModel(Collections.<GroupWrapper>emptyList(), tableColumnModel);
 		FlexiTableElement table = uifactory.addTableElement(ureq, "groupList", tableDataModel, tableCont);
@@ -207,7 +206,6 @@ public class GroupSearchController extends StepFormBasicController {
 				GroupWrapper wrapper = new GroupWrapper(group, sb.toString());
 				wrapper.setTutor(createSelection("tutor_" + group.getKey()));
 				wrapper.setParticipant(createSelection("participant_" + group.getKey()));
-				wrapper.setMail(createSelection("mail_" + group.getKey()));
 				groups.add(wrapper);
 			}
 
@@ -252,13 +250,11 @@ public class GroupSearchController extends StepFormBasicController {
 	private void doSave(UserRequest ureq) {
 		List<Long> ownerGroups = getCheckedTutorKeys();
 		List<Long> partGroups = getCheckedParticipantKeys();
-		List<Long> mailGroups = getCheckedMailKeys();
 		
 		if (isUsedInStepWizzard()){
 			// might be used in wizzard during user import or user bulk change. allow next/finish according to previous steps.
 			addToRunContext("ownerGroups", ownerGroups);
 			addToRunContext("partGroups", partGroups);
-			addToRunContext("mailGroups", mailGroups);
 			boolean groupsChoosen = (ownerGroups.size() !=0 || partGroups.size() != 0);
 			boolean validImport = getFromRunContext("validImport") != null && ((Boolean) getFromRunContext("validImport"));
 			boolean validBulkChange = getFromRunContext("validChange") != null && ((Boolean) getFromRunContext("validChange"));
@@ -269,7 +265,7 @@ public class GroupSearchController extends StepFormBasicController {
 			addToRunContext("validChange",isValid );
 			fireEvent(ureq, StepsEvent.ACTIVATE_NEXT);
 		} else {
-			fireEvent(ureq, new AddToGroupsEvent(ownerGroups, partGroups, mailGroups));
+			fireEvent(ureq, new AddToGroupsEvent(ownerGroups, partGroups));
 		}	
 	}
 
@@ -292,16 +288,6 @@ public class GroupSearchController extends StepFormBasicController {
 		}
 		return selected;		
 	}
-	
-	private List<Long> getCheckedMailKeys() {
-		List<Long> selected = new ArrayList<Long>();
-		for(GroupWrapper wrapper:tableDataModel.getObjects()) {
-			if(wrapper.getMail().isSelected(0)) {
-				selected.add(wrapper.getGroupKey());
-			}
-		}
-		return selected;		
-	}
 
 	@Override
 	protected void doDispose() {
@@ -316,7 +302,6 @@ public class GroupSearchController extends StepFormBasicController {
 		
 		private MultipleSelectionElement tutor;
 		private MultipleSelectionElement participant;
-		private MultipleSelectionElement mail;
 		
 		public GroupWrapper(BusinessGroup group, String courses) {
 			groupKey = group.getKey();
@@ -356,14 +341,6 @@ public class GroupSearchController extends StepFormBasicController {
 		public void setParticipant(MultipleSelectionElement participant) {
 			this.participant = participant;
 		}
-		
-		public MultipleSelectionElement getMail() {
-			return mail;
-		}
-		
-		public void setMail(MultipleSelectionElement mail) {
-			this.mail = mail;
-		}
 	}
 	
 	private static class GroupTableDataModel extends DefaultTableDataModel<GroupWrapper> implements FlexiTableDataModel {
@@ -403,7 +380,6 @@ public class GroupSearchController extends StepFormBasicController {
 				case courses: return option.getCourses();
 				case tutor: return option.getTutor();
 				case participant: return option.getParticipant();
-				case mail: return option.getMail();
 				default: return option;
 			}
 		}
@@ -419,8 +395,7 @@ public class GroupSearchController extends StepFormBasicController {
 		description("description"),
 		courses("table.header.resources"),
 		tutor("table.group.add.tutor"),
-		participant("table.group.add.participant"),
-		mail("send.email");
+		participant("table.group.add.participant");
 		
 		private final String i18n;
 		
diff --git a/src/main/java/org/olat/admin/user/imp/ImportStep02.java b/src/main/java/org/olat/admin/user/imp/ImportStep02.java
index 0d8405d753615efc5e78f71a6fbe2f6ad37c531b..2f0d4ecafb1c4a8bde24f99e0bfa0e8e02f7af41 100644
--- a/src/main/java/org/olat/admin/user/imp/ImportStep02.java
+++ b/src/main/java/org/olat/admin/user/imp/ImportStep02.java
@@ -20,6 +20,7 @@
 package org.olat.admin.user.imp;
 
 import org.olat.admin.user.groups.GroupSearchController;
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.impl.Form;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -29,6 +30,7 @@ import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig;
 import org.olat.core.gui.control.generic.wizard.Step;
 import org.olat.core.gui.control.generic.wizard.StepFormController;
 import org.olat.core.gui.control.generic.wizard.StepsRunContext;
+import org.olat.group.BusinessGroupModule;
 
 /**
  * 
@@ -40,11 +42,19 @@ import org.olat.core.gui.control.generic.wizard.StepsRunContext;
  * @author Roman Haag, roman.haag@frentix.com, www.frentix.com
  */
 public class ImportStep02 extends BasicStep {
+	
+	private final boolean mandatoryEmail;
 
 	public ImportStep02(UserRequest ureq) {
 		super(ureq);
 		setI18nTitleAndDescr("step2.description", "step2.short.description");
-		setNextStep(Step.NOSTEP);
+
+		mandatoryEmail = CoreSpringFactory.getImpl(BusinessGroupModule.class).isMandatoryEnrolmentEmail(ureq.getUserSession().getRoles());
+		if(mandatoryEmail) {
+			setNextStep(Step.NOSTEP);
+		} else {
+			setNextStep(new ImportStep03SendMail(ureq));
+		}
 	}
 
 	/**
@@ -52,7 +62,9 @@ public class ImportStep02 extends BasicStep {
 	 */
 	@Override
 	public PrevNextFinishConfig getInitialPrevNextFinishConfig() {
-		return new PrevNextFinishConfig(true, false, true);
+		boolean next = !mandatoryEmail;
+		boolean finish = mandatoryEmail;
+		return new PrevNextFinishConfig(true, next, finish);
 	}
 
 	/**
diff --git a/src/main/java/org/olat/admin/user/imp/ImportStep03SendMail.java b/src/main/java/org/olat/admin/user/imp/ImportStep03SendMail.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c57666e082c99018923b8eec392951268b1e3a8
--- /dev/null
+++ b/src/main/java/org/olat/admin/user/imp/ImportStep03SendMail.java
@@ -0,0 +1,64 @@
+/**
+ * <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.admin.user.imp;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.impl.Form;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.wizard.BasicStep;
+import org.olat.core.gui.control.generic.wizard.PrevNextFinishConfig;
+import org.olat.core.gui.control.generic.wizard.Step;
+import org.olat.core.gui.control.generic.wizard.StepFormController;
+import org.olat.core.gui.control.generic.wizard.StepsRunContext;
+
+/**
+ * 
+ * Step to choose if mails are send or not
+ * 
+ * Initial date: 19.02.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ImportStep03SendMail extends BasicStep {
+
+	public ImportStep03SendMail(UserRequest ureq) {
+		super(ureq);
+		setI18nTitleAndDescr("step3.description", "step3.short.description");
+		setNextStep(Step.NOSTEP);
+	}
+
+	/**
+	 * @see org.olat.core.gui.control.generic.wizard.BasicStep#getInitialPrevNextFinishConfig()
+	 */
+	@Override
+	public PrevNextFinishConfig getInitialPrevNextFinishConfig() {
+		return new PrevNextFinishConfig(true, false, true);
+	}
+
+	/**
+	 * @see org.olat.core.gui.control.generic.wizard.BasicStep#getStepController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl, org.olat.core.gui.control.generic.wizard.StepsRunContext, org.olat.core.gui.components.form.flexible.impl.Form)
+	 */
+	@Override
+	public StepFormController getStepController(UserRequest ureq, WindowControl windowControl, StepsRunContext stepsRunContext, Form form) {
+		StepFormController stepI = new SendMailConfirmationController(ureq, windowControl, form, stepsRunContext);
+		return stepI;
+	}
+
+}
diff --git a/src/main/java/org/olat/admin/user/imp/SendMailConfirmationController.java b/src/main/java/org/olat/admin/user/imp/SendMailConfirmationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..149d1f8ee601e6d92629b5ffcbf25407a499fd31
--- /dev/null
+++ b/src/main/java/org/olat/admin/user/imp/SendMailConfirmationController.java
@@ -0,0 +1,76 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.admin.user.imp;
+
+import java.util.List;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.impl.Form;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.wizard.StepFormBasicController;
+import org.olat.core.gui.control.generic.wizard.StepsEvent;
+import org.olat.core.gui.control.generic.wizard.StepsRunContext;
+
+
+/**
+ * 
+ * Initial date: 19.2.2013<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class SendMailConfirmationController extends StepFormBasicController {
+	
+	private static final String[] keys = { "send" };
+	
+	private MultipleSelectionElement typEl;
+
+	public SendMailConfirmationController(UserRequest ureq, WindowControl wControl, Form form, StepsRunContext stepsRunContext) {
+		super(ureq, wControl, form, stepsRunContext, LAYOUT_DEFAULT, null);
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		setFormDescription("step3.send.mail.description");
+		
+		@SuppressWarnings("unchecked")
+		List<Long> ownGroups = (List<Long>) getFromRunContext("ownerGroups");
+		@SuppressWarnings("unchecked")
+		List<Long> partGroups = (List<Long>) getFromRunContext("partGroups");
+		
+		String[] values = new String[] { translate("step3.send.mail") };
+		typEl = uifactory.addCheckboxesVertical("typ", "step3.send.label", formLayout, keys, values, null, 1);
+		typEl.setEnabled(ownGroups.size() > 0 || partGroups.size() > 0);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		addToRunContext("sendMail", new Boolean(typEl.isSelected(0)));
+		fireEvent(ureq, StepsEvent.ACTIVATE_NEXT);
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/admin/user/imp/UserImportController.java b/src/main/java/org/olat/admin/user/imp/UserImportController.java
index ff1b71eb56db4949e7512f3ba292d3e35da8d211..314ceb647569aa6e96e12d58577f126be3802e49 100644
--- a/src/main/java/org/olat/admin/user/imp/UserImportController.java
+++ b/src/main/java/org/olat/admin/user/imp/UserImportController.java
@@ -27,7 +27,6 @@ package org.olat.admin.user.imp;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -53,13 +52,9 @@ import org.olat.core.gui.control.generic.wizard.StepsRunContext;
 import org.olat.core.id.Identity;
 import org.olat.core.id.User;
 import org.olat.core.util.StringHelper;
-import org.olat.core.util.mail.MailTemplate;
-import org.olat.core.util.mail.MailerResult;
-import org.olat.core.util.mail.MailerWithTemplate;
-import org.olat.group.BusinessGroup;
+import org.olat.core.util.mail.MailPackage;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.model.BusinessGroupMembershipChange;
-import org.olat.group.ui.BGMailHelper;
 import org.olat.user.UserManager;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
 
@@ -75,7 +70,6 @@ public class UserImportController extends BasicController {
 
 	private List<UserPropertyHandler> userPropertyHandlers;
 	private static final String usageIdentifyer = UserImportController.class.getCanonicalName();
-	private List<List<String>> newIdents;
 	private boolean canCreateOLATPassword;
 	private VelocityContainer mainVC;
 	private Link startLink;
@@ -176,8 +170,9 @@ public class UserImportController extends BasicController {
 				boolean hasChanges = false;
 				try {
 					if (runContext.containsKey("validImport") && ((Boolean) runContext.get("validImport")).booleanValue()) {
-						// create new users and persist 
-						newIdents = (List<List<String>>) runContext.get("newIdents");
+						// create new users and persist
+						@SuppressWarnings("unchecked")
+						List<List<String>> newIdents = (List<List<String>>) runContext.get("newIdents");
 						for (Iterator<List<String>> it_news = newIdents.iterator(); it_news.hasNext();) {
 							List<String> singleUser = it_news.next();
 							doCreateAndPersistIdentity(singleUser);
@@ -187,12 +182,13 @@ public class UserImportController extends BasicController {
 						List<Long> ownGroups = (List<Long>) runContext.get("ownerGroups");
 						@SuppressWarnings("unchecked")
 						List<Long> partGroups = (List<Long>) runContext.get("partGroups");
-						@SuppressWarnings("unchecked")
-						List<Long> mailGroups = (List<Long>) runContext.get("mailGroups");
 
-						if (ownGroups.size() != 0 || partGroups.size() != 0){
+						if (ownGroups.size() > 0 || partGroups.size() > 0){
+							@SuppressWarnings("unchecked")
 							List<Object> allIdents = (List<Object>) runContext.get("idents");
-							processGroupAdditionForAllIdents(allIdents, ownGroups, partGroups, mailGroups);
+							Boolean sendMailObj = (Boolean)runContext.get("sendMail");
+							boolean sendmail = sendMailObj == null ? true : sendMailObj.booleanValue();
+							processGroupAdditionForAllIdents(allIdents, ownGroups, partGroups, sendmail);
 						}
 						hasChanges = true;
 					}
@@ -230,7 +226,7 @@ public class UserImportController extends BasicController {
 		return identities;
 	}
 
-	private void processGroupAdditionForAllIdents(List<Object> allIdents, List<Long> tutorGroups, List<Long> partGroups, List<Long> mailGroups) {
+	private void processGroupAdditionForAllIdents(List<Object> allIdents, List<Long> tutorGroups, List<Long> partGroups, boolean sendmail) {
 		Collection<Identity> identities = getIdentities(allIdents);
 		List<BusinessGroupMembershipChange> changes = new ArrayList<BusinessGroupMembershipChange>();
 		for(Identity identity:identities) {
@@ -249,22 +245,9 @@ public class UserImportController extends BasicController {
 				}
 			}
 		}
-		businessGroupService.updateMemberships(getIdentity(), changes, null);
-		DBFactory.getInstance().commit();
 		
-		if(mailGroups != null && !mailGroups.isEmpty()) {
-			List<BusinessGroup> notifGroups = businessGroupService.loadBusinessGroups(mailGroups);
-			for (BusinessGroup group : notifGroups) {
-				for(Identity identity:identities) {
-					MailTemplate mailTemplate = BGMailHelper.createAddParticipantMailTemplate(group, getIdentity());
-					MailerWithTemplate mailer = MailerWithTemplate.getInstance();
-					MailerResult mailerResult = mailer.sendMailAsSeparateMails(null, Collections.singletonList(identity), null, mailTemplate, null);
-					if (mailerResult.getReturnCode() != MailerResult.OK && isLogDebugEnabled()) {
-						logDebug("Problems sending Group invitation mail for identity: " + identity.getName() + " and group: " 
-								+ group.getName() + " key: " + group.getKey() + " mailerresult: " + mailerResult.getReturnCode(), null);
-					}
-				}
-			}
-		}
+		MailPackage mailing = new MailPackage(sendmail);
+		businessGroupService.updateMemberships(getIdentity(), changes, mailing);
+		DBFactory.getInstance().commit();
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties
index be5f3532c1ae933ddea12a5a67ab4afaf827bab9..67141bc89cb3608cd3580df1f5e8447cda382eae 100644
--- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_de.properties
@@ -36,6 +36,11 @@ step1.description=Vorschau der Benutzerdaten
 step1.nonewusers=Die Tabelle enth\u00E4lt keine neuen Benutzer. Sie k\u00F6nnen keine Benutzer importieren.
 step1.short.descr=Vorschau
 step2.description=Gruppe(n) auswählen
+step3.description=E-Mail-Benachrichtigung
+step3.short.description=E-Mail-Benachrichtigung
+step3.send.label=
+step3.send.mail=E-Mail versenden
+step3.send.mail.description=$org.olat.group.ui.main\:dialog.modal.bg.send.mail
 submit.import=Speichern
 table.user.existing=Neuer Benutzer?
 table.user.lang=Sprache
diff --git a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties
index 12eb5778a33739a76c4fabd6c618ea203a07f3f8..08f2e91dc5c085aee9ca5f8204cf20aa4223628d 100644
--- a/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/admin/user/imp/_i18n/LocalStrings_en.properties
@@ -36,6 +36,11 @@ step1.description=Preview of user data
 step1.nonewusers=There are no new users in this table. You will not be able to import new users.
 step1.short.descr=Preview
 step2.description=Choose group(s)
+step3.description=E-Mail notification
+step3.short.description=E-Mail notification
+step3.send.label=
+step3.send.mail=Send E-Mail
+step3.send.mail.description=$org.olat.group.ui.main\:dialog.modal.bg.send.mail
 submit.import=Save
 table.user.existing=New user?
 table.user.lang=Language
diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
index b4ce49317528d1fa49448b7397ffde5e27c3b42e..5788e528419c4c5a7f644ac7ed9e74355f47edb6 100644
--- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
+++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java
@@ -911,7 +911,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity {
 	private void notifyNewIdentityCreated(Identity newIdentity) {
 		//Save the identity on the DB. So can the listeners of the event retrieve it
 		//in cluster mode
-		DBFactory.getInstance().intermediateCommit();
+		DBFactory.getInstance().commit();
 		CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new NewIdentityCreatedEvent(newIdentity), IDENTITY_EVENT_CHANNEL);
 	}
 
@@ -1757,20 +1757,20 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity {
 	 * @see org.olat.basesecurity.Manager#saveIdentityStatus(org.olat.core.id.Identity)
 	 */
 	@Override
-	@Transactional
 	public Identity saveIdentityStatus(Identity identity, Integer status) {
 		Identity reloadedIdentity = loadForUpdate(identity.getKey()); 
 		reloadedIdentity.setStatus(status);
 		reloadedIdentity = dbInstance.getCurrentEntityManager().merge(reloadedIdentity);
+		dbInstance.commit();
 		return reloadedIdentity;
 	}
 	
 	@Override
-	@Transactional
 	public Identity setIdentityLastLogin(Identity identity) {
 		Identity reloadedIdentity = loadForUpdate(identity.getKey()); 
 		reloadedIdentity.setLastLogin(new Date());
 		reloadedIdentity = dbInstance.getCurrentEntityManager().merge(reloadedIdentity);
+		dbInstance.commit();
 		return reloadedIdentity;
 	}
 	
diff --git a/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterAdminControllerCluster.java b/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterAdminControllerCluster.java
index 42e7742c04b80f54c1f0bed0affbeaa162a389bd..9f180260bd7564f2ee70bb31661e88e561e35696 100644
--- a/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterAdminControllerCluster.java
+++ b/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterAdminControllerCluster.java
@@ -193,7 +193,7 @@ public class ClusterAdminControllerCluster extends BasicController {
 		releaseAllLocksFor = LinkFactory.createButtonSmall("releaseAllLocksFor", mainVc, this);
 		
 		mainVc.contextPut("eventBusListener", clusBus.toString());
-		mainVc.contextPut("busListenerInfos", clusBus.busInfos.getAsString());
+		mainVc.contextPut("busListenerInfos", clusBus.getBusInfosAsString());
 		
 		putInitialPanel(mainVc);
 	}
@@ -208,7 +208,7 @@ public class ClusterAdminControllerCluster extends BasicController {
 		nodeInfoVc.contextPut("stats",li);
 		nodeInfoVc.contextPut("thisNodeId", clusBus.clusterConfig.getNodeId());
 		mainVc.contextPut("eventBusListener", clusBus.toString());
-		mainVc.contextPut("busListenerInfos", clusBus.busInfos.getAsString());
+		mainVc.contextPut("busListenerInfos", clusBus.getBusInfosAsString());
 	}
 	
 	void updatePerfInfos() {
diff --git a/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterEventBus.java b/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterEventBus.java
index 8f3c141b62f50a2ced169e093a89e48bb1482f1f..966f0c252e8d8de8a906a077efa111db9a362f6b 100644
--- a/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterEventBus.java
+++ b/src/main/java/org/olat/commons/coordinate/cluster/jms/ClusterEventBus.java
@@ -26,7 +26,6 @@ package org.olat.commons.coordinate.cluster.jms;
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -40,20 +39,13 @@ import javax.jms.MessageProducer;
 import javax.jms.ObjectMessage;
 import javax.jms.Session;
 import javax.jms.Topic;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
 
 import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.gui.control.Event;
 import org.olat.core.id.OLATResourceable;
-import org.olat.core.logging.AssertException;
 import org.olat.core.logging.OLATRuntimeException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
-import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller;
 import org.olat.core.util.cluster.ClusterConfig;
 import org.olat.core.util.event.AbstractEventBus;
 import org.olat.core.util.event.GenericEventListener;
@@ -69,7 +61,7 @@ import org.olat.core.util.resource.OresHelper;
  * @author Felix Jost
  */
 public class ClusterEventBus extends AbstractEventBus implements MessageListener, GenericEventListener {
-	static OLog log = Tracing.createLoggerFor(ClusterEventBus.class);
+	private static final OLog log = Tracing.createLoggerFor(ClusterEventBus.class);
 	//ores helper is limited to 50 character, so truncate it
 	static final OLATResourceable CLUSTER_CHANNEL = OresHelper.createOLATResourceableType(ClusterEventBus.class.getName().substring(0, 50));
 
@@ -95,7 +87,7 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 	private int maxListSize = 10; // how many entries are kept in the outbound/inbound history. Just for administrative purposes
 	
 	// for bookkeeping how many resources have how many listeners
-	BusListenerInfos busInfos = new BusListenerInfos();
+	private final BusListenerInfos busInfos = new BusListenerInfos();
 	protected boolean isClusterInfoEventThreadRunning = true;
 	private ConnectionFactory connectionFactory;
 	private Topic destination;
@@ -110,9 +102,8 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 	private final SimpleProbe mrtgProbeJMSProcessingTime_ = new SimpleProbe();
 	
 	private final SimpleProbe mrtgProbeJMSEnqueueTime_ = new SimpleProbe();
-	final LinkedList<Object> incomingMessagesQueue_ = new LinkedList<Object>();
-	
-	private final static int LIMIT_ON_INCOMING_MESSAGE_QUEUE = 200;
+	//final LinkedList<Object> incomingMessagesQueue_ = new LinkedList<Object>();
+	//private final static int LIMIT_ON_INCOMING_MESSAGE_QUEUE = 200;
 	
 	/**
 	 * [used by spring]
@@ -166,9 +157,9 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 		t.setDaemon(true); // VM can shutdown even when this thread is still running
 		t.start();
 		// register to listen for other nodes' clusterinfoevents
-		this.registerFor(this, null, CLUSTER_CHANNEL);
-		
+		registerFor(this, null, CLUSTER_CHANNEL);
 		
+		/*
 		Thread serveThread = new Thread(new Runnable() {
 
 			public void run() {
@@ -210,6 +201,7 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 		});
 		serveThread.setDaemon(true);
 		serveThread.start();
+		*/
 	}
 	
 	public SimpleProbe getMrtgProbeJMSDeliveryTime() {
@@ -271,13 +263,12 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 		
 		nodeId = clusterConfig.getNodeId();
 		try {
-			//<XXX> TODO: cg/18.11.2008 ev JMS performance bottleneck; Do not check message-sequence => remove sync-block
-			synchronized (this) { //cluster_ok needed, not atomar read in one vm
+			//TODO jms synchronized (this) { //cluster_ok needed, not atomar read in one vm
 				msgId = ++latestSentMsgId;
 				ObjectMessage message = session.createObjectMessage();
 				message.setObject(new JMSWrapper(nodeId, msgId, ores, event));
 				producer.send(message);
-			}
+			//TODO jms }
 		} catch (Exception e) {
 			// cluster:::: what shall we do here: the JMS bus is broken! and we thus cannot know if other nodes are alive.
 			// if we are the only node running, then we could continue.
@@ -303,7 +294,7 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 	 * we receive a message here on the topic reserved for olat system bus messages. 
 	 */
 	public void onMessage(Message message) {
-		synchronized(incomingMessagesQueue_) {
+		/*synchronized(incomingMessagesQueue_) {
 			while(incomingMessagesQueue_.size()>LIMIT_ON_INCOMING_MESSAGE_QUEUE) {
 				try {
 					incomingMessagesQueue_.wait();
@@ -314,6 +305,20 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 			incomingMessagesQueue_.addFirst(message);
 			incomingMessagesQueue_.addFirst(System.currentTimeMillis());
 			incomingMessagesQueue_.notifyAll();
+		}*/
+		
+		try{
+			serveMessage(message, -1);
+		} catch(RuntimeException re) {
+			log.error("RuntimeException enountered by serve-thread:", re);
+		} catch(Error er) {
+			log.error("Error enountered by serve-thread:", er);
+		} finally {
+			try {
+				DBFactory.getInstance().commitAndCloseSession();
+			} catch (Exception e) {
+				log.error("", e);
+			}
 		}
 	}
 	
@@ -353,11 +358,12 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 			OLATResourceable ores = jmsWrapper.getOres();
 			boolean fromSameNode = clusterConfig.getNodeId().equals(nodeId);
 
-			// update nodeinfo statistics
-			NodeInfo nodeInfo = getNodeInfoFor(nodeId);
-			if (!nodeInfo.update(jmsWrapper)) {
-				log.warn("onMessage: update failed. clustereventbus: "+this);
-			}
+			//TODO jms update nodeinfo statistics, this doesn't work because we remove
+			//all the synchronization in the event bus
+			/* NodeInfo nodeInfo = getNodeInfoFor(nodeId);
+			if (log.isDebug() && !nodeInfo.update(jmsWrapper)) {
+				log.debug("onMessage: update failed. clustereventbus: "+this);
+			}*/
 
 			String recMsg = "received msg: "+(fromSameNode? "[same node]":"")+" from node:" + 
 			nodeId + ", olat-id:" + jmsWrapper.getMsgId() + ", ores:" + ores.getResourceableTypeName() + ":" + ores.getResourceableId() +
@@ -382,7 +388,6 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 			//TODO jms if (!fromSameNode) {
 				// distribute the unmarshalled event to all JVM wide listeners for this channel.
 				doFire(event, ores);
-				DBFactory.getInstance(false).commitAndCloseSession();
 			//TODO jms } // else message already sent "in-vm"
 			
 			// stats
@@ -451,7 +456,7 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 	 * cluster:::: to be improved: this is just a quick solution to output all data from all nodes
 	 * @return jmx-readable data of all statistics of all foreign cluster nodes
 	 */
-	public CompositeDataSupport getForeignClusterNodeStatistics() {
+	/*public CompositeDataSupport getForeignClusterNodeStatistics() {
 		Map<String, String> p = new HashMap<String, String>();
 		for (Integer key : nodeInfos.keySet()) {
 			NodeInfo fns = nodeInfos.get(key);
@@ -478,7 +483,7 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 		} catch (OpenDataException e) {
 			throw new AssertException("problem with jmx data generation", e);
 		}
-	}
+	}*/
 	
 	Map<Integer, NodeInfo> getNodeInfos() {
 		return nodeInfos;
@@ -516,6 +521,10 @@ public class ClusterEventBus extends AbstractEventBus implements MessageListener
 		}
 	}
 	
+	public String getBusInfosAsString() {
+		return busInfos.getAsString();
+	}
+	
 	/**
 	 * @return the copied list of the latest "maxListSize" received messages (copied so that iterating is failsafe)
 	 */
diff --git a/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLockManager.java b/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLockManager.java
index 1bd69c58a50df2e92e9f0448dcf22e7c59af5538..82b41a86c17a76462a0ef300ab1e69d5e198684c 100644
--- a/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLockManager.java
+++ b/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLockManager.java
@@ -26,13 +26,12 @@ package org.olat.commons.coordinate.cluster.lock;
 
 import java.util.List;
 
-import org.hibernate.type.StandardBasicTypes;
-import org.olat.core.commons.persistence.DBFactory;
-import org.olat.core.commons.persistence.DBQuery;
+import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.manager.BasicManager;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -48,6 +47,9 @@ public class ClusterLockManager extends BasicManager {
 	
 	private static final OLog log = Tracing.createLoggerFor(ClusterLockManager.class);
 	
+	@Autowired
+	private DB dbInstance;
+	
 	/**
 	 * [spring]
 	 */
@@ -65,16 +67,17 @@ public class ClusterLockManager extends BasicManager {
 	
 	LockImpl findLock(String asset) {
 		log.info("findLock: "+asset+" START");
-		DBQuery q = DBFactory.getInstance().createQuery(
-				"select alock from org.olat.commons.coordinate.cluster.lock.LockImpl as alock inner join fetch alock.owner where alock.asset = :asset");
-		q.setParameter("asset", asset);
-		List res = q.list();
+		StringBuilder sb = new StringBuilder();
+		sb.append("select alock from org.olat.commons.coordinate.cluster.lock.LockImpl as alock inner join fetch alock.owner where alock.asset=:asset");
+
+		List<LockImpl> res = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), LockImpl.class)
+				.setParameter("asset", asset).getResultList();
 		if (res.size() == 0) {
 			log.info("findLock: null END");
 			return null; 
 		} else {
 			log.info("findLock: "+res.get(0)+" END");
-			return (LockImpl) res.get(0);
+			return res.get(0);
 		}
 	}
 		
@@ -85,22 +88,21 @@ public class ClusterLockManager extends BasicManager {
 	
 	void saveLock(LockImpl alock) {
 		log.info("saveLock: "+alock+" START");
-		DBFactory.getInstance().saveObject(alock);
+		dbInstance.getCurrentEntityManager().persist(alock);
 		log.info("saveLock: "+alock+" END");
 	}
 
 	void deleteLock(LockImpl li) {
 		log.info("deleteLock: "+li+" START");
-		DBFactory.getInstance().deleteObject(li);		
+		dbInstance.getCurrentEntityManager().remove(li);		
 		log.info("deleteLock: "+li+" END");
 	}
 	
-	@SuppressWarnings("unchecked")
 	List<LockImpl> getAllLocks() {
 		log.info("getAllLocks START");
-		DBQuery q = DBFactory.getInstance().createQuery(
-				"select alock from org.olat.commons.coordinate.cluster.lock.LockImpl as alock inner join fetch alock.owner");
-		List<LockImpl> res = q.list();
+		StringBuilder sb = new StringBuilder();
+		sb.append("select alock from org.olat.commons.coordinate.cluster.lock.LockImpl as alock inner join fetch alock.owner");
+		List<LockImpl> res = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), LockImpl.class).getResultList();
 		log.info("getAllLocks END. res.length:"+ (res==null ? "null" : res.size()));
 		return res;
 	}
@@ -110,11 +112,14 @@ public class ClusterLockManager extends BasicManager {
 	 */
 	public void releaseAllLocksFor(Long identityKey) {
 		log.info("releaseAllLocksFor: " + identityKey + " START");	
-		DBFactory.getInstance().delete("from org.olat.commons.coordinate.cluster.lock.LockImpl as alock inner join fetch " +
-				"alock.owner as owner where owner.key = ?", identityKey, StandardBasicTypes.LONG);
+		StringBuilder sb = new StringBuilder();
+		sb.append("delete from org.olat.commons.coordinate.cluster.lock.LockImpl alock where alock.owner.key=:ownerKey");
+		int locks = dbInstance.getCurrentEntityManager().createQuery(sb.toString())
+			.setParameter("ownerKey", identityKey)
+			.executeUpdate();
 		// cluster:: can we save a query (and is it appropriate considering encapsulation) 
 		// here by saying: alock.owner as owner where owner.name = ? (using identName parameter)
-		log.info("releaseAllLocksFor: "+identityKey+" END");
+		log.info("releaseAllLocksFor: "+identityKey+" END (" + locks + " locks deleted)");
 	}
 
 }
diff --git a/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLocker.java b/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLocker.java
index 1bff9b4c659c484f10e1617f3f2c55e92c9616df..77203947623b305bc1a14d359e47f06bc64cbbfa 100644
--- a/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLocker.java
+++ b/src/main/java/org/olat/commons/coordinate/cluster/lock/ClusterLocker.java
@@ -41,7 +41,6 @@ import org.olat.core.util.coordinate.LockEntry;
 import org.olat.core.util.coordinate.LockResult;
 import org.olat.core.util.coordinate.LockResultImpl;
 import org.olat.core.util.coordinate.Locker;
-import org.olat.core.util.coordinate.PersistentLockManager;
 import org.olat.core.util.coordinate.Syncer;
 import org.olat.core.util.coordinate.SyncerCallback;
 import org.olat.core.util.event.EventBus;
@@ -61,8 +60,7 @@ import org.olat.resource.lock.pessimistic.PessimisticLockManager;
 // Must be abstract because Spring configuration of method 'getPersistentLockManager' :
 // to avoid circular reference method lookup is used for dependecy injection of persistent lock manager
 public abstract class ClusterLocker implements Locker, GenericEventListener {
-	protected OLog log = Tracing.createLoggerFor(this.getClass());
-	PersistentLockManager plm = null;
+	private static final OLog log = Tracing.createLoggerFor(ClusterLocker.class);
 
 	private Syncer syncer;
 	private EventBus eventBus;
@@ -136,6 +134,7 @@ public abstract class ClusterLocker implements Locker, GenericEventListener {
 			// since the lock is reentrant, a lock could be freed while a session still is in a locked workflow (2x lock and then once freed)
 			try {
 				clusterLockManager.releaseAllLocksFor(identKey);
+				DBFactory.getInstance().commit();
 			} catch (DBRuntimeException dbEx) {
 				log.warn("releaseAllLocksFor failed, close session and try it again for identName=" + identKey);
 				//TODO: 2010-04-23 Transactions [eglis]: OLAT-4318: this rollback has possibly unwanted
diff --git a/src/main/java/org/olat/commons/coordinate/cluster/lock/LockImpl.java b/src/main/java/org/olat/commons/coordinate/cluster/lock/LockImpl.java
index 354d96cae37cab14aa3dd31f562c0b4f417d8c95..452dcfe38f8ad4d69b4f77b3ea9b0492fd2b62b7 100644
--- a/src/main/java/org/olat/commons/coordinate/cluster/lock/LockImpl.java
+++ b/src/main/java/org/olat/commons/coordinate/cluster/lock/LockImpl.java
@@ -39,6 +39,7 @@ import org.olat.core.logging.AssertException;
  */
 public class LockImpl extends PersistentObject {
 
+	private static final long serialVersionUID = 1978265978735682673L;
 	private Identity owner;
 	private String asset;
 	private String nodeId;
@@ -91,4 +92,20 @@ public class LockImpl extends PersistentObject {
 		this.nodeId = nodeId;
 	}
 
+	@Override
+	public int hashCode() {
+		return getKey() == null ? 39746 : getKey().hashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof LockImpl) {
+			LockImpl lock = (LockImpl)obj;
+			return getKey() != null && getKey().equals(lock.getKey());
+		}
+		return false;
+	}
 }
diff --git a/src/main/java/org/olat/commons/info/portlet/InfoMessagePortletRunController.java b/src/main/java/org/olat/commons/info/portlet/InfoMessagePortletRunController.java
index 3c9e6b3b525d7d17f21bc0c6dfa6c4adaa3289eb..ff5f5f12953a472fea671e7dc7e68b55e4e38bfb 100644
--- a/src/main/java/org/olat/commons/info/portlet/InfoMessagePortletRunController.java
+++ b/src/main/java/org/olat/commons/info/portlet/InfoMessagePortletRunController.java
@@ -127,6 +127,7 @@ public class InfoMessagePortletRunController extends AbstractPortletRunControlle
 	@Override
 	public void event(Event event) {
 		if("new_info_message".equals(event.getCommand())) {
+			System.out.println(this.getIdentity().getName());
 			reloadModel(sortingCriteria);
 		}
 	}
diff --git a/src/main/java/org/olat/core/CoreBeanTypes.java b/src/main/java/org/olat/core/CoreBeanTypes.java
index 9cfdc5492571d8aa4d8b4620cde92d4ab6d736af..31a4a82ffbc76f14538ba86b9e0ccbf45e472f9a 100644
--- a/src/main/java/org/olat/core/CoreBeanTypes.java
+++ b/src/main/java/org/olat/core/CoreBeanTypes.java
@@ -26,7 +26,6 @@
 
 package org.olat.core;
 
-import org.olat.core.commons.persistence.AdditionalDBMappings;
 import org.olat.core.extensions.Extension;
 import org.olat.core.gui.control.generic.portal.Portlet;
 import org.olat.core.gui.control.navigation.SiteDefinition;
@@ -43,8 +42,7 @@ public enum CoreBeanTypes implements BeanType {
 	siteDefinition(SiteDefinition.class),
 	basicManager(BasicManager.class),
 	portlet(Portlet.class),
-	notificationsHandler(NotificationsHandler.class),
-	additionalDBMappings(AdditionalDBMappings.class);
+	notificationsHandler(NotificationsHandler.class);
 
 	
 	private Class extensionType;
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_ar.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_ar.properties
index fd5fe4eff4c9b78dd6b13bef68d57da0d10a58e3..4525c982b2a735b8dde564e3fb1092b297d5879a 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_ar.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_ar.properties
@@ -60,7 +60,7 @@ save=\u062D\u0641\u0638
 savesas=\u062D\u0641\u0638 \u0628\u0627\u0633\u0645
 search=\u0628\u062D\u062B
 select=\u0627\u062E\u062A\u064A\u0627\u0631
-server.no.response=\u0644\u0627 \u062A\u0648\u062C\u062F \u0627\u0633\u062A\u062C\u0627\u0628\u0629 \u0645\u0646 \u0627\u0644\u0633\u064A\u0631\u0641\u0631 \u0623\u0648 \u0645\u0646 \u0645\u062A\u0635\u0641\u062D\u0643 \u0644\u0645\u062F\u0629 \u0637\u0648\u064A\u0644\u0629\u060C \u0633\u064A\u062A\u0645 \u0625\u0639\u0627\u062F\u0629 \u062A\u062D\u0645\u064A\u0644 \u0647\u0630\u0647 \u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u0622\u0646.
+
 start=\u0623\u0628\u062F\u0623
 submit=\u062D\u0641\u0638
 table.action=\u0646\u0634\u0627\u0637
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_bg.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_bg.properties
index 8781518224a67ce9017b83b5dfbbc7a220a37dcf..be05cca71c0e23304bef4bdf2b37d694a182132a 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_bg.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_bg.properties
@@ -59,7 +59,7 @@ save=\u0417\u0430\u043F\u0430\u0437\u0435\u0442\u0435
 savesas=\u0417\u0430\u043F\u0430\u0437\u0435\u0442\u0435 \u043A\u0430\u0442\u043E
 search=\u0422\u044A\u0440\u0441\u0435\u0442\u0435
 select=\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435
-server.no.response=\u041D\u044F\u043C\u0430 \u043E\u0442\u0433\u043E\u0432\u043E\u0440 \u043E\u0442 \u0441\u044A\u0440\u0432\u044A\u0440\u0430 \u0438\u043B\u0438 \u0432\u0430\u0448\u0438\u044F\u0442 \u0431\u0440\u0430\u0443\u0437\u044A\u0440 \u043D\u0435 \u0440\u0435\u0430\u0433\u0438\u0440\u0430 \u043F\u043E\u0432\u0435\u0447\u0435. \u0422\u0430\u0437\u0438 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u0449\u0435 \u0431\u044A\u0434\u0435 \u043F\u0440\u0435\u0437\u0430\u0440\u0435\u0434\u0435\u043D\u0430.
+
 start=\u041E\u0442\u0432\u043E\u0440\u0435\u0442\u0435
 submit=\u0417\u0430\u043F\u0430\u0437\u0435\u0442\u0435
 table.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_cs.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_cs.properties
index d1c617561b985a5c41612346b7dcae7d0915ed95..1ad7815b1678c6961a93fd94d849f09d07fbcc7f 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_cs.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_cs.properties
@@ -59,7 +59,7 @@ save=Ulo\u017Eit
 savesas=Ulo\u017Eit jako
 search=Vyhledat
 select=Vybrat
-server.no.response=Server neodpov\u00EDd\u00E1 nebo prohl\u00ED\u017Ee\u010D nereaguje. Tato st\u00E1nka bude nyn\u00ED obnovena.
+
 start=Start
 submit=Ulo\u017Eit
 table.action=Akce
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_da.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_da.properties
index 9ca5446cc721a9bfae1cfc0d704b804e924ee625..42bc893552d34374b7808aa76a06fafcf20afe85 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_da.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_da.properties
@@ -39,7 +39,7 @@ save=Gem
 savesas=Gem som
 search=S\u00F8g
 select=V\u00E6lg
-server.no.response=Der er ikke noget svar fra serveren eller din browser reagerer ikke l\u00E6ngere. Denne side vil nu blive genindl\u00E6st.
+
 submit=Send
 table.action=Handling
 table.backward=Tilbage
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_de.properties
index af3d5def610262027108a4cf23023239f86deca6..75940b27c1be527a4a1c3ad9fbe149ddc250b7a5 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_de.properties
@@ -61,7 +61,8 @@ save=Speichern
 savesas=Speichern unter
 search=Suchen
 select=Ausw\u00E4hlen
-server.no.response=Der Server antwortet nicht oder Ihr Browser reagiert nicht mehr. Die Seite wird nun neu geladen.
+server.no.response.title=Kommunikationsfehler
+server.no.response=Die Aktion konnte nicht ausgeführt werden da der Server nicht antwortet oder überlastet ist. Versuchen Sie die Aktion erneut durchzuführen oder laden Sie die Seite neu.
 start=Start
 submit=Speichern
 table.action=Aktion
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_el.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_el.properties
index 48a4cd838237005bd755de9030cf318649675b8c..7500e9b7d4d3d1c81bad14c8b61045c48def73c2 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_el.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_el.properties
@@ -60,7 +60,7 @@ save=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7
 savesas=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7 \u03C9\u03C2
 search=\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7
 select=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE
-server.no.response=\u0394\u03B5\u03BD \u03C5\u03C0\u03AC\u03C1\u03C7\u03B5\u03B9 \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7 \u03B1\u03C0\u03CC \u03C4\u03BF\u03BD \u03B5\u03BE\u03C5\u03C0\u03B7\u03C1\u03B5\u03C4\u03B7\u03C4\u03AE \u03AE \u03BF \u03C6\u03C5\u03BB\u03BB\u03BF\u03BC\u03B5\u03C4\u03C1\u03B7\u03C4\u03AE\u03C2 \u03C3\u03B1\u03C2 \u03B4\u03B5\u03BD \u03B1\u03BD\u03C4\u03B9\u03B4\u03C1\u03AC \u03C0\u03B9\u03B1. \u0397 \u03C3\u03B5\u03BB\u03AF\u03B4\u03B1 \u03B1\u03C5\u03C4\u03AE \u03B8\u03B1 \u03B5\u03C0\u03B1\u03BD\u03B1\u03C6\u03BF\u03C1\u03C4\u03C9\u03B8\u03B5\u03AF.
+
 start=\u0388\u03BD\u03B1\u03C1\u03BE\u03B7
 submit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
 table.action=\u0395\u03BD\u03AD\u03C1\u03B3\u03B5\u03B9\u03B1
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_en.properties
index 7be8194cf81a1e764cdbd35ab89c535c45aa4733..1c4a544afc7ed83bb94fdf42ad17d296f5cc4e66 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_en.properties
@@ -61,7 +61,8 @@ save=Save
 savesas=Save as
 search=Search
 select=Select
-server.no.response=There is no response from the server or your browser does not react any longer. This page will now be reloaded.
+server.no.response.title=Communication error
+server.no.response=The requested action could not be executed since the server does not respond or is overloaded. Please try to execute the action again or reload the page. 
 start=Start
 submit=Save
 table.action=Action
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_es.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_es.properties
index 4d3dd8311c8fc0ef0296ca1be6d65050db2ac67f..e4c5638ea4be664cdd58b6e2936f315af8338e7f 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_es.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_es.properties
@@ -59,7 +59,7 @@ save=Guardar
 savesas=Guardar como
 search=Buscar
 select=Seleccionar
-server.no.response=El servidor no responde o su navegador est\u00E1 bloqueado. La p\u00E1gina ser\u00E1 cargada de nuevo.
+
 start=Inicio
 submit=Guardar
 table.action=Acci\u00F3n
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_fr.properties
index 095abbb25f30343a447586033b94af4a716212e9..1911b86b4dc2edc387425e5c7dedff8bcd416484 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_fr.properties
@@ -61,7 +61,7 @@ save=Enregistrer
 savesas=Sauvegarder sous
 search=Chercher
 select=S\u00E9lectionner
-server.no.response=Le serveur ne r\u00E9pond pas ou votre navigateur ne r\u00E9agit plus. La page est maintenant recharg\u00E9e.
+
 start=D\u00E9part
 submit=Enregistrer
 table.action=Action
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_it.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_it.properties
index 4c78a2b0f4e76c3f104a11e1476e779c5ca756cd..610b7db5c1e065010fde102c4992fc6401844060 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_it.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_it.properties
@@ -61,7 +61,7 @@ save=Salvare
 savesas=Salvare come
 search=Cercare
 select=Selezionare
-server.no.response=Il server non risponde o il Suo browser non reagisce. La pagina viene ricaricata.
+
 start=Avviare
 submit=Salvare
 table.action=Azione
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_jp.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_jp.properties
index 925a5cc185d47af4c4a256757d04ff186db3fd8d..756188ca420933e3ee8d2233e6360993229086f1 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_jp.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_jp.properties
@@ -60,7 +60,7 @@ save=\u4FDD\u5B58
 savesas=\u540D\u524D\u3092\u4ED8\u3051\u3066\u4FDD\u5B58\u3059\u308B
 search=\u691C\u7D22
 select=\u9078\u629E
-server.no.response=\u30B5\u30FC\u30D0\u304B\u3089\u30EC\u30B9\u30DD\u30F3\u30B9\u304C\u306A\u3044\u304B\u3001\u3042\u306A\u305F\u306E\u30D6\u30E9\u30A6\u30B6\u304C\u3053\u308C\u4EE5\u4E0A\u53CD\u5FDC\u3057\u306A\u3044\u3088\u3046\u3067\u3059\u3002\u3053\u306E\u30DA\u30FC\u30B8\u306F\u3001\u30EA\u30ED\u30FC\u30C9\u3055\u308C\u307E\u3059\u3002
+
 start=\u30B9\u30BF\u30FC\u30C8
 submit=\u4FDD\u5B58
 table.action=\u64CD\u4F5C
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_nl_NL.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_nl_NL.properties
index 00128ebf099d382c257a838e741bbe940ecb2478..62917bd823a103df1b3bacbced0aa0d8459712d3 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_nl_NL.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_nl_NL.properties
@@ -60,7 +60,7 @@ save=Opslaan
 savesas=Opslaan als
 search=Zoeken
 select=Selecteren
-server.no.response=De server geeft geen response of uw browser reageert niet meer. Deze pagina wordt nu opnieuw geladen.
+
 start=Start
 submit=Opslaan
 table.action=Actie
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_pl.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_pl.properties
index bc3c5ff574e4da22f3194b05a2d089ba737d65e0..cdea42180e828acdf83a03cd025c3ba632860f49 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_pl.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_pl.properties
@@ -61,7 +61,7 @@ save=Zapisz
 savesas=Zapisz jako
 search=Szukaj
 select=Wybierz
-server.no.response=Nast\u0105pi\u0142o chwilowe zerwanie \u0142\u0105czno\u015Bci z serwerem lub Twoja przegl\u0105darka nie reaguje na \u017C\u0105dania serwera. Prosz\u0119 czeka\u0107 - strona b\u0119dzie ponownie za\u0142adowana...
+
 start=Start
 submit=Zapisz
 table.action=Akcja
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_pt_BR.properties
index a38db4b71a8c03263618a2ccb6ae48bf10feefa5..cd85666dee4c8969eed7fafa9c17b8b33451dc97 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_pt_BR.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_pt_BR.properties
@@ -61,7 +61,7 @@ save=Salvar
 savesas=Salvar como
 search=Buscar
 select=Selecionar
-server.no.response=N\u00E3o h\u00E1 resposta do servidor ou seu browser n\u00E3o est\u00E1 respondendo.  Esta p\u00E1gina ser\u00E1 recarregada.
+
 start=Iniciar
 submit=Salvar
 table.action=A\u00E7\u00E3o
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_pt_PT.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_pt_PT.properties
index 86bc392af76582f7f5ee3fa5188e6bda7678b781..527d4d16bef8afcf247858828441056514488cf1 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_pt_PT.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_pt_PT.properties
@@ -39,7 +39,7 @@ save=Salvar
 savesas=Salvar como
 search=Buscar
 select=Selecionar
-server.no.response=N\u00E3o h\u00E1 resposta do servidor ou seu browser n\u00E3o est\u00E1 respondendo.  Esta p\u00E1gina ser\u00E1 recarregada.
+
 submit=Salvar
 table.action=A\u00E7\u00E3o
 table.backward=Voltar
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_ru.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_ru.properties
index 1608eb5876b8effef60e75963c7c6bc7ad0e692e..b3467b98cea2095541fd7cdf80567668b37b35ec 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_ru.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_ru.properties
@@ -61,7 +61,7 @@ save=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C
 savesas=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043A\u0430\u043A
 search=\u041F\u043E\u0438\u0441\u043A
 select=\u0412\u044B\u0431\u0440\u0430\u0442\u044C
-server.no.response=\u0421\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u043E\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0438\u043B\u0438 \u0412\u0430\u0448 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u0442. \u042D\u0442\u0430 \u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u0430 \u0435\u0449\u0451 \u0440\u0430\u0437. 
+
 start=\u0421\u0442\u0430\u0440\u0442
 submit=\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C
 table.action=\u041E\u043F\u0435\u0440\u0430\u0446\u0438\u044F
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_sq.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_sq.properties
index 1eb9891a9619d192ccf96ac0fe378368b3c2d6d7..295f42a74beac3fb944f46659e98fbed68654521 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_sq.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_sq.properties
@@ -59,7 +59,7 @@ save=Ruaj
 savesas=Ruaj si
 search=K\u00EBrko
 select=P\u00EBrzgjedh
-server.no.response=Nuk ka p\u00EBrgjigje prej serveri ose shfletuesi juaj tanim\u00EB nuk \u00EBsht\u00EB duke reaguar. Kjo tani faqe do t\u00EB ringarkohet.
+
 start=Nis
 submit=Ruaj
 table.action=Aksioni
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_zh_CN.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_zh_CN.properties
index 223ac68a8ab746bb4f416f37c70e703b1a29ff56..a0c0a676187b1477d1870762a16209b193e100e4 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_zh_CN.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_zh_CN.properties
@@ -60,7 +60,7 @@ save=\u4FDD\u5B58
 savesas=\u53E6\u5B58\u4E3A
 search=\u641C\u7D22
 select=\u9009\u62E9
-server.no.response=\u670D\u52A1\u5668\u6CA1\u6709\u53CD\u5E94\u6216\u60A8\u7684\u6D4F\u89C8\u5668\u957F\u65F6\u95F4\u6CA1\u6709\u64CD\u4F5C\u3002\u672C\u9875\u73B0\u5728\u4F1A\u88AB\u91CD\u65B0\u8F7D\u5165\u3002
+
 start=\u5F00\u59CB
 submit=\u4FDD\u5B58
 table.action=\u64CD\u4F5C
diff --git a/src/main/java/org/olat/core/_i18n/LocalStrings_zh_TW.properties b/src/main/java/org/olat/core/_i18n/LocalStrings_zh_TW.properties
index c224b902b0f73a66e7b9535baa114cbd4af5c6f4..c155fc8e5d9dd262a1a80cc3f6e043fd5c864f3d 100644
--- a/src/main/java/org/olat/core/_i18n/LocalStrings_zh_TW.properties
+++ b/src/main/java/org/olat/core/_i18n/LocalStrings_zh_TW.properties
@@ -60,7 +60,7 @@ save=\u5132\u5B58
 savesas=\u53E6\u5B58\u65B0\u6A94
 search=\u641C\u5C0B
 select=\u9078\u64C7
-server.no.response=\u4F3A\u670D\u5668\u6C92\u6709\u56DE\u61C9\u6216\u60A8\u7684\u700F\u89BD\u5668\u4E0D\u518D\u6709\u53CD\u61C9\u3002\u9019\u500B\u9801\u9762\u73FE\u5728\u5C07\u88AB\u91CD\u65B0\u8F09\u5165\u3002
+
 start=\u958B\u59CB
 submit=\u5132\u5B58
 table.action=\u52D5\u4F5C
diff --git a/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html b/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html
index e0c3bbd1fe2e43dfecad335178e0cb0ac47b825b..08d3ccce0a403b97a9f51ebc752f4d60ff62ea60 100644
--- a/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html
+++ b/src/main/java/org/olat/core/commons/chiefcontrollers/_content/body.html
@@ -34,6 +34,8 @@ o_info.drop = true;
 o_info.o_baseURI = "$r.staticLink("")";
 o_info.b_classPathStaticBaseURI = "${classPathStaticBaseURI}";
 o_info.b_textMarkingIframeIntervals = new Array();
+o_info.i18n_noresponse_title = "$r.escapeDoubleQuotes($r.translate("server.no.response.title"))";
+o_info.i18n_noresponse = "$r.escapeDoubleQuotes($r.translate("server.no.response"))";
 
 if (top!=self) {
 	top.location=self.location+"?o_winrndo=1";
diff --git a/src/main/java/org/olat/core/commons/persistence/AdditionalDBMappings.java b/src/main/java/org/olat/core/commons/persistence/AdditionalDBMappings.java
deleted file mode 100644
index f7ce832e0aaacb16bf955e91ba539fb6e4c1597c..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/core/commons/persistence/AdditionalDBMappings.java
+++ /dev/null
@@ -1,75 +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.persistence;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 
- * Description:<br>
- * Wrapper class for additional db mappings which will be loaded on startup.
- * Provide the list of annotated classes or hbm.xml files via spring config.
- * 
- * <P>
- * Initial Date:  23 jul. 2010 <br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- */
-public class AdditionalDBMappings {
-	
-	private List<Class<?>> annotatedClasses;
-	private List<String> xmlFiles;
-	
-	/**
-	 * [spring only]
-	 */
-	private AdditionalDBMappings() {/**/}
-	
-	public List<String> getXmlFiles() {
-		if(xmlFiles == null) {
-			xmlFiles = new ArrayList<String>();
-		}
-		return xmlFiles;
-	}
-	
-	/**
-	 * [spring]
-	 * @param xmlFiles
-	 */
-	public void setXmlFiles(List<String> xmlFiles) {
-		this.xmlFiles = xmlFiles;
-	}
-
-	public List<Class<?>> getAnnotatedClasses() {
-		if(annotatedClasses == null) {
-			annotatedClasses = new ArrayList<Class<?>>();
-		}
-		return annotatedClasses;
-	}
-
-	/**
-	 * [spring]
-	 * @param classes
-	 */
-	public void setAnnotatedClasses(List<Class<?>> classes) {
-		this.annotatedClasses = classes;
-	}
-}
diff --git a/src/main/java/org/olat/core/commons/persistence/AdditionalMappingsListFactoryBean.java b/src/main/java/org/olat/core/commons/persistence/AdditionalMappingsListFactoryBean.java
deleted file mode 100644
index eeadf5fa7bd270d16489ae2d52c4ed9390d3b869..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/core/commons/persistence/AdditionalMappingsListFactoryBean.java
+++ /dev/null
@@ -1,65 +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.persistence;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.olat.core.CoreBeanTypes;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * 
- * Description:<br>
- * FactoryBean
- * 
- * <P>
- * Initial Date:  23 jul. 2010 <br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- */
-public class AdditionalMappingsListFactoryBean implements FactoryBean<List>, ApplicationContextAware {
-	private ApplicationContext appCtx;
-
-	@Override
-	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-		this.appCtx = applicationContext;
-	}
-
-	@Override
-	public List<AdditionalDBMappings> getObject() throws Exception {
-		List<AdditionalDBMappings> result = new ArrayList<AdditionalDBMappings>();
-        result.addAll(appCtx.getBeansOfType(CoreBeanTypes.additionalDBMappings.getExtensionTypeClass(), false, false).values());
-        return result;
-	}
-
-	@Override
-	public Class<List> getObjectType() {
-		return List.class;
-	}
-
-	@Override
-	public boolean isSingleton() {
-		return false;
-	}
-}
diff --git a/src/main/java/org/olat/core/commons/persistence/DB.java b/src/main/java/org/olat/core/commons/persistence/DB.java
index 3bf3418dff35988682311f89fb7d744e3e75b7ff..505e0a0408f7c800aea0fe300ceb0964936972c6 100644
--- a/src/main/java/org/olat/core/commons/persistence/DB.java
+++ b/src/main/java/org/olat/core/commons/persistence/DB.java
@@ -44,7 +44,7 @@ public interface DB {
 	/**
 	 * Close the database session, clean threadlocal but only if necessary
 	 */
-	public void cleanUpSession();
+	//public void cleanUpSession();
 
 	/**
 	 * Create a DBQuery
@@ -162,18 +162,24 @@ public interface DB {
 	 */
 	public Persistable loadObject(Persistable persistable, boolean forceReloadFromDB);
 
+
 	/**
-	 * Checks if the transaction needs to be committed and does so if this is the case,
-	 * plus closes the connection in any case guaranteed.
-	 * <p>
-	 * Use this rather than commit() directly wherever possible!
+	 * Begin a new transaction (don't forget to commit the last one)
 	 */
-	public void commitAndCloseSession();
+	public void begin();
 	
 	/**
 	 * Call this to commit current changes.
 	 */
 	public void commit();
+	
+	/**
+	 * Checks if the transaction needs to be committed and does so if this is the case,
+	 * plus closes the connection in any case guaranteed.
+	 * <p>
+	 * Use this rather than commit() directly wherever possible!
+	 */
+	public void commitAndCloseSession();
   
 	/**
 	 * Calls rollback and closes the connection guaranteed.
diff --git a/src/main/java/org/olat/core/commons/persistence/DBFactory.java b/src/main/java/org/olat/core/commons/persistence/DBFactory.java
index a4e551d9789956bf8f5b57e2ab0622b7dc1d1c5c..98cd414b808773f5c8e557c1ec615bf06bf8f2d1 100644
--- a/src/main/java/org/olat/core/commons/persistence/DBFactory.java
+++ b/src/main/java/org/olat/core/commons/persistence/DBFactory.java
@@ -37,15 +37,15 @@ public class DBFactory {
 	 * @return the DB instance.
 	 */
 	public static DB getInstance() {
-		return DBImpl.getInstance(true);
+		return DBImpl.getInstance();
 	}
 
     public static DB getInstance(boolean initialize) {
-        return DBImpl.getInstance(initialize);
+        return DBImpl.getInstance();
     }
 
     public static DB getInstanceForClosing() {
-      return DBImpl.getInstanceForClosing();
+      return DBImpl.getInstance();
   }
 
 
diff --git a/src/main/java/org/olat/core/commons/persistence/DBImpl.java b/src/main/java/org/olat/core/commons/persistence/DBImpl.java
index 68dce32148d2b4526365fc18239dfedf61f562a0..20f17db9f9ab5380392f9b1cb2ee0c9375353286 100644
--- a/src/main/java/org/olat/core/commons/persistence/DBImpl.java
+++ b/src/main/java/org/olat/core/commons/persistence/DBImpl.java
@@ -37,6 +37,10 @@ import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.EntityTransaction;
 
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.ejb.HibernateEntityManager;
 import org.hibernate.ejb.HibernateEntityManagerFactory;
 import org.hibernate.stat.Statistics;
 import org.hibernate.type.Type;
@@ -64,8 +68,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	private static final int MAX_DB_ACCESS_COUNT = 500;
 	private static DBImpl INSTANCE;
 	
-	private final DBManager dbManagerDelegate = new DBManager();
-	
+	private String dbVendor;
 	private EntityManagerFactory emf;
 	private PlatformTransactionManager txManager;
 
@@ -79,6 +82,22 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	private DBImpl() {
 		INSTANCE = this;
 	}
+	
+	protected static DBImpl getInstance() {
+		return INSTANCE;
+	}
+	
+	@Override
+	public String getDbVendor() {
+		return dbVendor;
+	}
+	/**
+	 * [used by spring]
+	 * @param dbVendor
+	 */
+	public void setDbVendor(String dbVendor) {
+		this.dbVendor = dbVendor;
+	}
     
 	public void setEntityManagerFactory(EntityManagerFactory emf) {
 		this.emf = emf;
@@ -194,6 +213,14 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 		return em;
 	}
 	
+	private Session getSession(EntityManager em) {
+		return em.unwrap(HibernateEntityManager.class).getSession();
+	}
+	
+	private boolean unusableTrx(EntityTransaction trx) {
+		return trx == null || !trx.isActive() || trx.getRollbackOnly();
+	}
+	
 	private EntityManager getEntityManager() {
 		EntityManager txEm = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
 		if(txEm == null) {
@@ -273,9 +300,8 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	/**
 	 * Close the database session.
 	 */
+	@Override
 	public void closeSession() {
-		
-
 		getData().resetAccessCounter();
 		// Note: closeSession() now also checks if the connection is open at all
 		//  in OLAT-4318 a situation is described where commit() fails and closeSession()
@@ -312,68 +338,10 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 		}
 		data.remove();
 	}
-	
-	public void cleanUpSession() {
-		closeSession();
-	}
-
-	protected static DBImpl getInstance() {
-	  return getInstance(true);
-  }
-	/**
-	 * Get the DB instance. Initialisation is performed if flag is true.
-	 * 
-	 * @param initialize
-	 * @return the DB instance.
-	 */
-	protected static DBImpl getInstance(boolean initialize) {
-		/*
-		//OLAT-3621: paranoia check for error state: we need to catch errors at the earliest point possible. OLAT-3621 has a suspected situation
-		//           where an earlier transaction failed and didn't clean up nicely. To check this, we introduce error checking in getInstance here
-		EntityTransaction transaction = INSTANCE.getTransaction();
-		if (transaction!=null) {		
-			// Filter Exception form async TaskExecutorThread, there are exception allowed
-			if (transaction.isActive() && transaction.getRollbackOnly() && !Thread.currentThread().getName().equals("TaskExecutorThread")) {
-				INSTANCE.logWarn("getInstance: Transaction (still?) in Error state: "+transaction, new Exception("DBImpl begin transaction)"));
-			}
-		}  
-		
-		// if module is not active we return a non-initialized instance and take
-		// care that
-		// the only cleanup-calls to db.closeSession do nothing
-		if (initialize) {
-			INSTANCE.createSession();
-		}*/
-		return INSTANCE;
-	}
-
-	/**
-	 * Get db instance without checking transaction state
-	 * @return
-	 */
-	protected static DBImpl getInstanceForClosing() {
-		return INSTANCE;
-	}
-
-	/**
-	 * @return true if tread is initialized.
-	 */
-	boolean threadLocalsInitialized() {
-		return getData().isInitialized();
-	}
-
-	private void setInitialized(boolean initialized) {
-		getData().setInitialized(initialized);
-
-	}
-
-	boolean isInitialized() {
-		return getData().isInitialized();
-	}
   
 	private boolean contains(Object object) {
 		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.contains(em, object);
+		return em.contains(object);
 	}
 
 	/**
@@ -382,9 +350,16 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param query
 	 * @return DBQuery
 	 */
+	@Override
 	public DBQuery createQuery(String query) {
-		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.createQuery(em, query, getData());
+		try {
+			EntityManager em = getCurrentEntityManager();
+			Query q = getSession(em).createQuery(query);
+			return new DBQueryImpl(q);
+		} catch (HibernateException he) {
+			getData().setError(he);
+			throw new DBRuntimeException("Error while creating DBQueryImpl: ", he);
+		}
 	}
 
 	/**
@@ -392,9 +367,24 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * 
 	 * @param object
 	 */
+	@Override
 	public void deleteObject(Object object) {
 		EntityManager em = getCurrentEntityManager();
-		dbManagerDelegate.deleteObject(em, object, getData());
+		EntityTransaction trx = em.getTransaction();
+		if (unusableTrx(trx)) { // some program bug
+			throw new DBRuntimeException("cannot delete in a transaction that is rolledback or committed " + object);
+		}
+		try {
+			Object relaoded = em.merge(object);
+			em.remove(relaoded);
+			if (isLogDebugEnabled()) {
+				logDebug("delete (trans "+trx.hashCode()+") class "+object.getClass().getName()+" = "+object.toString());	
+			}
+		} catch (HibernateException e) { // we have some error
+			trx.setRollbackOnly();
+			getData().setError(e);
+			throw new DBRuntimeException("Delete of object failed: " + object, e);
+		}
 	}
 
 	/**
@@ -405,9 +395,29 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param type
 	 * @return nr of deleted rows
 	 */
+	@Override
 	public int delete(String query, Object value, Type type) {
+		int deleted = 0;
 		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.delete(em, query, value, type);
+		EntityTransaction trx = em.getTransaction();
+		if (unusableTrx(trx)) { // some program bug
+			throw new DBRuntimeException("cannot delete in a transaction that is rolledback or committed " + value);
+		}
+		try {
+			//old: deleted = getSession().delete(query, value, type);
+			Session si = getSession(em);
+			Query qu = si.createQuery(query);
+			qu.setParameter(0, value, type);
+			List foundToDel = qu.list();
+			int deletionCount = foundToDel.size();
+			for (int i = 0; i < deletionCount; i++ ) {
+				si.delete( foundToDel.get(i) );
+			}
+		} catch (HibernateException e) { // we have some error
+			trx.setRollbackOnly();
+			throw new DBRuntimeException ("Could not delete object: " + value, e);
+		}
+		return deleted;
 	}
 
 	/**
@@ -418,9 +428,28 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param types
 	 * @return nr of deleted rows
 	 */
+	@Override
 	public int delete(String query, Object[] values, Type[] types) {
 		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.delete(em, query, values, types);
+		EntityTransaction trx = em.getTransaction();
+		if (unusableTrx(trx)) { // some program bug
+			throw new DBRuntimeException("cannot delete in a transaction that is rolledback or committed " + values);
+		}
+		try {
+			//old: deleted = getSession().delete(query, values, types);
+			Session si = getSession(em);
+			Query qu = si.createQuery(query);
+			qu.setParameters(values, types);
+			List foundToDel = qu.list();
+			int deleted = foundToDel.size();
+			for (int i = 0; i < deleted; i++ ) {
+				si.delete( foundToDel.get(i) );
+			}	
+			return deleted;
+		} catch (HibernateException e) { // we have some error
+			trx.setRollbackOnly();
+			throw new DBRuntimeException ("Could not delete object: " + values, e);
+		}
 	}
 
 	/**
@@ -431,9 +460,20 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param type
 	 * @return List of results.
 	 */
+	@Override
 	public List find(String query, Object value, Type type) {
 		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.find(em, query, value, type, getData());
+		EntityTransaction trx = em.getTransaction();
+		try {
+			Query qu = getSession(em).createQuery(query);
+			qu.setParameter(0, value, type);
+			return qu.list();
+		} catch (HibernateException e) {
+			trx.setRollbackOnly();
+			String msg = "Find failed in transaction. Query: " +  query + " " + e;
+			getData().setError(e);
+			throw new DBRuntimeException(msg, e);
+		}
 	}
 
 	/**
@@ -444,9 +484,19 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param types
 	 * @return List of results.
 	 */
+	@Override
 	public List find(String query, Object[] values, Type[] types) {
 		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.find(em , query, values, types, getData());
+		try {
+			// old: li = getSession().find(query, values, types);
+			Query qu = getSession(em).createQuery(query);
+			qu.setParameters(values, types);
+			return qu.list();
+		} catch (HibernateException e) {
+			em.getTransaction().setRollbackOnly();
+			getData().setError(e);
+			throw new DBRuntimeException("Find failed in transaction. Query: " +  query + " " + e, e);
+		}
 	}
 
 	/**
@@ -455,9 +505,16 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param query
 	 * @return List of results.
 	 */
+	@Override
 	public List find(String query) {
 		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.find(em , query, getData());
+		try {
+			return em.createQuery(query).getResultList();
+		} catch (HibernateException e) {
+			em.getTransaction().setRollbackOnly();
+			getData().setError(e);
+			throw new DBRuntimeException("Find in transaction failed: " + query + " " + e, e);
+		}
 	}
 
 	/**
@@ -467,6 +524,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param key
 	 * @return Object, if any found. Null, if non exist. 
 	 */
+	@Override
 	public <U> U findObject(Class<U> theClass, Long key) {
 		return getCurrentEntityManager().find(theClass, key);
 	}
@@ -478,9 +536,13 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param key
 	 * @return Object.
 	 */
+	@Override
 	public <U> U loadObject(Class<U> theClass, Long key) {
-		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.loadObject(em , theClass, key);
+		try {
+			return getCurrentEntityManager().find(theClass, key);
+		} catch (Exception e) {
+			throw new DBRuntimeException("loadObject error: " + theClass + " " + key + " ", e);
+		}
 	}
 
 	/**
@@ -488,9 +550,20 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * 
 	 * @param object
 	 */
+	@Override
 	public void saveObject(Object object) {
 		EntityManager em = getCurrentEntityManager();
-		dbManagerDelegate.saveObject(em, object, getData());
+		EntityTransaction trx = em.getTransaction();
+		if (unusableTrx(trx)) { // some program bug
+			throw new DBRuntimeException("cannot save in a transaction that is rolledback or committed: " + object);
+		}
+		try {
+			em.persist(object);					
+		} catch (Exception e) { // we have some error
+			trx.setRollbackOnly();
+			getData().setError(e);
+			throw new DBRuntimeException("Save failed in transaction. object: " +  object, e);
+		}
 	}
 
 	/**
@@ -498,9 +571,20 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * 
 	 * @param object
 	 */
+	@Override
 	public void updateObject(Object object) {
 		EntityManager em = getCurrentEntityManager();
-		dbManagerDelegate.updateObject(em, object, getData());
+		EntityTransaction trx = em.getTransaction();
+		if (unusableTrx(trx)) { // some program bug
+			throw new DBRuntimeException("cannot update in a transaction that is rolledback or committed " + object);
+		}
+		try {
+			getSession(em).update(object);								
+		} catch (HibernateException e) { // we have some error
+			trx.setRollbackOnly();
+			getData().setError(e);
+			throw new DBRuntimeException("Update object failed in transaction. Query: " +  object, e);
+		}
 	}
 
 	/**
@@ -515,6 +599,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	/**
 	 * @return True if any errors occured in the previous DB call.
 	 */
+	@Override
 	public boolean isError() {
 		//EntityTransaction trx = getCurrentEntityManager().getTransaction();
 		EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
@@ -527,8 +612,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 		return getData() == null ? false : getData().isError();
 	}
 
-	boolean hasTransaction() {
-		//EntityManager em = getCurrentEntityManager();
+	private boolean hasTransaction() {
 		EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
 		if(em != null && em.isOpen()) {
 			EntityTransaction trx = em.getTransaction();
@@ -543,9 +627,49 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * @param persistable
 	 * @return the loaded object
 	 */
+	@Override
 	public Persistable loadObject(Persistable persistable) {
 		return loadObject(persistable, false);
 	}
+	
+
+	/**
+	 * Create a named hibernate query for the given name. Optionally the database
+	 * vendor is prepended to load database specific queries if available. Use
+	 * this only when absolutely necessary.
+	 * 
+	 * @param queryName The query name
+	 * @param vendorSpecific true: prepend the database vendor name to the query
+	 *          name, e.g. mysql_queryName; false: use queryName as is
+	 * @return the query or NULL if no such named query exists
+	 */
+	@Override
+	public DBQuery createNamedQuery(final String queryName, boolean vendorSpecific) {
+		if (queryName == null) {
+			throw new AssertException("queryName must not be NULL");
+		}
+		DBQuery dbq = null;
+		if (vendorSpecific) {
+			String finalQueryName = vendorSpecific ? dbVendor + "_" + queryName : queryName;
+			Session session = getSession(getCurrentEntityManager());
+			Query q = session.getNamedQuery(finalQueryName);
+			if (q == null) { 
+				// try fallback with normal query
+				q = session.getNamedQuery(queryName);
+			}
+			if (q == null) {
+				String msg = "Can not create namedQuery::" + finalQueryName;
+				if (vendorSpecific) {
+					msg += " for dbvendor::" + dbVendor + " and non db specific::" + queryName;
+				}
+				msg += ", named query does not exist";
+				logError(msg, null);
+			}	else {
+				dbq = new DBQueryImpl(q);
+			}
+		}
+		return dbq;
+	}	
 
 	/**
 	 * loads an object if needed. this makes sense if you have an object which had
@@ -558,6 +682,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 *          thread's session cache
 	 * @return the loaded Object
 	 */
+	@Override
 	public Persistable loadObject(Persistable persistable, boolean forceReloadFromDB) {
 		if (persistable == null) throw new AssertException("persistable must not be null");
 
@@ -572,14 +697,14 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 			
 			if (contains(persistable)) {
 				// case b - then we can use evict and load
-				dbManagerDelegate.evict(em, persistable, getData());
+				evict(em, persistable, getData());
 				return loadObject(theClass, persistable.getKey());
 			} else {
 				// case a or c - unfortunatelly we can't distinguish these two cases
 				// and session.refresh(Object) doesn't work.
 				// the only scenario that works is load/evict/load
 				Persistable attachedObj = (Persistable) loadObject(theClass, persistable.getKey());
-				dbManagerDelegate.evict(em, attachedObj, getData());
+				evict(em, attachedObj, getData());
 				return loadObject(theClass, persistable.getKey());
 			}
 		} else if (!contains(persistable)) { 
@@ -593,6 +718,15 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 			return persistable;
 		}
 	}
+	
+	private void evict(EntityManager em, Object object, ThreadLocalData data) {
+		try {
+			getSession(em).evict(object);			
+		} catch (Exception e) {
+			data.setError(e);
+			throw new DBRuntimeException("Error in evict() Object from Database. ", e);
+		}
+	}
 
 	@Override
 	public void commitAndCloseSession() {
@@ -620,9 +754,16 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 		}
 	}
 
+	@Override
+	public void begin() {
+		//this will begin a new transaction
+		getCurrentEntityManager();
+	}
+
 	/**
 	 * Call this to commit a transaction opened by beginTransaction().
 	 */
+	@Override
 	public void commit() {
 		if (isLogDebugEnabled()) logDebug("commit start...", null);
 		try {
@@ -673,6 +814,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	/**
 	 * Call this to rollback current changes.
 	 */
+	@Override
 	public void rollback() {
 		if (isLogDebugEnabled()) logDebug("rollback start...", null);
 		try {
@@ -693,6 +835,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	 * Statistics must be enabled first, when you want to use it. 
 	 * @return Return Hibernates statistics object.
 	 */
+	@Override
 	public Statistics getStatistics() {
 		if(emf instanceof HibernateEntityManagerFactory) {
 			return ((HibernateEntityManagerFactory)emf).getSessionFactory().getStatistics();
@@ -703,6 +846,7 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 	/**
 	 * @see org.olat.core.commons.persistence.DB#intermediateCommit()
 	 */
+	@Override
 	public void intermediateCommit() {
 		commit();
 		closeSession();
@@ -721,41 +865,4 @@ public class DBImpl extends LogDelegator implements DB, Destroyable {
 			}
 		}
 	}
-	
-	//
-	// fxdiff qti-statistics (praktikum MK)
-	// Extensions used for native SQL queries
-	//
-	private String dbVendor = null;
-	
-	@Override
-	public String getDbVendor() {
-		return dbVendor;
-	}
-	/**
-	 * [used by spring]
-	 * @param dbVendor
-	 */
-	public void setDbVendor(String dbVendor) {
-		this.dbVendor = dbVendor;
-	}
-
-	/**
-	 * Create a named hibernate query for the given name. Optionally the database
-	 * vendor is prepended to load database specific queries if available. Use
-	 * this only when absolutely necessary.
-	 * 
-	 * @param queryName The query name
-	 * @param vendorSpecific true: prepend the database vendor name to the query
-	 *          name, e.g. mysql_queryName; false: use queryName as is
-	 * @return the query or NULL if no such named query exists
-	 */
-	public DBQuery createNamedQuery(final String queryName, boolean vendorSpecific) {
-		if (queryName == null) {
-			throw new AssertException("queryName must not be NULL");
-		}
-		
-		EntityManager em = getCurrentEntityManager();
-		return dbManagerDelegate.createNamedQuery(em, queryName, dbVendor, vendorSpecific);
-	}	
 }
diff --git a/src/main/java/org/olat/core/commons/persistence/DBManager.java b/src/main/java/org/olat/core/commons/persistence/DBManager.java
deleted file mode 100644
index 335c61fe7f57840810e7eb27a7a2385684dc8b5d..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/core/commons/persistence/DBManager.java
+++ /dev/null
@@ -1,426 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.  
-* <p>
-*/ 
-
-package org.olat.core.commons.persistence;
-
-import java.util.List;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityTransaction;
-
-import org.hibernate.HibernateException;
-import org.hibernate.Query;
-import org.hibernate.Session;
-import org.hibernate.ejb.HibernateEntityManager;
-import org.hibernate.type.Type;
-import org.olat.core.commons.persistence.DBImpl.ThreadLocalData;
-import org.olat.core.logging.AssertException;
-import org.olat.core.logging.DBRuntimeException;
-import org.olat.core.manager.BasicManager;
-
-/**
- * 
- * @author Andreas Ch. Kapp
- * @author Christian Guretzki
- */
-class DBManager extends BasicManager {
-
-	DBManager() {
-		//
-	}
-	
-	private boolean unusableTrx(EntityTransaction trx) {
-		return trx == null || !trx.isActive() || trx.getRollbackOnly();
-	}
-
-	/**
-	 * Hibernate Update method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param o Object to be updated
-	 */	
-	void updateObject(EntityManager em, Object o, ThreadLocalData data) {
-		EntityTransaction trx = em.getTransaction();
-		if (unusableTrx(trx)) { // some program bug
-			throw new DBRuntimeException("cannot update in a transaction that is rolledback or committed " + o);
-		}
-		try {
-			getSession(em).update(o);
-			if (isLogDebugEnabled()) {
-				logDebug("update (trans "+trx.hashCode()+") class "+o.getClass().getName()+" = "+o.toString());	
-			}									
-		} catch (HibernateException e) { // we have some error
-			trx.setRollbackOnly();
-			data.setError(e);
-			throw new DBRuntimeException("Update object failed in transaction. Query: " +  o , e);
-		}
-	}
-	
-	/**
-	 * Hibernate Delete method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param o Object to be deleted
-	 */	
-	void deleteObject(EntityManager em,  Object o, ThreadLocalData data) {
-		EntityTransaction trx = em.getTransaction();
-		if (unusableTrx(trx)) { // some program bug
-			throw new DBRuntimeException("cannot delete in a transaction that is rolledback or committed " + o);
-		}
-		try {
-			Object relaoded = em.merge(o);
-			em.remove(relaoded);
-			if (isLogDebugEnabled()) {
-				logDebug("delete (trans "+trx.hashCode()+") class "+o.getClass().getName()+" = "+o.toString());	
-			}
-		} catch (HibernateException e) { // we have some error
-			trx.setRollbackOnly();
-			data.setError(e);
-			throw new DBRuntimeException("Delete of object failed: " + o, e);
-		}
-	}
-	
-	/**
-	 * Hibernate Save method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param o Object to be saved
-	 */	
-	void saveObject(EntityManager em, Object o, ThreadLocalData data) {
-		EntityTransaction trx = em.getTransaction();
-		if (unusableTrx(trx)) { // some program bug
-			throw new DBRuntimeException("cannot save in a transaction that is rolledback or committed: " + o);
-		}
-		try {
-			em.persist(o);
-			if (isLogDebugEnabled()) {
-				logDebug("save (trans "+trx.hashCode()+") class "+o.getClass().getName()+" = "+o.toString());	
-			}						
-		} catch (Exception e) { // we have some error
-			trx.setRollbackOnly();
-			data.setError(e);
-			throw new DBRuntimeException("Save failed in transaction. object: " +  o, e);
-		}
-	}
-
-	/**
-	 * Hibernate Load method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param theClass The class for the object to be loaded
-	 * @param pK The primary key for the object
-	 */	
-	<U> U loadObject(EntityManager em, Class<U> theClass, Long pK) {
-		U o = null;
-		EntityTransaction trx = em.getTransaction();
-		try {
-			o = em.find(theClass, pK);
-			if (isLogDebugEnabled()) {
-				logDebug("load (res " +(o == null? "null": "ok")+")(trans "+trx.hashCode()+") key "+pK+" class "+theClass.getName());	
-			}
-		} catch (Exception e) {
-			String msg = "loadObject error: " + theClass + " " + pK + " ";
-			throw new DBRuntimeException(msg, e);
-		}
-		return o;
-	}
-	
-	/**
-	 * Hibernate Find method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param query The HQL query
-	 * @param value The value to search for
-	 * @param type The Hibernate datatype of the search value 
-	 */	
-	List find(EntityManager em, String query, Object value, Type type, ThreadLocalData data) {
-		List li = null;
-		EntityTransaction trx = em.getTransaction();
-		try {
-			boolean doLog = isLogDebugEnabled();
-			long start = 0;
-			if (doLog) start = System.currentTimeMillis();
-
-			// old: li = this.getSession().find(query, value, type);
-			Query qu = getSession(em).createQuery(query);
-			qu.setParameter(0, value, type);
-			li = qu.list();
-			
-			if (doLog) {
-				long time = (System.currentTimeMillis() - start);
-				logQuery("find (time "+time+", res " +(li == null? "null": ""+li.size())+")(trans "+trx.hashCode()+")", new Object[] {value}, new Type[] {type}, query);	
-			}
-		} catch (HibernateException e) {
-			trx.setRollbackOnly();
-			String msg = "Find failed in transaction. Query: " +  query + " " + e;
-			data.setError(e);
-			throw new DBRuntimeException(msg, e);
-		}
-		return li;
-	}
-
-	/**
-	 * Hibernate Find method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param query The HQL query
-	 * @param values The object array containing all search values 
-	 * @param types The object array containing all Hibernate datatype of the search values 
-	 */	
-	List find(EntityManager em, String query, Object [] values, Type [] types, ThreadLocalData data) {
-		List li = null;
-		EntityTransaction trx = em.getTransaction();
-		try {
-			boolean doLog = isLogDebugEnabled();
-			long start = 0;
-			if (doLog) start = System.currentTimeMillis();
-			// old: li = getSession().find(query, values, types);
-			Query qu = getSession(em).createQuery(query);
-			qu.setParameters(values, types);
-			li = qu.list();
-			
-			
-			if (doLog) {
-				long time = (System.currentTimeMillis() - start);
-				logQuery("find (time "+time+", res " +(li == null? "null": ""+li.size())+")(trans "+trx.hashCode()+")", values, types, query);	
-			}			
-	
-		} catch (HibernateException e) {
-			trx.setRollbackOnly();
-			String msg = "Find failed in transaction. Query: " +  query + " " + e;
-			data.setError(e);
-			throw new DBRuntimeException(msg, e);
-		}
-		return li;
-	}
-	
-	/**
-	 * Hibernate find method. Use this in a transactional context by using
-	 * your current transaction object.
-	 * @param trx The current db transaction
-	 * @param query The HQL query
-	 */	
-	List find(EntityManager em, String query, ThreadLocalData data) {
-		List li = null;
-		EntityTransaction trx = em.getTransaction();
-		try {
-			boolean doLog = isLogDebugEnabled();
-			long start = 0;
-			if (doLog) start = System.currentTimeMillis();
-			// old: li = getSession().find(query);
-			Query qu = getSession(em).createQuery(query);
-			li = qu.list();
-
-			if (doLog) {
-				long time = (System.currentTimeMillis() - start);
-				logQuery("find (time "+time+", res " +(li == null? "null": ""+li.size())+")(trans "+trx.hashCode()+")", null, null, query);	
-			}
-		} catch (HibernateException e) {
-			String msg = "Find in transaction failed: " + query + " " + e;
-			trx.setRollbackOnly();
-			data.setError(e);
-			throw new DBRuntimeException(msg, e);
-		}
-		return li;
-	}
-
-	
-	Session getSession(EntityManager em) {
-		return em.unwrap(HibernateEntityManager.class).getSession();
-	}
-	
-	/**
-	 * @param query
-	 * @return Hibernate Query object.
-	 */
-	DBQuery createQuery(EntityManager em, String query, ThreadLocalData data) {
-		Query q = null;
-		DBQuery dbq = null;
-		try {
-			q = getSession(em).createQuery(query);
-			dbq = new DBQueryImpl(q);
-		} catch (HibernateException he) {
-			data.setError(he);
-			throw new DBRuntimeException("Error while creating DBQueryImpl: ", he);
-		}
-		return dbq;
-	}
-	
-	DBQuery createNamedQuery(EntityManager em, String queryName, String dbVendor, boolean vendorSpecific) {
-		if (queryName == null) {
-			throw new AssertException("queryName must not be NULL");
-		}
-		Query q= null;
-		DBQuery dbq = null;
-		if (vendorSpecific) {
-			String finalQueryName = vendorSpecific ? dbVendor + "_" + queryName : queryName;
-			q = getSession(em).getNamedQuery(finalQueryName);
-			if (q == null) { 
-				// try fallback with normal query
-				q = getSession(em).getNamedQuery(queryName);
-			}
-			if (q == null) {
-				String msg = "Can not create namedQuery::" + finalQueryName;
-				if (vendorSpecific) {
-					msg += " for dbvendor::" + dbVendor + " and non db specific::" + queryName;
-				}
-				msg += ", named query does not exist";
-				logError(msg, null);
-			}	else {
-
-				dbq = new DBQueryImpl(q);
-			}
-		}
-		return dbq;
-	}
-
-	/**
-	 * Hibernate Contains method
-	 * @param object
-	 * @return True if the Object instance is in the Hibernate Session.
-	 */
-	boolean contains(EntityManager em, Object object) {
-		return em.contains(object);
-	}
-	
-
-	/**
-	 * Hibernates Evict method
-	 * @param object The object to be removed from hibernates session cache
-	 */
-	void evict(EntityManager em, Object object, ThreadLocalData data) {
-		try {
-			getSession(em).evict(object);			
-		} catch (Exception e) {
-			data.setError(e);
-			throw new DBRuntimeException("Error in evict() Object from Database. ", e);
-		}
-	}
-	
-	/**
-	 * Hibernate refresh method
-	 * @return object a persistent or detached instance
-	 */
-	void refresh(EntityManager em, Object object, ThreadLocalData data) {
-		try{
-			em.refresh(object);
-		} catch(Exception e) {
-			data.setError(e);
-			throw new DBRuntimeException("Error in refresh() Object from Database. ", e);
-		}
-	}
-	
-	int delete(EntityManager em, String query, Object value, Type type) {	
-		int deleted = 0;
-
-		EntityTransaction trx = em.getTransaction();
-		if (unusableTrx(trx)) { // some program bug
-			throw new DBRuntimeException("cannot delete in a transaction that is rolledback or committed " + value);
-		}
-		try {
-			//old: deleted = getSession().delete(query, value, type);
-			
-			Session si = getSession(em);
-			Query qu = si.createQuery(query);
-			qu.setParameter(0, value, type);
-			List foundToDel = qu.list();
-			int deletionCount = foundToDel.size();
-			for (int i = 0; i < deletionCount; i++ ) {
-				si.delete( foundToDel.get(i) );
-			}
-			
-			if (isLogDebugEnabled()) {
-				logQuery("delete (trans "+trx.hashCode()+")",new Object[] {value}, new Type[] {type}, query);	
-			}
-		} catch (HibernateException e) { // we have some error
-			trx.setRollbackOnly();
-			throw new DBRuntimeException ("Could not delete object: " + value, e);
-		}
-		return deleted;
-	}
-
-	int delete(EntityManager em, String query, Object[] values, Type[] types) {
-		int deleted = 0;
-		EntityTransaction trx = em.getTransaction();
-		if (unusableTrx(trx)) { // some program bug
-			throw new DBRuntimeException("cannot delete in a transaction that is rolledback or committed " + values);
-		}
-		try {
-			//old: deleted = getSession().delete(query, values, types);
-			Session si = getSession(em);
-			Query qu = si.createQuery(query);
-			qu.setParameters(values, types);
-			List foundToDel = qu.list();
-			deleted = foundToDel.size();
-			for (int i = 0; i < deleted; i++ ) {
-				si.delete( foundToDel.get(i) );
-			}
-			
-			if (isLogDebugEnabled()) {
-				logQuery("delete (trans "+trx.hashCode()+")", values, types, query);	
-			}			
-		} catch (HibernateException e) { // we have some error
-			trx.setRollbackOnly();
-			throw new DBRuntimeException ("Could not delete object: " + values, e);
-		}
-		return deleted;
-	}
-
-	/**
-	 * Find a Object by its identifier. 
-	 * This method should be used instead of loadObject when it is ok to not find the object.
-	 * In opposite to the loadObject method this method will return null and not throw a 
-	 * DBRuntimeException when the object can't be loaded.
-	 * @param theClass
-	 * @param key
-	 * @return an persistent object.
-	 */
-	Object findObject(EntityManager em, Class theClass, Long key) {
-		//o_clusterREVIEW see Session.java
-		Object o = getSession(em).get(theClass, key);
-		if (isLogDebugEnabled()) {
-			logDebug("findload (res " +(o == null? "null": "ok")+") key "+key+" class "+theClass.getName());	
-		}			
-		return o;
-	}
-	
-	private void logQuery(String info, Object[] values, Type[] types, String query) {
-		StringBuilder sb = new StringBuilder(info);
-		sb.append(": args: ");
-		if (values == null) {
-			sb.append(" none");
-		}
-		else {
-			for (int i = 0; i < values.length; i++) {
-				Object val = values[i];
-				Type type = types[i];
-				sb.append((val == null? "NULL": val.toString())).append("(").append(type.getName()).append(" ), ");
-			}
-		}
-		sb.append(", query: ").append(query);
-		logDebug(sb.toString());
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/persistence/OLATPersistenceUnitManager.java b/src/main/java/org/olat/core/commons/persistence/OLATPersistenceUnitManager.java
deleted file mode 100644
index da9fe7495f0ae05b42590188f593d1a7fa2762db..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/core/commons/persistence/OLATPersistenceUnitManager.java
+++ /dev/null
@@ -1,70 +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.persistence;
-
-import java.util.List;
-
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
-import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager;
-import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
-
-/**
- * 
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- */
-public class OLATPersistenceUnitManager extends DefaultPersistenceUnitManager {
-
-	private OLog log = Tracing.createLoggerFor(OLATPersistenceUnitManager.class);
-	
-	private AdditionalDBMappings[] additionalDBMappings;
-
-	public void setAdditionalDBMappings(AdditionalDBMappings[] additionalDBMappings) {
-		this.additionalDBMappings = additionalDBMappings;
-	}
-
-	@Override
-	protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
-		try {
-			if(additionalDBMappings != null && additionalDBMappings.length > 0) {
-				for(AdditionalDBMappings addMapping:additionalDBMappings) {
-					List<String> xmlFiles = addMapping.getXmlFiles();
-					if(xmlFiles != null) {
-						for (String mapping : xmlFiles) {
-							pui.addMappingFileName(mapping.trim());
-						}
-					}
-					
-					List<Class<?>> annotatedClasses = addMapping.getAnnotatedClasses();
-					if(annotatedClasses != null) {
-						for(Class<?> annotatedClass:annotatedClasses) {
-							pui.addManagedClassName(annotatedClass.getName());
-						}
-					}
-				}
-			}
-		} catch (Exception e) {
-			log.error("Error during the post processing of the hibernate session factory.", e);
-		}
-		
-		super.postProcessPersistenceUnitInfo(pui);
-	}
-
-}
diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml
index b7fb15d58f679a93037cb5c9739a085137dbad94..efccf6a15c4dd86f2240ee8ce98bb57efbf9563b 100644
--- a/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml
+++ b/src/main/java/org/olat/core/commons/persistence/_spring/core_persistence.xml
@@ -67,11 +67,23 @@
 		<mapping-file>org/olat/course/statistic/weekly/WeeklyStat.hbm.xml</mapping-file>
 		<mapping-file>org/olat/course/statistic/homeorg/HomeOrgStat.hbm.xml</mapping-file>
 		<mapping-file>org/olat/course/statistic/orgtype/OrgTypeStat.hbm.xml</mapping-file>
+		<mapping-file>org/olat/portfolio/model/artefacts/AbstractArtefact.hbm.xml</mapping-file>
+		<mapping-file>org/olat/modules/fo/portfolio/ForumArtefact.hbm.xml</mapping-file>
+		<mapping-file>org/olat/modules/wiki/portfolio/WikiArtefact.hbm.xml</mapping-file>
+		<mapping-file>org/olat/modules/webFeed/portfolio/BlogArtefact.hbm.xml</mapping-file>
+		<mapping-file>org/olat/modules/webFeed/portfolio/LiveBlogArtefact.hbm.xml</mapping-file>
+		<mapping-file>org/olat/course/assessment/portfolio/EfficiencyStatementArtefact.hbm.xml</mapping-file>
+		<mapping-file>org/olat/portfolio/model/structel/StructureElement.hbm.xml</mapping-file>
+		<mapping-file>org/olat/portfolio/model/notification/Notifications.hbm.xml</mapping-file>
+		<mapping-file>org/olat/portfolio/model/restriction/CollectRestriction.hbm.xml</mapping-file>
 		<mapping-file>org/olat/core/dispatcher/mapper/model/PersistedMapper.hbm.xml</mapping-file>
 		<mapping-file>org/olat/core/commons/services/commentAndRating/impl/UserCommentImpl.hbm.xml</mapping-file>
 		<mapping-file>org/olat/core/commons/services/commentAndRating/impl/UserRatingImpl.hbm.xml</mapping-file>
 		<mapping-file>org/olat/core/commons/services/mark/impl/MarkImpl.hbm.xml</mapping-file>
 		<mapping-file>org/olat/core/commons/services/tagging/model/TagImpl.hbm.xml</mapping-file>
+		<mapping-file>org/olat/core/util/mail/model/DBMail.hbm.xml</mapping-file>
+		<mapping-file>org/olat/core/util/mail/model/DBMailAttachment.hbm.xml</mapping-file>
+		<mapping-file>org/olat/core/util/mail/model/DBMailRecipient.hbm.xml</mapping-file>
 		<mapping-file>org/olat/core/logging/activity/LoggingObject.hbm.xml</mapping-file>
 		<mapping-file>org/olat/course/db/impl/CourseDBEntryImpl.hbm.xml</mapping-file>
 		<mapping-file>org/olat/modules/coach/model/EfficiencyStatementStatEntry.hbm.xml</mapping-file>
diff --git a/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml b/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml
index 03a6479c1d991a1950527065d1212cdfbf4f65da..d2828d9b2394335669ffa36a10dcebdd03a3b177 100644
--- a/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml
+++ b/src/main/java/org/olat/core/commons/persistence/_spring/databaseCorecontext.xml
@@ -5,12 +5,8 @@
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-		
-	<bean id="collectingAdditionalDBMappings" class="org.olat.core.commons.persistence.AdditionalMappingsListFactoryBean"/>
-	
 	<!-- Persistence unit manager -->
-	<bean id="pum" class="org.olat.core.commons.persistence.OLATPersistenceUnitManager" depends-on="databaseUpgrader">
-		<property name="additionalDBMappings" ref="collectingAdditionalDBMappings" />
+	<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" depends-on="databaseUpgrader">
   		<property name="persistenceXmlLocations">
     		<list>
      			<value>classpath:/org/olat/core/commons/persistence/_spring/core_persistence.xml</value>
diff --git a/src/main/java/org/olat/core/gui/components/table/BooleanColumnDescriptor.java b/src/main/java/org/olat/core/gui/components/table/BooleanColumnDescriptor.java
index 3d05fd65610970292b305fd5533aadc2f7126ff2..79ae772fcb1b7baf2f11b237951f87cdb838812f 100644
--- a/src/main/java/org/olat/core/gui/components/table/BooleanColumnDescriptor.java
+++ b/src/main/java/org/olat/core/gui/components/table/BooleanColumnDescriptor.java
@@ -76,28 +76,29 @@ public class BooleanColumnDescriptor extends DefaultColumnDescriptor {
 	 * @see org.olat.core.gui.components.table.ColumnDescriptor#renderValue(org.olat.core.gui.render.StringOutput,
 	 *      int, org.olat.core.gui.render.Renderer)
 	 */
+	@Override
 	public void renderValue(final StringOutput sb, final int row, final Renderer renderer) {
-		Boolean bool = (Boolean) getModelData(row);
-		boolean appendNothing = bool == null;
-		if (appendNothing){
-			return;
-		}
-		String val = (bool.booleanValue() ? trueValue : falseValue);
-		if(StringHelper.containsNonWhitespace(val)) {
-			sb.append(val);
+		Object obj = getModelData(row);
+		if(obj instanceof Boolean) {
+			Boolean bool = (Boolean)obj;
+			String val = (bool.booleanValue() ? trueValue : falseValue);
+			if(StringHelper.containsNonWhitespace(val)) {
+				sb.append(val);
+			}
 		}
 	}
 
 	/**
 	 * @see org.olat.core.gui.components.table.ColumnDescriptor#getAction(int)
 	 */
+	@Override
 	public String getAction(final int row) {
 		if (!hasAction) {
 			return null;
 		} else {
-			Boolean bool = (Boolean) getModelData(row);
+			Object bool = getModelData(row);
 			// make sure the bool is not null before checkings its value
-			if (bool != null && bool.booleanValue()) {
+			if (bool instanceof Boolean && ((Boolean)bool).booleanValue()) {
 				return super.getAction(row);
 			} else {
 				return null;
diff --git a/src/main/java/org/olat/core/gui/components/table/Table.java b/src/main/java/org/olat/core/gui/components/table/Table.java
index 372a0bba4c5f9394671496de21dd6bbd7f792404..cf8a15457906b6644ac27bf03f6d2225898147a1 100644
--- a/src/main/java/org/olat/core/gui/components/table/Table.java
+++ b/src/main/java/org/olat/core/gui/components/table/Table.java
@@ -29,7 +29,6 @@ package org.olat.core.gui.components.table;
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 
@@ -53,7 +52,7 @@ import org.olat.core.util.filter.FilterFactory;
  * 
  * @author Felix Jost
  */
-public class Table extends Component implements Comparator {
+public class Table extends Component {
 	private static final int NO_ROW_SELECTED = -1;
 	private static final int DEFAULT_RESULTS_PER_PAGE = 20;
 	private static final int INITIAL_COLUMNSIZE = 5;
@@ -127,7 +126,6 @@ public class Table extends Component implements Comparator {
 	private List<Integer> sorter;
 
 	private int sortColumn = 0;
-	private ColumnDescriptor currentSortingCd;
 	private boolean sortAscending = true;
 
 	// config
@@ -557,7 +555,7 @@ public class Table extends Component implements Comparator {
 
 	protected void resort() {
 		if (isSortingEnabled()) {
-			currentSortingCd = getColumnDescriptor(sortColumn); // we sort after this
+			ColumnDescriptor currentSortingCd = getColumnDescriptor(sortColumn); // we sort after this
 			// column descriptor
 			// notify all nonactive ColumnDescriptors about their state
 			int cdcnt = getColumnCount();
@@ -574,31 +572,13 @@ public class Table extends Component implements Comparator {
 						+ " in sorting process, maybe you have set the tabledatamodel before the columndescriptors?");
 			}
 			currentSortingCd.sortingAboutToStart();
-			long start = 0;
-			boolean logDebug = Tracing.isDebugEnabled(Table.class);
-			if (logDebug){
-				start = System.currentTimeMillis();
-			}
-			Collections.sort(sorter, this);
-			if (logDebug) {
-				long stop = System.currentTimeMillis();
-				TableDataModel model = getTableDataModel();
-				Tracing.logDebug("sorting time for " + (model==null ? "null" : model.getRowCount()) + " rows:" + (stop - start) + " ms", Table.class);
-			}
-			// do not reset paging to first page (see OLAT-1340)			
-			//if (currentPageId != null) currentPageId = new Integer(1); 
+			Collections.sort(sorter, new TableComparator(currentSortingCd, sortAscending));
 		}
 	}
-
-	/**
-	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
-	 */
-	public int compare(final Object a, final Object b) {
-		// the objects to come in are Integers of the sorter List, meaning the
-		// original row in the datatablemodel
-		int rowa = ((Integer) a).intValue();
-		int rowb = ((Integer) b).intValue();
-		return (sortAscending ? currentSortingCd.compareTo(rowa, rowb) : currentSortingCd.compareTo(rowb, rowa));
+	
+	public TableComparator getComparator() {
+		ColumnDescriptor currentSortingCd = getColumnDescriptor(sortColumn);
+		return new TableComparator(currentSortingCd, sortAscending);
 	}
 
 	/**
diff --git a/src/main/java/org/olat/core/gui/components/table/TableComparator.java b/src/main/java/org/olat/core/gui/components/table/TableComparator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2c75f2c709bfbc58b5dd1f51497674dcdbad48e
--- /dev/null
+++ b/src/main/java/org/olat/core/gui/components/table/TableComparator.java
@@ -0,0 +1,45 @@
+/**
+ * <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.gui.components.table;
+
+import java.util.Comparator;
+
+/**
+ * 
+ * @author srosse
+ *
+ */
+public class TableComparator implements Comparator<Integer> {
+
+	private final boolean sortAscending;
+	private final ColumnDescriptor cd;
+	
+	public TableComparator(ColumnDescriptor cd, boolean sortAscending) {
+		this.cd = cd;
+		this.sortAscending = sortAscending;
+	}
+	
+	@Override
+	public int compare(Integer a, Integer b) {
+		int rowa = a.intValue();
+		int rowb = b.intValue();
+		return (sortAscending ? cd.compareTo(rowa, rowb) : cd.compareTo(rowb, rowa));
+	}
+}
diff --git a/src/main/java/org/olat/core/gui/components/table/TableController.java b/src/main/java/org/olat/core/gui/components/table/TableController.java
index 324242c1468ea22784df5183972e7f70533b0194..e2b5b5c78e9d4959bc88179ec5284bfa7fc604b9 100644
--- a/src/main/java/org/olat/core/gui/components/table/TableController.java
+++ b/src/main/java/org/olat/core/gui/components/table/TableController.java
@@ -665,7 +665,7 @@ public class TableController extends BasicController {
 		for (int i = objectMarkers.nextSetBit(0); i >= 0; i = objectMarkers.nextSetBit(i + 1)) {
 			sortedIndexes.add(i);
 		}
-		Collections.sort(sortedIndexes, table);
+		Collections.sort(sortedIndexes, table.getComparator());
 		Iterator<Integer> indexesIterator = sortedIndexes.iterator();
 		while (indexesIterator.hasNext()) {
 			results.add(defaultTableDataModel.getObject(indexesIterator.next()));
diff --git a/src/main/java/org/olat/core/gui/control/floatingresizabledialog/_content/index_ext.html b/src/main/java/org/olat/core/gui/control/floatingresizabledialog/_content/index_ext.html
index 5656aebc273fe58573e124d8075b0ab8491d68fd..8a500031b6c4edb5c2e0e52e7b3558d39dd8eec5 100644
--- a/src/main/java/org/olat/core/gui/control/floatingresizabledialog/_content/index_ext.html
+++ b/src/main/java/org/olat/core/gui/control/floatingresizabledialog/_content/index_ext.html
@@ -8,7 +8,7 @@
 </div>
 <script type="text/javascript">
 /* <![CDATA[ */
-	jQuery(function(){
+	Ext.onReady(function(){
 		var winPosition = null;
 		var winHeight = 0;
 		var winWidth = 0;
@@ -113,7 +113,17 @@
 					$r.javaScriptBgCommand("close")
 				}		
 			});
+						
+			if(winPosition != null) {
+				${panelName}.setPosition(winPosition[0],winPosition[1]);
+			} else {
+				${panelName}.setPosition(${offsetX},${offsetY});
+			}
+			${panelName}.show(this);
 			
+			## Add resize and move listeners after window positioning is finished, otherwhise the callbacks are 
+			## triggered right away which is not necessary (start width/height/posiiton must not be reported back 
+			## to server, only user initiated changes)
 			${panelName}.on('resize', function(win, width, height){
 				#if ($ajaxFlags.isIframePostEnabled())
 				if (!o_info.linkbusy) {
@@ -145,13 +155,6 @@
 					//
 				}
 			});
-			
-			if(winPosition != null) {
-				${panelName}.setPosition(winPosition[0],winPosition[1]);
-			} else {
-				${panelName}.setPosition(${offsetX},${offsetY});
-			}
-			${panelName}.show(this);
 		}
 	//delay is needed for IE to solve timing problem
 	},{delay:1000});
diff --git a/src/main/java/org/olat/core/gui/control/winmgr/_content/serverpart.html b/src/main/java/org/olat/core/gui/control/winmgr/_content/serverpart.html
index 87361c50319137fc4d7752241c5b9f4d9e792cf3..83cd27ffd62ac1606716c1db6e71507511ddc6bd 100644
--- a/src/main/java/org/olat/core/gui/control/winmgr/_content/serverpart.html
+++ b/src/main/java/org/olat/core/gui/control/winmgr/_content/serverpart.html
@@ -127,7 +127,7 @@ JSON <iframe src="javascript:false;document.write('');"  name="$iframeName" clas
 ## for safari: we cannot use display:none which would be the obvious choice here
 <div id="oaawrp" style="visibility:hidden;width:0px;height:0px">
 ## don't use the document.write approach, triggers an 'page contains insecure elements' warning (OLAT-4548). Load empty.html instead
-<iframe src='$r.staticLink("empty.html")' name="$iframeName" id="$iframeName" width="1" height="1"></iframe>
+<iframe src='$r.staticLink("empty.html")' name="$iframeName" id="$iframeName" width="1" height="1" onload="clearAfterAjaxIframeCall()"></iframe>
 ## try javascript:void(0)
 </div>
 #end	
diff --git a/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java b/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java
index 8f9eff9191c05d3ce054215b2645ca66a137e8c2..ce51b18bf5b113119849c9bff32d49147cfa77ac 100644
--- a/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java
+++ b/src/main/java/org/olat/core/logging/activity/UserActivityLoggerImpl.java
@@ -379,9 +379,10 @@ public class UserActivityLoggerImpl implements IUserActivityLogger {
 			throw new IllegalArgumentException("resourceInfo must not be null");
 		}
 
-		int existingPos = getLoggingResourceableList().indexOf(loggingResourceable);
+		List<ILoggingResourceable> loggingResourceableList = getLoggingResourceableList();
+		int existingPos = loggingResourceableList.indexOf(loggingResourceable);
 		if (existingPos!=-1) {
-			ILoggingResourceable existingRI = getLoggingResourceableList().get(existingPos);
+			ILoggingResourceable existingRI = loggingResourceableList.get(existingPos);
 			if (existingRI.getName()!=null && loggingResourceable.getName()!=null &&
 					existingRI.getName().equals(loggingResourceable.getName())) {
 				// ignore - already set
@@ -393,10 +394,19 @@ public class UserActivityLoggerImpl implements IUserActivityLogger {
 			}
 			// otherwise we have a matching resourceInfo already registered (same type,id) but with a different name
 			// let's update it
-			getLoggingResourceableList().remove(existingPos);
+			loggingResourceableList.remove(existingPos);
 		}
 		
-		getLoggingResourceableList().add(loggingResourceable);
+		if(OlatResourceableType.node.equals(loggingResourceable.getResourceableType())) {
+			//remove other node resource
+			for(Iterator<ILoggingResourceable> logIt=loggingResourceableList.iterator(); logIt.hasNext(); ) {
+				if(OlatResourceableType.node.equals(logIt.next().getResourceableType())) {
+					logIt.remove();
+				}
+			}
+		}
+		
+		loggingResourceableList.add(loggingResourceable);
 
 		if (runtimeParent_!=null) {
 			runtimeParent_.addLoggingResourceInfo(loggingResourceable);
diff --git a/src/main/java/org/olat/core/servlets/OLATServlet.java b/src/main/java/org/olat/core/servlets/OLATServlet.java
index f05306231d9670084527574c47292539bd011810..6a829b344ae0228f94a12403328b378c109afdab 100644
--- a/src/main/java/org/olat/core/servlets/OLATServlet.java
+++ b/src/main/java/org/olat/core/servlets/OLATServlet.java
@@ -141,7 +141,7 @@ public class OLATServlet extends HttpServlet {
 			I18nManager.remove18nInfoFromThread();
 			Tracing.setUreq(null);
 			GUIInterna.end(request);
-			DBFactory.getInstanceForClosing().cleanUpSession();
+			DBFactory.getInstanceForClosing().closeSession();
 		}
 	}
 
diff --git a/src/main/java/org/olat/core/util/UserSession.java b/src/main/java/org/olat/core/util/UserSession.java
index afed6bd399d5e78545b1b761cf5104a2d2cc74aa..b83a52ec97e6b5d8ab00f0e4ee408ab959d95f9e 100644
--- a/src/main/java/org/olat/core/util/UserSession.java
+++ b/src/main/java/org/olat/core/util/UserSession.java
@@ -380,7 +380,7 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList
 		// called by tomcat's timer thread -> we need to close!! since the next unbound will be called from the same tomcat-thread
 		finally {
 			//o_clusterNOK: put into managed transaction wrapper
-			DBFactory.getInstance(false).commitAndCloseSession();
+			DBFactory.getInstance().commitAndCloseSession();
 		}
 	}
 
diff --git a/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacheWrapper.java b/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacheWrapper.java
index 641edcebbc9ff09f5f6173c5c604d371fa2710aa..f30214c32c93af6b4d6d6789ab79fb7d45996214 100644
--- a/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacheWrapper.java
+++ b/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacheWrapper.java
@@ -73,9 +73,7 @@ public class InfinispanCacheWrapper<U,V extends Serializable> implements CacheWr
 	public V get(U key) {
 		V elem;
 		try {
-			synchronized (cache) {//cluster_ok by definition of this class as used in single vm
-				elem = cache.get(key);				
-			}
+			elem = cache.get(key);				
 		} catch (IllegalStateException e) {
 			throw new OLATRuntimeException("cache state error for cache " + cache.getName(), e);
 		} catch (CacheException e) {
@@ -86,30 +84,23 @@ public class InfinispanCacheWrapper<U,V extends Serializable> implements CacheWr
 
 	@Override
 	public void remove(Object key) {
-		synchronized (cache) {//cluster_ok by definition of this class as used in single vm
-			cache.remove(key);
-		}
+		cache.remove(key);
 	}
 	
 	@Override
 	public V update(U key, V value) {
 		V reloaded;
-		synchronized (cache) {
-			if(cache.containsKey(key)) {
-				reloaded = cache.replace(key, value);
-			} else {
-				reloaded = cache.put(key, value);
-			}
-		}	
+		if(cache.containsKey(key)) {
+			reloaded = cache.replace(key, value);
+		} else {
+			reloaded = cache.put(key, value);
+		}
 		return reloaded;
 	}
 
 	@Override
 	public V put(U key, V value) {
-		V reloaded;
-		synchronized (cache) {
-			reloaded = cache.put(key, value);
-		}
-		return reloaded;
+		V oldOne = cache.put(key, value);
+		return oldOne;
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacher.java b/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacher.java
index ff7d0a4db95910576a5b218429c6a7188c1ec235..3565314374e79a8aff8ad99826d44b8d7578504c 100644
--- a/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacher.java
+++ b/src/main/java/org/olat/core/util/cache/infinispan/InfinispanCacher.java
@@ -34,6 +34,7 @@ import org.infinispan.configuration.cache.ConfigurationBuilder;
 import org.infinispan.eviction.EvictionStrategy;
 import org.infinispan.manager.EmbeddedCacheManager;
 import org.infinispan.transaction.TransactionMode;
+import org.infinispan.util.concurrent.IsolationLevel;
 import org.olat.core.util.cache.CacheConfig;
 import org.olat.core.util.cache.CacheWrapper;
 import org.olat.core.util.coordinate.Cacher;
@@ -88,6 +89,10 @@ public class InfinispanCacher implements Cacher {
 			builder.expiration().maxIdle(maxIdle);
 			builder.transaction().transactionMode(TransactionMode.NON_TRANSACTIONAL);
 			builder.dataContainer().storeAsBinary().storeValuesAsBinary(false);
+			builder.locking().concurrencyLevel(1000);
+			builder.locking().useLockStriping(false);
+			builder.locking().lockAcquisitionTimeout(15000);
+			builder.locking().isolationLevel(IsolationLevel.READ_COMMITTED);
 			Configuration configurationOverride = builder.build();
 			cacheManager.defineConfiguration(cacheName, configurationOverride);
 		}
diff --git a/src/main/java/org/olat/core/util/mail/MailPackage.java b/src/main/java/org/olat/core/util/mail/MailPackage.java
index 79abcfd7c0cdcd96fd5f745bffbdfed54aa20d69..d88f80083154f8588402f9bb75f94b874f3ffcd2 100644
--- a/src/main/java/org/olat/core/util/mail/MailPackage.java
+++ b/src/main/java/org/olat/core/util/mail/MailPackage.java
@@ -19,6 +19,8 @@
  */
 package org.olat.core.util.mail;
 
+import java.util.UUID;
+
 /**
  * A mail package is the sum of the template, the context and it's result.
  * All or part of thesse can be null.
@@ -29,52 +31,43 @@ package org.olat.core.util.mail;
  */
 public class MailPackage {
 	
+	private final String uuid;
 	private final boolean sendEmail;
 	private final MailTemplate template;
 	private final MailContext context;
 	private final MailerResult result;
 	
 	public MailPackage() {
-		this.sendEmail = true;
-		this.template = null;
-		this.context = null;
-		this.result = new MailerResult();
+		this(true);
 	}
 	
 	public MailPackage(boolean sendMail) {
-		this.sendEmail = sendMail;
-		this.template = null;
-		this.context = null;
-		this.result = new MailerResult();
+		this(null, new MailerResult(), (MailContext)null, sendMail);
 	}
 	
 	public MailPackage(MailTemplate template, MailContext context) {
-		this.sendEmail = true;
-		this.template = template;
-		this.context = context;
-		this.result = new MailerResult();
+		this(template, new MailerResult(), context, true);
 	}
 	
 	public MailPackage(MailTemplate template, String businessPath, boolean sendMail) {
-		this.sendEmail = sendMail;
-		this.template = template;
-		this.context = new MailContextImpl(null, null, businessPath);
-		this.result = new MailerResult();
+		this(template, new MailerResult(), new MailContextImpl(null, null, businessPath), sendMail);
 	}
 	
 	public MailPackage(MailerResult result, String businessPath, boolean sendMail) {
-		this.sendEmail = sendMail;
-		this.template = null;
-		this.context = new MailContextImpl(null, null, businessPath);
-		this.result = result;
+		this(null, result, new MailContextImpl(null, null, businessPath), sendMail);
 	}
 	
 	public MailPackage(MailTemplate template, MailerResult result, String businessPath, boolean sendMail) {
+		this(template, result, new MailContextImpl(null, null, businessPath), sendMail);
+	}
+	
+	public MailPackage(MailTemplate template, MailerResult result, MailContext context, boolean sendMail) {
 		this.sendEmail = sendMail;
 		this.template = template;
-		this.context = new MailContextImpl(null, null, businessPath);
+		this.context = context;
 		this.result = result;
-	}
+		this.uuid = UUID.randomUUID().toString();
+	} 
 
 
 	/**
@@ -86,6 +79,10 @@ public class MailPackage {
 		return sendEmail;
 	}
 
+	public String getUuid() {
+		return uuid;
+	}
+
 	public MailTemplate getTemplate() {
 		return template;
 	}
diff --git a/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java b/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java
index 8c8bc80222917882007e69c9a31ac7697fd1fd4b..c2ae87fe267bd8a0ce048324479a944ce29e14b6 100644
--- a/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java
+++ b/src/main/java/org/olat/core/util/mail/MailerWithTemplate.java
@@ -153,8 +153,13 @@ public class MailerWithTemplate {
 	 */
 	public MailerResult sendMailAsSeparateMails(MailContext mCtxt, List<Identity> recipientsTO, List<Identity> recipientsCC,
 			MailTemplate template, Identity sender) {
+		return sendMailAsSeparateMails(mCtxt, recipientsTO, recipientsCC, template, sender, null);
+	}
+	
+	public MailerResult sendMailAsSeparateMails(MailContext mCtxt, List<Identity> recipientsTO, List<Identity> recipientsCC,
+			MailTemplate template, Identity sender, String uuid) {
 		
-		String metaId = UUID.randomUUID().toString().replace("-", "");
+		String metaId = uuid == null ? UUID.randomUUID().toString().replace("-", "") : uuid;
 		MailerResult result = new MailerResult();
 		if (CoreSpringFactory.getImpl(MailModule.class).getMailhost() == null) {
 			result.setReturnCode(MailerResult.MAILHOST_UNDEFINED);
diff --git a/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml b/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml
index c9ace44fec135339010320b43c60d906d5e7b478..21d1dba537953da092f6b8ff7e1a72f1cc3954bf 100644
--- a/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml
+++ b/src/main/java/org/olat/core/util/mail/_spring/mailContext.xml
@@ -64,16 +64,6 @@
 		<property name="notificationsManager" ref="org.olat.core.util.notifications.NotificationsManager"/>
 	</bean>
 	
-	<bean id="mailDBMappings" class="org.olat.core.commons.persistence.AdditionalDBMappings">
-		<property name="xmlFiles">
-			<list>								
-				<value>org/olat/core/util/mail/model/DBMail.hbm.xml</value>
-				<value>org/olat/core/util/mail/model/DBMailAttachment.hbm.xml</value>
-				<value>org/olat/core/util/mail/model/DBMailRecipient.hbm.xml</value>
-			</list>
-		</property>
-	</bean>
-	
 	<bean id="org.olat.core.util.mail.manager.MailNotificationsHandler" class="org.olat.core.util.mail.manager.MailNotificationsHandler">
 		<property name="mailModule" ref="mailModule"/>
 	</bean>
diff --git a/src/main/java/org/olat/core/util/mail/ui/SendDocumentsByEMailController.java b/src/main/java/org/olat/core/util/mail/ui/SendDocumentsByEMailController.java
index 14d548e2643b5e93cba800e256d58d509a275651..3b10e860b39b2494e5e055e3f65f5697822aea30 100644
--- a/src/main/java/org/olat/core/util/mail/ui/SendDocumentsByEMailController.java
+++ b/src/main/java/org/olat/core/util/mail/ui/SendDocumentsByEMailController.java
@@ -59,6 +59,7 @@ import org.olat.core.gui.control.generic.folder.FolderHelper;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.gui.util.CSSHelper;
 import org.olat.core.id.Identity;
+import org.olat.core.id.ModifiedInfo;
 import org.olat.core.id.Persistable;
 import org.olat.core.id.Preferences;
 import org.olat.core.id.User;
@@ -570,6 +571,8 @@ public class SendDocumentsByEMailController extends FormBasicController implemen
 	}
 
 	private class EMailIdentity implements Identity {
+
+		private static final long serialVersionUID = -2899896628137672419L;
 		private final String email;
 		private final User user;
 
@@ -626,7 +629,9 @@ public class SendDocumentsByEMailController extends FormBasicController implemen
 		}
 	}
 
-	private class EMailUser implements User {
+	private class EMailUser implements User, ModifiedInfo {
+
+		private static final long serialVersionUID = 7260225880639460228L;
 		private final EMailPreferences prefs = new EMailPreferences();
 		private Map<String, String> data = new HashMap<String, String>();
 
@@ -640,7 +645,6 @@ public class SendDocumentsByEMailController extends FormBasicController implemen
 			return null;
 		}
 
-		@SuppressWarnings("unused")
 		public boolean equalsByPersistableKey(Persistable persistable) {
 			return this == persistable;
 		}
@@ -649,19 +653,23 @@ public class SendDocumentsByEMailController extends FormBasicController implemen
 			return null;
 		}
 
+		@Override
+		public void setLastModified(Date date) {
+			//
+		}
+
 		public Date getCreationDate() {
 			return null;
 		}
 
-		@SuppressWarnings("unused")
-		public void setProperty(String propertyName, String propertyValue) {/**/
+		public void setProperty(String propertyName, String propertyValue) {
+			//
 		}
 
-		@SuppressWarnings("unused")
-		public void setPreferences(Preferences prefs) {/**/
+		public void setPreferences(Preferences prefs) {
+			//
 		}
 
-		@SuppressWarnings("unused")
 		public String getProperty(String propertyName, Locale locale) {
 			return data.get(propertyName);
 		}
@@ -679,6 +687,8 @@ public class SendDocumentsByEMailController extends FormBasicController implemen
 	}
 
 	private class EMailPreferences implements Preferences {
+		private static final long serialVersionUID = 7039109437910126584L;
+
 		@Override
 		public String getLanguage() {
 			return getLocale().getLanguage();
diff --git a/src/main/java/org/olat/core/util/session/UserSessionManager.java b/src/main/java/org/olat/core/util/session/UserSessionManager.java
index 2db259279773a8f32f06e6dd3b529f5b46f03c13..49fe5b7127b33c5655c9bf893fdcfa429b1ba75b 100644
--- a/src/main/java/org/olat/core/util/session/UserSessionManager.java
+++ b/src/main/java/org/olat/core/util/session/UserSessionManager.java
@@ -33,6 +33,7 @@ import javax.annotation.PostConstruct;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
+import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.control.Disposable;
 import org.olat.core.gui.control.Event;
 import org.olat.core.helpers.Settings;
@@ -84,6 +85,8 @@ public class UserSessionManager implements GenericEventListener {
 	private static final AtomicInteger sessionCountRest = new AtomicInteger();
 	private static final AtomicInteger sessionCountDav = new AtomicInteger();
 	
+	@Autowired
+	private DB dbInstance;
 	@Autowired
 	private UserSessionModule sessionModule;
 	@Autowired
@@ -340,10 +343,16 @@ public class UserSessionManager implements GenericEventListener {
 	 * called to make sure the current authenticated user (if there is one at all)
 	 * is cleared and signed off. This method is firing the SignOnOffEvent Multiuserevent.
 	 */
-	public synchronized void signOffAndClear(UserSession usess) {  //o_clusterOK by:fj
+	public void signOffAndClear(UserSession usess) {  //o_clusterOK by:fj
+		internSignOffAndClear(usess);
+		//commit all changes after sign off, especially commit lock which were
+		//deleted by dispose methods
+		dbInstance.commit();
+	}
+	
+	private void internSignOffAndClear(UserSession usess) {
 		boolean isDebug = log.isDebug();
 		if(isDebug) log.debug("signOffAndClear() START");
-		//
 		
 		signOffAndClearWithout(usess);
 		// handle safely
@@ -533,7 +542,7 @@ public class UserSessionManager implements GenericEventListener {
 			if (userRoles != null && !userRoles.isOLATAdmin()) {
 				//do not logout administrators
 				try {
-					signOffAndClear(userSession);
+					internSignOffAndClear(userSession);
 					if(userSession.getSessionInfo() != null && userSession.getSessionInfo().getSession() != null) {
 						userSession.getSessionInfo().getSession().invalidate();
 					}
@@ -571,7 +580,7 @@ public class UserSessionManager implements GenericEventListener {
 			try {
 				UserSession userSession = (UserSession) iterator.next();
 				if (!userSession.getRoles().isOLATAdmin() && !userSession.getSessionInfo().isWebDAV()) {
-					signOffAndClear(userSession);
+					internSignOffAndClear(userSession);
 					invalidateCounter++;
 				}
 			} catch (Throwable th) {
diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java
index 91fe292e9dd1dde2352281c6732c4e65fa7bb9bf..43048880cae0b097ee2cda105ac66ece9f0477f7 100644
--- a/src/main/java/org/olat/course/CourseFactory.java
+++ b/src/main/java/org/olat/course/CourseFactory.java
@@ -764,7 +764,10 @@ public class CourseFactory extends BasicManager {
 			 StatusDescription[] status = publishProcess.testPublishSet(locale);
 			 //publish not possible when there are errors
 			 for(int i = 0; i < status.length; i++) {
-				 if(status[i].isError()) return;
+				 if(status[i].isError()) {
+					 log.error("Status error by publish: " + status[i].getLongDescription(locale));
+					 return;
+				 }
 			 }
 		 }
 
diff --git a/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties
index ab0bcbd6946b67c95a6aad3998056f773edb0176..aec25736f55bae9e7595c8c7f4122f96102a196d 100644
--- a/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Tue Dec 18 17:51:16 CET 2012
+#Fri Feb 01 13:48:21 CET 2013
 action=Action
 add.member=Add member
 assessment=Assessment tool
@@ -9,6 +9,7 @@ dedup.done=Purging of course and group members has been terminated successfully
 dedup.members=Purge members
 dedup.members.notfound=No members found that are both course members and group members at the same time.
 dialog.modal.bg.leave.text=Do you really want to remove the user(s) {0} from the course and all the groups?
+dialog.modal.bg.send.mail=$org.olat.group.ui.main\:dialog.modal.bg.send.mail
 edit.member=Edit member
 edit.member.groups=Group membership
 edit.member.groups.desc=Add user to the groups below by selecting the appropriate checkboxes.
@@ -63,6 +64,7 @@ table.header.graduate=$org.olat.group.ui.main\:table.header.graduate
 table.header.groups=Groups
 table.header.lastName=Last name
 table.header.lastTime=Last visit
+table.header.login=$org.olat.group.ui.main\:table.header.login
 table.header.mail=E-mail
 table.header.participants=Participant
 table.header.participantsCount=Assigned
diff --git a/src/main/java/org/olat/course/nodes/BCCourseNode.java b/src/main/java/org/olat/course/nodes/BCCourseNode.java
index eaa284ef8be8e88020dd896bd3437c0f4bb2cc99..728e9f2282996386bf55efbb585e039f5c4c3d34 100644
--- a/src/main/java/org/olat/course/nodes/BCCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/BCCourseNode.java
@@ -307,7 +307,7 @@ public class BCCourseNode extends GenericCourseNode {
 		//only here we know which translator to take for translating condition error messages
 		oneClickStatusCache = null;
 		String translatorStr = Util.getPackageName(BCCourseNodeEditController.class);
-		List statusDescs =isConfigValidWithTranslator(cev, translatorStr,getConditionExpressions());
+		List<StatusDescription> statusDescs =isConfigValidWithTranslator(cev, translatorStr,getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(statusDescs);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java
index 067f0a482b696ce16d884f82f5d449dd73f70311..54d07fbbb909fd00b27fcff0e38e6e0d86bda044 100644
--- a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java
+++ b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java
@@ -138,7 +138,7 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode {
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(LTIEditController.class);
-		List sds =  isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds =  isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/CPCourseNode.java b/src/main/java/org/olat/course/nodes/CPCourseNode.java
index bdffd52cb74c5d00359530ae32c69c57429891ce..3053ad18da781c98a43975d976f473bd1bae49ee 100644
--- a/src/main/java/org/olat/course/nodes/CPCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/CPCourseNode.java
@@ -144,7 +144,7 @@ public class CPCourseNode extends AbstractAccessableCourseNode {
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(ConditionEditController.class);
-		List statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		return StatusDescriptionHelper.sort(statusDescs);
 	}
 
diff --git a/src/main/java/org/olat/course/nodes/DialogCourseNode.java b/src/main/java/org/olat/course/nodes/DialogCourseNode.java
index 1ec97f693d64c78d3ea1d8b49f3422818d79472f..490461dd740eab5d333770f1a1a2fd10ed4ecb6c 100644
--- a/src/main/java/org/olat/course/nodes/DialogCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/DialogCourseNode.java
@@ -129,7 +129,7 @@ public class DialogCourseNode extends AbstractAccessableCourseNode {
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(DialogCourseNodeEditController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/ENCourseNode.java b/src/main/java/org/olat/course/nodes/ENCourseNode.java
index ab86cc70d087b33fe5df7f80636c16d9f83c70c5..bce419c536a6fedd62a1268e671d94d4bbefa095 100644
--- a/src/main/java/org/olat/course/nodes/ENCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/ENCourseNode.java
@@ -186,8 +186,8 @@ public class ENCourseNode extends AbstractAccessableCourseNode {
 		// error messages
 		String translatorStr = Util.getPackageName(ConditionEditController.class);
 
-		List condErrs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
-		List missingNames = new ArrayList();
+		List<StatusDescription> condErrs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> missingNames = new ArrayList<StatusDescription>();
 		/*
 		 * check group and area names for existence
 		 */
diff --git a/src/main/java/org/olat/course/nodes/FOCourseNode.java b/src/main/java/org/olat/course/nodes/FOCourseNode.java
index 374f34e99492f2550dd7cc9a5884d031c0d58f00..c93a30c2eb81d754daf1a644e5a634fe423a7f45 100644
--- a/src/main/java/org/olat/course/nodes/FOCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/FOCourseNode.java
@@ -346,7 +346,7 @@ public class FOCourseNode extends GenericCourseNode {
 		oneClickStatusCache = null;
 		//only here we know which translator to take for translating condition error messages
 		String translatorStr = Util.getPackageName(FOCourseNodeEditController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr,getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr,getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
index d6baeacf41a18fee2e39276019db5e4738630d63..36c82ae09e65e897f98953ed3710ed32bf672301 100644
--- a/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQSURVCourseNode.java
@@ -150,7 +150,7 @@ public class IQSURVCourseNode extends AbstractAccessableCourseNode {
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(IQEditController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
index 320254aa7a189859e68da3bb47b82c5a4fd01ec6..0e88bc0ebfcf9128d58bee4e8ddd7a5889886ad8 100644
--- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
@@ -160,7 +160,7 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements As
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(IQEditController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/MSCourseNode.java b/src/main/java/org/olat/course/nodes/MSCourseNode.java
index 92a72f99eeb96bb79b68892305e8dba3fc069208..0ed964ad368e62476ac1b5a72995e50410e7a3f2 100644
--- a/src/main/java/org/olat/course/nodes/MSCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/MSCourseNode.java
@@ -56,6 +56,7 @@ import org.olat.course.run.scoring.ScoreEvaluation;
 import org.olat.course.run.userview.NodeEvaluation;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.modules.ModuleConfiguration;
+import org.olat.properties.Property;
 import org.olat.repository.RepositoryEntry;
 
 /**
@@ -198,7 +199,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(MSEditFormController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
@@ -227,7 +228,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Assess
 	@Override
 	public String informOnDelete(Locale locale, ICourse course) {
 		CoursePropertyManager cpm = PersistingCoursePropertyManager.getInstance(course);
-		List list = cpm.listCourseNodeProperties(this, null, null, null);
+		List<Property> list = cpm.listCourseNodeProperties(this, null, null, null);
 		if (list.size() == 0) return null; // no properties created yet
 		Translator trans = new PackageTranslator(PACKAGE_MS, locale);
 		return trans.translate("warn.nodedelete");
diff --git a/src/main/java/org/olat/course/nodes/OpenMeetingsCourseNode.java b/src/main/java/org/olat/course/nodes/OpenMeetingsCourseNode.java
index 144571901cf1b35c8344b6c49f5071de0c65b14e..09fd2dad865d50abdcd2d40e7e65aa729bdae9cd 100644
--- a/src/main/java/org/olat/course/nodes/OpenMeetingsCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/OpenMeetingsCourseNode.java
@@ -170,17 +170,19 @@ public class OpenMeetingsCourseNode extends AbstractAccessableCourseNode {
 		if (oneClickStatusCache != null) { return oneClickStatusCache[0]; }
 		
 		StatusDescription sd = StatusDescription.NOERROR;
-		OpenMeetingsManager openMeetingsManager = CoreSpringFactory.getImpl(OpenMeetingsManager.class);
-		Long roomId = openMeetingsManager.getRoomId(null, groupMgr.getCourseResource(), getIdent());
-		if(roomId == null) {
-			String shortKey = "error.noroom.short";
-			String longKey = "error.noroom.long";
-			String[] params = new String[] { getShortTitle() };
-			String translPackage = Util.getPackageName(OpenMeetingsRoomEditController.class);
-			sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translPackage);
-			sd.setDescriptionForUnit(getIdent());
-			// set which pane is affected by error
-			sd.setActivateableViewIdentifier(CPEditController.PANE_TAB_CPCONFIG);
+		if(groupMgr != null) {
+			OpenMeetingsManager openMeetingsManager = CoreSpringFactory.getImpl(OpenMeetingsManager.class);
+			Long roomId = openMeetingsManager.getRoomId(null, groupMgr.getCourseResource(), getIdent());
+			if(roomId == null) {
+				String shortKey = "error.noroom.short";
+				String longKey = "error.noroom.long";
+				String[] params = new String[] { getShortTitle() };
+				String translPackage = Util.getPackageName(OpenMeetingsRoomEditController.class);
+				sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, translPackage);
+				sd.setDescriptionForUnit(getIdent());
+				// set which pane is affected by error
+				sd.setActivateableViewIdentifier(CPEditController.PANE_TAB_CPCONFIG);
+			}
 		}
 		return sd;
 	}
diff --git a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java
index 6e394168e92da9fb8ee8762885fd665b4e201002..97b41a581efde1f3739f4c33cd468d214d4f8fe7 100644
--- a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java
@@ -140,8 +140,6 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess
 	private Condition  conditionDrop, conditionScoring, conditionReturnbox;
 	private Condition  conditionProjectBroker;
 
-	private transient CourseGroupManager groupMgr;
-
 	/**
 	 * Default constructor.
 	 */
@@ -159,7 +157,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess
 		updateModuleConfigDefaults(false);
 		ProjectBrokerCourseEditorController childTabCntrllr = ProjectBrokerControllerFactory.createCourseEditController(ureq, wControl, course, euce, this );
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
-		groupMgr = course.getCourseEnvironment().getCourseGroupManager();
+		CourseGroupManager groupMgr = course.getCourseEnvironment().getCourseGroupManager();
 		NodeEditController editController = new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, groupMgr, euce, childTabCntrllr);
 		editController.addControllerListener(childTabCntrllr);
 		return editController;
@@ -285,10 +283,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess
 		// error messages
 		String translatorStr = Util.getPackageName(ProjectBrokerCourseEditorController.class);
 		// check if group-manager is already initialized
-		if (groupMgr == null) {
-			groupMgr = cev.getCourseGroupManager();
-		}
-		List sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
@@ -320,7 +315,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess
 	public String informOnDelete(Locale locale, ICourse course) {
 		Translator trans = new PackageTranslator(PACKAGE_PROJECTBROKER, locale);
 		CoursePropertyManager cpm = PersistingCoursePropertyManager.getInstance(course);
-		List list = cpm.listCourseNodeProperties(this, null, null, null);
+		List<Property> list = cpm.listCourseNodeProperties(this, null, null, null);
 		if (list.size() != 0) return trans.translate(NLS_WARN_NODEDELETE); // properties exist
 		File fDropboxFolder = new File(FolderConfig.getCanonicalRoot() + DropboxController.getDropboxPathRelToFolderRoot(course.getCourseEnvironment(), this));
 		if (fDropboxFolder.exists() && fDropboxFolder.list().length > 0) return trans.translate(NLS_WARN_NODEDELETE); // Dropbox folder contains files
@@ -654,7 +649,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess
 	public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) {
 		Identity identity = userCourseEnvironment.getIdentityEnvironment().getIdentity();
 		CoursePropertyManager propMgr = userCourseEnvironment.getCourseEnvironment().getCoursePropertyManager();
-		List samples = propMgr.findCourseNodeProperties(this, identity, null, TaskController.PROP_ASSIGNED);
+		List<Property> samples = propMgr.findCourseNodeProperties(this, identity, null, TaskController.PROP_ASSIGNED);
 		if (samples.size() == 0) return null; // no sample assigned yet
 		return ((Property) samples.get(0)).getStringValue();
 	}
@@ -811,13 +806,13 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Assess
 	 * @see org.olat.course.nodes.GenericCourseNode#getConditionExpressions()
 	 */
 	@Override
-	public List getConditionExpressions() {
-		ArrayList retVal;
-		List parentsConditions = super.getConditionExpressions();
+	public List<ConditionExpression> getConditionExpressions() {
+		List<ConditionExpression> retVal;
+		List<ConditionExpression> parentsConditions = super.getConditionExpressions();
 		if (parentsConditions.size() > 0) {
-			retVal = new ArrayList(parentsConditions);
+			retVal = new ArrayList<ConditionExpression>(parentsConditions);
 		} else {
-			retVal = new ArrayList();
+			retVal = new ArrayList<ConditionExpression>();
 		}
 		//
 		String conditionProjectBroker = getConditionProjectBroker().getConditionExpression();
diff --git a/src/main/java/org/olat/course/nodes/STCourseNode.java b/src/main/java/org/olat/course/nodes/STCourseNode.java
index 84a3823f9a99b7ee7dc338c75028d7c7906a7e6c..16daeab80b756dcebcdbd7f03261e6afb2a0fd89 100644
--- a/src/main/java/org/olat/course/nodes/STCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/STCourseNode.java
@@ -316,7 +316,7 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess
 		// only here we know which translator to take for translating condition
 		// error messages
 		String translatorStr = Util.getPackageName(STCourseNodeEditController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/TACourseNode.java b/src/main/java/org/olat/course/nodes/TACourseNode.java
index b07822134640a1626cd577a90fd9b7f8e85a6e50..75d12dfbf916a05e007269d817749b2777a31c83 100644
--- a/src/main/java/org/olat/course/nodes/TACourseNode.java
+++ b/src/main/java/org/olat/course/nodes/TACourseNode.java
@@ -160,8 +160,6 @@ public class TACourseNode extends GenericCourseNode implements AssessableCourseN
 
 	private Condition conditionTask, conditionDrop, conditionReturnbox, conditionScoring, conditionSolution;
 
-	private transient CourseGroupManager groupMgr;
-	
 	private static final OLog log = Tracing.createLoggerFor(TACourseNode.class);
 
 	/**
@@ -181,7 +179,7 @@ public class TACourseNode extends GenericCourseNode implements AssessableCourseN
 		updateModuleConfigDefaults(false);
 		TACourseNodeEditController childTabCntrllr = new TACourseNodeEditController(ureq, wControl, course, this, course.getCourseEnvironment().getCourseGroupManager(), euce);
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
-		groupMgr = course.getCourseEnvironment().getCourseGroupManager();
+		CourseGroupManager groupMgr = course.getCourseEnvironment().getCourseGroupManager();
 		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, groupMgr, euce, childTabCntrllr);
 	}
 
@@ -289,9 +287,6 @@ public class TACourseNode extends GenericCourseNode implements AssessableCourseN
 		// error messages
 		String translatorStr = Util.getPackageName(TACourseNodeEditController.class);
 		// check if group-manager is already initialized
-		if (groupMgr == null) {
-			groupMgr = cev.getCourseGroupManager();
-		}
 		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
diff --git a/src/main/java/org/olat/course/nodes/WikiCourseNode.java b/src/main/java/org/olat/course/nodes/WikiCourseNode.java
index 9bc8711da7b938d54633a085bc44687ef28c0f90..d7a3d0c934e300af323ba4b8bb40bd9ec80a1789 100644
--- a/src/main/java/org/olat/course/nodes/WikiCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/WikiCourseNode.java
@@ -168,7 +168,7 @@ public class WikiCourseNode extends AbstractAccessableCourseNode {
 		oneClickStatusCache = null;
 		//only here we know which translator to take for translating condition error messages
 		String translatorStr = Util.getPackageName(WikiEditController.class);
-		List sds = isConfigValidWithTranslator(cev, translatorStr,getConditionExpressions());
+		List<StatusDescription> sds = isConfigValidWithTranslator(cev, translatorStr,getConditionExpressions());
 		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
 		return oneClickStatusCache;
 	}
diff --git a/src/main/java/org/olat/course/nodes/bc/BCWebService.java b/src/main/java/org/olat/course/nodes/bc/BCWebService.java
index 8b588e9511bd0dd50277f10a924c610e4c4014ad..ea59fbf3a08d0984345626ea10783f9694eac48c 100644
--- a/src/main/java/org/olat/course/nodes/bc/BCWebService.java
+++ b/src/main/java/org/olat/course/nodes/bc/BCWebService.java
@@ -23,6 +23,7 @@ import static org.olat.restapi.security.RestSecurityHelper.getUserRequest;
 import static org.olat.restapi.security.RestSecurityHelper.isAuthor;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -367,7 +368,7 @@ public class BCWebService extends AbstractCourseNodeWebService {
 		}	
 	}
 	
-	public static FolderVO createFolderVO(IdentityEnvironment ienv, ICourse course, BCCourseNode bcNode, Set<String> subscribed) {
+	public static FolderVO createFolderVO(IdentityEnvironment ienv, ICourse course, BCCourseNode bcNode, Collection<String> subscribed) {
 		OlatNamedContainerImpl container = BCCourseNode.getSecurisedNodeFolderContainer(bcNode, course.getCourseEnvironment(), ienv);
 		VFSSecurityCallback secCallback = container.getLocalSecurityCallback();
 		
diff --git a/src/main/java/org/olat/course/tree/CourseEditorTreeNode.java b/src/main/java/org/olat/course/tree/CourseEditorTreeNode.java
index 17d249cdb9c18007096236c5c291a3e445d14601..f304cdbfac992505248ca62ae596cc40959ca083 100644
--- a/src/main/java/org/olat/course/tree/CourseEditorTreeNode.java
+++ b/src/main/java/org/olat/course/tree/CourseEditorTreeNode.java
@@ -29,6 +29,7 @@ import java.util.List;
 
 import org.olat.core.gui.components.tree.GenericTreeNode;
 import org.olat.core.util.nodes.INode;
+import org.olat.course.condition.interpreter.ConditionExpression;
 import org.olat.course.editor.StatusDescription;
 import org.olat.course.nodes.CourseNode;
 import org.olat.course.nodes.CourseNodeConfiguration;
@@ -41,6 +42,8 @@ import org.olat.course.nodes.CourseNodeFactory;
  */
 public class CourseEditorTreeNode extends GenericTreeNode {
 
+	private static final long serialVersionUID = 3324118582289106497L;
+
 	/*
 	 * The course node... Important: coursenode's structure is not updated!
 	 */
@@ -173,7 +176,7 @@ public class CourseEditorTreeNode extends GenericTreeNode {
 		//do not show errors if marked for deletion
 		if(deleted) return null;
 		//
-		List conditions = cn.getConditionExpressions();
+		List<ConditionExpression> conditions = cn.getConditionExpressions();
 		if (conditions.size() > 0) return "o_midlock";
 		return null;
 	}
diff --git a/src/main/java/org/olat/group/_spring/businessGroupContext.xml b/src/main/java/org/olat/group/_spring/businessGroupContext.xml
index 3cd2545334bb4f34efbb2746972f3ee726ab6901..04f80970af9de272bf0d05c6cfc497d8b5be98cf 100644
--- a/src/main/java/org/olat/group/_spring/businessGroupContext.xml
+++ b/src/main/java/org/olat/group/_spring/businessGroupContext.xml
@@ -124,6 +124,7 @@
 	<bean class="org.olat.core.extensions.action.GenericActionExtension" name="groups.open" init-method="initExtensionPoints">
 		<property name="order" value="8201" />
 		<property name="navigationKey" value="OpenGroups" />
+		<property name="securityCallbackClassName" value="org.olat.resource.accesscontrol.AccessControlModuleEnabledSecurityCallback" />
 		<property name="actionController">	
 			<bean class="org.olat.core.gui.control.creator.AutoCreator" scope="prototype">
 				<property name="className" value="org.olat.group.ui.main.OpenBusinessGroupsController"/>
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
index 416d9243161658e897da9b1e7c92b52f67bdd7b9..111d77dabe32888c0d9e143d8d5556b5eb8c6443 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupMailing.java
@@ -113,8 +113,9 @@ public class BusinessGroupMailing {
 		if(context == null) {
 			context = new MailContextImpl(null, null, "[BusinessGroup:" + group.getKey() + "]");
 		}
-
-		MailerResult result = mailer.sendMailAsSeparateMails(context, Collections.singletonList(identity), null, template, ureqIdentity);
+		
+		String metaId = mailing != null ? mailing.getUuid() : null;
+		MailerResult result = mailer.sendMailAsSeparateMails(context, Collections.singletonList(identity), null, template, ureqIdentity, metaId);
 		if(mailing != null) {
 			mailing.appendResult(result);
 		}
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
index bdf2aca9546e4fc3485b62017010e65c4de4d986..8ccf427363cbcda11cdb568ba331fcb547881f39 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
@@ -32,6 +32,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import javax.annotation.PostConstruct;
 
@@ -211,7 +212,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroup updateBusinessGroup(Identity ureqIdentity, BusinessGroup group, String name, String description,
 			Integer minParticipants, Integer maxParticipants) {
 		
@@ -226,12 +226,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 		//auto rank if possible
 		autoRankCheck(ureqIdentity, bg, previousMaxParticipants);
 		BusinessGroup updatedGroup = businessGroupDAO.merge(bg);
-
+		dbInstance.commit();
 		return updatedGroup;
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroup updateBusinessGroup(Identity ureqIdentity, BusinessGroup group, String name, String description,
 			Integer minParticipants, Integer maxParticipants, Boolean waitingList, Boolean autoCloseRanks) {
 		
@@ -252,7 +251,9 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 		bg.setLastUsage(new Date(System.currentTimeMillis()));
 		//auto rank if possible
 		autoRankCheck(ureqIdentity, bg, previousMaxParticipants);
-		return businessGroupDAO.merge(bg);
+		BusinessGroup mergedGroup = businessGroupDAO.merge(bg);
+		dbInstance.commit();
+		return mergedGroup;
 	}
 	
 	private void autoRankCheck(Identity identity, BusinessGroup updatedGroup, Integer previousMaxParticipants) {
@@ -301,7 +302,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroup setLastUsageFor(final Identity identity, final BusinessGroup group) {
 		BusinessGroup reloadedBusinessGroup = businessGroupDAO.loadForUpdate(group.getKey());
 		reloadedBusinessGroup.setLastUsage(new Date());
@@ -318,7 +318,9 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			}
 			securityManager.touchMembership(identity, secGroups);
 		}
-		return businessGroupDAO.merge(reloadedBusinessGroup);
+		BusinessGroup mergedGroup = businessGroupDAO.merge(reloadedBusinessGroup);
+		dbInstance.commit();
+		return mergedGroup;
 	}
 
 	@Override
@@ -347,13 +349,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public List<BusinessGroup> loadAllBusinessGroups() {
 		return businessGroupDAO.loadAll();
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroup copyBusinessGroup(Identity identity, BusinessGroup sourceBusinessGroup, String targetName, String targetDescription,
 			Integer targetMin, Integer targetMax,  boolean copyAreas, boolean copyCollabToolConfig, boolean copyRights,
 			boolean copyOwners, boolean copyParticipants, boolean copyMemberVisibility, boolean copyWaitingList, boolean copyRelations) {
@@ -441,7 +441,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroup mergeBusinessGroups(final Identity ureqIdentity, BusinessGroup targetGroup,
 			final List<BusinessGroup> groupsToMerge, MailPackage mailing) {
 		groupsToMerge.remove(targetGroup);//to be sure
@@ -501,6 +500,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 		for(BusinessGroup group:groupsToMerge) {
 			deleteBusinessGroup(group);
 		}
+		dbInstance.commit();
 		return targetGroup;
 	}
 
@@ -552,6 +552,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			}
 		}
 		removeOwners(ureqIdentity, ownerToRemove, group);
+		dbInstance.commit();
 	}
 
 	@Override
@@ -700,7 +701,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public void deleteBusinessGroup(BusinessGroup group) {
 		try{
 			OLATResourceableJustBeforeDeletedEvent delEv = new OLATResourceableJustBeforeDeletedEvent(group);
@@ -750,6 +750,8 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			// delete the publisher attached to this group (e.g. the forum and folder
 			// publisher)
 			notificationsManager.deletePublishersOf(group);
+
+			dbInstance.commit();
 	
 			log.audit("Deleted Business Group", group.toString());
 		} catch(DBRuntimeException dbre) {
@@ -770,7 +772,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public MailerResult deleteBusinessGroupWithMail(BusinessGroup businessGroupTodelete, String businessPath, Identity deletedBy, Locale locale) {
 		Codepoint.codepoint(this.getClass(), "deleteBusinessGroupWithMail");
 			
@@ -794,13 +795,14 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 		}
 		// now delete the group first
 		deleteBusinessGroup(businessGroupTodelete);
+		dbInstance.commit();
 		// finally send email
 		MailerWithTemplate mailer = MailerWithTemplate.getInstance();
 		MailTemplate mailTemplate = BGMailHelper.createDeleteGroupMailTemplate(businessGroupTodelete, deletedBy);
 		if (mailTemplate != null) {
-			//fxdiff VCRP-16: intern mail system
+			String metaId = UUID.randomUUID().toString();
 			MailContext context = new MailContextImpl(businessPath);
-			MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, users, null, mailTemplate, null);
+			MailerResult mailerResult = mailer.sendMailAsSeparateMails(context, users, null, mailTemplate, null, metaId);
 			//MailHelper.printErrorsAndWarnings(mailerResult, wControl, locale);
 			return mailerResult;
 		}
@@ -818,7 +820,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroupAddResponse addOwners(Identity ureqIdentity, Roles ureqRoles, List<Identity> addIdentities,
 			BusinessGroup group, MailPackage mailing) {
 		BusinessGroupAddResponse response = new BusinessGroupAddResponse();
@@ -929,7 +930,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroupAddResponse addParticipants(Identity ureqIdentity, Roles ureqRoles, List<Identity> addIdentities,
 			BusinessGroup group, MailPackage mailing) {	
 		BusinessGroupAddResponse response = new BusinessGroupAddResponse();
@@ -945,21 +945,20 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 				response.getIdentitiesAlreadyInGroup().add(identity);
 			}
 		}
-
+		dbInstance.commit();
 		return response;
 	}
 	
 	@Override
-	@Transactional
 	public void cancelPendingParticipation(Identity ureqIdentity, ResourceReservation reservation) {
 		if(reservation != null && "BusinessGroup".equals(reservation.getResource().getResourceableTypeName())) {
 			BusinessGroup group = businessGroupDAO.loadForUpdate(reservation.getResource().getResourceableId());
 			transferFirstIdentityFromWaitingToParticipant(ureqIdentity, group, null);
+			dbInstance.commit();
 		}
 	}
 
 	@Override
-	@Transactional
 	public void acceptPendingParticipation(Identity ureqIdentity, Identity reservationOwner, OLATResource resource) {
 		ResourceReservation reservation = acService.getReservation(reservationOwner, resource);
 		if(reservation != null && "BusinessGroup".equals(resource.getResourceableTypeName())) {
@@ -977,6 +976,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			}
 			
 			reservationDao.deleteReservation(reservation);
+			dbInstance.commit();
 		}
 	}
 
@@ -1002,17 +1002,16 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 	
 	@Override
-	@Transactional
 	public void removeParticipants(Identity ureqIdentity, List<Identity> identities, BusinessGroup group, MailPackage mailing) {
 		group = businessGroupDAO.loadForUpdate(group.getKey());
 		for (Identity identity : identities) {
 		  removeParticipant(ureqIdentity, identity, group, mailing);
 		  log.audit("removed identiy '" + identity.getName() + "' from securitygroup with key " + group.getPartipiciantGroup().getKey());
 		}
+		dbInstance.commit();
 	}
 
 	@Override
-	@Transactional
 	public void removeMembers(Identity ureqIdentity, List<Identity> identities, OLATResource resource, MailPackage mailing) {
 		if(identities == null || identities.isEmpty() || resource == null) return;//nothing to do
 		
@@ -1067,6 +1066,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 				reservationDao.deleteReservation(reservation);
 			}
 		}
+		dbInstance.commit();
 	}
 	
 	private final BusinessGroupMembershipViewImpl removeGroupMembers(Identity ureqIdentity, BusinessGroupMembershipViewImpl currentMembership,
@@ -1139,6 +1139,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 				log.audit("added identity '" + identity.getName() + "' to securitygroup with key " + currBusinessGroup.getPartipiciantGroup().getKey());
 			}
 		}
+		dbInstance.commit();
 		return response;
 	}
 
@@ -1155,11 +1156,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	@Override
 	public void removeFromWaitingList(Identity ureqIdentity, List<Identity> identities, BusinessGroup businessGroup, MailPackage mailing) {
 		businessGroup = businessGroupDAO.loadForUpdate(businessGroup.getKey());
-		
 		for (Identity identity : identities) {
 		  removeFromWaitingList(ureqIdentity, identity, businessGroup, mailing);
 		  log.audit("removed identiy '" + identity.getName() + "' from securitygroup with key " + businessGroup.getOwnerGroup().getKey());
 		}
+		dbInstance.commit();
 	}
 	
 	@Override
@@ -1177,7 +1178,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public BusinessGroupAddResponse moveIdentityFromWaitingListToParticipant(Identity ureqIdentity, List<Identity> identities, 
 			BusinessGroup currBusinessGroup, MailPackage mailing) {
 		
@@ -1198,7 +1198,8 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 				response.getIdentitiesAlreadyInGroup().add(identity);
 			}
 		}
-		
+
+		dbInstance.commit();
 		return response;
 	}
 	
@@ -1255,7 +1256,8 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			enrollStatus.setEnrolled(BGMembership.participant);						
 			if (log.isDebug()) log.debug("doEnroll as participant committed");
 		}
-		
+
+		dbInstance.commit();
 		log.info("doEnroll end", identity.getName());
 		return enrollStatus;
 	}
@@ -1362,7 +1364,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public void addResourceTo(BusinessGroup group, RepositoryEntry re) {
 		businessGroupRelationDAO.addRelationToResource(group, re.getOlatResource());
 		//add author permission
@@ -1373,7 +1374,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public void addResourcesTo(List<BusinessGroup> groups, List<RepositoryEntry> resources) {
 		if(groups == null || groups.isEmpty()) return;
 		if(resources == null || resources.isEmpty()) return;
@@ -1439,13 +1439,12 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public void dedupMembers(Identity ureqIdentity, RepositoryEntry entry, boolean coaches, boolean participants) {
 		dedupSingleRepositoryentry(ureqIdentity, entry, coaches, participants, false);
+		dbInstance.commit();
 	}
 	
 	@Override
-	@Transactional
 	public int countDuplicateMembers(RepositoryEntry entry, boolean coaches, boolean participants) {
 		return dedupSingleRepositoryentry(null, entry, coaches, participants, true);
 	}
@@ -1497,7 +1496,6 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 	}
 
 	@Override
-	@Transactional
 	public void removeResourceFrom(List<BusinessGroup> groups, RepositoryEntry re) {
 		if(groups == null || groups.isEmpty()) {
 			return; // nothing to do
@@ -1515,10 +1513,10 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 				dbInstance.commit();
 			}
 		}
+		dbInstance.commit();
 	}
 	
 	@Override
-	@Transactional
 	public void removeResource(OLATResource resource) {
 		SearchBusinessGroupParams params = new SearchBusinessGroupParams();
 		List<BusinessGroup> groups = findBusinessGroups(params, resource, 0, -1);
@@ -1530,6 +1528,7 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 			securityManager.deletePolicy(group.getOwnerGroup(), Constants.PERMISSION_COACH, resource);
 			securityManager.deletePolicy(group.getPartipiciantGroup(), Constants.PERMISSION_PARTI, resource);
 		}
+		dbInstance.commit();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/group/manager/ContactDAO.java b/src/main/java/org/olat/group/manager/ContactDAO.java
index 3e116be6263d7f194167a0836311c9cb20c36b50..80eb851d49c9166b741473693404f97e1b8ed944 100644
--- a/src/main/java/org/olat/group/manager/ContactDAO.java
+++ b/src/main/java/org/olat/group/manager/ContactDAO.java
@@ -19,7 +19,10 @@
  */
 package org.olat.group.manager;
 
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.persistence.TypedQuery;
 
@@ -46,6 +49,29 @@ public class ContactDAO {
 
 	@Autowired
 	private DB dbInstance;
+	
+	
+	public Collection<Long> getDistinctGroupOwnersParticipants(Identity me) {
+		List<Long> owners = getMembersForCount(me, BusinessGroupOwnerViewImpl.class);
+		List<Long> participants = getMembersForCount(me, BusinessGroupParticipantViewImpl.class);
+		Set<Long> contacts = new HashSet<Long>(participants);
+		contacts.addAll(owners);
+		return contacts;
+	}
+	
+	private List<Long> getMembersForCount(Identity me, Class<?> cl) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select distinct(memv.identityKey) from ").append(cl.getName()).append(" memv ")
+		  .append(" where memv.ownerSecGroupKey in (")
+		  .append("   select ownerSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi where ownerSgmi.identity.key=:identKey")
+		  .append(" ) or memv.participantSecGroupKey in (")
+		  .append("   select partSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi where partSgmi.identity.key=:identKey")
+		  .append(" )");
+		
+		return dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Long.class)
+				.setParameter("identKey", me.getKey())
+				.getResultList();
+	}
 
 	public List<BusinessGroupOwnerViewImpl> getGroupOwners(Identity me) {
 		return getMembers(me, BusinessGroupOwnerViewImpl.class);
@@ -60,8 +86,7 @@ public class ContactDAO {
 		sb.append("select memv from ").append(cl.getName()).append(" memv ")
 		  .append(" where memv.ownerSecGroupKey in (")
 		  .append("   select ownerSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as ownerSgmi where ownerSgmi.identity.key=:identKey")
-		  .append(" ) or")
-		  .append(" memv.participantSecGroupKey in (")
+		  .append(" ) or memv.participantSecGroupKey in (")
 		  .append("   select partSgmi.securityGroup from ").append(SecurityGroupMembershipImpl.class.getName()).append(" as partSgmi where partSgmi.identity.key=:identKey")
 		  .append(" )");
 		
diff --git a/src/main/java/org/olat/group/model/AddToGroupsEvent.java b/src/main/java/org/olat/group/model/AddToGroupsEvent.java
index 73d21444da9bec225b279fd5cd88ef365ff980c9..e572da6dff31efb7a13e6a47e70423c1973ddacc 100644
--- a/src/main/java/org/olat/group/model/AddToGroupsEvent.java
+++ b/src/main/java/org/olat/group/model/AddToGroupsEvent.java
@@ -38,13 +38,11 @@ public class AddToGroupsEvent extends Event {
 	
 	private List<Long> ownerList;
 	private List<Long> participantList;
-	private List<Long> mailForGroupsList;
 
-	public AddToGroupsEvent(List<Long> ownLong, List<Long> partLong, List<Long> mailLong) {
+	public AddToGroupsEvent(List<Long> ownLong, List<Long> partLong) {
 		super("addToGroups");
 		this.ownerList = ownLong;
 		this.participantList = partLong;
-		this.mailForGroupsList = mailLong;
 	}
 
 	public List<Long> getOwnerGroupKeys() {
@@ -54,9 +52,9 @@ public class AddToGroupsEvent extends Event {
 	public List<Long> getParticipantGroupKeys() {
 		return participantList;
 	}
-
-	public List<Long> getMailForGroupsList() {
-		return mailForGroupsList;
+	
+	public boolean isEmpty() {
+		return (ownerList == null || ownerList.isEmpty())
+				&& (participantList == null || participantList.isEmpty());
 	}
-
 }
diff --git a/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java b/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java
index a8f207ba67bffb9fdbde50219ca17774af18fd8e..60b8642c3553674846332b95a47c588a2d30e391 100644
--- a/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java
+++ b/src/main/java/org/olat/group/ui/edit/BusinessGroupMembersController.java
@@ -97,8 +97,10 @@ public class BusinessGroupMembersController extends BasicController {
 		mainVC.put("members", membersController.getInitialComponent());
 		
 		addMemberLink = LinkFactory.createButton("add.member", mainVC, this);
+		addMemberLink.setElementCssClass("o_sel_group_add_member");
 		mainVC.put("addMembers", addMemberLink);
 		importMemberLink = LinkFactory.createButton("import.member", mainVC, this);
+		importMemberLink.setElementCssClass("o_sel_group_import_members");
 		mainVC.put("importMembers", importMemberLink);
 	}
 	
diff --git a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties
index f6fdf192034c2d9d861f4510eddac58b712e0162..123ef061d268585ea11681f1b39a8395cb50354b 100644
--- a/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/group/ui/edit/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Tue Dec 18 16:59:56 CET 2012
+#Fri Feb 01 13:48:31 CET 2013
 add.member=$org.olat.group.ui.main\:add.member
 areachoice.no.areas.admin=No learning areas found. Please create a learning area within your group management.
 areachoice.no.areas.owner=No learning areas found. New learning areas can only be created by users who have access to the entire group management.
@@ -117,6 +117,7 @@ table.header.graduate=$org.olat.group.ui.main\:table.header.graduate
 table.header.groups=$org.olat.group.ui.main\:table.header.groups
 table.header.lastName=$org.olat.group.ui.main\:table.header.lastName
 table.header.lastTime=$org.olat.group.ui.main\:table.header.lastTime
+table.header.login=org.olat.group.ui.main\:table.header.login
 table.header.mail=$org.olat.group.ui.main\:table.header.mail
 table.header.participants=$org.olat.group.ui.main\:table.header.participants
 table.header.participantsCount=$org.olat.group.ui.main\:table.header.participantsCount
diff --git a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
index b97b17a747d169937f274ca06b8c92cf28694613..1728d9c8918b3914353bb28830e538c6938fec0e 100644
--- a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
+++ b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
@@ -62,13 +62,7 @@ import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
 import org.olat.core.util.mail.ContactList;
 import org.olat.core.util.mail.ContactMessage;
-import org.olat.core.util.mail.MailContext;
-import org.olat.core.util.mail.MailContextImpl;
-import org.olat.core.util.mail.MailHelper;
 import org.olat.core.util.mail.MailPackage;
-import org.olat.core.util.mail.MailTemplate;
-import org.olat.core.util.mail.MailerResult;
-import org.olat.core.util.mail.MailerWithTemplate;
 import org.olat.core.util.session.UserSessionManager;
 import org.olat.course.member.MemberListController;
 import org.olat.group.BusinessGroup;
@@ -77,7 +71,6 @@ import org.olat.group.BusinessGroupModule;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.BusinessGroupShort;
 import org.olat.group.model.BusinessGroupMembershipChange;
-import org.olat.group.ui.BGMailHelper;
 import org.olat.group.ui.main.MemberListTableModel.Cols;
 import org.olat.instantMessaging.InstantMessagingModule;
 import org.olat.instantMessaging.InstantMessagingService;
@@ -433,7 +426,6 @@ public abstract class AbstractMemberListController extends BasicController imple
 	}
 	
 	protected void doChangePermission(UserRequest ureq, MemberPermissionChangeEvent changes, List<Identity> members, boolean sendMail) {
-
 		MailPackage mailing = new MailPackage(sendMail);
 		if(repoEntry != null) {
 			List<RepositoryEntryPermissionChangeEvent> repoChanges = changes.generateRepositoryChanges(members);
@@ -443,46 +435,10 @@ public abstract class AbstractMemberListController extends BasicController imple
 		//commit all changes to the group memberships
 		List<BusinessGroupMembershipChange> allModifications = changes.generateBusinessGroupMembershipChange(members);
 		businessGroupService.updateMemberships(getIdentity(), allModifications, mailing);
-		DBFactory.getInstance().commitAndCloseSession();
-		
-		/*if(sendMail && allModifications != null && !allModifications.isEmpty()) {
-			for (BusinessGroupMembershipChange mod : allModifications) {
-				sendMailAfterChangePermission(mod);
-			}
-		}
 
-		//make sure all is committed before loading the model again (I see issues without)
-		//DBFactory.getInstance().commitAndCloseSession();
-		*/
 		reloadModel();
 	}
 	
-	protected void sendMailAfterChangePermission(BusinessGroupMembershipChange mod) {
-		MailTemplate template = null;
-		if(mod.getParticipant() != null) {
-			if(mod.getParticipant().booleanValue()) {
-				 template = BGMailHelper.createAddParticipantMailTemplate(mod.getGroup(), mod.getMember());
-			} else {
-				 template = BGMailHelper.createRemoveParticipantMailTemplate(mod.getGroup(), mod.getMember());
-			}
-		}
-		
-		if(mod.getWaitingList() != null) {
-			if(mod.getWaitingList().booleanValue()) {
-				template = BGMailHelper.createAddWaitinglistMailTemplate(mod.getGroup(), mod.getMember());
-			} else {
-				template = BGMailHelper.createRemoveWaitinglistMailTemplate(mod.getGroup(), mod.getMember());
-			}
-		}
-		
-		if(template != null) {	
-			MailerWithTemplate mailer = MailerWithTemplate.getInstance();
-			MailContext ctx = new MailContextImpl(null, null, getWindowControl().getBusinessControl().getAsString());
-			MailerResult mailerResult = mailer.sendMailAsSeparateMails(ctx, Collections.singletonList(mod.getMember()), null, template, getIdentity());
-			MailHelper.printErrorsAndWarnings(mailerResult, getWindowControl(), getLocale());
-		}
-	}
-	
 	protected void doLeave(List<Identity> members, boolean sendMail) {
 		MailPackage mailing = new MailPackage(sendMail);
 		if(repoEntry != null) {
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java b/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java
index 26325e0fdbe589fcba7dc41295c7543e71a76e21..554d158bc35454488e2862fd5e4fe160a7148802 100644
--- a/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupSearchController.java
@@ -322,8 +322,8 @@ public class BusinessGroupSearchController extends FormBasicController implement
 		}
 		
 		if(rolesEl != null && rolesEl.isOneSelected()) {
-			e.setAttendee(rolesEl.isSelected(0) || rolesEl.isSelected(1));
-			e.setOwner(rolesEl.isSelected(0) || rolesEl.isSelected(2));
+			e.setOwner(rolesEl.isSelected(0) || rolesEl.isSelected(1));
+			e.setAttendee(rolesEl.isSelected(0) || rolesEl.isSelected(2));
 			e.setWaiting(rolesEl.isSelected(0) || rolesEl.isSelected(3));
 		}
 		
diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties
index 5eab6ed19845a2c0d208b48ca736dc4037f104c8..e4157da6448a4d0729d48ad8345a13695d3036b0 100644
--- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Tue Dec 18 17:12:34 CET 2012
+#Fri Feb 01 13:48:43 CET 2013
 accept=Confirm
 action=Action
 add.member=Add member
@@ -35,13 +35,11 @@ dialog.modal.bg.leave.text=If you leave the group "{0}" you will no longer have
 dialog.modal.bg.mail.text=Do you want to inform the members of this group by email?
 dialog.modal.bg.remove.text=Do you really want to remove these persons "{0}" from the group?
 dialog.modal.bg.send.mail=Would you like to notify the respective members?
-remove.send.mail=Notification
-remove.send.mail.label=Send E-mail
 edit.member=Edit membership
 edit.member.groups=Group memberships
 edit.member.title=Member rights course {0}
-error.atleastone=At least one owner is required in a course.
 email.group=Send E-mail
+error.atleastone=At least one owner is required in a course.
 group.access.success=Access to group is successful
 group.used.in.course=This group is used in the following courses\:
 hide=Hide information
@@ -51,8 +49,6 @@ index.header=Groups
 index.intro=The following list shows all groups, learning groups, and right groups you participate in.
 index.table.nogroup=You are not registered in any group.
 info.group.deleted=This group has been deleted.
-
-
 main.menu.title=Groups
 main.menu.title.alt=Groups
 marked.groups=Bookmark
@@ -88,6 +84,8 @@ owned.groups=Coach
 owned.groups.2=Coached
 pending.reservations=<h4>Accept group and course memberships</h4>You have been invited to the following groups and courses. For each listed groups and courses select the button "$\:accept" or "$\:reject" and finally save your choice with the button "$org.olat.core\:ok". You can safely skip this question now using the button "$org.olat.core\:cancel" and answer them on your next login.
 reject=Reject
+remove.send.mail=Notification
+remove.send.mail.label=Send E-mail
 reservation.coach=as coach
 role.group.participant=Group member
 role.group.tutor=Group coach
@@ -140,6 +138,7 @@ table.header.lastTime=Last visit
 table.header.lastUsage=Last access (admin)
 table.header.leave=Leave
 table.header.leave.waiting=Leave
+table.header.login=User name
 table.header.mail=E-mail
 table.header.mark=Bookmark
 table.header.participants=Participant
diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
index 161bfcaf2b2328344c2239454a48032c6d6771d5..97b880b82eed185cc3d2b3ffa552533f6d4573a3 100644
--- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
+++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
@@ -209,7 +209,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 	private Controller accessController;
 	
 	private boolean needActivation;
-	private final boolean chatAvailable;
+	private boolean chatAvailable;
 
 	/**
 	 * Do not use this constructor! Use the BGControllerFactory instead!
@@ -253,10 +253,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 		addLoggingResourceable(LoggingResourceable.wrap(businessGroup));
 		ThreadLocalUserActivityLogger.log(GroupLoggingAction.GROUP_OPEN, getClass());
 		
-		chatAvailable = CoreSpringFactory.getImpl(InstantMessagingModule.class).isEnabled() &&
-				CoreSpringFactory.getImpl(InstantMessagingModule.class).isGroupEnabled() && 
-				CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(businessGroup).isToolEnabled(CollaborationTools.TOOL_CHAT);
-
+		chatAvailable = isChatAvailable();
 		isAdmin = ureq.getUserSession().getRoles().isOLATAdmin()
 				|| ureq.getUserSession().getRoles().isGroupManager()
 				|| securityManager.isIdentityPermittedOnResourceable(getIdentity(), Constants.PERMISSION_ACCESS, businessGroup);
@@ -330,6 +327,13 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 		}
 	}
 	
+	private boolean isChatAvailable() {
+		return CoreSpringFactory.getImpl(InstantMessagingModule.class).isEnabled() &&
+				CoreSpringFactory.getImpl(InstantMessagingModule.class).isGroupEnabled() && 
+				CollaborationToolsFactory.getInstance().getOrCreateCollaborationTools(businessGroup).isToolEnabled(CollaborationTools.TOOL_CHAT);
+
+	}
+	
 	private Component getOnWaitingListMessage(UserRequest ureq, BusinessGroup group) {
 		VelocityContainer vc = createVelocityContainer("waiting");
 		vc.contextPut("name", group.getName());
@@ -908,7 +912,9 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 			if (event.getCommand().equals(BusinessGroupModifiedEvent.CONFIGURATION_MODIFIED_EVENT)) {
 				// reset business group property manager
 				// update reference to update business group object
-				businessGroup = businessGroupService.loadBusinessGroup(this.businessGroup);
+				businessGroup = businessGroupService.loadBusinessGroup(businessGroup);
+				chatAvailable = isChatAvailable();
+				
 				main.contextPut("BuddyGroup", businessGroup);
 				TreeModel trMdl = buildTreeModel();
 				bgTree.setTreeModel(trMdl);
diff --git a/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java b/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java
index d2ad6b3e5f298cf8e6656d0ea2fed1854f6ab5ae..0392fabfcaf0cf75619be43bd93a660535c25380 100644
--- a/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java
+++ b/src/main/java/org/olat/group/ui/wizard/BGMailTemplateController.java
@@ -139,14 +139,16 @@ public class BGMailTemplateController extends FormBasicController {
 				}
 			}
 			
-			bodyElem.clearError();
-			if (bodyElem.getValue().trim().length() == 0) {
-				bodyElem.setErrorKey("mailtemplateform.error.emptyfield", null);
-				allOk &= false;
-			}
-			if (bodyElem.getValue().indexOf("#") != -1) {
-				bodyElem.setErrorKey("mailtemplateform.error.velocity", null);
-				allOk &= false;
+			if(bodyElem != null) {
+				bodyElem.clearError();
+				if (bodyElem.getValue().trim().length() == 0) {
+					bodyElem.setErrorKey("mailtemplateform.error.emptyfield", null);
+					allOk &= false;
+				}
+				if (bodyElem.getValue().indexOf("#") != -1) {
+					bodyElem.setErrorKey("mailtemplateform.error.velocity", null);
+					allOk &= false;
+				}
 			}
 		}
 		return allOk && super.validateFormLogic(ureq);
diff --git a/src/main/java/org/olat/gui/control/_content/olatFooter.html b/src/main/java/org/olat/gui/control/_content/olatFooter.html
index 0090d60dd9a851fc01a8365fabb44db026341e0b..80d2fd36cd4c012398de2d3efc66f49942dd4b93 100644
--- a/src/main/java/org/olat/gui/control/_content/olatFooter.html
+++ b/src/main/java/org/olat/gui/control/_content/olatFooter.html
@@ -2,7 +2,7 @@
 	#if ($loggedIn)
 		<span id="b_username">$r.translate("footer.logged.in.as", ["$username"])</span>
 	#end 
-	<span id="b_counter">( $r.render("userCounter") $r.translate("other.users.online") )</span>
+	<span id="b_counter">($r.render("userCounter") $r.translate("other.users.online"))</span>
 </div>
 <div id="b_footer_version">
 	<a href="http://www.openolat.org" title="Homepage of the Open Source LMS OpenOLAT" target="_blank">$olatversion</a>
diff --git a/src/main/java/org/olat/instantMessaging/InstantMessagingService.java b/src/main/java/org/olat/instantMessaging/InstantMessagingService.java
index 05edd4e7ccbbaabfc642439b05d213cbaccd70ec..9c4b9d76f17619b0f071eb3bafc5d5fca4f747c4 100644
--- a/src/main/java/org/olat/instantMessaging/InstantMessagingService.java
+++ b/src/main/java/org/olat/instantMessaging/InstantMessagingService.java
@@ -55,8 +55,6 @@ public interface InstantMessagingService {
 	
 	public Buddy getBuddyById(Long identityKey);
 	
-	public List<Buddy> getOnlineBuddies();
-	
 	/**
 	 * Return the list of users who are chating
 	 * @param chatResource
diff --git a/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml b/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml
index 0e76ba9265e2fbc27a1484669c9db8738f942aea..e14f22673c11f1b61d35de4a831af3faaa694027 100644
--- a/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml
+++ b/src/main/java/org/olat/instantMessaging/_spring/instantMessagingContext.xml
@@ -51,7 +51,6 @@
 				<value>org.olat.admin.SystemAdminMainController</value>		
 			</list>
 		</property>
-		<property name="enabled" value="${instantMessaging.enable}"/>
 		<property name="parentTreeNodeIdentifier" value="modulesParent" /> 
 	</bean>
 	
diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
index 39a767034d28afceac806da94b35474ef164e44a..d10941ef65ab412bdca2a5415d63e11780a9d4da 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
@@ -20,7 +20,11 @@
 package org.olat.instantMessaging.manager;
 
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import javax.persistence.TypedQuery;
 
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
@@ -52,10 +56,6 @@ public class InstantMessagePreferencesDAO {
 	}
 	
 	public String getStatus(Long identityKey) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select msg.rosterDefaultStatus from ").append(ImPreferencesImpl.class.getName()).append(" msg ")
-		  .append(" where msg.identity.key=:identityKey");
-		
 		List<String> msgs = dbInstance.getCurrentEntityManager()
 				.createNamedQuery("loadIMRosterStatusByIdentity", String.class)
 				.setParameter("identityKey", identityKey)
@@ -66,6 +66,58 @@ public class InstantMessagePreferencesDAO {
 		}
 		return msgs.get(0);
 	}
+	
+	public int countAvailableBuddies(List<Long> buddies) {
+		if(buddies == null || buddies.isEmpty()) {
+			return 0;
+		}
+		
+		TypedQuery<Number> query = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("countAvailableBuddiesIn", Number.class);
+
+		int hibernateInBatch = 500;
+		int firstResult = 0;
+		int total = 0;
+		do {
+			int toIndex = Math.min(firstResult + hibernateInBatch, buddies.size());
+			List<Long> inParameter = buddies.subList(firstResult, toIndex);
+			query.setParameter("buddyKeys", inParameter);
+			firstResult += inParameter.size();
+			
+			Number count = query.getSingleResult();
+			total += count.intValue();
+		} while(firstResult < buddies.size());
+
+		return total;
+	}
+	
+	public Map<Long,String> getBuddyStatus(List<Long> buddies) {
+		if(buddies == null || buddies.isEmpty()) {
+			return new HashMap<Long,String>();
+		}
+		
+		TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("mapStatusByBuddiesIn", Object[].class);
+
+		int hibernateInBatch = 250;
+		int firstResult = 0;
+		Map<Long,String> statusMap = new HashMap<Long,String>();
+		do {
+			int toIndex = Math.min(firstResult + hibernateInBatch, buddies.size());
+			List<Long> inParameter = buddies.subList(firstResult, toIndex);
+			query.setParameter("buddyKeys", inParameter);
+			firstResult += inParameter.size();
+			
+			List<Object[]> statusList = query.getResultList();
+			for(Object[] status:statusList) {
+				Long identityKey = (Long)status[0];
+				String state = (String)status[1];
+				statusMap.put(identityKey, state);
+			}
+		} while(firstResult < buddies.size());
+
+		return statusMap;
+	}
 
 	/**
 	 * Synchronized to prevent
@@ -73,10 +125,6 @@ public class InstantMessagePreferencesDAO {
 	 * @return
 	 */
 	public synchronized ImPreferencesImpl getPreferences(Identity identity) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select msg from ").append(ImPreferencesImpl.class.getName()).append(" msg ")
-		  .append(" where msg.identity.key=:identityKey");
-		
 		List<ImPreferencesImpl> msgs = dbInstance.getCurrentEntityManager()
 				.createNamedQuery("loadIMPreferencesByIdentity", ImPreferencesImpl.class)
 				.setParameter("identityKey", identity.getKey())
@@ -111,10 +159,6 @@ public class InstantMessagePreferencesDAO {
 	}
 	
 	private ImPreferencesImpl loadForUpdate(Identity from) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select msg from ").append(ImPreferencesImpl.class.getName()).append(" msg ")
-		  .append(" where msg.identity.key=:identityKey");
-		
 		List<ImPreferencesImpl> msgs = dbInstance.getCurrentEntityManager()
 				.createNamedQuery("loadIMPreferencesForUpdate", ImPreferencesImpl.class)
 				.setParameter("identityKey", from.getKey())
diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
index e4463413f51b547c91ce932fc78f3a03bd4dfb51..477ef9d49a46614fae8d5f38b3500d2917c96835 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java
@@ -24,8 +24,11 @@ import java.util.Calendar;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.IdentityShort;
@@ -103,9 +106,9 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 
 	@Override
-	@Transactional
 	public boolean deleteGroupDataFor(BusinessGroup group) {
 		imDao.deleteMessages(group);
+		dbInstance.commit();
 		return true;
 	}
 
@@ -115,21 +118,22 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 
 	@Override
-	@Transactional
 	public ImPreferences getImPreferences(Identity identity) {
-		return prefsDao.getPreferences(identity);
+		ImPreferences prefs = prefsDao.getPreferences(identity);
+		dbInstance.commit();
+		return prefs;
 	}
 
 	@Override
-	@Transactional
 	public void updateImPreferences(Identity identity, boolean visible) {
 		prefsDao.updatePreferences(identity, visible);
+		dbInstance.commit();
 	}
 
 	@Override
-	@Transactional
 	public void updateStatus(Identity identity, String status) {
 		prefsDao.updatePreferences(identity, status);
+		dbInstance.commit();
 	}
 
 	@Override
@@ -165,9 +169,10 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 
 	@Override
-	@Transactional
 	public InstantMessage sendMessage(Identity from, String fromNickName, boolean anonym, String body, OLATResourceable chatResource) {
 		InstantMessage message = imDao.createMessage(from, fromNickName, anonym, body, chatResource);
+		dbInstance.commit();//commit before sending event
+		
 		InstantMessagingEvent event = new InstantMessagingEvent("message", chatResource);
 		event.setFromId(from.getKey());
 		event.setName(fromNickName);
@@ -178,11 +183,11 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 	
 	@Override
-	@Transactional
 	public InstantMessage sendPrivateMessage(Identity from, Long toIdentityKey, String body, OLATResourceable chatResource) {
 		String name = userManager.getUserDisplayName(from.getUser());
 		InstantMessage message = imDao.createMessage(from, name, false, body, chatResource);
 		imDao.createNotification(from.getKey(), toIdentityKey, chatResource);
+		dbInstance.commit();//commit before sending event
 		
 		InstantMessagingEvent event = new InstantMessagingEvent("message", chatResource);
 		event.setFromId(from.getKey());
@@ -204,7 +209,6 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 
 	@Override
-	@Transactional
 	public void sendPresence(Identity me, String nickName, boolean anonym, boolean vip, OLATResourceable chatResource) {
 		InstantMessagingEvent event = new InstantMessagingEvent("participant", chatResource);
 		event.setAnonym(anonym);
@@ -215,6 +219,8 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		}
 		String fullName = userManager.getUserDisplayName(me.getUser());
 		rosterDao.updateRosterEntry(chatResource, me, fullName, nickName, anonym, vip);
+		dbInstance.commit();//commit before sending event
+		
 		coordinator.getCoordinator().getEventBus().fireEventToListenersOf(event, chatResource);
 	}
 	
@@ -230,20 +236,52 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		String status = getOnlineStatus(identityKey);
 		return new Buddy(identity.getKey(), identity.getName(), fullname, false, status);
 	}
+	
+
+	@Override
+	public BuddyStats getBuddyStats(Identity me) {
+		BuddyStats stats = new BuddyStats();
+		
+		Calendar cal = Calendar.getInstance();
+		cal.add(Calendar.YEAR, -1);
+		//count all my buddies
+		Collection<Long> buddiesColl = contactDao.getDistinctGroupOwnersParticipants(me);
+		List<Long> buddies = new ArrayList<Long>(buddiesColl);
+		buddies.remove(me.getKey());
+		stats.setOfflineBuddies(buddies.size());
+
+		//filter online users
+		for(Iterator<Long> buddyIt=buddies.iterator(); buddyIt.hasNext(); ) {
+			Long buddyKey = buddyIt.next();
+			boolean online = isOnline(buddyKey);
+			if(!online) {
+				buddyIt.remove();
+			}
+		}
+		
+		//count online users which are available
+		int online = prefsDao.countAvailableBuddies(buddies);
+		stats.setOnlineBuddies(online);
+		return stats;
+	}
 
 	@Override
 	public List<BuddyGroup> getBuddyGroups(Identity me, boolean offlineUsers) {
 		List<BuddyGroup> groups = new ArrayList<BuddyGroup>(25);
 		Map<Long,BuddyGroup> groupMap = new HashMap<Long,BuddyGroup>();
-		Map<Long, String> identityKeys = new HashMap<Long, String>();
-		for(BusinessGroupOwnerViewImpl owner:contactDao.getGroupOwners(me)) {
-			addBuddyToGroupList(owner, me, groupMap, groups, identityKeys, true, offlineUsers);
+		Map<Long, String> identityKeyToStatus = new HashMap<Long, String>();
+		List<BusinessGroupOwnerViewImpl> ownerList = contactDao.getGroupOwners(me);
+		collectMembersStatus(ownerList, identityKeyToStatus);
+		List<BusinessGroupParticipantViewImpl> participantList = contactDao.getParticipants(me);
+		collectMembersStatus(participantList, identityKeyToStatus);
+		for(BusinessGroupOwnerViewImpl owner:ownerList) {
+			addBuddyToGroupList(owner, me, groupMap, groups, identityKeyToStatus, true, offlineUsers);
 		}
-		for(BusinessGroupParticipantViewImpl participant:contactDao.getParticipants(me)) {
-			addBuddyToGroupList(participant, me, groupMap, groups, identityKeys, false, offlineUsers);
+		for(BusinessGroupParticipantViewImpl participant:participantList) {
+			addBuddyToGroupList(participant, me, groupMap, groups, identityKeyToStatus, false, offlineUsers);
 		}
 		
-		Map<Long,String> nameMap = userManager.getUserDisplayNames(identityKeys.keySet());
+		Map<Long,String> nameMap = userManager.getUserDisplayNames(identityKeyToStatus.keySet());
 		for(BuddyGroup group:groups) {
 			for(Buddy buddy:group.getBuddy()) {
 				buddy.setName(nameMap.get(buddy.getIdentityKey()));	
@@ -251,15 +289,52 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		}
 		return groups;
 	}
+	
+	private void collectMembersStatus(List<? extends BusinessGroupMemberView> members, Map<Long, String> identityKeyToStatus) {
+		Set<Long> loadStatus = new HashSet<Long>();
+		for(BusinessGroupMemberView member:members) {
+			Long identityKey = member.getIdentityKey();
+			if(!identityKeyToStatus.containsKey(identityKey) && !loadStatus.contains(identityKey)) {
+				boolean online = isOnline(member.getIdentityKey());
+				if(online) {
+					loadStatus.add(identityKey);
+				} else {
+					identityKeyToStatus.put(identityKey, Presence.unavailable.name());
+				}
+			}
+		}
+		
+		if(loadStatus.size() > 0) {
+			List<Long> statusToLoadList = new ArrayList<Long>(loadStatus);
+			Map<Long,String> statusMap = prefsDao.getBuddyStatus(statusToLoadList);
+			for(Long toLoad:statusToLoadList) {
+				String status = statusMap.get(toLoad);
+				if(status == null) {
+					identityKeyToStatus.put(toLoad, Presence.available.name());	
+				} else {
+					identityKeyToStatus.put(toLoad, status);	
+				}
+			}
+		}	
+	}
+	
 	private void addBuddyToGroupList(BusinessGroupMemberView member, Identity me, Map<Long,BuddyGroup> groupMap,
-			List<BuddyGroup> groups, Map<Long, String> identityKeys, boolean vip, boolean offlineUsers) {
+			List<BuddyGroup> groups, Map<Long, String> identityKeyToStatus, boolean vip, boolean offlineUsers) {
 		if(me != null && me.getKey().equals(member.getIdentityKey())) {
 			return;
 		}
-		String status = identityKeys.get(member.getIdentityKey());
+		String status = identityKeyToStatus.get(member.getIdentityKey());
 		if(status == null) {
-			status = getOnlineStatus(member.getIdentityKey());
-			identityKeys.put(member.getIdentityKey(), status);
+			boolean online = isOnline(member.getIdentityKey());
+			if(online) {
+				status = prefsDao.getStatus(member.getIdentityKey());
+				if(status == null) {
+					status = Presence.available.name();
+				}
+			} else {
+				status = Presence.unavailable.name();
+			}
+			identityKeyToStatus.put(member.getIdentityKey(), status);
 		}
 		
 		if(offlineUsers || Presence.available.name().equals(status)) {
@@ -273,30 +348,6 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 		}
 	}
 
-	@Override
-	public List<Buddy> getOnlineBuddies() {
-		Collection<Long> ids = sessionManager.getUsersOnline();
-		List<IdentityShort> contacts = securityManager.loadIdentityShortByKeys(ids);
-		List<Buddy> buddies = new ArrayList<Buddy>(contacts.size());
-		for(IdentityShort contact:contacts) {
-			String fullname = userManager.getUserDisplayName(contact);
-			String status = getOnlineStatus(contact.getKey());
-			buddies.add(new Buddy(contact.getKey(), contact.getName(), fullname, false, status));
-		}
-		return buddies;
-	}
-
-	@Override
-	public BuddyStats getBuddyStats(Identity me) {
-		BuddyStats stats = new BuddyStats();
-		
-		Calendar cal = Calendar.getInstance();
-		cal.add(Calendar.YEAR, -1);
-		stats.setOfflineBuddies(securityManager.countUniqueUserLoginsSince(cal.getTime()));
-		stats.setOnlineBuddies(sessionManager.getUserSessionsCnt());
-		return stats;
-	}
-
 	@Override
 	public List<Buddy> getBuddiesListenTo(OLATResourceable chatResource) {
 		List<RosterEntryView> roster = rosterDao.getRosterView(chatResource, 0, -1);
@@ -312,23 +363,31 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant
 	}
 	
 	private String getOnlineStatus(Long identityKey) {
-		boolean online = sessionManager.isOnline(identityKey);
-		return online ? Presence.available.name() : Presence.unavailable.name();
+		return isOnline(identityKey) ? Presence.available.name() : Presence.unavailable.name();
+	}
+	
+	/**
+	 * Return true if the identity is logged in on the instance
+	 * @param identityKey
+	 * @return
+	 */
+	private boolean isOnline(Long identityKey) {
+		return sessionManager.isOnline(identityKey);
 	}
 
 	@Override
-	@Transactional
 	public void listenChat(Identity identity, OLATResourceable chatResource,
 			boolean anonym, boolean vip, GenericEventListener listener) {
 		String fullName = userManager.getUserDisplayName(identity.getUser());
 		rosterDao.updateRosterEntry(chatResource, identity, fullName, null, anonym, vip);
+		dbInstance.commit();
 		coordinator.getCoordinator().getEventBus().registerFor(listener, identity, chatResource);
 	}
 
 	@Override
-	@Transactional
 	public void unlistenChat(Identity identity, OLATResourceable chatResource, GenericEventListener listener) {
 		rosterDao.deleteEntry(identity, chatResource);
+		dbInstance.commit();
 		coordinator.getCoordinator().getEventBus().deregisterFor(listener, chatResource);
 	}
 
diff --git a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
index 441d22ee52552d3f5c67b089153ab1cb73f062ae..25ef298f95c92bd6079eb2650f9dcc6462294f7c 100644
--- a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
@@ -22,7 +22,6 @@ package org.olat.instantMessaging.manager;
 import java.util.Date;
 import java.util.List;
 
-import javax.persistence.LockModeType;
 import javax.persistence.TypedQuery;
 
 import org.olat.core.commons.persistence.DB;
diff --git a/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java b/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java
index 0ce29e655bb3cb16127308c2d97dbdfac3b3e8ea..6df47ce15cc20cc14acef31c7bf5d1b9f1940530 100644
--- a/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java
+++ b/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java
@@ -60,7 +60,9 @@ import org.olat.instantMessaging.ImPreferences;
 	@NamedQuery(name="loadIMRosterStatusByIdentity", query="select msg.rosterDefaultStatus from impreferences msg where msg.identity.key=:identityKey"),
 	@NamedQuery(name="loadIMPreferencesByIdentity", query="select msg from impreferences msg where msg.identity.key=:identityKey"),
 	@NamedQuery(name="loadIMPreferencesForUpdate", query="select msg from impreferences msg where msg.identity.key=:identityKey",
-		lockMode=LockModeType.PESSIMISTIC_WRITE)
+		lockMode=LockModeType.PESSIMISTIC_WRITE),
+	@NamedQuery(name="countAvailableBuddiesIn", query="select count(msg.identity.key) from impreferences msg where msg.identity.key in(:buddyKeys) and msg.rosterDefaultStatus='available'"),
+	@NamedQuery(name="mapStatusByBuddiesIn", query="select msg.identity.key, msg.rosterDefaultStatus from impreferences msg where msg.identity.key in (:buddyKeys)")
 })
 public class ImPreferencesImpl implements ImPreferences, Persistable, CreateInfo {
 
diff --git a/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java b/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java
index ce9a8042a62bb1b0dfdb4b0e36c6548e68d3a71a..167e03cda735783616834076e36aab13825b45e7 100644
--- a/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java
+++ b/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java
@@ -304,6 +304,10 @@ public class InstantMessagingMainController extends BasicController implements G
 		} else {
 			imStatus = status;
 		}
+		if(imStatus == null) {
+			imStatus = Presence.available.name();
+		  imService.updateStatus(getIdentity(), imStatus);
+		}
 		String cssClass = "o_instantmessaging_" + imStatus + "_icon";
 		statusChangerLink.setCustomEnabledLinkCSS("b_small_icon " + cssClass);
 	}
diff --git a/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java b/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java
index ea2a7363010a5f76dfdfd1e784379dd29fed3c82..92b4a4e9004faba36e93e6556359ba88b758178c 100644
--- a/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java
+++ b/src/main/java/org/olat/modules/fo/restapi/MyForumsWebService.java
@@ -26,6 +26,7 @@ import static org.olat.restapi.security.RestSecurityHelper.getRoles;
 import static org.olat.restapi.security.RestSecurityHelper.isAdmin;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -67,11 +68,6 @@ import org.olat.group.BusinessGroupService;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.properties.Property;
 import org.olat.properties.PropertyManager;
-import org.olat.repository.RepositoryEntry;
-import org.olat.repository.RepositoryManager;
-import org.olat.repository.SearchRepositoryEntryParameters;
-import org.olat.resource.accesscontrol.ACService;
-import org.olat.resource.accesscontrol.AccessResult;
 import org.olat.restapi.group.LearningGroupWebService;
 
 /**
@@ -161,7 +157,7 @@ public class MyForumsWebService {
 		}
 
 		Map<Long,Long> groupNotified = new HashMap<Long,Long>();
-		Map<Long,Long> courseNotified = new HashMap<Long,Long>();
+		Map<Long,Collection<Long>> courseNotified = new HashMap<Long,Collection<Long>>();
 		final Set<Long> subscriptions = new HashSet<Long>();
 		
 		NotificationsManager man = NotificationsManager.getInstance();
@@ -178,13 +174,35 @@ public class MyForumsWebService {
 					groupNotified.put(groupKey, forumKey);
 				} else if("CourseModule".equals(resName)) {
 					Long courseKey = sub.getPublisher().getResId();
-					courseNotified.put(courseKey, forumKey);
+					if(!courseNotified.containsKey(courseKey)) {
+						courseNotified.put(courseKey, new ArrayList<Long>());
+					}
+					courseNotified.get(courseKey).add(forumKey);
 				}
 			}
 		}
 		
 		final List<ForumVO> forumVOs = new ArrayList<ForumVO>();
-		
+		final IdentityEnvironment ienv = new IdentityEnvironment(retrievedUser, roles);
+		for(Map.Entry<Long, Collection<Long>> e:courseNotified.entrySet()) {
+			final Long courseKey = e.getKey();
+			final Collection<Long> forumKeys = e.getValue();
+			final ICourse course = CourseFactory.loadCourse(courseKey);
+			new CourseTreeVisitor(course, ienv).visit(new Visitor() {
+				@Override
+				public void visit(INode node) {
+					if(node instanceof FOCourseNode) {
+						FOCourseNode forumNode = (FOCourseNode)node;
+						ForumVO forumVo = ForumCourseNodeWebService.createForumVO(course, forumNode, subscriptions);
+						if(forumKeys.contains(forumVo.getForumKey())) {
+							forumVOs.add(forumVo);
+						}
+					}
+				}
+			});
+		}
+
+		/*
 		RepositoryManager rm = RepositoryManager.getInstance();
 		ACService acManager = CoreSpringFactory.getImpl(ACService.class);
 		SearchRepositoryEntryParameters repoParams = new SearchRepositoryEntryParameters(retrievedUser, roles, "CourseModule");
@@ -210,7 +228,7 @@ public class MyForumsWebService {
 					log.error("", e);
 				}
 			}
-		}
+		}*/
 		
 		//start found forums in groups
 		BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
diff --git a/src/main/java/org/olat/modules/webFeed/FeedViewHelper.java b/src/main/java/org/olat/modules/webFeed/FeedViewHelper.java
index 84f495855f03d74b49fda5c6400d78ea6bf4fd15..d4f18b077780e7bffef2caa422dd126f782b481c 100644
--- a/src/main/java/org/olat/modules/webFeed/FeedViewHelper.java
+++ b/src/main/java/org/olat/modules/webFeed/FeedViewHelper.java
@@ -77,6 +77,8 @@ public class FeedViewHelper {
 	private int page = 0;
 	private List<Item> cachedItems;
 	private FeedSecurityCallback callback;
+	//
+	private FeedManager feedManager = FeedManager.getInstance();
 
 	/**
 	 * Use this constructor for localized content (like e.g. date formats)
@@ -175,6 +177,10 @@ public class FeedViewHelper {
 	 * @return The media url of the item
 	 */
 	public String getMediaUrl(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		String file = null;
 		Enclosure enclosure = item.getEnclosure();
 		if (enclosure != null) {
@@ -225,6 +231,10 @@ public class FeedViewHelper {
 	 * @return The formatted last modified date string of the item
 	 */
 	public String getLastModified(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		String lastModified = null;
 		Date date = item.getLastModified();
 		if (date != null) {
@@ -238,6 +248,10 @@ public class FeedViewHelper {
 	 * @return The formatted last modified date string of the item
 	 */
 	private String getPublishDate(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		String publishDate = null;
 		Date date = item.getPublishDate();
 		if (date != null) {
@@ -251,6 +265,10 @@ public class FeedViewHelper {
 	 * @return Information about publication date and author
 	 */
 	private String getPublishInfo(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		String info = null;
 		String date = getPublishDate(item);
 		String author = item.getAuthor();
@@ -275,6 +293,10 @@ public class FeedViewHelper {
 	 * @return Information about the item. Is it draft, scheduled or published?
 	 */
 	public String getInfo(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		String info = null;
 		if (item.isDraft()) {
 			info = translator.translate("feed.item.draft");
@@ -287,6 +309,10 @@ public class FeedViewHelper {
 	}
 	
 	public boolean isModified(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		return item.getModifierKey() > 0 && StringHelper.containsNonWhitespace(item.getModifier());
 	}
 	
@@ -295,6 +321,10 @@ public class FeedViewHelper {
 	 * @return Information about the item. Is it draft, scheduled or published?
 	 */
 	public String getModifierInfo(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		if (isModified(item)) {
 			String date = getLastModified(item);
 			String modifier = item.getModifier();
@@ -315,8 +345,11 @@ public class FeedViewHelper {
 		return lastModified;
 	}
 	
-	//fxdiff FXOLAT-118: size for video podcast
 	public String getWidth(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		int width = item.getWidth();
 		if(width > 0 && width < 2000) {
 			return Integer.toString(width);
@@ -324,8 +357,11 @@ public class FeedViewHelper {
 		return "400";
 	}
 	
-	//fxdiff FXOLAT-118: size for video podcast
 	public String getHeight(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+
 		int height = item.getHeight();
 		if(height > 0 && height < 2000) {
 			return Integer.toString(height);
@@ -369,6 +405,10 @@ public class FeedViewHelper {
 	 *         the FeedMediaDispatcher
 	 */
 	public String getItemDescriptionForBrowser(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+		
 		String itemDescription = item.getDescription();
 		if (itemDescription != null) {
 			if (feed.isExternal()) {
@@ -393,6 +433,10 @@ public class FeedViewHelper {
 	 *         the FeedMediaDispatcher
 	 */
 	public String getItemContentForBrowser(Item item) {
+		// Reload item to prevent displaying of stale content
+		feed = feedManager.getFeed(feed);
+		item = feedManager.getItem(feed, item.getGuid());
+		
 		String itemContent = item.getContent();
 		if (itemContent != null) {
 			if (feed.isExternal()) {
@@ -543,6 +587,7 @@ public class FeedViewHelper {
 	 * @param callback
 	 */
 	public void resetItems(FeedSecurityCallback callback) {
+		feed = feedManager.getFeed(feed);
 		cachedItems = feed.getFilteredItems(callback, identity);
 	}
 
diff --git a/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java b/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java
index a28350d1d20464f1b02500d20813bad48181013f..87ed1233561e8fa691b8e38fe2f689b0f52ca0bb 100644
--- a/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java
+++ b/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java
@@ -428,6 +428,8 @@ public class ItemsController extends BasicController implements Activateable2 {
 
 		} else if (itemLinks != null && itemLinks.contains(source)) {
 			Item item = (Item) ((Link) source).getUserObject();
+			// Reload first, could be stale
+			item = feedManager.getItem(feed, item.getGuid());					
 			displayItemController(ureq, item);
 
 		} else if (source == makeInternalButton) {
@@ -564,7 +566,7 @@ public class ItemsController extends BasicController implements Activateable2 {
 				// remove delete and edit buttons of this item
 				deleteButtons.remove(source);
 				for (Link editButton : editButtons) {
-					if (editButton.getUserObject() == item) {
+					if (item.equals(editButton.getUserObject())) {
 						editButtons.remove(editButton);
 						break;
 					}
@@ -807,7 +809,7 @@ public class ItemsController extends BasicController implements Activateable2 {
 		Link result = null;
 		if (buttons != null && item != null) {
 			for (Link button : buttons) {
-				if (button.getUserObject() == item) {
+				if (item.equals(button.getUserObject())) {
 					result = button;
 					break;
 				}
diff --git a/src/main/java/org/olat/notifications/NotificationsManagerImpl.java b/src/main/java/org/olat/notifications/NotificationsManagerImpl.java
index 5597d7358d6b8a0191864d6e28aaab5653c5e77f..3a30d22317b8c139a1d4119f894aa5a9923a0077 100644
--- a/src/main/java/org/olat/notifications/NotificationsManagerImpl.java
+++ b/src/main/java/org/olat/notifications/NotificationsManagerImpl.java
@@ -849,6 +849,9 @@ public class NotificationsManagerImpl extends NotificationsManager implements Us
 		}
 		
 		if(sendEvents) {
+			//commit all things on the database
+			DBFactory.getInstance().commit();
+			
 			// channel-notify all interested listeners (e.g. the pnotificationsportletruncontroller)
 			// 1. find all subscribers which can be affected
 			List<Subscriber> subscribers = getValidSubscribersOf(publisher);
diff --git a/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml b/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml
index 7f8f0cb75ac2a24341d2ea1d82e5973c2f55b9fd..4ec77e24b7b53bedef893d7183a4697a3c22d2a9 100644
--- a/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml
+++ b/src/main/java/org/olat/portfolio/_spring/portfolioContext.xml
@@ -147,25 +147,6 @@
 	<bean id="org.olat.portfolio.manager.EPNotificationsHandler" class="org.olat.portfolio.manager.EPNotificationsHandler">
 	</bean>
 
-	<!-- add the db-mappings here or in the module-context where your XYArtefactHandler for the appropriate type is. 
-	this allows real decoupling of the ePortfolio-Module from olatcore.
-	-->
-	<bean id="portfolioDBMappings" class="org.olat.core.commons.persistence.AdditionalDBMappings">
-		<property name="xmlFiles">
-			<list>								
-				<value>org/olat/portfolio/model/artefacts/AbstractArtefact.hbm.xml</value>
-				<value>org/olat/modules/fo/portfolio/ForumArtefact.hbm.xml</value>
-				<value>org/olat/modules/wiki/portfolio/WikiArtefact.hbm.xml</value>
-				<value>org/olat/modules/webFeed/portfolio/BlogArtefact.hbm.xml</value>
-				<value>org/olat/modules/webFeed/portfolio/LiveBlogArtefact.hbm.xml</value>
-				<value>org/olat/course/assessment/portfolio/EfficiencyStatementArtefact.hbm.xml</value>
-				<value>org/olat/portfolio/model/structel/StructureElement.hbm.xml</value>
-				<value>org/olat/portfolio/model/notification/Notifications.hbm.xml</value>
-				<value>org/olat/portfolio/model/restriction/CollectRestriction.hbm.xml</value>
-			</list>
-		</property>
-	</bean>
-
 	<!-- wrapper for add-link in folder -->
 	<bean name="folderCMDAddToEPortfolio" class="org.olat.core.gui.control.creator.AutoCreator" >
 		<property name="className" value="org.olat.portfolio.ui.artefacts.collect.CmdAddToEPortfolioImpl"/>
diff --git a/src/main/java/org/olat/portfolio/ui/artefacts/collect/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/portfolio/ui/artefacts/collect/_i18n/LocalStrings_en.properties
index 4d045483af1874754f0dade4115418235aa10dd1..eefa32914068831a34dcda36d85198ad09ce270b 100644
--- a/src/main/java/org/olat/portfolio/ui/artefacts/collect/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/portfolio/ui/artefacts/collect/_i18n/LocalStrings_en.properties
@@ -1,4 +1,4 @@
-#Tue Apr 10 10:29:43 CEST 2012
+#Fri Feb 01 13:49:54 CET 2013
 add.artefact=Add artefact
 add.artefact.blog=Create learning journal/blog
 add.artefact.import=Import artefact/folder
@@ -28,13 +28,16 @@ file.artefact.source.info=File upload
 file.upload=Select file
 file.upload.no.file=At least one file has to be uploaded.
 file.upload.too.big=The file uploaded is too big. Only a max. of {0} KB is allowed.
+just=click on "Finish."
 map.not.choosable=A binder can not be selected as target.
 move.artefact.actual.node=Current linking
 move.artefact.descr=Select the target (page or structural element) where this artifact should be moved to.
-no.no.map.as.target=Do not select any binder
+no.map.as.target=Choose no binder
 no.map.as.target.desc=Please select this element if you don't want to add your artefact to a binder. It is always possible to add an artefact later on.
+no.no.map.as.target=Do not select any binder
 no.structs.available=There aren't any binders to which you could add this artefact.
 pose.tags.link=Suggest tags appropriate for this content
+propose.tags.link=Recommend tag for this content
 proposed.tags=The following tags are suggested due to your content\:
 reflexion.too.long=The reflection provided exceeds the max. length ({0} characters).
 step0.description=Record meta data
@@ -50,11 +53,11 @@ step2.short.descr=Please confirm that you are the author of this artefact and ow
 step3.chelp.hover=Help to record reflections
 step3.description=Record reflection
 step3.short.descr=Please note down why you have chosen this artefact.
+step4.description=Choose binder
 step4.destep4.my.maps=My binders
-step4.short.descr=Please select the target location (binder, page, or structural element) to which this artefact should be added. It is also possible to skip this step and allocate your artefact to a binder later on. In this case just click on "Finish."
-just click on "Finish."
+step4.my.maps=My binders
 step4.nomapselected=Please select a target
-
+step4.short.descr=Please select the target location (binder, page, or structural element) to which this artefact should be added. It is also possible to skip this step and allocate your artefact to a binder later on. In this case just click on "Finish."
 stepform.cancel=Cancel
 stepform.submit=Save
 tag.input.hint=Click here to add new tags.
diff --git a/src/main/java/org/olat/repository/RepositoryMailing.java b/src/main/java/org/olat/repository/RepositoryMailing.java
index 6b06e3c7856f20a488a76d0b74cea49da70d0eba..1a5f6894899ea07536bb2087b43d69e8bce60a7d 100644
--- a/src/main/java/org/olat/repository/RepositoryMailing.java
+++ b/src/main/java/org/olat/repository/RepositoryMailing.java
@@ -126,7 +126,8 @@ public class RepositoryMailing {
 			context = new MailContextImpl(null, null, "[RepositoryEntry:" + re.getKey() + "]");
 		}
 
-		MailerResult result = mailer.sendMailAsSeparateMails(context, Collections.singletonList(identity), null, template, ureqIdentity);
+		String metaId = mailing == null ? null : mailing.getUuid();
+		MailerResult result = mailer.sendMailAsSeparateMails(context, Collections.singletonList(identity), null, template, ureqIdentity, metaId);
 		if(mailing != null) {
 			mailing.appendResult(result);
 		}
diff --git a/src/main/java/org/olat/repository/RepositoryManager.java b/src/main/java/org/olat/repository/RepositoryManager.java
index 45e02e8a2bc799c56d23105a4e50e9d192ac9b2e..4e847d0c3226168e020f71b8bde28332da13c0af 100644
--- a/src/main/java/org/olat/repository/RepositoryManager.java
+++ b/src/main/java/org/olat/repository/RepositoryManager.java
@@ -33,7 +33,6 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
-import javax.persistence.EntityManager;
 import javax.persistence.LockModeType;
 import javax.persistence.TypedQuery;
 
@@ -97,7 +96,6 @@ import org.olat.resource.accesscontrol.manager.ACReservationDAO;
 import org.olat.resource.accesscontrol.model.ResourceReservation;
 import org.olat.util.logging.activity.LoggingResourceable;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
 
 /**
  * Initial Date:  Mar 31, 2004
@@ -461,7 +459,6 @@ public class RepositoryManager extends BasicManager {
 	 * @param the repository entry key (not the olatresourceable key)
 	 * @return Repo entry represented by key or null if no such entry or key is null.
 	 */
-	@Transactional(readOnly=true)
 	public RepositoryEntry lookupRepositoryEntry(Long key) {
 		if (key == null) return null;
 		return lookupRepositoryEntry(key, false) ;
@@ -472,7 +469,6 @@ public class RepositoryManager extends BasicManager {
 	 * @param the repository entry key (not the olatresourceable key)
 	 * @return Repo entry represented by key or null if no such entry or key is null.
 	 */
-	@Transactional(readOnly=true)
 	public RepositoryEntry lookupRepositoryEntry(Long key, boolean strict) {
 		if (key == null) return null;
 		if(strict) {
@@ -758,7 +754,6 @@ public class RepositoryManager extends BasicManager {
 	 * Increment the launch counter.
 	 * @param re
 	 */
-	@Transactional
 	public RepositoryEntry incrementLaunchCounter(RepositoryEntry re) {
 		RepositoryEntry reloadedRe = loadForUpdate(re);
 		if(reloadedRe == null) return null;//deleted
@@ -768,6 +763,7 @@ public class RepositoryManager extends BasicManager {
 		updateLifeCycle(reloadedRe);
 		
 		RepositoryEntry updatedRe = DBFactory.getInstance().getCurrentEntityManager().merge(reloadedRe);
+		DBFactory.getInstance().commit();
 		return updatedRe;
 	}
 
@@ -775,7 +771,6 @@ public class RepositoryManager extends BasicManager {
 	 * Increment the download counter.
 	 * @param re
 	 */
-	@Transactional
 	public RepositoryEntry incrementDownloadCounter( final RepositoryEntry re) {
 		RepositoryEntry reloadedRe = loadForUpdate(re);
 		if(reloadedRe == null) return null;//deleted
@@ -784,6 +779,7 @@ public class RepositoryManager extends BasicManager {
 		reloadedRe.setLastUsage(new Date());
 		updateLifeCycle(reloadedRe);
 		RepositoryEntry updatedRe = DBFactory.getInstance().getCurrentEntityManager().merge(reloadedRe);
+		DBFactory.getInstance().commit();
 		return updatedRe;
 	}
 
@@ -791,22 +787,22 @@ public class RepositoryManager extends BasicManager {
 	 * Set last-usage date to to now for certain repository-entry.
 	 * @param 
 	 */
-	@Transactional
 	public RepositoryEntry setLastUsageNowFor(final RepositoryEntry re) {
 		if (re == null) return null;
 		RepositoryEntry reloadedRe = loadForUpdate(re);
 		reloadedRe.setLastUsage(new Date());
 		RepositoryEntry updatedRe = DBFactory.getInstance().getCurrentEntityManager().merge(reloadedRe);
+		DBFactory.getInstance().commit();
 		return updatedRe;
 	}
 
-	@Transactional
 	public RepositoryEntry setAccess(final RepositoryEntry re, int access, boolean membersOnly ) {
 		RepositoryEntry reloadedRe = loadForUpdate(re);
 		reloadedRe.setAccess(access);
 		reloadedRe.setMembersOnly(membersOnly);//fxdiff VCRP-1,2: access control of resources
 		
 		RepositoryEntry updatedRe = DBFactory.getInstance().getCurrentEntityManager().merge(reloadedRe);
+		DBFactory.getInstance().commit();
 		return updatedRe;
 	}
 
@@ -817,7 +813,6 @@ public class RepositoryManager extends BasicManager {
 	 * @param description If null, nothing happen
 	 * @return
 	 */
-	@Transactional
 	public RepositoryEntry setDescriptionAndName(final RepositoryEntry re, String displayName, String description ) {
 		RepositoryEntry reloadedRe = loadForUpdate(re);
 		if(StringHelper.containsNonWhitespace(displayName)) {
@@ -827,10 +822,10 @@ public class RepositoryManager extends BasicManager {
 			reloadedRe.setDescription(description);
 		}
 		RepositoryEntry updatedRe = DBFactory.getInstance().getCurrentEntityManager().merge(reloadedRe);
+		DBFactory.getInstance().commit();
 		return updatedRe;
 	}
 
-	@Transactional
 	public RepositoryEntry setProperties(final RepositoryEntry re, boolean canCopy, boolean canReference, boolean canLaunch, boolean canDownload ) {
 		RepositoryEntry reloadedRe = loadForUpdate(re);
 		reloadedRe.setCanCopy(canCopy);
@@ -838,6 +833,7 @@ public class RepositoryManager extends BasicManager {
 		reloadedRe.setCanLaunch(canLaunch);
 		reloadedRe.setCanDownload(canDownload);
 		RepositoryEntry updatedRe = DBFactory.getInstance().getCurrentEntityManager().merge(reloadedRe);
+		DBFactory.getInstance().commit();
 		return updatedRe;
 	}
 	
diff --git a/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java b/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java
index 85dfbb802c596bda4affd79f3dd5a01da0d7f363..ff63a6383f1c7e5ff9dbba2a97a9132e0dfa4191 100644
--- a/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java
+++ b/src/main/java/org/olat/repository/controllers/RepositoryDetailsController.java
@@ -205,11 +205,15 @@ public class RepositoryDetailsController extends BasicController implements Gene
 		main = createVelocityContainer("details");
 		
 		downloadButton = LinkFactory.createButton("details.download", main, this);
+		downloadButton.setElementCssClass("o_sel_repo_download_button");
 		LinkFactory.markDownloadLink(downloadButton);
 		launchButton = LinkFactory.createButton("details.launch", main, this);
+		launchButton.setElementCssClass("o_sel_repo_launch_button");
 		
 		backLink = LinkFactory.createLinkBack(main, this);
+		backLink.setElementCssClass("o_sel_repo_back_button");
 		loginLink = LinkFactory.createLink("repo.login", main, this);
+		loginLink.setElementCssClass("o_sel_repo_login_button");
 		
 		putInitialPanel(main);
 	}
@@ -448,14 +452,15 @@ public class RepositoryDetailsController extends BasicController implements Gene
 		RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(repositoryEntry);
 		if (isNewController) {
 			detailsToolC.addHeader(translate("tools.details.header"));
-			detailsToolC.addLink(ACTION_LAUNCH, translate("details.launch"), TOOL_LAUNCH, null);
+			detailsToolC.addLink(ACTION_LAUNCH, translate("details.launch"), TOOL_LAUNCH, null, "o_sel_repo_launch", false);
 		}
 		detailsToolC.setEnabled(TOOL_LAUNCH, checkIsRepositoryEntryLaunchable(ureq) && !corrupted);
 		if (!isGuestOnly) {
 			if (isNewController) {
 				//mark as download link
-				detailsToolC.addLink(ACTION_DOWNLOAD, translate("details.download"), TOOL_DOWNLOAD, null, true);
-				detailsToolC.addLink(ACTION_DOWNLOAD_BACKWARD_COMPAT, translate("details.download.compatible"), TOOL_DOWNLOAD_BACKWARD_COMPAT, null, true);
+				detailsToolC.addLink(ACTION_DOWNLOAD, translate("details.download"), TOOL_DOWNLOAD, null, "o_sel_repo_download", true);
+				detailsToolC.addLink(ACTION_DOWNLOAD_BACKWARD_COMPAT, translate("details.download.compatible"), TOOL_DOWNLOAD_BACKWARD_COMPAT,
+						null, "o_sel_repo_download_backward", true);
 				//bookmark
 				boolean marked = markManager.isMarked(repositoryEntry, getIdentity(), null);
 				String css = marked ? "b_mark_set" : "b_mark_not_set";
@@ -490,11 +495,11 @@ public class RepositoryDetailsController extends BasicController implements Gene
 						detailsToolC.addLink(ACTION_EDITDESC, translate("details.chdesc"), TOOL_CHDESC, null, "o_sel_repo_edit_descritpion", false);
 						detailsToolC.addLink(ACTION_EDITPROP, translate("details.chprop"), TOOL_CHPROP, null, "o_sel_repor_edit_properties", false);
 					}
-					detailsToolC.addLink(ACTION_ADD_CATALOG, translate("details.catadd"), TOOL_CATALOG, null);
+					detailsToolC.addLink(ACTION_ADD_CATALOG, translate("details.catadd"), TOOL_CATALOG, null, "o_sel_repo_add_to_catalog", false);
 					
 					detailsToolC.addHeader(translate("table.action"));
 					if ((OresHelper.isOfType(repositoryEntry.getOlatResource(), CourseModule.class)) && (!RepositoryManager.getInstance().createRepositoryEntryStatus(repositoryEntry.getStatusCode()).isClosed())) {
-						detailsToolC.addLink(ACTION_CLOSE_RESSOURCE, translate("details.close.ressoure"), TOOL_CLOSE_RESSOURCE, null);
+						detailsToolC.addLink(ACTION_CLOSE_RESSOURCE, translate("details.close.ressoure"), TOOL_CLOSE_RESSOURCE, null, "o_sel_repo_close_resource", false);
 						if(corrupted) {
 							detailsToolC.setEnabled(TOOL_CLOSE_RESSOURCE, false);
 						}
@@ -508,15 +513,15 @@ public class RepositoryDetailsController extends BasicController implements Gene
 			}
 			if (isNewController) {
 				if(isAuthor) {
-					detailsToolC.addLink(ACTION_COPY, translate("details.copy"), TOOL_COPY, null);
+					detailsToolC.addLink(ACTION_COPY, translate("details.copy"), TOOL_COPY, null, "o_sel_repo_copy", false);
 				}
 			}
 			if (isOwner) {
 				if (isNewController) {
-					detailsToolC.addLink(ACTION_DELETE, translate("details.delete"));
+					detailsToolC.addLink(ACTION_DELETE, translate("details.delete"), null, null, "o_sel_repo_delete", false);
 					detailsToolC.addHeader(translate("details.members"));
-					detailsToolC.addLink(ACTION_MEMBERS, translate("details.members"));
-					detailsToolC.addLink(ACTION_ORDERS, translate("details.orders"));
+					detailsToolC.addLink(ACTION_MEMBERS, translate("details.members"), null, null, "o_sel_repo_members", false);
+					detailsToolC.addLink(ACTION_ORDERS, translate("details.orders"), null, null, "o_sel_repo_booking", false);
 				}
 				// enable
 				if(isAuthor) {
diff --git a/src/main/java/org/olat/repository/controllers/RepositoryMembersController.java b/src/main/java/org/olat/repository/controllers/RepositoryMembersController.java
index 3df0b88446f3c3da9d9bf477f46ee641dc22d020..61c9847b7c1f85882825e666f8eb9bd5766d2796 100644
--- a/src/main/java/org/olat/repository/controllers/RepositoryMembersController.java
+++ b/src/main/java/org/olat/repository/controllers/RepositoryMembersController.java
@@ -151,20 +151,18 @@ public class RepositoryMembersController extends AbstractMemberListController {
 	protected void addMembers(UserRequest ureq, StepsRunContext runContext) {
 		@SuppressWarnings("unchecked")
 		List<Identity> members = (List<Identity>)runContext.get("members");
-		
+		MailTemplate template = (MailTemplate)runContext.get("mailTemplate");
 		MemberPermissionChangeEvent changes = (MemberPermissionChangeEvent)runContext.get("permissions");
 		
 		//commit changes to the repository entry
 		MailerResult result = new MailerResult();
-		MailPackage reMailing = new MailPackage(result, getWindowControl().getBusinessControl().getAsString(), true);
+		MailPackage reMailing = new MailPackage(template, result, getWindowControl().getBusinessControl().getAsString(), template != null);
 		List<RepositoryEntryPermissionChangeEvent> repoChanges = changes.generateRepositoryChanges(members);
 		repositoryManager.updateRepositoryEntryMembership(getIdentity(), ureq.getUserSession().getRoles(), repoEntry, repoChanges, reMailing);
 
 		//commit all changes to the group memberships
 		List<BusinessGroupMembershipChange> allModifications = changes.generateBusinessGroupMembershipChange(members);
-
-		MailTemplate template = (MailTemplate)runContext.get("mailTemplate");
-		MailPackage bgMailing = new MailPackage(template, result, getWindowControl().getBusinessControl().getAsString(), true);
+		MailPackage bgMailing = new MailPackage(template, result, getWindowControl().getBusinessControl().getAsString(), template != null);
 		businessGroupService.updateMemberships(getIdentity(), allModifications, bgMailing);
 		MailHelper.printErrorsAndWarnings(result, getWindowControl(), getLocale());
 	}
diff --git a/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_de.properties
index dfec9100f8869b190918eb4132fd73c94b4e0065..20de6a2e1d8be56d03037ce32668d8250086dc9f 100644
--- a/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_de.properties
@@ -6,7 +6,7 @@ error.atleastone=$org.olat.course.member\:error.atleastone
 import.member=$org.olat.group.ui.main\:import.member
 home=$org.olat.group.ui.main\:home
 assessment=$org.olat.group.ui.main\:assessment
-
+table.header.online=$org.olat.group.ui.main\:table.header.online
 table.header.edit=$org.olat.group.ui.main\:table.header.edit
 table.header.remove=$org.olat.group.ui.main\:table.header.remove
 table.header.graduate=$org.olat.group.ui.main\:table.header.graduate
diff --git a/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_en.properties
index c4a7b94742921c7da7a1d24f31167470da12180e..9a4175444df814f99a21664d5b8397a219bde568 100644
--- a/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/repository/controllers/_i18n/LocalStrings_en.properties
@@ -1,12 +1,15 @@
-#Tue Dec 18 17:59:47 CET 2012
+#Fri Feb 01 13:50:18 CET 2013
 add.member=$org.olat.group.ui.main\:add.member
 assessment=$org.olat.group.ui.main\:assessment
 dialog.modal.bg.leave.text=$org.olat.group.ui.main\:dialog.modal.bg.leave.text
+dialog.modal.bg.send.mail=$org.olat.group.ui.main\:dialog.modal.bg.send.mail
 edit.member=$org.olat.group.ui.main\:edit.member
 edit.member.groups=$org.olat.group.ui.main\:edit.member.groups
 error.atleastone=$org.olat.course.member\:error.atleastone
 home=$org.olat.group.ui.main\:home
 import.member=$org.olat.group.ui.main\:import.member
+nomembers=XXX No members
+table.header.online=$org.olat.group.ui.main\:table.header.online
 table.header.edit=$org.olat.group.ui.main\:table.header.edit
 table.header.firstName=$org.olat.group.ui.main\:table.header.firstName
 table.header.firstTime=$org.olat.group.ui.main\:table.header.firstTime
@@ -24,4 +27,3 @@ table.header.role=$org.olat.group.ui.main\:table.header.role
 table.header.tutors=$org.olat.group.ui.main\:table.header.tutors
 table.header.tutorsCount=$org.olat.group.ui.main\:table.header.tutorsCount
 table.header.waitingList=$org.olat.group.ui.main\:table.header.waitingList
-dialog.modal.bg.send.mail=$org.olat.group.ui.main\:dialog.modal.bg.send.mail
diff --git a/src/main/java/org/olat/resource/accesscontrol/AccessControlModuleEnabledSecurityCallback.java b/src/main/java/org/olat/resource/accesscontrol/AccessControlModuleEnabledSecurityCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ce311b840d98c77a20b5f750cb2e5e010b9ed0f
--- /dev/null
+++ b/src/main/java/org/olat/resource/accesscontrol/AccessControlModuleEnabledSecurityCallback.java
@@ -0,0 +1,46 @@
+/**
+ * <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>
+ * 22.02.2013 by frentix GmbH, http://www.frentix.com
+ * <p>
+ **/
+package org.olat.resource.accesscontrol;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.extensions.action.ActionExtensionSecurityCallback;
+import org.olat.core.gui.UserRequest;
+
+/**
+ * @author Florian Gnaegi, frentix GmbH
+ * 
+ * This callback returns true when the access control module is enabled, false otherwise
+ * 
+ */
+public class AccessControlModuleEnabledSecurityCallback implements
+		ActionExtensionSecurityCallback {
+
+	private final AccessControlModule acModule = CoreSpringFactory.getImpl(AccessControlModule.class);
+
+	/**
+	 * @see org.olat.core.extensions.action.ActionExtensionSecurityCallback#
+	 * isAllowedToLaunchActionController(org.olat.core.gui.UserRequest)
+	 */
+	@Override
+	public boolean isAllowedToLaunchActionController(UserRequest ureq) {
+		return acModule.isEnabled();
+	}
+
+}
diff --git a/src/main/java/org/olat/resource/accesscontrol/provider/paypal/PaypalIPNFilter.java b/src/main/java/org/olat/resource/accesscontrol/provider/paypal/PaypalIPNFilter.java
index 29996af16e059aeacce962611807176a8c8a5766..4b1b0700c5e50f1efb34dd1cb9a68072c3575700 100644
--- a/src/main/java/org/olat/resource/accesscontrol/provider/paypal/PaypalIPNFilter.java
+++ b/src/main/java/org/olat/resource/accesscontrol/provider/paypal/PaypalIPNFilter.java
@@ -75,7 +75,7 @@ public class PaypalIPNFilter implements Filter {
 			//we must log all errors, it's critical for this part of the payment
 			log.error("Paypal IPN unexpected error", t);
 		} finally {
-			DBFactory.getInstanceForClosing().cleanUpSession();
+			DBFactory.getInstanceForClosing().closeSession();
 		}
 	}
 
diff --git a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
index e2df563d3e31ae0ca044857d9f25ad2ccc71d426..7c547937ca904d116cc74f0b0b0d92a0e98e424d 100644
--- a/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
+++ b/src/main/java/org/olat/restapi/repository/course/CoursesWebService.java
@@ -264,6 +264,8 @@ public class CoursesWebService {
 	public static ICourse importCourse(UserRequest ureq, Identity identity, File fCourseImportZIP,
 			String displayName, String softKey, int access) {
 		
+		log.info("REST Import course " + displayName + " START");
+		
 		OLATResource newCourseResource = OLATResourceManager.getInstance().createOLATResourceInstance(CourseModule.class);
 		ICourse course = CourseFactory.importCourseFromZip(newCourseResource, fCourseImportZIP);
 		if (course == null) {
@@ -313,9 +315,12 @@ public class CoursesWebService {
 		editorRootNode.setNewnode(false);
 		
 		CourseFactory.closeCourseEditSession(course.getResourceableId(), false);
+		log.info("REST Import course " + displayName + " END");
 		
 		//publish
+		log.info("REST Publish course " + displayName + " START");
 		CourseFactory.publishCourse(course, identity, ureq.getLocale());
+		log.info("REST Publish course " + displayName + " END");
 
 		return course;
 	}
diff --git a/src/main/java/org/olat/user/UserImpl.hbm.xml b/src/main/java/org/olat/user/UserImpl.hbm.xml
index 1e0d46953c3d99d9265c5405d00530d6db427bfd..6e0ecad20808c83ecfcef07bb65d93148ab68852 100644
--- a/src/main/java/org/olat/user/UserImpl.hbm.xml
+++ b/src/main/java/org/olat/user/UserImpl.hbm.xml
@@ -2,12 +2,8 @@
 <!DOCTYPE hibernate-mapping PUBLIC 
         "-//Hibernate/Hibernate Mapping DTD//EN"
         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
-
 <hibernate-mapping default-lazy="false">
   <class name="org.olat.user.UserImpl" table="o_user">  
-  
-		<cache usage="transactional" />
-
     <id name="key" column="user_id" type="long" unsaved-value="null">
       <generator class="hilo"/>
     </id>
diff --git a/src/main/java/org/olat/user/restapi/UserFoldersWebService.java b/src/main/java/org/olat/user/restapi/UserFoldersWebService.java
index fd3fc96173efe40e1343dce5ee1a04204b4a172a..39262b06b09d20524767119d5188d48fdcbf5692 100644
--- a/src/main/java/org/olat/user/restapi/UserFoldersWebService.java
+++ b/src/main/java/org/olat/user/restapi/UserFoldersWebService.java
@@ -24,12 +24,11 @@ import static org.olat.restapi.security.RestSecurityHelper.getRoles;
 import static org.olat.restapi.security.RestSecurityHelper.isAdmin;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.GET;
@@ -53,8 +52,6 @@ import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl;
 import org.olat.core.id.Identity;
 import org.olat.core.id.IdentityEnvironment;
 import org.olat.core.id.Roles;
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
 import org.olat.core.util.nodes.INode;
 import org.olat.core.util.notifications.NotificationsManager;
 import org.olat.core.util.notifications.Subscriber;
@@ -71,11 +68,6 @@ import org.olat.course.run.userview.CourseTreeVisitor;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.model.SearchBusinessGroupParams;
-import org.olat.repository.RepositoryEntry;
-import org.olat.repository.RepositoryManager;
-import org.olat.repository.SearchRepositoryEntryParameters;
-import org.olat.resource.accesscontrol.ACService;
-import org.olat.resource.accesscontrol.AccessResult;
 import org.olat.restapi.group.LearningGroupWebService;
 import org.olat.restapi.support.vo.FolderVO;
 import org.olat.restapi.support.vo.FolderVOes;
@@ -92,7 +84,7 @@ import org.olat.restapi.support.vo.FolderVOes;
 @Path("users/{identityKey}/folders")
 public class UserFoldersWebService {
 	
-	private OLog log = Tracing.createLoggerFor(UserFoldersWebService.class);
+	//private static final OLog log = Tracing.createLoggerFor(UserFoldersWebService.class);
 
 	@Path("personal")
 	public VFSWebservice getFolder(@PathParam("identityKey") Long identityKey, @Context HttpServletRequest request) {
@@ -190,7 +182,7 @@ public class UserFoldersWebService {
 		}
 
 		final Map<Long,Long> groupNotified = new HashMap<Long,Long>();
-		final Map<Long,Set<String>> courseNotified = new HashMap<Long,Set<String>>();
+		final Map<Long,Collection<String>> courseNotified = new HashMap<Long,Collection<String>>();
 		NotificationsManager man = NotificationsManager.getInstance();
 		{//collect subscriptions
 			List<String> notiTypes = Collections.singletonList("FolderModule");
@@ -203,7 +195,7 @@ public class UserFoldersWebService {
 				} else if("CourseModule".equals(resName)) {
 					Long courseKey = sub.getPublisher().getResId();
 					if(!courseNotified.containsKey(courseKey)) {
-						courseNotified.put(courseKey,new HashSet<String>());
+						courseNotified.put(courseKey,new ArrayList<String>());
 					}
 					courseNotified.get(courseKey).add(sub.getPublisher().getSubidentifier());
 				}
@@ -211,7 +203,26 @@ public class UserFoldersWebService {
 		}
 
 		final List<FolderVO> folderVOs = new ArrayList<FolderVO>();
+		final IdentityEnvironment ienv = new IdentityEnvironment(retrievedUser, roles);
+		for(Map.Entry<Long, Collection<String>> e:courseNotified.entrySet()) {
+			final Long courseKey = e.getKey();
+			final Collection<String> nodeKeys = e.getValue();
+			final ICourse course = CourseFactory.loadCourse(courseKey);
+			new CourseTreeVisitor(course, ienv).visit(new Visitor() {
+				@Override
+				public void visit(INode node) {
+					if(node instanceof BCCourseNode) {
+						BCCourseNode bcNode = (BCCourseNode)node;
+						if(nodeKeys.contains(bcNode.getIdent())) {
+							FolderVO folder = BCWebService.createFolderVO(ienv, course, bcNode, courseNotified.get(course.getResourceableId()));
+							folderVOs.add(folder);
+						}
+					}
+				}
+			});
+		}
 		
+		/*
 		RepositoryManager rm = RepositoryManager.getInstance();
 		ACService acManager = CoreSpringFactory.getImpl(ACService.class);
 		SearchRepositoryEntryParameters repoParams = new SearchRepositoryEntryParameters(retrievedUser, roles, "CourseModule");
@@ -238,7 +249,7 @@ public class UserFoldersWebService {
 					log.error("", e);
 				}
 			}
-		}
+		}*/
 		
 		//start found forums in groups
 		BusinessGroupService bgs = CoreSpringFactory.getImpl(BusinessGroupService.class);
diff --git a/src/main/resources/infinispan-config.xml b/src/main/resources/infinispan-config.xml
index 37a50c8a2c995d373c3cc159978f4dbebf9821bd..a8219708fefb87868eee8616fbc4e2a3de1d3f9e 100644
--- a/src/main/resources/infinispan-config.xml
+++ b/src/main/resources/infinispan-config.xml
@@ -3,7 +3,7 @@
             xmlns="urn:infinispan:config:5.1"
             xsi:schemaLocation="urn:infinispan:config:5.1 http://www.infinispan.org/schemas/infinispan-config-5.1.xsd">
    <global>
-      <globalJmxStatistics allowDuplicateDomains="false" />
+      <globalJmxStatistics allowDuplicateDomains="true" />
    </global>
 
    <default>
@@ -12,24 +12,28 @@
    </default>
    
 	<namedCache name="MapperService@mapper">
+		<locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000" useLockStriping="false"/>
 		<eviction maxEntries="1000" strategy="LRU"/>
 		<expiration maxIdle="300000" wakeUpInterval="5000"/>
 		<transaction transactionMode="NON_TRANSACTIONAL" />
 	</namedCache>
    
 	<namedCache name="OpenMeetingsManager@session">
+		<locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000" useLockStriping="false"/>
 		<eviction maxEntries="1000" strategy="LRU"/>
 		<expiration maxIdle="900000" wakeUpInterval="5000"/>
 		<transaction transactionMode="NON_TRANSACTIONAL" />
 	</namedCache>
 	
 	<namedCache name="UserSessionManager@usersession">
+		<locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000" useLockStriping="false"/>
 		<eviction strategy="NONE"/>
 		<expiration lifespan="-1" maxIdle="-1" wakeUpInterval="0"/>
 		<transaction transactionMode="TRANSACTIONAL" />
 	</namedCache>
 	
 	<namedCache name="CalendarManager@calendar">
+		<locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000" useLockStriping="false"/>
 		<eviction maxEntries="500" strategy="LRU"/>
 		<expiration maxIdle="900000" wakeUpInterval="5000"/>
 		<transaction transactionMode="NON_TRANSACTIONAL" />
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index 5f88e20e1b68f0892b84edc48c47195d1369d8e3..090a1e4153ed8c6f49f28a2d5dbd5c18097b00d5 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -434,6 +434,11 @@ db.vendor=mysql
 db.vendor.values=mysql,postgresql
 db.vendor.values.comment=supported vendors currently include "mysql" and "postgresql", Hsqldb is used for development
 
+# The local data source works out of the box with the c3p0 database connection pool. However, we stronlgy 
+# recommend using a jndi container managed data source for better stability and realibility. The local data source
+# and c3p0 connection pool will be removed in future releases!
+# When using jndi, make sure you copy the database connector to your application server lib directory and remove it from 
+# the OpenOLAT release.
 db.source=local
 db.source.values=local,jndi
 db.source.values.comment=supports jdbc connections created locally (local) or search them with a jndi name (jndi)
diff --git a/src/main/webapp/static/js/functions.js b/src/main/webapp/static/js/functions.js
index 0bf392e4841767f76643f34a54a660d64d7e9ca5..833860f6ea39651f0d15ee5c2f8eceba25e51dca 100644
--- a/src/main/webapp/static/js/functions.js
+++ b/src/main/webapp/static/js/functions.js
@@ -458,6 +458,7 @@ function o_ainvoke(r) {
 					case 3:  // createParentRedirectTo leads to a full page reload
 						wi.o2c = 0;//??
 						var rurl = cda["rurl"];
+						wi.o_afterserver();
 						wi.document.location.replace(rurl);
 						break;
 					case 5: // create redirect for external resource mapper
@@ -567,6 +568,21 @@ function o_ainvoke(r) {
 */
 }
 
+/**
+ * Method to remove the ajax-busy stuff and let the user click links again. This
+ * should only be called from the ajax iframe onload method to make sure the UI
+ * does not freeze when the server for whatever reason does not respond as expected.
+ */
+function clearAfterAjaxIframeCall() {
+	if (o_info.linkbusy) {
+		// A normal ajax call will clear the linkbusy, so something went wrong in 
+		// the ajax channel, e.g. error message from apache or no response from server
+		// Call afterserver to remove busy icon clear the linkbusy flag
+		o_afterserver();
+		showMessageBox('info', o_info.i18n_noresponse_title, o_info.i18n_noresponse, undefined);
+	}
+}
+
 function showAjaxBusy() {
 	// release o_info.linkbusy only after a successful server response 
 	// - otherwhise the response gets overriden by next request
diff --git a/src/main/webapp/static/themes/openolat/all/_icons.scss b/src/main/webapp/static/themes/openolat/all/_icons.scss
index 98d398e1da4a0fd1cbdedbba26fd83b7a9d10f5f..9bf18b9ac96377d9f9ca528758d9bd582d48a61b 100644
--- a/src/main/webapp/static/themes/openolat/all/_icons.scss
+++ b/src/main/webapp/static/themes/openolat/all/_icons.scss
@@ -186,8 +186,52 @@ div.b_ext_elem .x-tree-node-expanded .x-tree-node-icon.b_filetype_folder, .b_fil
 .b_filetype_xsl { background-image: url('../openolat/images/docs/document_tags.png') ! important; }
 .b_filetype_zip { background-image: url('../openolat/images/docs/document-zipper.png') ! important; }
 
-/* tab icons in nav  and in LE-resources table*/
+/* large icons, as used in library */
+.b_large_icon.b_filetype_file { background-image: url('../openolat/images/docs_large/_blank.png') ! important; }
+.b_large_icon.b_filetype_avi { background-image: url('../openolat/images/docs_large/avi.png') ! important; }
+.b_large_icon.b_filetype_bat { background-image: url('../openolat/images/docs_large/exe.png') ! important; }
+.b_large_icon.b_filetype_bmp { background-image: url('../openolat/images/docs_large/bmp.png') ! important; }
+.b_large_icon.b_filetype_css, { background-image: url('../openolat/images/docs_large/css.png') ! important; }
+.b_large_icon.b_filetype_doc, .b_filetype_docx { background-image: url('../openolat/images/docs_large/doc.png') ! important; }
+.b_large_icon.b_filetype_dvi { background-image: url('../openolat/images/docs_large/avi.png') ! important; }
+.b_large_icon.b_filetype_exe { background-image: url('../openolat/images/docs_large/exe.png') ! important; }
+.b_large_icon.b_filetype_folder { background-image: url('../openolat/images/docs_large/_blank.png')  ! important; }
+.b_large_icon.b_filetype_gif { background-image: url('../openolat/images/docs_large/gif.png') ! important; }
+.b_large_icon.b_filetype_gz { background-image: url('../openolat/images/docs_large/tgz.png') ! important; }
+.b_large_icon.b_filetype_htm, .b_large_icon.b_filetype_html { background-image: url('../openolat/images/docs_large/html.png') ! important; }
+.b_large_icon.b_filetype_ico { 	background-image: url('../openolat/images/docs_large/gif.png') ! important; }
+.b_large_icon.b_filetype_jpeg, .b_large_icon.b_filetype_jpg { background-image: url('../openolat/images/docs_large/jpg.png') ! important; }
+.b_large_icon.b_filetype_js { background-image: url('../openolat/images/docs_large/java.png') ! important; }
+.b_large_icon.b_filetype_log { background-image: url('../openolat/images/docs_large/txt.png') ! important; }
+.b_large_icon.b_filetype_midi { background-image: url('../openolat/images/docs_large/midi.png') ! important; }
+.b_large_icon.b_filetype_mp4, .b_large_icon.b_filetype_m4v, .b_large_icon.b_filetype_webm, .b_large_icon.b_filetype_ogg { background-image: url('../openolat/images/docs_large/mp4.png') ! important; }
+.b_large_icon.b_filetype_flv { background-image: url('../openolat/images/docs_large/flv.png') ! important; }
+.b_large_icon.b_filetype_video, .b_large_icon.b_filetype_mov { background-image: url('../openolat/images/docs_large/qt.png') ! important; }
+.b_large_icon.b_filetype_audio, .b_large_icon.b_filetype_mp3,.b_filetype_m3u { background-image: url('../openolat/images/docs_large/mp3.png') ! important; }
+.b_large_icon.b_filetype_mpeg,.b_large_icon.b_filetype_mpg { background-image: url('../openolat/images/docs_large/mpg.png') ! important; }
+.b_large_icon.b_filetype_odp { background-image: url('../openolat/images/docs_large/odp.png') ! important; }
+.b_large_icon.b_filetype_ods { background-image: url('../openolat/images/docs_large/ods.png') ! important; }
+.b_large_icon.b_filetype_odt { background-image: url('../openolat/images/docs_large/odt.png') ! important; }
+.b_large_icon.b_filetype_odg { background-image: url('../openolat/images/docs_large/odg.png') ! important; }
+.b_large_icon.b_filetype_odf { background-image: url('../openolat/images/docs_large/odf.png') ! important; }
+.b_large_icon.b_filetype_pdf { background-image: url('../openolat/images/docs_large/pdf.png') ! important; }
+.b_large_icon.b_filetype_png { background-image: url('../openolat/images/docs_large/png.png') ! important; }
+.b_large_icon.b_filetype_ppt, .b_large_icon.b_filetype_pptx { background-image: url('../openolat/images/docs_large/ppt.png') ! important; }
+.b_large_icon.b_filetype_ps { background-image: url('../openolat/images/docs_large/pdf.png') ! important; }
+.b_large_icon.b_filetype_qt,.b_large_icon.b_filetype_ra,.b_large_icon.b_filetype_ram { background-image: url('../openolat/images/docs_large/qt.png') ! important; }
+.b_large_icon.b_filetype_readme, .b_large_icon.b_filetype_README { background-image: url('../openolat/images/docs_large/text.png') ! important; }
+.b_large_icon.b_filetype_rtf { background-image: url('../openolat/images/docs_large/rtf.png') ! important; }
+.b_large_icon.b_filetype_tar,.b_large_icon.b_filetype_tgz { background-image: url('../openolat/images/docs_large/gtz.png') ! important; }
+.b_large_icon.b_filetype_tiff { background-image: url('../openolat/images/docs_large/tiff.png') ! important; }
+.b_large_icon.b_filetype_txt { background-image: url('../openolat/images/docs_large/txt.png') ! important; }
+.b_large_icon.b_filetype_wav { background-image: url('../openolat/images/docs_large/wav.png') ! important; }
+.b_large_icon.b_filetype_xls, .b_filetype_xlsx { background-image: url('../openolat/images/docs_large/xls.png') ! important; }
+.b_large_icon.b_filetype_xml{ background-image: url('../openolat/images/docs_large/xml.png') ! important; }
+.b_large_icon.b_filetype_xsl { background-image: url('../openolat/images/docs_large/xsl.png') ! important; }
+.b_large_icon.b_filetype_zip { background-image: url('../openolat/images/docs_large/zip.png') ! important; }
+
 
+/* tab icons in nav  and in LE-resources table*/
 
 // the default 
 li.b_nav_site div, li.b_nav_tab div { background: url('../openolat/images/application.png') no-repeat left 50%; padding-left: 18px;	}			
diff --git a/src/main/webapp/static/themes/openolat/all/modules/_library.scss b/src/main/webapp/static/themes/openolat/all/modules/_library.scss
index de02a15644205a9592e3f5f6291f7094a421cacf..512e01a7acfa8d1589a27bc068b3094540a26bab 100644
--- a/src/main/webapp/static/themes/openolat/all/modules/_library.scss
+++ b/src/main/webapp/static/themes/openolat/all/modules/_library.scss
@@ -32,9 +32,9 @@ div.f_library_catalog {
 			@include o-border-radius(4px);
 			@include o-box-shadow(0,1px,2px,#D3D3D3);
 			
-			div.f_thumbnail {float:left; border-right:1px solid #eeeeee; }
+			div.f_thumbnail {float:left; border-right:1px solid #eeeeee; margin-right: 1em;}
 			div.f_thumbnail_inner { width:200px; height:200px; }
-			div.f_thumbnail_unavailable { width:200px; height:200px; background-image:url(../openolat/images/no_preview.png); background-repeat:no-repeat; background-position:50% 50%;  }
+			div.f_thumbnail_unavailable { width:200px; height:200px; background-repeat:no-repeat; background-position:50% 50%;  }
 			
 			div.f_metadata_text { padding-bottom: 35px; }
 			div.f_metadata_text_inner { width:100%; }
@@ -167,15 +167,30 @@ div.f_library_catalog_condensed {
 div.f_library_overview {
 	img { float: right; max-width: 50%; }
 	p {padding-left: 20px;}
-	div.f_library_big_icon { float:right; width: 425px; height: 282px; background: url(../openolat/images/library_image.png) no-repeat;}
-	
+	div.f_library_big_icon { 
+		float:right; 
+		background-repeat:  no-repeat;
+	   	background-size: 100%;
+		/*
+		width: 425px; 
+		height: 282px; 
+		*/
+		width: 45%; /* scale dynamically */
+		height: 300px; /* can not scale dynamically, thus make large enough */
+		margin: 0 20px 0 20px;
+	}
+		
 	div.f_library_newest_files ul li {
 		white-space: normal; padding-bottom: 0.3em;
 		a { background-position: top left; min-height: 16px; }
 	}
 }
 
-.f_library_icon { background-image: url(../openolat/images/library.png) }
+
+/* icons */
+.f_library_big_icon { background-image: url(../openolat/images/library_image.png); }
+.f_library_icon { background-image: url(../openolat/images/library.png); }
+.f_thumbnail_unavailable { background-image:url(../openolat/images/no_preview.png); }
 	
 	
 	
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/_blank.png b/src/main/webapp/static/themes/openolat/images/docs_large/_blank.png
new file mode 100644
index 0000000000000000000000000000000000000000..d93aa5a55008e4634473febdc983cd96fa803968
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/_blank.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/_page.png b/src/main/webapp/static/themes/openolat/images/docs_large/_page.png
new file mode 100644
index 0000000000000000000000000000000000000000..25e5249c92af921a2cbeb5b86c4f9c8daa8035df
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/_page.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/aac.png b/src/main/webapp/static/themes/openolat/images/docs_large/aac.png
new file mode 100644
index 0000000000000000000000000000000000000000..5f385791490c9cea07faae352a9cb6e31b6e4bd5
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/aac.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/ai.png b/src/main/webapp/static/themes/openolat/images/docs_large/ai.png
new file mode 100644
index 0000000000000000000000000000000000000000..c34c8ebd75cc67515e9ed52f2308bf3cc5713bdb
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/ai.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/aiff.png b/src/main/webapp/static/themes/openolat/images/docs_large/aiff.png
new file mode 100644
index 0000000000000000000000000000000000000000..a985c4f560c9a733cfed04598d54849fb1fed7fd
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/aiff.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/avi.png b/src/main/webapp/static/themes/openolat/images/docs_large/avi.png
new file mode 100644
index 0000000000000000000000000000000000000000..e9f593846b6fd16979daec7d5d9bdd97d65ef31f
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/avi.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/bmp.png b/src/main/webapp/static/themes/openolat/images/docs_large/bmp.png
new file mode 100644
index 0000000000000000000000000000000000000000..173b5fa41434eb4523c6072ba32a815a0c0ee383
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/bmp.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/c.png b/src/main/webapp/static/themes/openolat/images/docs_large/c.png
new file mode 100644
index 0000000000000000000000000000000000000000..843035061c7932a3d5e88afbd1b4c7e68629ec65
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/c.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/cpp.png b/src/main/webapp/static/themes/openolat/images/docs_large/cpp.png
new file mode 100644
index 0000000000000000000000000000000000000000..553bccc6bfd7d60563004cb4cc53c405d92e849f
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/cpp.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/css.png b/src/main/webapp/static/themes/openolat/images/docs_large/css.png
new file mode 100644
index 0000000000000000000000000000000000000000..78ebc0683fbe40b08c553103ba40007b44d29e00
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/css.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/dat.png b/src/main/webapp/static/themes/openolat/images/docs_large/dat.png
new file mode 100644
index 0000000000000000000000000000000000000000..0995743cefc522aa734be78adaaace3565097b6e
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/dat.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/dmg.png b/src/main/webapp/static/themes/openolat/images/docs_large/dmg.png
new file mode 100644
index 0000000000000000000000000000000000000000..829eafba978a2c547301d007c19d75aea8d8d087
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/dmg.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/doc.png b/src/main/webapp/static/themes/openolat/images/docs_large/doc.png
new file mode 100644
index 0000000000000000000000000000000000000000..a6f9d967743058e42f84e82286c0a036b355547d
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/doc.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/dotx.png b/src/main/webapp/static/themes/openolat/images/docs_large/dotx.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a842f95f943565623bdbd9201e02ef2bdbdd643
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/dotx.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/dwg.png b/src/main/webapp/static/themes/openolat/images/docs_large/dwg.png
new file mode 100644
index 0000000000000000000000000000000000000000..38c033c9e78b16f73ce91c5eda028de98f734445
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/dwg.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/dxf.png b/src/main/webapp/static/themes/openolat/images/docs_large/dxf.png
new file mode 100644
index 0000000000000000000000000000000000000000..b181e5403fdbfecb4211b21dd15a684d5bda0df8
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/dxf.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/eps.png b/src/main/webapp/static/themes/openolat/images/docs_large/eps.png
new file mode 100644
index 0000000000000000000000000000000000000000..288a0fc4da166b22dcf6ea179480788de8d1e753
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/eps.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/exe.png b/src/main/webapp/static/themes/openolat/images/docs_large/exe.png
new file mode 100644
index 0000000000000000000000000000000000000000..ecf80ce71c85116343d45a53b4f3b8d61eb119ef
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/exe.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/flv.png b/src/main/webapp/static/themes/openolat/images/docs_large/flv.png
new file mode 100644
index 0000000000000000000000000000000000000000..a713d8c7a40a2338376df6a1fcfac3ee86c65ed8
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/flv.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/gif.png b/src/main/webapp/static/themes/openolat/images/docs_large/gif.png
new file mode 100644
index 0000000000000000000000000000000000000000..02294f11207276f764f5dc1b1ae4bca15706dca4
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/gif.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/h.png b/src/main/webapp/static/themes/openolat/images/docs_large/h.png
new file mode 100644
index 0000000000000000000000000000000000000000..100108282e6b0c256f67a19b08684e2d9263077e
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/h.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/hpp.png b/src/main/webapp/static/themes/openolat/images/docs_large/hpp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ac13ddc3c95880c861ffa93c223761ad6967b3a4
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/hpp.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/html.png b/src/main/webapp/static/themes/openolat/images/docs_large/html.png
new file mode 100644
index 0000000000000000000000000000000000000000..ac3cddbd3cacfe419c384d775b3a16344db6f860
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/html.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/ics.png b/src/main/webapp/static/themes/openolat/images/docs_large/ics.png
new file mode 100644
index 0000000000000000000000000000000000000000..798329593701bd8427b813bf08f47a31e54dda6e
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/ics.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/iso.png b/src/main/webapp/static/themes/openolat/images/docs_large/iso.png
new file mode 100644
index 0000000000000000000000000000000000000000..c237eee0b8a3f1d56962b40f33341a8f38c04448
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/iso.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/java.png b/src/main/webapp/static/themes/openolat/images/docs_large/java.png
new file mode 100644
index 0000000000000000000000000000000000000000..dcb3eda7ac058e3f0a3be5390af25bf3ac30bfaa
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/java.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/jpg.png b/src/main/webapp/static/themes/openolat/images/docs_large/jpg.png
new file mode 100644
index 0000000000000000000000000000000000000000..555f5b12d36d362f9e2610488dd0166dcb19b529
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/jpg.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/key.png b/src/main/webapp/static/themes/openolat/images/docs_large/key.png
new file mode 100644
index 0000000000000000000000000000000000000000..14468c0857926521c9a697883d9bcbb6d8c18a57
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/key.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/mid.png b/src/main/webapp/static/themes/openolat/images/docs_large/mid.png
new file mode 100644
index 0000000000000000000000000000000000000000..7a1b8940513c166d904e6b3f2db7c9df44a6d2c0
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/mid.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/mp3.png b/src/main/webapp/static/themes/openolat/images/docs_large/mp3.png
new file mode 100644
index 0000000000000000000000000000000000000000..5beab9c0ca7dbd6471b09fbba0607411cb33cc43
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/mp3.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/mp4.png b/src/main/webapp/static/themes/openolat/images/docs_large/mp4.png
new file mode 100644
index 0000000000000000000000000000000000000000..5f1f7fb702e2ab7801cfa980d45908bffbf68171
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/mp4.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/mpg.png b/src/main/webapp/static/themes/openolat/images/docs_large/mpg.png
new file mode 100644
index 0000000000000000000000000000000000000000..6267ed0f101294b0a179d8a8b795ae0df2e9e6e9
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/mpg.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/odf.png b/src/main/webapp/static/themes/openolat/images/docs_large/odf.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b427cff176227cd3db1aed09a298d64f8203f68
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/odf.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/ods.png b/src/main/webapp/static/themes/openolat/images/docs_large/ods.png
new file mode 100644
index 0000000000000000000000000000000000000000..33603ec0d640fccda72b32a742f3f29c4887c927
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/ods.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/odt.png b/src/main/webapp/static/themes/openolat/images/docs_large/odt.png
new file mode 100644
index 0000000000000000000000000000000000000000..ceb535c32eec79a893d939f1055a96c8ebca969b
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/odt.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/otp.png b/src/main/webapp/static/themes/openolat/images/docs_large/otp.png
new file mode 100644
index 0000000000000000000000000000000000000000..7e277e0cba6a0918d9fda7a3c4c8a6f485663e60
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/otp.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/ots.png b/src/main/webapp/static/themes/openolat/images/docs_large/ots.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef0bb44b88de80fa6f65e5127c52b57f3fff8f0c
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/ots.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/ott.png b/src/main/webapp/static/themes/openolat/images/docs_large/ott.png
new file mode 100644
index 0000000000000000000000000000000000000000..54d6b3dd434f06e6e4cae827dde8c7e165b83288
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/ott.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/pdf.png b/src/main/webapp/static/themes/openolat/images/docs_large/pdf.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa1c01c2bc13cfa2820f1e5c08313b6bc283e16c
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/pdf.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/php.png b/src/main/webapp/static/themes/openolat/images/docs_large/php.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1102f1597638942fd8e66ae9a142086ce7ff6d3
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/php.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/png.png b/src/main/webapp/static/themes/openolat/images/docs_large/png.png
new file mode 100644
index 0000000000000000000000000000000000000000..76a35f63d765966db6a3dbd16ad7d94a7fb8e601
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/png.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/ppt.png b/src/main/webapp/static/themes/openolat/images/docs_large/ppt.png
new file mode 100644
index 0000000000000000000000000000000000000000..6450f8b6f9c33cd3a67b0ab088b07492fcd53596
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/ppt.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/psd.png b/src/main/webapp/static/themes/openolat/images/docs_large/psd.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5ca8a57c99f8520fd936a0b7fef182c95b18c40
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/psd.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/py.png b/src/main/webapp/static/themes/openolat/images/docs_large/py.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d7fe4c80fc807014acbf2025c2a3c3c15dae997
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/py.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/qt.png b/src/main/webapp/static/themes/openolat/images/docs_large/qt.png
new file mode 100644
index 0000000000000000000000000000000000000000..d2dafea880849ea96664535dde90f75b5b58abc9
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/qt.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/rar.png b/src/main/webapp/static/themes/openolat/images/docs_large/rar.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc19dedfb8a546e053073dff9b8e3587ec22cb2d
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/rar.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/rb.png b/src/main/webapp/static/themes/openolat/images/docs_large/rb.png
new file mode 100644
index 0000000000000000000000000000000000000000..5396a57e92664768c0c5a17b3e426a74af39d769
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/rb.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/rtf.png b/src/main/webapp/static/themes/openolat/images/docs_large/rtf.png
new file mode 100644
index 0000000000000000000000000000000000000000..bfad9a7d465fcc44931c784884acafccd0c41708
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/rtf.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/sql.png b/src/main/webapp/static/themes/openolat/images/docs_large/sql.png
new file mode 100644
index 0000000000000000000000000000000000000000..7cab3c02ef7edf41dab183a9fa711a1b8cc6c172
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/sql.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/tga.png b/src/main/webapp/static/themes/openolat/images/docs_large/tga.png
new file mode 100644
index 0000000000000000000000000000000000000000..7ead14c5d9d8ab001874c8d964ffc49f9015f118
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/tga.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/tgz.png b/src/main/webapp/static/themes/openolat/images/docs_large/tgz.png
new file mode 100644
index 0000000000000000000000000000000000000000..f2fae615e79c9e33c03f42feac986cc6795e0a7f
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/tgz.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/tiff.png b/src/main/webapp/static/themes/openolat/images/docs_large/tiff.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb8c124e9394389241400ffd8511f13a42682701
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/tiff.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/txt.png b/src/main/webapp/static/themes/openolat/images/docs_large/txt.png
new file mode 100644
index 0000000000000000000000000000000000000000..c8d9c5e8dbdb4c546237bc0e775333cc238934bd
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/txt.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/wav.png b/src/main/webapp/static/themes/openolat/images/docs_large/wav.png
new file mode 100644
index 0000000000000000000000000000000000000000..01e81866a289dbb9e5a31bfabc5ddde872301417
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/wav.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/xls.png b/src/main/webapp/static/themes/openolat/images/docs_large/xls.png
new file mode 100644
index 0000000000000000000000000000000000000000..42f9cacf0d6afd1c4dfec3b8980759fb9e61f758
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/xls.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/xlsx.png b/src/main/webapp/static/themes/openolat/images/docs_large/xlsx.png
new file mode 100644
index 0000000000000000000000000000000000000000..f734071fe4a7e12552b2429c3dfda462a53bbc48
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/xlsx.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/xml.png b/src/main/webapp/static/themes/openolat/images/docs_large/xml.png
new file mode 100644
index 0000000000000000000000000000000000000000..9bef978b1b31b51ea43b909c3c2f34ef0972cfd3
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/xml.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/yml.png b/src/main/webapp/static/themes/openolat/images/docs_large/yml.png
new file mode 100644
index 0000000000000000000000000000000000000000..beabb178c72958a7666a589edc1a45bb4834aa7d
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/yml.png differ
diff --git a/src/main/webapp/static/themes/openolat/images/docs_large/zip.png b/src/main/webapp/static/themes/openolat/images/docs_large/zip.png
new file mode 100644
index 0000000000000000000000000000000000000000..30afc8464347b7c1125579d038484e7ca2fd5a08
Binary files /dev/null and b/src/main/webapp/static/themes/openolat/images/docs_large/zip.png differ
diff --git a/src/test/java/org/olat/core/commons/persistence/DBTest.java b/src/test/java/org/olat/core/commons/persistence/DBTest.java
index 1f326e653aeda36c3b3c424af560dd3f44acee91..be411d95c81b720fbcaf63c86a7bf7957a61a563 100644
--- a/src/test/java/org/olat/core/commons/persistence/DBTest.java
+++ b/src/test/java/org/olat/core/commons/persistence/DBTest.java
@@ -32,17 +32,32 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+
+import junit.framework.Assert;
+
 import org.junit.Test;
 import org.olat.core.logging.DBRuntimeException;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.properties.Property;
 import org.olat.properties.PropertyManager;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.model.RepositoryEntryShortImpl;
 import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.orm.jpa.EntityManagerFactoryUtils;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
 
 
 /**
@@ -53,8 +68,12 @@ import org.olat.test.OlatTestCase;
  */
 public class DBTest extends OlatTestCase {
 	
-	private final OLog log = Tracing.createLoggerFor(DBTest.class);
-
+	private static final OLog log = Tracing.createLoggerFor(DBTest.class);
+	
+	@Autowired
+ 	private RepositoryManager repositoryManager;
+	@Autowired
+ 	private EntityManagerFactory emf;
 		
 	/**
 	 * testCloseOfUninitializedSession
@@ -62,16 +81,99 @@ public class DBTest extends OlatTestCase {
 	@Test
 	public void testCloseOfUninitializedSession() {
 		// first get a initialized db
-		DB db = DBImpl.getInstance(false);
+		DB db = DBImpl.getInstance();
 		//close it
 		db.closeSession();
 		//then get a uninitialized db
-		db = DBImpl.getInstance(false);
+		db = DBImpl.getInstance();
 		// and close it.
 		db.closeSession();
-		
 	}
 	
+	@Test
+	public void testMergeEntityManager() {	
+ 		EntityManager em1 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+ 		Assert.assertNull(em1);
+ 		List<RepositoryEntryShortImpl> res = repositoryManager.loadRepositoryEntryShortsByResource(Collections.singletonList(27l), "CourseModule");
+ 		Assert.assertNotNull(res);
+ 		EntityManager em2 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+ 		Assert.assertNotNull(em2);
+ 		
+ 		EntityTransaction trx = em2.getTransaction();
+ 		Assert.assertTrue(trx.isActive());
+ 		trx.commit();
+ 		
+ 		EntityManagerFactoryUtils.closeEntityManager(em2);
+ 		
+ 		EntityManager em3 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+ 		Assert.assertNotNull(em3);
+
+ 		//search in the thread local used by Spring
+ 		List<TransactionSynchronization> syncs = TransactionSynchronizationManager.getSynchronizations();
+ 		Assert.assertNotNull(syncs);
+ 		TransactionSynchronizationManager.clear();
+ 		Map<Object,Object> map = TransactionSynchronizationManager.getResourceMap();
+ 		Assert.assertNotNull(map);
+ 		EntityManager em4 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+ 		Assert.assertNotNull(em4);
+ 		
+ 		//unbind the entity manager
+ 		if(map.containsKey(emf)) {
+			TransactionSynchronizationManager.unbindResource(emf);
+		}
+ 		
+ 		//no entity manager anymore
+ 		EntityManager em5 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+ 		Assert.assertNull(em5);
+ 	}
+	
+	@Test
+	public void testMergeEntityManager_transactional() {
+		CountDownLatch latch = new CountDownLatch(1);
+		TestThread test = new TestThread(repositoryManager, latch);
+		test.start();
+ 
+		try {
+			latch.await(20, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			log.error("", e);
+			fail("Takes too long");
+		}
+		
+		Assert.assertFalse(test.hasError());
+ 	}
+	
+ 	private class TestThread extends Thread {
+ 		private boolean error;
+ 		private final CountDownLatch latch;
+ 		private final RepositoryManager repositoryManager;
+ 		
+ 		public TestThread(RepositoryManager repositoryManager, CountDownLatch latch) {
+ 			this.latch = latch;
+ 			this.repositoryManager = repositoryManager;
+ 		}
+ 		
+ 		public boolean hasError() {
+ 			return error;
+ 		}
+		
+ 		public void run() {
+ 			try {
+				EntityManager em1 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+				Assert.assertNull(em1);
+				repositoryManager.lookupRepositoryEntry(27l, false);
+				EntityManager em2 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
+				//Transactional annotation must clean-up the entity manager
+				Assert.assertNull(em2);
+			} catch (Exception e) {
+				error = true;
+				log.error("", e);
+			} finally {
+				latch.countDown();
+			}
+ 		}
+ 	}
+	
 	/**
 	 * testErrorHandling
 	 */
diff --git a/src/test/java/org/olat/core/commons/persistence/EntityManagerTest.java b/src/test/java/org/olat/core/commons/persistence/EntityManagerTest.java
deleted file mode 100644
index 086ec633b7ba3bf1138f16d1a1b71c18208220c4..0000000000000000000000000000000000000000
--- a/src/test/java/org/olat/core/commons/persistence/EntityManagerTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.olat.core.commons.persistence;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityTransaction;
-
-import org.junit.Test;
-import org.olat.repository.RepositoryEntry;
-import org.olat.repository.RepositoryManager;
-import org.olat.repository.model.RepositoryEntryShortImpl;
-import org.olat.test.OlatTestCase;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.orm.jpa.EntityManagerFactoryUtils;
-import org.springframework.transaction.support.TransactionSynchronization;
-import org.springframework.transaction.support.TransactionSynchronizationManager;
-
-/**
- * this is 
- * 
- * 
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- *
- */
-public class EntityManagerTest extends OlatTestCase {
-	
-	@Autowired
-	private RepositoryManager repositoryManager;
-	@Autowired
-	private EntityManagerFactory emf;
-	
-	
-
-	@Test
-	public void test2() {
-		
-		EntityManager em1 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
-		System.out.println("current1: " + em1);
-		List<RepositoryEntryShortImpl> res = repositoryManager.loadRepositoryEntryShortsByResource(Collections.singletonList(27l), "CourseModule");
-		
-		EntityManager em2 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
-		System.out.println("current2: " + em2);
-		
-		
-		EntityTransaction trx = em2.getTransaction();
-		System.out.println("Active: " + trx.isActive());
-		
-		trx.commit();
-		
-		EntityManagerFactoryUtils.closeEntityManager(em2);
-		
-		EntityManager em3 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
-		System.out.println("current3: " + em3);
-		
-		
-		List<TransactionSynchronization> syncs = TransactionSynchronizationManager.getSynchronizations();
-		TransactionSynchronizationManager.clear();
-		Map<Object,Object> map = TransactionSynchronizationManager.getResourceMap();
-		EntityManager em4 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
-		System.out.println("current4: " + em4);
-		
-	}
-	
-
-	public void test3() {
-		//lookupRepositoryEntry(Long key, boolean strict) 
-		
-		new TestThread(27l, repositoryManager).start();
-
-		try {
-			Thread.sleep(60000);
-		} catch (InterruptedException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	}
-	
-	private class TestThread extends Thread {
-		private Long reKey;
-		private RepositoryManager repositoryManager;
-		
-		public TestThread(Long reKey, RepositoryManager repositoryManager) {
-			this.reKey = reKey;
-			this.repositoryManager = repositoryManager;
-		}
-		
-		public void run() {
-			
-			EntityManager em1 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
-			System.out.println("em1: " + em1);
-			RepositoryEntry re = repositoryManager.lookupRepositoryEntry(27l, false);
-			EntityManager em2 = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
-			System.out.println("em2: " + em2);
-			
-			System.out.println(re);
-			
-			
-		}
-		
-	}
-
-}
diff --git a/src/test/java/org/olat/core/util/i18n/I18nTest.java b/src/test/java/org/olat/core/util/i18n/I18nTest.java
index 784ab3fbc0bdeeedd9c08ec64c319008123d9476..ac1ee0b14cefd98f787769c30899da6e0b535457 100644
--- a/src/test/java/org/olat/core/util/i18n/I18nTest.java
+++ b/src/test/java/org/olat/core/util/i18n/I18nTest.java
@@ -653,7 +653,7 @@ public class I18nTest extends OlatTestCase {
 		assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Eingaben</i> </br >*<b>bold</b>*<br>_<i>italic</i>_<br>* Listen", testLocale, testLocale, null, true).size());
 		assertEquals(1, i18nMgr.findI18nItemsByValueSearch("dargestellt werden. Bitte rufen Sie", testLocale, testLocale, null, true).size());
 		// multi line value search
-		assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Die Seite wird nun neu geladen.", testLocale, testLocale, null, true).size());
+		assertEquals(1, i18nMgr.findI18nItemsByValueSearch("Die Aktion konnte nicht ausgef\u00FChrt werden", testLocale, testLocale, null, true).size());
 	}
 
 	/**
diff --git a/src/test/java/org/olat/core/util/locks/SynchManagerTest.java b/src/test/java/org/olat/core/util/locks/SynchManagerTest.java
deleted file mode 100644
index 477cd011add72218697772c04d0d1648c5507c73..0000000000000000000000000000000000000000
--- a/src/test/java/org/olat/core/util/locks/SynchManagerTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
-* OLAT - Online Learning and Training<br>
-* http://www.olat.org
-* <p>
-* Licensed under the Apache License, Version 2.0 (the "License"); <br>
-* you may not use this file except in compliance with the License.<br>
-* You may obtain a copy of the License at
-* <p>
-* http://www.apache.org/licenses/LICENSE-2.0
-* <p>
-* Unless required by applicable law or agreed to in writing,<br>
-* software distributed under the License is distributed on an "AS IS" BASIS, <br>
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
-* See the License for the specific language governing permissions and <br>
-* limitations under the License.
-* <p>
-* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
-* University of Zurich, Switzerland.
-* <hr>
-* <a href="http://www.openolat.org">
-* OpenOLAT - Online Learning and Training</a><br>
-* This file has been modified by the OpenOLAT community. Changes are licensed
-* under the Apache 2.0 license as the original file.  
-* <p>
-*/ 
-
-package org.olat.core.util.locks;
-
-
-import org.apache.log4j.Logger;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.olat.core.id.OLATResourceable;
-import org.olat.core.util.resource.OresHelper;
-
-/**
- * 
- * @author Christian Guretzki
- */
-@RunWith(JUnit4.class)
-public class SynchManagerTest {
-
-	private static Logger log = Logger.getLogger(SynchManagerTest.class.getName());
-
-	/**
-	 * @see junit.framework.TestCase#setUp()
-	 */
-	@Before public void setup() throws Exception {
-	}
-
-	/**
-	 * Creates 3 OLAT-resourceable, two with same key, one with an other key.
-	 * Compare the resulting synchronization objects.
-	 * With the same key, the synch objects must be same objects.
-	 * With different key, the synch objects must be different objects.
-	 */
-	@Test public void testGetSynchLockFor() throws Exception {
-		//SynchManager synchManager = SynchManager.getInstance();
-		// Create synch-object 1 for ores with key=1
-		Long oresKey1 = new Long(1);
-		OLATResourceable resource1 = OresHelper.createOLATResourceableInstance(this.getClass(),oresKey1);
-		
-		// cluster:: gen new test
-		/*Object synchObject1 = synchManager.getSynchLockFor(resource1);
-    // Create synch-object 2 for ores with key=2
-		Long oresKey2 = new Long(2);
-		OLATResourceable resource2 = OresHelper.createOLATResourceableInstance(this.getClass(),oresKey2);
-		Object synchObject2 = synchManager.getSynchLockFor(resource2);
-    // Create synch-object 3 for ores with key=1
-		OLATResourceable resource1_1 = OresHelper.createOLATResourceableInstance(this.getClass(),oresKey1);
-		Object synchObject1_1 = synchManager.getSynchLockFor(resource1_1);
-		
-		assertSame("Synch objects instances are not equals !",synchObject1,synchObject1_1);
-		assertNotSame("Synch objects instances are not equals !",synchObject1,synchObject2);
-		*/
-	}
-
-}
\ No newline at end of file
diff --git a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java
index 8cb53468c7004ef121603923b81425b5e2e68561..d06ba8567e439016da6f94882d1220eff795d0af 100644
--- a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java
+++ b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerTest.java
@@ -294,6 +294,7 @@ public class EnrollmentManagerTest extends OlatTestCase implements WindowControl
 		@Override
 		public void run() {
 			try {
+				sleep(10);
 				IdentityEnvironment ienv = new IdentityEnvironment();
 				ienv.setIdentity(identity);
 				UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
diff --git a/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java
index d224d8d65ca0332f92687b684349fe282451aba5..750323b44f82fd41d0663776461211874e1ae20f 100644
--- a/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java
+++ b/src/test/java/org/olat/course/nodes/feed/FunctionalBlogTest.java
@@ -210,8 +210,8 @@ public class FunctionalBlogTest {
 		Assert.assertTrue(functionalUtil.login(browser, functionalUtil.getUsername(), functionalUtil.getPassword(), true));
 		Assert.assertTrue(functionalAdministrationSiteUtil.clearCache(browser,
 				new String[]{
-				"SingleVMCacher@org.olat.modules.webFeed.dispatching.Path_feed__0",
-				"SingleVMCacher@org.olat.modules.webFeed.managers.FeedManagerImpl_feed__0"
+				"FeedManager@feed",
+				"Path@feed"
 				}
 		));
 
diff --git a/src/test/java/org/olat/group/FunctionalGroupTest.java b/src/test/java/org/olat/group/FunctionalGroupTest.java
index 0a268ded062047e87823841e4434f9f4636297e6..c18ac0d47d4ddb0727cdc8e90ced090ee0109671 100644
--- a/src/test/java/org/olat/group/FunctionalGroupTest.java
+++ b/src/test/java/org/olat/group/FunctionalGroupTest.java
@@ -190,7 +190,6 @@ public class FunctionalGroupTest {
 		}
 		
 		/* logout */
-		functionalUtil.idle(tutor0);
 		functionalUtil.logout(tutor0);
 	}
 
@@ -254,7 +253,6 @@ public class FunctionalGroupTest {
 		
 		
 		/* logout tutor */
-		functionalUtil.idle(tutor0);
 		functionalUtil.logout(tutor0);
 	}
 
@@ -311,7 +309,6 @@ public class FunctionalGroupTest {
 				CONFIGURE_ACCESS_CONTROL_DESCRIPTION, CONFIGURE_ACCESS_CONTROL_ACCESS_CODE));
 		
 		/* logout tutor */
-		functionalUtil.idle(tutor0);
 		functionalUtil.logout(tutor0);
 		
 		/*
@@ -348,7 +345,6 @@ public class FunctionalGroupTest {
 		}
 		
 		/* logout student */
-		functionalUtil.idle(student0);
 		functionalUtil.logout(student0);
 	}
 	
@@ -408,7 +404,7 @@ public class FunctionalGroupTest {
 		Assert.assertTrue(functionalGroupsSiteUtil.openMyGroup(tutor0, groups[0].getName()));
 
 		/* add participant */
-		Assert.assertTrue(functionalGroupsSiteUtil.addUser(tutor0, students[0].getLogin()));
+		Assert.assertTrue(functionalGroupsSiteUtil.addUser(tutor0, students[0].getLogin(), false, true, false));
 
 		/* logout tutor */
 		functionalUtil.idle(tutor0);
@@ -426,4 +422,18 @@ public class FunctionalGroupTest {
 		functionalUtil.idle(student0);
 		functionalUtil.logout(student0);
 	}
+	
+	@Ignore
+	@Test
+	@RunAsClient
+	public void checkInvitation(){
+		//TODO:JK: implement me
+	}
+	
+	@Ignore
+	@Test
+	@RunAsClient
+	public void checkVisitingCard(){
+		//TODO:JK: implement me
+	}
 }
diff --git a/src/test/java/org/olat/instantMessaging/FunctionalInstantMessagingTest.java b/src/test/java/org/olat/instantMessaging/FunctionalInstantMessagingTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffd71c853ea5b384f37e12cec0e18157c2f0118e
--- /dev/null
+++ b/src/test/java/org/olat/instantMessaging/FunctionalInstantMessagingTest.java
@@ -0,0 +1,78 @@
+/**
+ * <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.instantMessaging;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.olat.test.ArquillianDeployments;
+import org.olat.util.FunctionalUtil;
+import org.olat.util.FunctionalVOUtil;
+
+/**
+ * 
+ * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
+ */
+@Ignore
+@RunWith(Arquillian.class)
+public class FunctionalInstantMessagingTest {
+	
+	@Deployment(testable = false)
+	public static WebArchive createDeployment() {
+		return ArquillianDeployments.createDeployment();
+	}
+
+	@ArquillianResource
+	URL deploymentUrl;
+
+	static FunctionalUtil functionalUtil;
+
+	static FunctionalVOUtil functionalVOUtil;
+	
+	static boolean initialized = false;
+	
+	@Before
+	public void setup() throws IOException, URISyntaxException{
+		if(!initialized){
+			functionalUtil = new FunctionalUtil();
+			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
+			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
+			
+			initialized = true;
+		}
+	}
+
+	@Ignore
+	@Test
+	@RunAsClient
+	public void checkChat(){
+		//TODO:JK: implement me
+	}
+}
diff --git a/src/test/java/org/olat/repository/FunctionalRepositoryTest.java b/src/test/java/org/olat/repository/FunctionalRepositoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc703be17a0fbb0eeb27690371b22911cf4c8d8c
--- /dev/null
+++ b/src/test/java/org/olat/repository/FunctionalRepositoryTest.java
@@ -0,0 +1,121 @@
+/**
+ * <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.repository;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.olat.restapi.support.vo.CourseVO;
+import org.olat.restapi.support.vo.GroupVO;
+import org.olat.restapi.support.vo.RepositoryEntryVO;
+import org.olat.test.ArquillianDeployments;
+import org.olat.user.restapi.UserVO;
+import org.olat.util.FunctionalRepositorySiteUtil;
+import org.olat.util.FunctionalUtil;
+import org.olat.util.FunctionalVOUtil;
+
+import com.thoughtworks.selenium.DefaultSelenium;
+
+/**
+ * 
+ * @author jkraehemann, joel.kraehemann@frentix.com, frentix.com
+ */
+@Ignore
+@RunWith(Arquillian.class)
+public class FunctionalRepositoryTest {
+	
+	@Deployment(testable = false)
+	public static WebArchive createDeployment() {
+		return ArquillianDeployments.createDeployment();
+	}
+
+	@Drone
+	DefaultSelenium browser;
+
+	@ArquillianResource
+	URL deploymentUrl;
+
+	static FunctionalUtil functionalUtil;
+	static FunctionalRepositorySiteUtil functionalRepositorySiteUtil;
+
+	static FunctionalVOUtil functionalVOUtil;
+	
+	static boolean initialized = false;
+	
+	@Before
+	public void setup() throws IOException, URISyntaxException{
+		if(!initialized){
+			functionalUtil = new FunctionalUtil();
+			functionalUtil.setDeploymentUrl(deploymentUrl.toString());
+
+			functionalRepositorySiteUtil = functionalUtil.getFunctionalRepositorySiteUtil();
+			
+			functionalVOUtil = new FunctionalVOUtil(functionalUtil.getUsername(), functionalUtil.getPassword());
+			
+			initialized = true;
+		}
+	}
+	
+	@Ignore
+	@Test
+	@RunAsClient
+	public void checkCopyCourse() throws URISyntaxException, IOException{
+		/*
+		 * prerequisites for test created via REST
+		 */
+		/* create tutor */
+		UserVO tutorVO = functionalVOUtil.createTestAuthors(deploymentUrl, 1).get(0);
+		
+		/* import course */
+		CourseVO courseVO = functionalVOUtil.importAllElementsCourse(deploymentUrl);
+		
+		RepositoryEntryVO repoEntryVO = functionalVOUtil.getRepositoryEntryByKey(deploymentUrl, courseVO.getRepoEntryKey());
+		functionalVOUtil.addOwnerToRepositoryEntry(deploymentUrl, repoEntryVO, tutorVO);
+		
+		/* create groups */
+		List<GroupVO> groupVO = functionalVOUtil.createTestCourseGroups(deploymentUrl, 3);
+		
+		/* create learning areas */
+		//TODO:JK: implement me
+		
+		/*
+		 * create or configure content
+		 */
+		//TODO:JK: implement me
+		
+		/*
+		 * verify content
+		 */
+		//TODO:JK: implement me
+		
+	}
+}
diff --git a/src/test/java/org/olat/resource/lock/pessimistic/PLockTest.java b/src/test/java/org/olat/resource/lock/pessimistic/PLockTest.java
index 1f0b44e1beff06bf6569e59937f8c8be0c7d9c3b..c52df08e4ddf7a2fecca56a095070f56e2915fa6 100644
--- a/src/test/java/org/olat/resource/lock/pessimistic/PLockTest.java
+++ b/src/test/java/org/olat/resource/lock/pessimistic/PLockTest.java
@@ -38,7 +38,6 @@ import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.log4j.Logger;
 import org.junit.Test;
 import org.olat.basesecurity.BaseSecurityManager;
 import org.olat.basesecurity.SecurityGroup;
@@ -55,9 +54,7 @@ public class PLockTest extends OlatTestCase {
 
 	private static final int MAX_COUNT = 5; //5; //30;
 	private static final int MAX_USERS_MORE = 20; //20; //100;
-	
-	private static Logger log = Logger.getLogger(PLockTest.class.getName());
-	
+
 	
 	@Test public void testReentrantLock() {
 		long start = System.currentTimeMillis();
@@ -439,7 +436,7 @@ public class PLockTest extends OlatTestCase {
 			};
 			new Thread(r).start();
 		}	
-		int i;
+
 		// 4. wait till all are finished or it takes too long
 		try {
 			boolean interrupt = doneSignal.await(20, TimeUnit.SECONDS);
diff --git a/src/test/java/org/olat/restapi/MyForumsTest.java b/src/test/java/org/olat/restapi/MyForumsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5a41c28c46394bcbd96eafea7049c5da2ad38ac
--- /dev/null
+++ b/src/test/java/org/olat/restapi/MyForumsTest.java
@@ -0,0 +1,151 @@
+/**
+* OLAT - Online Learning and Training<br>
+* http://www.olat.org
+* <p>
+* Licensed under the Apache License, Version 2.0 (the "License"); <br>
+* you may not use this file except in compliance with the License.<br>
+* You may obtain a copy of the License at
+* <p>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p>
+* Unless required by applicable law or agreed to in writing,<br>
+* software distributed under the License is distributed on an "AS IS" BASIS, <br>
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+* See the License for the specific language governing permissions and <br>
+* limitations under the License.
+* <p>
+* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
+* University of Zurich, Switzerland.
+* <hr>
+* <a href="http://www.openolat.org">
+* OpenOLAT - Online Learning and Training</a><br>
+* This file has been modified by the OpenOLAT community. Changes are licensed
+* under the Apache 2.0 license as the original file.  
+* <p>
+*/
+
+package org.olat.restapi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.UUID;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.core.id.IdentityEnvironment;
+import org.olat.core.id.Roles;
+import org.olat.core.util.nodes.INode;
+import org.olat.core.util.notifications.NotificationsManager;
+import org.olat.core.util.notifications.PublisherData;
+import org.olat.core.util.notifications.SubscriptionContext;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.core.util.tree.Visitor;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
+import org.olat.course.nodes.FOCourseNode;
+import org.olat.course.run.userview.CourseTreeVisitor;
+import org.olat.modules.fo.Forum;
+import org.olat.modules.fo.restapi.ForumVOes;
+import org.olat.repository.RepositoryEntry;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatJerseyTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class MyForumsTest extends OlatJerseyTestCase {
+
+	private static boolean setup;
+	private static ICourse myCourse;
+	private static RepositoryEntry myCourseRe;
+	
+	@Autowired
+	private DB dbInstance;
+	
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+		
+		if(setup) return;
+		
+		URL courseWithForumsUrl = MyForumsTest.class.getResource("myCourseWS.zip");
+		Assert.assertNotNull(courseWithForumsUrl);
+		File courseWithForums = new File(courseWithForumsUrl.toURI());
+		myCourseRe = CourseFactory.deployCourseFromZIP(courseWithForums, 4);	
+		Assert.assertNotNull(myCourseRe);
+		myCourse = CourseFactory.loadCourse(myCourseRe.getOlatResource().getResourceableId());
+
+		setup = true;
+	}
+	
+	/**
+	 * Test retrieve the forum which the user subscribe in a course.
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	public void myForums() throws IOException, URISyntaxException {
+		final Identity id = JunitTestHelper.createAndPersistIdentityAsUser("my-" + UUID.randomUUID().toString());
+		dbInstance.commitAndCloseSession();
+		
+		//load my forums
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login(id.getName(), "A6B7C8"));
+		
+		//subscribed to nothing
+		URI uri = UriBuilder.fromUri(getContextURI()).path("users").path(id.getKey().toString()).path("forums").build();
+		HttpGet method = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response = conn.execute(method);
+		assertEquals(200, response.getStatusLine().getStatusCode());
+		InputStream body = response.getEntity().getContent();
+		ForumVOes forums = conn.parse(body, ForumVOes.class);
+		Assert.assertNotNull(forums);
+		Assert.assertNotNull(forums.getForums());
+		Assert.assertEquals(0, forums.getForums().length);
+		
+		//subscribe to the forum
+		IdentityEnvironment ienv = new IdentityEnvironment(id, new Roles(false, false, false, false, false, false, false));
+		new CourseTreeVisitor(myCourse, ienv).visit(new Visitor() {
+			@Override
+			public void visit(INode node) {
+				if(node instanceof FOCourseNode) {
+					FOCourseNode forumNode = (FOCourseNode)node;	
+					Forum forum = forumNode.loadOrCreateForum(myCourse.getCourseEnvironment());
+					String businessPath = "[RepositoryEntry:" + myCourseRe.getKey() + "][CourseNode:" + forumNode.getIdent() + "]";
+					SubscriptionContext forumSubContext = new SubscriptionContext("CourseModule", myCourse.getResourceableId(), forumNode.getIdent());
+					PublisherData forumPdata = new PublisherData(OresHelper.calculateTypeName(Forum.class), forum.getKey().toString(), businessPath);
+					NotificationsManager.getInstance().subscribe(id, forumSubContext, forumPdata);
+				}
+			}
+		});
+		dbInstance.commitAndCloseSession();
+		
+		//retrieve my forums
+		HttpGet method2 = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response2 = conn.execute(method2);
+		assertEquals(200, response2.getStatusLine().getStatusCode());
+		InputStream body2 = response2.getEntity().getContent();
+		ForumVOes forums2 = conn.parse(body2, ForumVOes.class);
+		Assert.assertNotNull(forums2);
+		Assert.assertNotNull(forums2.getForums());
+		Assert.assertEquals(1, forums2.getForums().length);
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/org/olat/restapi/UserFoldersTest.java b/src/test/java/org/olat/restapi/UserFoldersTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..12c3303f3f148825d9e414697a6aafcc5e182946
--- /dev/null
+++ b/src/test/java/org/olat/restapi/UserFoldersTest.java
@@ -0,0 +1,149 @@
+/**
+* OLAT - Online Learning and Training<br>
+* http://www.olat.org
+* <p>
+* Licensed under the Apache License, Version 2.0 (the "License"); <br>
+* you may not use this file except in compliance with the License.<br>
+* You may obtain a copy of the License at
+* <p>
+* http://www.apache.org/licenses/LICENSE-2.0
+* <p>
+* Unless required by applicable law or agreed to in writing,<br>
+* software distributed under the License is distributed on an "AS IS" BASIS, <br>
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+* See the License for the specific language governing permissions and <br>
+* limitations under the License.
+* <p>
+* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
+* University of Zurich, Switzerland.
+* <hr>
+* <a href="http://www.openolat.org">
+* OpenOLAT - Online Learning and Training</a><br>
+* This file has been modified by the OpenOLAT community. Changes are licensed
+* under the Apache 2.0 license as the original file.  
+* <p>
+*/
+
+package org.olat.restapi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.UUID;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.core.id.IdentityEnvironment;
+import org.olat.core.id.Roles;
+import org.olat.core.util.nodes.INode;
+import org.olat.core.util.notifications.NotificationsManager;
+import org.olat.core.util.notifications.PublisherData;
+import org.olat.core.util.notifications.SubscriptionContext;
+import org.olat.core.util.tree.Visitor;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
+import org.olat.course.nodes.BCCourseNode;
+import org.olat.course.run.userview.CourseTreeVisitor;
+import org.olat.repository.RepositoryEntry;
+import org.olat.restapi.support.vo.FolderVOes;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatJerseyTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class UserFoldersTest extends OlatJerseyTestCase {
+
+	private static boolean setup;
+	private static ICourse myCourse;
+	private static RepositoryEntry myCourseRe;
+	
+	@Autowired
+	private DB dbInstance;
+	
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+		
+		if(setup) return;
+		
+		URL courseWithForumsUrl = UserFoldersTest.class.getResource("myCourseWS.zip");
+		Assert.assertNotNull(courseWithForumsUrl);
+		File courseWithForums = new File(courseWithForumsUrl.toURI());
+		myCourseRe = CourseFactory.deployCourseFromZIP(courseWithForums, 4);	
+		Assert.assertNotNull(myCourseRe);
+		myCourse = CourseFactory.loadCourse(myCourseRe.getOlatResource().getResourceableId());
+
+		setup = true;
+	}
+	
+	/**
+	 * Test retrieve the folder which the user subscribe in a course.
+	 * @throws IOException
+	 * @throws URISyntaxException
+	 */
+	@Test
+	public void myFolders() throws IOException, URISyntaxException {
+		final Identity id = JunitTestHelper.createAndPersistIdentityAsUser("my-" + UUID.randomUUID().toString());
+		dbInstance.commitAndCloseSession();
+		
+		//load my forums
+		RestConnection conn = new RestConnection();
+		assertTrue(conn.login(id.getName(), "A6B7C8"));
+		
+		//subscribed to nothing
+		URI uri = UriBuilder.fromUri(getContextURI()).path("users").path(id.getKey().toString()).path("folders").build();
+		HttpGet method = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response = conn.execute(method);
+		assertEquals(200, response.getStatusLine().getStatusCode());
+		InputStream body = response.getEntity().getContent();
+		FolderVOes folders = conn.parse(body, FolderVOes.class);
+		Assert.assertNotNull(folders);
+		Assert.assertNotNull(folders.getFolders());
+		Assert.assertEquals(0, folders.getFolders().length);
+		
+		//subscribe to the forum
+		IdentityEnvironment ienv = new IdentityEnvironment(id, new Roles(false, false, false, false, false, false, false));
+		new CourseTreeVisitor(myCourse, ienv).visit(new Visitor() {
+			@Override
+			public void visit(INode node) {
+				if(node instanceof BCCourseNode) {
+					BCCourseNode folderNode = (BCCourseNode)node;	
+					String relPath = BCCourseNode.getFoldernodePathRelToFolderBase(myCourse.getCourseEnvironment(), folderNode);
+					String businessPath = "[RepositoryEntry:" + myCourseRe.getKey() + "][CourseNode:" + folderNode.getIdent() + "]";
+					SubscriptionContext folderSubContext = new SubscriptionContext("CourseModule", myCourse.getResourceableId(), folderNode.getIdent());
+					PublisherData folderPdata = new PublisherData("FolderModule", relPath, businessPath);
+					NotificationsManager.getInstance().subscribe(id, folderSubContext, folderPdata);
+				}
+			}
+		});
+		dbInstance.commitAndCloseSession();
+		
+		//retrieve my folders
+		HttpGet method2 = conn.createGet(uri, MediaType.APPLICATION_JSON, true);
+		HttpResponse response2 = conn.execute(method2);
+		assertEquals(200, response2.getStatusLine().getStatusCode());
+		InputStream body2 = response2.getEntity().getContent();
+		FolderVOes folders2 = conn.parse(body2, FolderVOes.class);
+		Assert.assertNotNull(folders2);
+		Assert.assertNotNull(folders2.getFolders());
+		Assert.assertEquals(1, folders2.getFolders().length);
+	}
+}
diff --git a/src/test/java/org/olat/restapi/UserMgmtTest.java b/src/test/java/org/olat/restapi/UserMgmtTest.java
index ab00780b56e1c2113ab70e577f8addcdbd5e6033..a6d4d6dc37a032abc58449ba284ad0012e3a5b97 100644
--- a/src/test/java/org/olat/restapi/UserMgmtTest.java
+++ b/src/test/java/org/olat/restapi/UserMgmtTest.java
@@ -930,7 +930,7 @@ public class UserMgmtTest extends OlatJerseyTestCase {
 	
 	@Test
 	public void testPortrait() throws IOException, URISyntaxException {
-		URL portraitUrl = CoursesElementsTest.class.getResource("portrait.jpg");
+		URL portraitUrl = UserMgmtTest.class.getResource("portrait.jpg");
 		assertNotNull(portraitUrl);
 		File portrait = new File(portraitUrl.toURI());
 		RestConnection conn = new RestConnection();
diff --git a/src/test/java/org/olat/restapi/myCourseWS.zip b/src/test/java/org/olat/restapi/myCourseWS.zip
new file mode 100644
index 0000000000000000000000000000000000000000..88eb7d686788b23b1fd5b62835575bb701a48a77
Binary files /dev/null and b/src/test/java/org/olat/restapi/myCourseWS.zip differ
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 87e98e9cb19c831d066beb501ae0d004efe8a7f5..5e4647c821663c6ddaa0002a022bba384029d271 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -45,7 +45,6 @@ import org.junit.runners.Suite;
 @Suite.SuiteClasses({
 	org.olat.core.util.i18n.I18nTest.class,
 	// org.olat.core.util.mail.MailTest.class, // redisabled since mails are sent despite the fact that the whitelist is enabled
-	org.olat.core.util.locks.SynchManagerTest.class,
 	org.olat.core.gui.components.table.MultiSelectColumnDescriptorTest.class,
 	org.olat.core.gui.components.table.TableEventTest.class,
 	org.olat.core.gui.components.table.TableMultiSelectEventTest.class,
@@ -166,10 +165,12 @@ import org.junit.runners.Suite;
 	org.olat.restapi.GroupFoldersTest.class,
 	org.olat.restapi.GroupMgmtTest.class,
 	org.olat.restapi.I18nTest.class,
+	org.olat.restapi.MyForumsTest.class,
 	org.olat.restapi.NotificationsTest.class,
 	org.olat.restapi.RepositoryEntriesTest.class,
 	org.olat.restapi.RestApiLoginFilterTest.class,
 	org.olat.restapi.UserAuthenticationMgmtTest.class,
+	org.olat.restapi.UserFoldersTest.class,
 	org.olat.restapi.UserMgmtTest.class,
 	org.olat.restapi.ContactsTest.class,
 	org.olat.restapi.SystemTest.class,
diff --git a/src/test/java/org/olat/test/ArquillianDeployments.java b/src/test/java/org/olat/test/ArquillianDeployments.java
index c249067fbba21211f86ab62935cd36b0ad7f0a72..9df2649d647e3c1ec551f8931c793a5e4df4a445 100644
--- a/src/test/java/org/olat/test/ArquillianDeployments.java
+++ b/src/test/java/org/olat/test/ArquillianDeployments.java
@@ -36,7 +36,7 @@ public class ArquillianDeployments {
 	public static final String WEBINF    = "src/main/webapp/WEB-INF";
 	public static final String WEBINF_TOMCAT = "src/main/webapp-tomcat/WEB-INF";
 	public static final String TEST_RSRC = "src/test/resources";
-	public static final String LIB_DIR   = "target/openolat-lms-8.3-SNAPSHOT/WEB-INF/lib";
+	public static final String LIB_DIR   = "target/openolat-lms-8.4-SNAPSHOT/WEB-INF/lib";
 
 	
 	public static WebArchive createDeployment() {
diff --git a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java
index fcc0e1cd3dfe291fc3a1a6ea93205fedfcd165d1..4068046e3550f9af79bb0627cd6478b1583f01e1 100644
--- a/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalAdministrationSiteUtil.java
@@ -33,12 +33,11 @@ public class FunctionalAdministrationSiteUtil {
 	private final static OLog log = Tracing.createLoggerFor(FunctionalAdministrationSiteUtil.class);
 	
 	public enum AdministrationSiteAction {
-		INFORMATION("o_sel_sysinfo"),
-		CONFIGURATION("o_sel_sysconfig"),
-		MAINTENANCE("o_sel_sysadmin"),
+		SYSTEM("o_sel_system"),
+		CORE_FUNCTIONS("o_sel_sysconfig"),
+		MODULES("o_sel_modules"),
 		CUSTOMIZATION("o_sel_customizing"),
-		ADVANCED_PROPERTIES("o_sel_advancedproperties"),
-		BOOKINGS("o_sel_booking");
+		DEVELOPMENT("o_sel_devel");
 		
 		private String actionCss;
 		
@@ -55,24 +54,45 @@ public class FunctionalAdministrationSiteUtil {
 		}
 	}
 	
-	public enum SystemConfigurationAction {
-		LAYOUT("o_sel_layout"),
+	public enum SystemAction {
+		SYSTEM_INFO("o_sel_sysinfo"),
+		SESSIONS("o_sel_sessions"),
+		ERRORS("o_sel_errors"),
+		CACHES("o_sel_caches"),
+		LOCKS("o_sel_locks"),
+		HIBERNATE("o_sel_hibernate"),
+		JAVAVM("o_sel_javavm");
+		
+		private String actionCss;
+		
+		SystemAction(String actionCss){
+			setActionCss(actionCss);
+		}
+
+		public String getActionCss() {
+			return actionCss;
+		}
+
+		public void setActionCss(String actionCss) {
+			this.actionCss = actionCss;
+		}
+	}
+	
+	public enum CoreFunctionsAction {
 		LANGUAGES("o_sel_i18n"),
 		QUOTA("o_sel_quota"),
 		VERSIONIG("o_sel_versioning"),
-		PORTFOLIO("o_sel_portfolio"),
-		RESAPI("o_sel_restapi"),
-		EXTENSIONS("o_sel_extensions"),
+		RESTAPI("o_sel_restapi"),
 		EMAIL("o_sel_mail"),
-		VITERO("o_sel_vitero"),
-		SETUP("o_sel_properties"),
 		SELF_REGISTRATION("o_sel_selfregistration"),
-		PAYPAL("o_sel_paypal"),
-		GROUP("o_sel_group");
+		STATISTICS("o_sel_statistics"),
+		SEARCH("o_sel_search"),
+		NOTIFICATIONS("o_sel_notifications"),
+		PASSWORDS("o_sel_userbulkchangepw");
 		
 		private String actionCss;
 		
-		SystemConfigurationAction(String actionCss){
+		CoreFunctionsAction(String actionCss){
 			setActionCss(actionCss);
 		}
 
@@ -85,15 +105,18 @@ public class FunctionalAdministrationSiteUtil {
 		}
 	}
 	
-	public enum SystemMaintenanceAction {
-		STATISTICS("o_sel_statistics"),
-		SEARCH("o_sel_search"),
-		NOTIFICATIONS("o_sel_notifications"),
-		PASSWORDS("o_sel_userbulkchangepw");
+	public enum ModulesAction {
+		PORTFOLIO("o_sel_portfolio"),
+		VITERO("o_sel_vitero"),
+		OPENMEETINGS("o_sel_openmeetings"),
+		PAYPAL("o_sel_paypal"),
+		BOOKING("o_sel_booking"),
+		GROUP("o_sel_group"),
+		CATALOG("o_sel_catalog");
 		
 		private String actionCss;
 		
-		SystemMaintenanceAction(String actionCss){
+		ModulesAction(String actionCss){
 			setActionCss(actionCss);
 		}
 
@@ -106,13 +129,35 @@ public class FunctionalAdministrationSiteUtil {
 		}
 	}
 	
-	public enum CustomizingAction {
+	public enum CustomizationAction {
+		LAYOUT("o_sel_layout"),
 		TRANSLATION("o_sel_translation"),
 		REGISTRATION("o_sel_registration");
 		
 		private String actionCss;
 		
-		CustomizingAction(String actionCss){
+		CustomizationAction(String actionCss){
+			setActionCss(actionCss);
+		}
+
+		public String getActionCss() {
+			return actionCss;
+		}
+
+		public void setActionCss(String actionCss) {
+			this.actionCss = actionCss;
+		}
+	}
+	
+	public enum DevelopmentAction {
+		EXTENSIONS("o_sel_extensions"),
+		PROPERTIES("o_sel_properties"),
+		ADVANCED_PROPERTIES("o_sel_advancedproperties"),
+		SNOOP("o_sel_snoop");
+		
+		private String actionCss;
+		
+		DevelopmentAction(String actionCss){
 			setActionCss(actionCss);
 		}
 
@@ -155,84 +200,62 @@ public class FunctionalAdministrationSiteUtil {
 	 */
 	public boolean openActionByMenuTree(Selenium browser, Object action){
 		functionalUtil.idle(browser);
-		
+
 		StringBuffer selectorBuffer;
-		
+
 		if(action instanceof AdministrationSiteAction){
-			 selectorBuffer = new StringBuffer();
-			
+			selectorBuffer = new StringBuffer();
+
 			selectorBuffer.append("xpath=//li[contains(@class, '")
 			.append(((AdministrationSiteAction) action).getActionCss())
 			.append("')]//a[contains(@class, '")
 			.append(functionalUtil.getTreeLevel1Css())
 			.append("')]");
-		}else if(action instanceof SystemConfigurationAction){
-			/* check if not collapsed */
-			 selectorBuffer = new StringBuffer();
+		}else{
+			String actionL1Css = null;
+			String actionL2Css = null;
 			
-			 selectorBuffer.append("xpath=//li[contains(@class, '")
-			 .append(AdministrationSiteAction.CONFIGURATION.getActionCss())
-			 .append("')]//a[contains(@class, '")
-			 .append(functionalUtil.getTreeLevelOpenCss())
-			 .append("')]");
-			 
-			if(browser.isElementPresent(selectorBuffer.toString())){
-				browser.click(selectorBuffer.toString());
-				functionalUtil.idle(browser);
+			if(action instanceof SystemAction){
+				actionL1Css = AdministrationSiteAction.SYSTEM.getActionCss();
+				actionL2Css = ((SystemAction) action).getActionCss();
+			}else if(action instanceof CoreFunctionsAction){
+				actionL1Css = AdministrationSiteAction.CORE_FUNCTIONS.getActionCss();
+				actionL2Css = ((CoreFunctionsAction) action).getActionCss();
+			}else if(action instanceof ModulesAction){
+				actionL1Css = AdministrationSiteAction.MODULES.getActionCss();
+				actionL2Css = ((ModulesAction) action).getActionCss();
+			}else if(action instanceof CustomizationAction){
+				actionL1Css = AdministrationSiteAction.CUSTOMIZATION.getActionCss();
+				actionL2Css = ((SystemAction) action).getActionCss();
+			}else if(action instanceof DevelopmentAction){
+				actionL1Css = AdministrationSiteAction.DEVELOPMENT.getActionCss();
+				actionL2Css = ((DevelopmentAction) action).getActionCss();
+			}else{
+				return(false);
 			}
-
-			/* click */
-			selectorBuffer = new StringBuffer();
 			
-			selectorBuffer.append("xpath=//li[contains(@class, '")
-			.append(((SystemConfigurationAction) action).getActionCss())
-			.append("')]//a[contains(@class, '")
-			.append(functionalUtil.getTreeLevel2Css())
-			.append("')]");
-		}else if(action instanceof SystemMaintenanceAction){
 			/* check if not collapsed */
-			 selectorBuffer = new StringBuffer();
-			
-			 selectorBuffer.append("xpath=//li[contains(@class, '")
-			 .append(AdministrationSiteAction.MAINTENANCE.getActionCss())
-			 .append("')]//a[contains(@class, '")
-			 .append(functionalUtil.getTreeLevelOpenCss())
-			 .append("')]");
-			 
-			if(browser.isElementPresent(selectorBuffer.toString())){
-				browser.click(selectorBuffer.toString());
-				functionalUtil.idle(browser);
-			}
+			selectorBuffer = new StringBuffer();
 
-			/* click */
 			selectorBuffer.append("xpath=//li[contains(@class, '")
-			.append(((SystemMaintenanceAction) action).getActionCss())
+			.append(actionL1Css)
 			.append("')]//a[contains(@class, '")
-			.append(functionalUtil.getTreeLevel2Css())
+			.append(functionalUtil.getTreeLevelOpenCss())
 			.append("')]");
-		}else if(action instanceof CustomizingAction){
-			/* check if not collapsed */
-			 selectorBuffer = new StringBuffer();
-			
-			 selectorBuffer.append("xpath=//li[contains(@class, '")
-			 .append(AdministrationSiteAction.CUSTOMIZATION.getActionCss())
-			 .append("')]//a[contains(@class, '")
-			 .append(functionalUtil.getTreeLevelOpenCss())
-			 .append("')]");
-			 
+
 			if(browser.isElementPresent(selectorBuffer.toString())){
 				browser.click(selectorBuffer.toString());
 				functionalUtil.idle(browser);
 			}
 
 			/* click */
+			selectorBuffer = new StringBuffer();
+
 			selectorBuffer.append("xpath=//li[contains(@class, '")
-			.append(((CustomizingAction) action).getActionCss())
+			.append(actionL2Css)
 			.append("')]//a[contains(@class, '")
 			.append(functionalUtil.getTreeLevel2Css())
 			.append("')]");
-		}else{
-			return(false);
 		}
 		
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
@@ -253,16 +276,14 @@ public class FunctionalAdministrationSiteUtil {
 			return(false);
 		}
 		
-		if(!openActionByMenuTree(browser, AdministrationSiteAction.INFORMATION)){
+		if(!openActionByMenuTree(browser, AdministrationSiteAction.SYSTEM)){
 			return(false);
 		}
 		
-		if(!functionalUtil.openContentTab(browser, SystemInformationTabs.CACHES.ordinal())){
+		if(!openActionByMenuTree(browser, SystemAction.CACHES)){
 			return(false);
 		}
 		
-		functionalUtil.idle(browser);
-		
 		/* click show all*/
 		StringBuffer selectorBuffer = new StringBuffer();
 		
diff --git a/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java b/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java
index 8a852a9adf09e61688868d4557aee13f9c1497c8..af9830766461f46d42bd6c47f7aa3f3419b384d9 100644
--- a/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalGroupsSiteUtil.java
@@ -42,8 +42,10 @@ public class FunctionalGroupsSiteUtil {
 	
 	public final static String SEARCH_GROUP_BUTTONS_CSS = "o_sel_group_search_groups_buttons";
 	
-	public final static String IMPORT_USER_CSS = "o_sel_group_import_users";
-	public final static String ADD_USER_CSS = "o_sel_group_add_user";
+	public final static String ADD_MEMBER_CSS = "o_sel_group_add_member";
+	public final static String IMPORT_MEMBERS_CSS = "o_sel_group_import_members";
+	
+	public final static String GROUP_IMPORT_1_WIZARD_CSS = "o_sel_group_import_1_wizard";
 	
 	public final static String USERSEARCH_AUTOCOMPLETION_CSS = "o_sel_usersearch_autocompletion";
 	public final static String USERSEARCH_SEARCHFORM_CSS = "o_sel_usersearch_searchform";
@@ -215,8 +217,10 @@ public class FunctionalGroupsSiteUtil {
 	
 	private String searchGroupButtonsCss;
 	
-	private String importUserCss;
-	private String addUserCss;
+	private String addMemberCss;
+	private String importMembersCss;
+	
+	private String groupImport1WizardCss;
 	
 	private String usersearchAutocompletionCss;
 	private String usersearchSearchformCss;
@@ -244,8 +248,10 @@ public class FunctionalGroupsSiteUtil {
 		
 		this.searchGroupButtonsCss = SEARCH_GROUP_BUTTONS_CSS;
 		
-		this.importUserCss = IMPORT_USER_CSS;
-		this.addUserCss = ADD_USER_CSS;
+		this.addMemberCss = ADD_MEMBER_CSS;
+		this.importMembersCss = IMPORT_MEMBERS_CSS;
+		
+		this.groupImport1WizardCss = GROUP_IMPORT_1_WIZARD_CSS;
 		
 		this.usersearchAutocompletionCss = USERSEARCH_AUTOCOMPLETION_CSS;
 		this.usersearchSearchformCss = USERSEARCH_SEARCHFORM_CSS;
@@ -272,8 +278,6 @@ public class FunctionalGroupsSiteUtil {
 	 * @return true on success otherwise false
 	 */
 	public boolean openActionByMenuTree(Selenium browser, Object action){
-		functionalUtil.idle(browser);
-		
 		StringBuffer selectorBuffer;
 		
 		if(action instanceof GroupsSiteAction){
@@ -544,6 +548,8 @@ public class FunctionalGroupsSiteUtil {
 	 * @return
 	 */
 	public boolean openGroupsTabActionByMenuTree(Selenium browser, GroupsTabAction action){
+		functionalUtil.idle(browser);
+		
 		StringBuffer selectorBuffer = new StringBuffer();
 		
 		selectorBuffer.append("xpath=//ul[contains(@class, '")
@@ -579,37 +585,30 @@ public class FunctionalGroupsSiteUtil {
 		
 		if(ArrayUtils.contains(tools, GroupTools.INFORMATION)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.INFORMATION.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(tools, GroupTools.EMAIL)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.EMAIL.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(tools, GroupTools.CALENDAR)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.CALENDAR.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(tools, GroupTools.FOLDER)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.FOLDER.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(tools, GroupTools.FORUM)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.FORUM.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(tools, GroupTools.WIKI)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.WIKI.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(tools, GroupTools.EPORTFOLIO)){
 			functionalUtil.clickCheckbox(browser, null, Integer.toString(GroupTools.EPORTFOLIO.ordinal()));
-			functionalUtil.idle(browser);
 		}
 		
 		return(true);
@@ -668,27 +667,22 @@ public class FunctionalGroupsSiteUtil {
 		
 		if(ArrayUtils.contains(conf, MembersConfiguration.CAN_SEE_COACHES)){
 			functionalUtil.clickCheckbox(browser, null, MembersConfiguration.CAN_SEE_COACHES.getValue());
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(conf, MembersConfiguration.CAN_SEE_PARTICIPANTS)){
 			functionalUtil.clickCheckbox(browser, null, MembersConfiguration.CAN_SEE_PARTICIPANTS.getValue());
-			functionalUtil.idle(browser);
 		}
 
 		if(ArrayUtils.contains(conf, MembersConfiguration.ALL_CAN_SEE_COACHES)){
 			functionalUtil.clickCheckbox(browser, null, MembersConfiguration.ALL_CAN_SEE_COACHES.getValue());
-			functionalUtil.idle(browser);
 		}
 
 		if(ArrayUtils.contains(conf, MembersConfiguration.ALL_CAN_SEE_PARTICIPANTS)){
 			functionalUtil.clickCheckbox(browser, null, MembersConfiguration.ALL_CAN_SEE_PARTICIPANTS.getValue());
-			functionalUtil.idle(browser);
 		}
 		
 		if(ArrayUtils.contains(conf, MembersConfiguration.ALL_CAN_DOWNLOAD_LIST_OF_MEMBERS)){
 			functionalUtil.clickCheckbox(browser, null, MembersConfiguration.ALL_CAN_DOWNLOAD_LIST_OF_MEMBERS.getValue());
-			functionalUtil.idle(browser);
 		}
 		
 		return(true);
@@ -701,7 +695,7 @@ public class FunctionalGroupsSiteUtil {
 	 * @param userName
 	 * @return
 	 */
-	public boolean addUser(Selenium browser, String userName){
+	public boolean addUser(Selenium browser, String userName, boolean coach, boolean participant, boolean waitingList){
 		if(!openGroupsTabActionByMenuTree(browser, GroupsTabAction.ADMINISTRATION)){
 			return(false);
 		}
@@ -717,9 +711,9 @@ public class FunctionalGroupsSiteUtil {
 		/* click add User(s) */
 		StringBuffer selectorBuffer = new StringBuffer();
 		
-		selectorBuffer.append("xpath=(//a[contains(@class, '")
-		.append(getAddUserCss())
-		.append("')])[2]");
+		selectorBuffer.append("xpath=//a[contains(@class, '")
+		.append(getAddMemberCss())
+		.append("')]");
 		
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		browser.click(selectorBuffer.toString());
@@ -729,7 +723,7 @@ public class FunctionalGroupsSiteUtil {
 		
 		selectorBuffer.append("xpath=(//fieldset[contains(@class, '")
 		.append(getUsersearchSearchformCss())
-		.append("')]//form//input[@type='text'])[1]");
+		.append("')]//input[@type='text'])[1]");
 		
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		browser.type(selectorBuffer.toString(), userName);
@@ -739,7 +733,7 @@ public class FunctionalGroupsSiteUtil {
 		
 		selectorBuffer.append("xpath=(//fieldset[contains(@class, '")
 		.append(getUsersearchSearchformCss())
-		.append("')]//form//a[contains(@class, '")
+		.append("')]//a[contains(@class, '")
 		.append(functionalUtil.getButtonCss())
 		.append("')])[1]");
 		
@@ -751,32 +745,53 @@ public class FunctionalGroupsSiteUtil {
 		
 		selectorBuffer.append("xpath=(//fieldset[contains(@class, '")
 		.append(getUsersearchSearchformCss())
-		.append("')]//form//tr//td//input[@type='checkbox'])[1]");
+		.append("')]//tr//td//input[@type='checkbox'])[1]");
 		
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		browser.click(selectorBuffer.toString());
 		
-		/* click choose */
-		selectorBuffer = new StringBuffer();
+		/* click next */
+		functionalUtil.clickWizardNext(browser, getGroupImport1WizardCss());
+		functionalUtil.clickWizardNext(browser, getGroupImport1WizardCss());
 		
-		selectorBuffer.append("xpath=(//fieldset[contains(@class, '")
-		.append(getUsersearchSearchformCss())
-		.append("')]//form//input[@type='submit' and contains(@class, '")
-		.append(functionalUtil.getButtonCss())
-		.append("')])[1]");
-
-		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
-		browser.click(selectorBuffer.toString());
+		/* grant rights */
+		StringBuffer templateBuffer = new StringBuffer();
 		
-		/* no mail just next */
-		selectorBuffer = new StringBuffer();
+		templateBuffer.append("xpath=(//div[contains(@class, '")
+		.append(getGroupImport1WizardCss())
+		.append("')]//fieldset//tr//td//input[@type='checkbox'])");
 		
-		selectorBuffer.append("xpath=(//fieldset//form//div[contains(@class, 'b_button_group')]//button[contains(@class, '")
-		.append(functionalUtil.getButtonCss())
-		.append("')])[1]");
+		if(coach){
+			selectorBuffer = new StringBuffer(templateBuffer);
+			
+			selectorBuffer.append("[1]");
+			
+			functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
+			browser.click(selectorBuffer.toString());
+		}
 		
-		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
-		browser.click(selectorBuffer.toString());
+		if(participant){
+			selectorBuffer = new StringBuffer(templateBuffer);
+			
+			selectorBuffer.append("[2]");
+			
+			functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
+			browser.click(selectorBuffer.toString());
+		}
+		
+		if(waitingList){
+			selectorBuffer = new StringBuffer(templateBuffer);
+			
+			selectorBuffer.append("[3]");
+			
+			functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
+			browser.click(selectorBuffer.toString());
+		}
+
+		functionalUtil.clickWizardNext(browser, getGroupImport1WizardCss());
+		
+		/* will send mail by clicking finish */
+		functionalUtil.clickWizardFinish(browser, getGroupImport1WizardCss());
 		
 		return(true);
 	}
@@ -1053,22 +1068,30 @@ public class FunctionalGroupsSiteUtil {
 		this.searchGroupButtonsCss = searchGroupButtonsCss;
 	}
 
-	public String getImportUserCss() {
-		return importUserCss;
+	public String getAddMemberCss() {
+		return addMemberCss;
 	}
 
-	public void setImportUserCss(String importUserCss) {
-		this.importUserCss = importUserCss;
+	public void setAddMemberCss(String addMemberCss) {
+		this.addMemberCss = addMemberCss;
 	}
 
-	public String getAddUserCss() {
-		return addUserCss;
+	public String getImportMembersCss() {
+		return importMembersCss;
 	}
 
-	public void setAddUserCss(String addUserCss) {
-		this.addUserCss = addUserCss;
+	public void setImportMembersCss(String importMembersCss) {
+		this.importMembersCss = importMembersCss;
 	}
 
+	public String getGroupImport1WizardCss() {
+		return groupImport1WizardCss;
+	}
+
+	public void setGroupImport1WizardCss(String groupImport1WizardCss) {
+		this.groupImport1WizardCss = groupImport1WizardCss;
+	}
+	
 	public String getUsersearchAutocompletionCss() {
 		return usersearchAutocompletionCss;
 	}
diff --git a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java
index 669dac4bb537078ae319a8879cfb9dc46bba3923..526c99a60df2f8a6e7e627d627662a980a04fa52 100644
--- a/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java
+++ b/src/test/java/org/olat/util/FunctionalRepositorySiteUtil.java
@@ -1037,7 +1037,9 @@ public class FunctionalRepositorySiteUtil {
 		.append(getRepositoryPopupCss())
 		.append("')]//form//div[contains(@class, '")
 		.append(getRepositorySaveDetailsCss())
-		.append("')]//button)[1]");
+		.append("')]//button[contains(@class, '")
+		.append(functionalUtil.getButtonDirtyCss())
+		.append("')])[1]");
 		
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		
@@ -1055,7 +1057,7 @@ public class FunctionalRepositorySiteUtil {
 		functionalUtil.waitForPageToLoadElement(browser, selectorBuffer.toString());
 		
 		browser.click(selectorBuffer.toString());
-		
+
 		functionalUtil.waitForPageToUnloadElement(browser, selectorBuffer.toString());
 		
 		return(true);
diff --git a/src/test/java/org/olat/util/FunctionalUtil.java b/src/test/java/org/olat/util/FunctionalUtil.java
index 6ea164c30b66aa102a6e9a7c123046986717f9c9..680fc26cd1d395021dd9d43acf6c82f12962b884 100644
--- a/src/test/java/org/olat/util/FunctionalUtil.java
+++ b/src/test/java/org/olat/util/FunctionalUtil.java
@@ -46,17 +46,15 @@ public class FunctionalUtil {
 	
 	public final static String LOGIN_PAGE = "dmz";
 	public final static String ACKNOWLEDGE_CHECKBOX = "acknowledge_checkbox";
-	
-	public final static String INFO_DIALOG = "o_interceptionPopup";
 
 	public final static long TIMEOUT = 60000;
 	public final static long POLL_INTERVAL = 100;
 	
 	public enum WaitLimitAttribute {
-		NORMAL("0"),
-		EXTENDED("5000"),
-		SAVE("10000"),
-		VERY_SAVE("20000");
+		NORMAL("10000"),
+		EXTENDED("20000"),
+		SAVE("30000"),
+		VERY_SAVE("60000");
 		
 		private String extend;
 		private long extendAsLong;
@@ -146,7 +144,8 @@ public class FunctionalUtil {
 	public final static String WINDOW_CLOSE_LINK_CSS = "b_link_close";
 	
 	public final static String FORM_SAVE_XPATH = "//button[@type='button' and last()]";
-	
+
+	public final static String INFO_CSS = "b_info";
 	public final static String INFO_MESSAGE_BOX_CSS = "o_sel_info_message";
 	
 	private String username;
@@ -158,8 +157,6 @@ public class FunctionalUtil {
 	private String loginPage;
 	private String acknowledgeCheckbox;
 	
-	private String infoDialog;
-	
 	private String olatTopNavigationLogoutCss;
 	
 	private String olatNavigationSiteCss;
@@ -191,6 +188,8 @@ public class FunctionalUtil {
 	
 	private String windowCloseLinkCss;
 	
+	private String infoCss;
+	
 	private String buttonCss;
 	private String buttonDirtyCss;
 	private String backButtonCss;
@@ -240,8 +239,6 @@ public class FunctionalUtil {
 		loginPage = LOGIN_PAGE;
 		acknowledgeCheckbox = ACKNOWLEDGE_CHECKBOX;
 		
-		infoDialog = INFO_DIALOG;
-		
 		olatTopNavigationLogoutCss = OLAT_TOP_NAVIGATION_LOGOUT_CSS;
 		
 		olatNavigationSiteCss = OLAT_NAVIGATION_SITE_CSS;
@@ -273,6 +270,8 @@ public class FunctionalUtil {
 		
 		windowCloseLinkCss = WINDOW_CLOSE_LINK_CSS;
 		
+		infoCss = INFO_CSS;
+		
 		buttonCss = BUTTON_CSS;
 		buttonDirtyCss = BUTTON_DIRTY_CSS;
 		backButtonCss = BACK_BUTTON_CSS;
@@ -767,7 +766,7 @@ public class FunctionalUtil {
 		break;
 		case ADMINISTRATION:
 		{
-			retval = functionalAdministrationSiteUtil.openActionByMenuTree(browser, AdministrationSiteAction.INFORMATION);
+			retval = functionalAdministrationSiteUtil.openActionByMenuTree(browser, AdministrationSiteAction.SYSTEM);
 		}
 		break;
 		}
@@ -879,8 +878,8 @@ public class FunctionalUtil {
 	    	//TODO:JK: find a way to solve endless loop
 	    	//while(browser.isElementPresent("class="+ getInfoDialog())){
 	    		/* click last button */
-	    	if(browser.isElementPresent("id="+ getInfoDialog())){
-	    		browser.click("xpath=//form//div//button[@type='button']/../../span/a[@class='b_button']");
+	    	if(browser.isElementPresent("//div[contains(@class, '"+ getInfoCss() + "')]")){
+	    		browser.click("xpath=//form//div//button[@type='button']/../../span/a[contains(@class, '" + getButtonCss() + "')]");
 	    		waitForPageToLoad(browser);
 	    	}
 	    	//}
@@ -1438,14 +1437,6 @@ public class FunctionalUtil {
 		this.acknowledgeCheckbox = acknowledgeCheckbox;
 	}
 
-	public String getInfoDialog() {
-		return infoDialog;
-	}
-
-	public void setInfoDialog(String infoDialog) {
-		this.infoDialog = infoDialog;
-	}
-
 	public String getOlatTopNavigationLogoutCss() {
 		return olatTopNavigationLogoutCss;
 	}
@@ -1671,6 +1662,14 @@ public class FunctionalUtil {
 		this.windowCloseLinkCss = windowCloseLinkCss;
 	}
 
+	public String getInfoCss() {
+		return infoCss;
+	}
+
+	public void setInfoCss(String infoCss) {
+		this.infoCss = infoCss;
+	}
+
 	public String getButtonCss() {
 		return buttonCss;
 	}