diff --git a/src/main/java/org/olat/basesecurity/AuthHelper.java b/src/main/java/org/olat/basesecurity/AuthHelper.java
index 3aaa608f680c6dc6c7ed9ddfde0467132c4cc152..5c3d65f67efed8dfedd757cfd21f65ec21789b92 100644
--- a/src/main/java/org/olat/basesecurity/AuthHelper.java
+++ b/src/main/java/org/olat/basesecurity/AuthHelper.java
@@ -30,6 +30,7 @@ import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -37,7 +38,6 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpSession;
 
 import org.olat.basesecurity.manager.GroupDAO;
-import org.olat.commons.rss.RSSUtil;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappController;
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
@@ -66,6 +66,8 @@ import org.olat.core.util.WebappHelper;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.session.UserSessionManager;
+import org.olat.course.assessment.AssessmentMode;
+import org.olat.course.assessment.AssessmentModeManager;
 import org.olat.login.AuthBFWCParts;
 import org.olat.login.GuestBFWCParts;
 import org.olat.portfolio.manager.InvitationDAO;
@@ -304,15 +306,17 @@ public class AuthHelper {
 			return LOGIN_NOTAVAILABLE;
 		}
 		
-		// set authprovider
-		//usess.getIdentityEnvironment().setAuthProvider(authProvider);
+		//need to block the all things for assessment?
+		AssessmentModeManager assessmentManager = CoreSpringFactory.getImpl(AssessmentModeManager.class);
+		List<AssessmentMode> modes = assessmentManager.getAssessmentModeFor(identity);
+		if(!modes.isEmpty()) {
+			usess.setAssessmentModes(modes);
+		}
 		
 		//set the language
 		usess.setLocale( I18nManager.getInstance().getLocaleOrDefault(identity.getUser().getPreferences().getLanguage()) );
 		// update fontsize in users session globalsettings
 		Windows.getWindows(ureq).getWindowManager().setFontSize(Integer.parseInt(identity.getUser().getPreferences().getFontsize() ));		
-		// put users personal rss token into session
-		RSSUtil.putPersonalRssTokenInSession(ureq);
 		// calculate session info and attach it to the user session
 		setSessionInfoFor(identity, authProvider, ureq, rest);
 		//confirm signedOn
diff --git a/src/main/java/org/olat/commons/rss/RSSUtil.java b/src/main/java/org/olat/commons/rss/RSSUtil.java
index e8d7b7191c21c52467b929e5f653a65d8a074dea..a12adc91839bd9423447d9c478a25155ea4acf86 100644
--- a/src/main/java/org/olat/commons/rss/RSSUtil.java
+++ b/src/main/java/org/olat/commons/rss/RSSUtil.java
@@ -50,62 +50,37 @@ public class RSSUtil {
 	public static final String RSS_AUTH_TOKEN_KEY = "rsstoken";
 	/** path prefix for personal rss feed **/
 	public static final String RSS_PREFIX_PERSONAL = "/personal/";
-	/** path prefix for public rss feed **/
-	public static final String RSS_PREFIX_PUBLIC = "/public/";
 	
 	/** OLAT server URI **/
-  public static final String URI_SERVER;
-  /** Personal rss channel URI prefix **/
-  public static final String URI_PERSONAL_CHANNEL;
-  /** Public rss channel URI prefix **/
-  public static final String URI_PUBLIC_CHANNEL;
-  static {
+	public static final String URI_SERVER;
+	/** Personal rss channel URI prefix **/
+	public static final String URI_PERSONAL_CHANNEL;
+	
+	static {
 		URI_SERVER = Settings.getServerContextPathURI() + "/";
 		URI_PERSONAL_CHANNEL = URI_SERVER + "rss" + RSS_PREFIX_PERSONAL;
-		URI_PUBLIC_CHANNEL = URI_SERVER + "rss" + RSS_PREFIX_PUBLIC;
-  }
-
+	}
 
 	/**
-	 * Puts the users rss token into the httpsession. If no token is available one is
-	 * generated and peristed in the database
+	 * Calculates the absolute URL to the users personal rss feed
 	 * @param ureq
-	 * @return String the token
+	 * @return String
 	 */
-	public static String putPersonalRssTokenInSession(UserRequest ureq) {
-		Identity identity = ureq.getIdentity();
+	public static String getPersonalRssLink(UserRequest ureq) {
 		String token = null;
+		Identity identity = ureq.getIdentity();
 		BaseSecurity secManager = BaseSecurityManager.getInstance();
-		Authentication auth = secManager.findAuthentication(identity, RSSUtil.RSS_AUTH_PROVIDER);
+		Authentication auth = secManager.findAuthentication(identity, RSS_AUTH_PROVIDER);
 		if (auth == null) {
 			// no token found - create one
 			 token = RandomStringUtils.randomAlphanumeric(6);
-			 auth = secManager.createAndPersistAuthentication(identity, RSSUtil.RSS_AUTH_PROVIDER, identity.getName(), token, null);
+			 auth = secManager.createAndPersistAuthentication(identity, RSS_AUTH_PROVIDER, identity.getName(), token, null);
 		} else {
 			token = auth.getCredential();
 		}
-		ureq.getUserSession().putEntry(RSSUtil.RSS_AUTH_TOKEN_KEY, token);
-		return token;
-	}
-
-	/**
-	 * Calculates the absolute URL to the users personal rss feed
-	 * @param ureq
-	 * @return String
-	 */
-	public static String getPersonalRssLink(UserRequest ureq) {
-		String token = (String) ureq.getUserSession().getEntry(RSSUtil.RSS_AUTH_TOKEN_KEY);
-		return(getPersonalRssLink(ureq.getIdentity(), token));
-	}
-
-	/**
-	 * Calculates the absolute URL to the users personal rss feed
-	 * @param identity
-	 * @param token
-	 * @return String
-	 */
-	public static String getPersonalRssLink(Identity identity, String token) {
-		String link = RSSUtil.URI_PERSONAL_CHANNEL + identity.getName() + "/" + token + "/" + "olat.rss";
-		return link;
+		
+		StringBuilder sb = new StringBuilder();
+		return sb.append(RSSUtil.URI_PERSONAL_CHANNEL).append(ureq.getIdentity().getName())
+				.append("/").append(token).append("/olat.rss").toString();
 	}
 }
diff --git a/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java b/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java
index d737e3fe514b6a8c438175572b637c4820764dca..2552a1c6c8b5ba6e14eeaf0efbfc09cc4c5ecd25 100644
--- a/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java
+++ b/src/main/java/org/olat/core/commons/contextHelp/ContextHelpLayoutControllerCreator.java
@@ -28,6 +28,7 @@ import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayout;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
@@ -55,29 +56,35 @@ class ContextHelpLayoutControllerCreator implements BaseFullWebappPopupLayout {
 	/**
 	 * @see org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayout#getFullWebappParts()
 	 */
+	@Override
 	public BaseFullWebappControllerParts getFullWebappParts() {
-		return new BaseFullWebappControllerParts() {
 		
+		return new BaseFullWebappControllerParts() {
+
+			@Override
 			public List<SiteInstance> getSiteInstances(UserRequest ureq, WindowControl control) {
 				// no static sites
 				return null;
 			}
-		
+
+			@Override
 			public Controller getContentController(UserRequest ureq, WindowControl wControl) {
 				// the content for the Pop-up Window
 				return contentControllerCreator.createController(ureq, wControl);
 			}
-		
-			public Controller createTopNavController(UserRequest ureq, WindowControl wControl) {
-				Controller topnavCtr = null;
+
+			@Override
+			public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) {
+				TopNavController topnavCtr = null;
 				// ----------- topnav, optional (e.g. for imprint, logout) ------------------		
 				if (CoreSpringFactory.containsBean("fullWebApp.ContextHelpTopNavControllerCreator")) {
 					ControllerCreator topnavControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.ContextHelpTopNavControllerCreator");
-					topnavCtr = topnavControllerCreator.createController(ureq, wControl);
+					topnavCtr = (TopNavController)topnavControllerCreator.createController(ureq, wControl);
 				}
 				return topnavCtr;
 			}
-		
+
+			@Override
 			public Controller createHeaderController(UserRequest ureq, WindowControl control) {
 				Controller headerCtr = null;
 				// ----------- header, optional (e.g. for logo, advertising ) ------------------		
@@ -87,7 +94,8 @@ class ContextHelpLayoutControllerCreator implements BaseFullWebappPopupLayout {
 				}
 				return headerCtr;
 			}
-		
+
+			@Override
 			public Controller createFooterController(UserRequest ureq, WindowControl control) {
 				Controller footerCtr = null;
 				// ----------- footer, optional (e.g. for copyright, powerd by) ------------------
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
index 4618c9316401fbb4546bdb7cb82f31593bf3ea38..e873996591192596753d993963cc1e94d09631ee 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java
@@ -26,6 +26,7 @@
 package org.olat.core.commons.fullWebApp;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -69,7 +70,6 @@ import org.olat.core.gui.control.VetoableCloseController;
 import org.olat.core.gui.control.WindowBackOffice;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
-import org.olat.core.gui.control.creator.ControllerCreator;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
 import org.olat.core.gui.control.generic.dtabs.DTab;
 import org.olat.core.gui.control.generic.dtabs.DTabImpl;
@@ -81,6 +81,7 @@ import org.olat.core.gui.control.navigation.SiteInstance;
 import org.olat.core.gui.control.util.ZIndexWrapper;
 import org.olat.core.gui.control.winmgr.JSCommand;
 import org.olat.core.gui.themes.Theme;
+import org.olat.core.gui.util.SyntheticUserRequest;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.BusinessControlFactory;
@@ -95,13 +96,20 @@ import org.olat.core.logging.JavaScriptTracingController;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.event.GenericEventListener;
 import org.olat.core.util.i18n.I18nManager;
 import org.olat.core.util.i18n.I18nModule;
 import org.olat.core.util.prefs.Preferences;
 import org.olat.core.util.resource.OresHelper;
+import org.olat.course.assessment.AssessmentMode;
+import org.olat.course.assessment.AssessmentModeManager;
+import org.olat.course.assessment.AssessmentModeNotificationEvent;
+import org.olat.course.assessment.model.TransientAssessmentMode;
+import org.olat.course.assessment.ui.AssessmentModeUserConfirmationController;
 import org.olat.gui.control.UserToolsMenuController;
 import org.olat.home.HomeSite;
+import org.olat.login.AfterLoginInterceptionController;
 
 /**
  * Description:<br>
@@ -136,8 +144,10 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 	private Panel cssHolder, guimsgHolder, currentMsgHolder;
 	private VelocityContainer guimsgVc, stickymsgVc, mainVc, navSitesVc, navTabsVc;
 
+	private OLATResourceable lockedResource;
 	// NEW FROM FullChiefController
-	private Controller topnavCtr, footerCtr;
+	private TopNavController topnavCtr;
+	private Controller footerCtr;
 	private UserToolsMenuController userToolsMenuCtrl;
 	private SiteInstance curSite;
 	private DTab curDTab;
@@ -152,17 +162,16 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 	// used as link id which is load url safe (e.g. replayable
 	private int dtabCreateCounter = 0;
 	// the sites list
-	
 	private SiteInstance userTools;
 	private List<SiteInstance> sites;
 	private Map<SiteInstance, BornSiteInstance> siteToBornSite = new HashMap<SiteInstance, BornSiteInstance>();
-	//fxdiff BAKS-7 Resume function
 	private Map<SiteInstance,HistoryPoint> siteToBusinessPath = new HashMap<SiteInstance,HistoryPoint>();
 
-	//
 	private BaseFullWebappControllerParts baseFullWebappControllerParts;
 	protected Controller contentCtrl;
-	private Controller aftLHookCtr;
+	private AfterLoginInterceptionController aftLHookCtr;
+	private AssessmentModeUserConfirmationController modeCtrl;
+	
 	private StackedPanel initialPanel;
 	private DTabs myDTabsImpl;
 	private static Integer MAX_TAB;
@@ -186,12 +195,6 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		// define the new windowcontrol
 		WindowControl myWControl = new BaseFullWebappWindowControl(this, wbo);
 		overrideWindowControl(myWControl);
-
-		/*
-		 * BaseFullWebappController provides access to Dynamic Tabs
-		 * on the same window and not on all Windows! 
-		 * TODO:pb discuss with HJZ multi window concept.
-		 */
 		
 		// detach DTabs implementation from the controller - DTabs may be fetched from the window and locked on (synchronized access).
 		// if this is controller the controller is locked instead of only the DTabs part.
@@ -216,19 +219,23 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		// ------ all the frame preparation is finished ----
 		initializeBase(ureq, winman, initialPanel);
 		
-
-        // present an overlay with configured afterlogin-controllers or nothing if none configured.
-        // presented only once per session.
-    	Boolean alreadySeen = ((Boolean)ureq.getUserSession().getEntry(PRESENTED_AFTER_LOGIN_WORKFLOW));
-    	if (ureq.getUserSession().isAuthenticated() && alreadySeen == null) {
-    		aftLHookCtr = ((ControllerCreator) CoreSpringFactory.getBean("fullWebApp.AfterLoginInterceptionControllerCreator"))
-    				.createController(ureq, getWindowControl());
-    		listenTo(aftLHookCtr);
-    		aftLHookCtr.getInitialComponent();
-    		ureq.getUserSession().putEntry(PRESENTED_AFTER_LOGIN_WORKFLOW, Boolean.TRUE);
+		if(ureq.getUserSession().isAuthenticated() && ureq.getUserSession().getAssessmentModes() != null && ureq.getUserSession().getAssessmentModes().size() > 0) {
+    		modeCtrl = new AssessmentModeUserConfirmationController(ureq, getWindowControl());
+    		listenTo(modeCtrl);
+    		modeCtrl.getInitialComponent();
+    	} else {
+    		// present an overlay with configured afterlogin-controllers or nothing if none configured.
+    		// presented only once per session.
+    		Boolean alreadySeen = ((Boolean)ureq.getUserSession().getEntry(PRESENTED_AFTER_LOGIN_WORKFLOW));
+    		if (ureq.getUserSession().isAuthenticated() && alreadySeen == null) {
+    			aftLHookCtr = new AfterLoginInterceptionController(ureq, getWindowControl());
+    			listenTo(aftLHookCtr);
+    			aftLHookCtr.getInitialComponent();
+    			ureq.getUserSession().putEntry(PRESENTED_AFTER_LOGIN_WORKFLOW, Boolean.TRUE);
+	    	}
     	}
 		
-    	if(aftLHookCtr == null || aftLHookCtr.isDisposed()) {
+    	if(modeCtrl == null && (aftLHookCtr == null || aftLHookCtr.isDisposed())) {
     		initializeDefaultSite(ureq);
     	}
 		
@@ -244,6 +251,9 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		//move to a i18nModule? languageManger? languageChooserController?
 		OLATResourceable wrappedLocale = OresHelper.createOLATResourceableType(Locale.class);
 		ureq.getUserSession().getSingleUserEventCenter().registerFor(this, getIdentity(), wrappedLocale);
+		//register for assessment mode
+		CoordinatorManager.getInstance().getCoordinator().getEventBus()
+			.registerFor(this, getIdentity(), AssessmentModeNotificationEvent.ASSESSMENT_MODE_NOTIFICATION);
 		// register for global sticky message changed events
 		GlobalStickyMessage.registerForGlobalStickyMessage(this, ureq.getIdentity());	
 	}
@@ -475,7 +485,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 	private void initializeDefaultSite(UserRequest ureq) {
 		if (sites != null && sites.size() > 0
 				&& curSite == null && curDTab == null
-				&& contentCtrl == null) {
+				&& contentCtrl == null && lockedResource == null) {
 			SiteInstance s = sites.get(0);
 			//activate site only if no content was set -> allow content before activation of default site.
 			activateSite(s, ureq, null, false);
@@ -636,6 +646,8 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if(aftLHookCtr == source) {
 			initializeDefaultSite(ureq);
+		} else if(modeCtrl == source) {
+			initializeDefaultSite(ureq);
 		} else {
 			int tabIndex = dtabsControllers.indexOf(source);
 			if (tabIndex > -1) {
@@ -710,9 +722,18 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		modalPanel.setContent(modalStackP);
 	}
 
-	// FROM FULLCHIEFCONTROLLER
+	/**
+	 * Activate a site if not locked
+	 * 
+	 * @param s
+	 * @param ureq
+	 * @param entries
+	 * @param forceReload
+	 */
 	private void activateSite(SiteInstance s, UserRequest ureq,
 			List<ContextEntry> entries, boolean forceReload) {
+		if(lockedResource != null) return;
+		
 		BornSiteInstance bs = siteToBornSite.get(s);
 		GuiStack gs;
 		Controller resC;
@@ -894,8 +915,6 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 				// closing one dtab in _browser tab one_ and then closing the same dtab
 				// once again in the _browser tab two_ leads to the case where dtabIndex
 				// is -1, e.g. not found causing the redscreen described in the issue.
-				// TODO:2008-07-25: pb: define concept of "multi windowing" "main windowing"
-				// and reconsider this place.
 				//
 				// NOTHING TO REMOVE, return
 				return;
@@ -918,7 +937,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 			navTabsVc.remove(navTabsVc.getComponent("a" + delt.hashCode()));
 			navTabsVc.remove(navTabsVc.getComponent("ca" + delt.hashCode()));
 			navTabsVc.remove(navTabsVc.getComponent("cp" + delt.hashCode()));
-			if (delt == curDTab) { // if we close the current tab -> return to the previous
+			if (delt == curDTab && ureq != null) { // if we close the current tab -> return to the previous
 				popTheTabState(ureq);
 			} // else just remove the dtabs
 			delt.dispose();//dispose tab and controllers in tab
@@ -964,9 +983,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 	 * @param dt
 	 */
 	private void requestCloseTab(UserRequest ureq, DTab delt) {
-
-		Controller c = delt.getController(); // FIXME:fj: test
-		// vetoableclosecontroller
+		Controller c = delt.getController();
 		if (c instanceof VetoableCloseController) {
 			VetoableCloseController vcc = (VetoableCloseController) c;
 			// rembember current dtab, and swap to the temporary one
@@ -1009,11 +1026,17 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 	 *      java.lang.String)
 	 */
 	public DTab createDTab(OLATResourceable ores, OLATResourceable repoOres, String title) {
+		final DTabImpl dt;
 		if (dtabs.size() >= getMaxTabs()) {
 			getWindowControl().setError(translate("warn.tabsfull"));
-			return null;
+			dt = null;
+		} else if(lockedResource != null && (
+				!lockedResource.getResourceableId().equals(ores.getResourceableId()) 
+				|| !lockedResource.getResourceableTypeName().equals(ores.getResourceableTypeName()))) {
+			dt = null;
+		} else {
+			dt = new DTabImpl(ores, repoOres, title, getWindowControl());
 		}
-		DTabImpl dt = new DTabImpl(ores, repoOres, title, getWindowControl());
 		return dt;
 	}
 
@@ -1110,17 +1133,9 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		// in all other cases the "focus of interest" (where the calculation of the
 		// guipath is started) matches the controller which listens to the
 		// event caused by a user interaction.
-		// WindowBackOffice wboNew = getWindowControl().getWindowBackOffice(); //
 		// this is the starting point.
-		// getWindowControl().getWindowBackOffice().adjustGuiPathCenter(getWindowControl().getWindowControlInfo());
 	}
 
-	/**
-	 * FIXME:fj: change className to class
-	 * 
-	 * @see org.olat.core.gui.control.generic.dtabs.DTabs#activateStatic(org.olat.core.gui.UserRequest,
-	 *      java.lang.String, java.lang.String)
-	 */
 	public void activateStatic(UserRequest ureq, String className, List<ContextEntry> entries) {
 		if(className != null && className.endsWith("HomeSite")) {
 			activateSite(userTools, ureq, entries, false);
@@ -1136,6 +1151,7 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		}
 	}
 
+	@Override
 	public void event(Event event) {
 		if (event == Window.AFTER_VALIDATING) {
 			// now update the guimessage
@@ -1179,9 +1195,18 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		} else if (event instanceof ChiefControllerMessageEvent) {
 			// msg can be set to show only on one node or on all nodes
 			updateStickyMessage();
+		} else if (AssessmentModeNotificationEvent.command.equals(event.getCommand())
+				&& event instanceof AssessmentModeNotificationEvent) {
+			if(lockedResource == null) {
+				AssessmentModeNotificationEvent amne = (AssessmentModeNotificationEvent)event;
+				if(amne.getAssessedIdentityKeys().contains(getIdentity().getKey())) {
+					asyncLockResource(amne.getAssessementMode());
+				}
+			}
 		}
 	}
 
+	@Override
 	public boolean hasStaticSite(Class<? extends SiteInstance> type) {
 		boolean hasSite = false;
 		if(sites != null && sites.size() > 0) {
@@ -1194,6 +1219,35 @@ public class BaseFullWebappController extends BasicController implements ChiefCo
 		return hasSite;
 	}
 
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		this.lockedResource = resource;
+		if(topnavCtr != null) {
+			topnavCtr.lockResource(resource);
+		}
+		if(userToolsMenuCtrl != null) {
+			userToolsMenuCtrl.lockResource(resource);
+		}
+		
+		navSitesVc.setVisible(false);
+		for(int i=dtabsControllers.size(); i-->0; ) {
+			DTab tab = dtabs.get(i);
+			removeDTab(null, tab);
+		}
+	}
+	
+	private void asyncLockResource(TransientAssessmentMode mode) {
+		logAudit("Async lock resource for user: " + getIdentity().getName() + " (" + mode.getResource() + ")", null);
+		lockResource(mode.getResource());
+		
+		AssessmentModeManager assessmentModeManager = CoreSpringFactory.getImpl(AssessmentModeManager.class);
+
+		UserRequest ureq = new SyntheticUserRequest(getIdentity(), getLocale());
+		modeCtrl = new AssessmentModeUserConfirmationController(ureq, getWindowControl(), Collections.singletonList(mode));
+		listenTo(modeCtrl);
+		modeCtrl.getInitialComponent();
+	}
+
 	/**
 	 * [used by velocity] helper for velocity
 	 * 
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java
index 190ddbbf58fb5fff97637b7539b9d725de297787..163f501b566d51f0fd9448a66c06fd8aa2c38444 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappControllerParts.java
@@ -69,7 +69,7 @@ public interface BaseFullWebappControllerParts {
 	 * @param wControl
 	 * @return
 	 */
-	public Controller createTopNavController(UserRequest ureq, WindowControl wControl);
+	public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl);
 	
 	/**
 	 * footer controller (user count, logged in user, logo, verson info, etc)
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java
index 1c0dce780b3d677d2dc1632729281fa53a4b5433..e90c94855f8c3bc2a227f8f906b4a546645eb65a 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappDTabs.java
@@ -51,22 +51,22 @@ class BaseFullWebappDTabs implements DTabs {
 		webappCtrl.activateStatic(ureq, className, entries);
 	}
 
+	@Override
 	public boolean addDTab(UserRequest ureq, DTab dt) {
 		return webappCtrl.addDTab(ureq, dt);
 	}
-	
-	public DTab createDTab(OLATResourceable ores, String title) {
-		return webappCtrl.createDTab(ores, null, title);
-	}
-	
+
+	@Override
 	public DTab createDTab(OLATResourceable ores, OLATResourceable initialOres, String title) {
 		return webappCtrl.createDTab(ores, initialOres, title);
 	}
 
+	@Override
 	public DTab getDTab(OLATResourceable ores) {
 		return webappCtrl.getDTab(ores);
 	}
 
+	@Override
 	public void removeDTab(UserRequest ureq, DTab dt) {
 		webappCtrl.removeDTab(ureq, dt);
 	}
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/TopNavController.java b/src/main/java/org/olat/core/commons/fullWebApp/TopNavController.java
new file mode 100644
index 0000000000000000000000000000000000000000..98b367baba4f6df0d0b06b37465a17166c2f6e00
--- /dev/null
+++ b/src/main/java/org/olat/core/commons/fullWebApp/TopNavController.java
@@ -0,0 +1,35 @@
+/**
+ * <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.fullWebApp;
+
+import org.olat.core.gui.control.Controller;
+import org.olat.core.id.OLATResourceable;
+
+/**
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public interface TopNavController extends Controller {
+	
+	public void lockResource(OLATResourceable resource);
+
+}
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java
index a78493b8d8b50fdf5a6cdbf55dfd1e01b8fda0c3..174ad0d5a1f63384c2d63384c008b29aee126afd 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappMinimalLayoutControllerCreator.java
@@ -28,6 +28,7 @@ import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
@@ -69,12 +70,12 @@ class BaseFullWebappMinimalLayoutControllerCreator implements BaseFullWebappPopu
 				return contentControllerCreator.createController(ureq, wControl);
 			}
 		
-			public Controller createTopNavController(UserRequest ureq, WindowControl wControl) {
-				Controller topnavCtr = null;
+			public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) {
+				TopNavController topnavCtr = null;
 				// ----------- topnav, optional (e.g. for imprint, logout) ------------------		
 				if (CoreSpringFactory.containsBean("fullWebApp.MinimalTopNavControllerCreator")) {
 					ControllerCreator topnavControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.MinimalTopNavControllerCreator");
-					topnavCtr = topnavControllerCreator.createController(ureq, wControl);
+					topnavCtr = (TopNavController)topnavControllerCreator.createController(ureq, wControl);
 				}
 				return topnavCtr;
 			}
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java
index 5ebef78f3f88e7d2a7fe80f4dfe5235fbed20d4f..bf2a85ebdcbf53747622aae4634f01b39f928199 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java
+++ b/src/main/java/org/olat/core/commons/fullWebApp/popup/BaseFullWebappPrintLayoutControllerCreator.java
@@ -22,6 +22,7 @@ package org.olat.core.commons.fullWebApp.popup;
 import java.util.List;
 
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
@@ -58,7 +59,7 @@ class BaseFullWebappPrintLayoutControllerCreator implements BaseFullWebappPopupL
 			}
 
 			@Override
-			public Controller createTopNavController(UserRequest ureq, WindowControl wControl) {
+			public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) {
 				return null;
 			}
 
diff --git a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml
index a32dc8bb97b701bc4079104f08804a1a843f4f96..e586b67bde018096fd40e9b10ccf38aa7604ce6f 100644
--- a/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml
+++ b/src/main/java/org/olat/core/commons/services/scheduler/_spring/schedulerContext.xml
@@ -45,6 +45,7 @@ How to add a new job:
             <ref bean="updateQtiResultsTriggerOnyx"/>
             <ref bean="acReservationCleanupJob"/>
             <ref bean="mapperSlayerTrigger"/>
+            <ref bean="assessmentNotificationsTrigger"/>
         </list>
     </property>
 </bean>
diff --git a/src/main/java/org/olat/core/gui/control/ChiefController.java b/src/main/java/org/olat/core/gui/control/ChiefController.java
index aba2002dad324df30ce33c6ddbf10ec212b1a211..e67580fcd0db3178346014f53316710046030dc6 100644
--- a/src/main/java/org/olat/core/gui/control/ChiefController.java
+++ b/src/main/java/org/olat/core/gui/control/ChiefController.java
@@ -27,8 +27,9 @@
 package org.olat.core.gui.control;
 
 import org.olat.core.gui.components.Window;
-import org.olat.core.gui.control.navigation.SiteInstance;
 import org.olat.core.gui.components.htmlheader.jscss.CustomCSS;
+import org.olat.core.gui.control.navigation.SiteInstance;
+import org.olat.core.id.OLATResourceable;
 /**
  * Description: <br>
  * 
@@ -49,6 +50,8 @@ public interface ChiefController extends Controller {
 	
 	public boolean wishReload(boolean erase);
 	
+	public void lockResource(OLATResourceable resource);
+	
 	/**
 	 * Set a class to the &lt;body&gt;
 	 * @param cssClass
diff --git a/src/main/java/org/olat/core/gui/control/DefaultChiefController.java b/src/main/java/org/olat/core/gui/control/DefaultChiefController.java
index d00a61080c18821bdc7ecd4624134942c4f56ff2..88d3ed77da10a2a6350a0ea23b9e07dba50b8256 100644
--- a/src/main/java/org/olat/core/gui/control/DefaultChiefController.java
+++ b/src/main/java/org/olat/core/gui/control/DefaultChiefController.java
@@ -29,6 +29,7 @@ package org.olat.core.gui.control;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.Window;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.logging.AssertException;
 
 /**
@@ -72,6 +73,11 @@ public abstract class DefaultChiefController extends DefaultController implement
 	public ScreenMode getScreenMode() {
 		return screenMode;
 	}
+	
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		//
+	}
 
 	/**
 	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
diff --git a/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml b/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml
index 222dbf25579b8c69e772cfc31f5ee998750d2463..5b76b421fead582d2b70a8282bd6b095c3041c4f 100644
--- a/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml
+++ b/src/main/java/org/olat/core/gui/control/_spring/fullWebAppContext.xml
@@ -5,16 +5,6 @@
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd">
 
-	<!--
-		**************************************************************************
-		*** Configure the controller-workflow which should be presented		   ***
-		*** right after a user logged in.                                      ***
-		*** See comment in AfterLoginInterceptorController                     ***
-		**************************************************************************
-	-->
-	<bean id="fullWebApp.AfterLoginInterceptionControllerCreator" class="org.olat.core.gui.control.creator.AutoCreator" >
-		<property name="className" value="org.olat.login.AfterLoginInterceptionController"/>
-	</bean>
 	
 	<!-- the specifed creator is responsible for the frameworks popup browser window layout.
 	     Special layouts must be implemented by wrapping the content into a content-layouting controller -->
diff --git a/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java b/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java
index e563067b8f9bca4dea97b682aec072333fb595dc..4658cbc2537ca9395a14663744a64f5217842e79 100644
--- a/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java
+++ b/src/main/java/org/olat/core/gui/control/generic/dtabs/DTabs.java
@@ -46,13 +46,6 @@ public interface DTabs {
 	 */
 	public DTab getDTab(OLATResourceable ores);
 
-	/**
-	 * @param ores
-	 * @param title
-	 * @return the tab or null if the headerbar is full. if null, the implementation of the DTabs should issue a warning to the current windowcontrol
-	 */
-	public DTab createDTab(OLATResourceable ores, String title);
-
 	/**
 	 * @param ores
 	 * @param repoOres
diff --git a/src/main/java/org/olat/core/util/UserSession.java b/src/main/java/org/olat/core/util/UserSession.java
index 2d461eb366240febee13fd35f536ae93d35c2c5b..d3e9238679fc0557d68cb2f2ef5cee26e900237d 100644
--- a/src/main/java/org/olat/core/util/UserSession.java
+++ b/src/main/java/org/olat/core/util/UserSession.java
@@ -60,6 +60,7 @@ import org.olat.core.util.prefs.Preferences;
 import org.olat.core.util.prefs.PreferencesFactory;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.session.UserSessionManager;
+import org.olat.course.assessment.AssessmentMode;
 
 /**
  * Description: <BR/>the httpsession contains an instance of this class. the
@@ -76,6 +77,7 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList
 	// the environment (identity, locale, ..) of the identity
 	private IdentityEnvironment identityEnvironment;
 	private SessionInfo sessionInfo;
+	private List<AssessmentMode> assessmentModes;
 	private transient Map<String,Object> store;
 	/**
 	 * things to put into that should not be clear when signing on (e.g. remember url for a direct jump)
@@ -286,6 +288,14 @@ public class UserSession implements HttpSessionBindingListener, GenericEventList
 		return identityEnvironment;
 	}
 
+	public List<AssessmentMode> getAssessmentModes() {
+		return assessmentModes;
+	}
+
+	public void setAssessmentModes(List<AssessmentMode> assessmentModes) {
+		this.assessmentModes = assessmentModes;
+	}
+
 	/**
 	 * may be null
 	 * <p>
diff --git a/src/main/java/org/olat/course/assessment/AssessmentMode.java b/src/main/java/org/olat/course/assessment/AssessmentMode.java
index cfd906bcaeec9bf2a3fa802da63a816d68786e7c..fcf5d32f6fc8fc2ec69942aeba619a41f9064d2a 100644
--- a/src/main/java/org/olat/course/assessment/AssessmentMode.java
+++ b/src/main/java/org/olat/course/assessment/AssessmentMode.java
@@ -24,6 +24,7 @@ import java.util.Set;
 
 import org.olat.core.id.CreateInfo;
 import org.olat.core.id.ModifiedInfo;
+import org.olat.repository.RepositoryEntry;
 
 /**
  * 
@@ -42,6 +43,8 @@ public interface AssessmentMode extends ModifiedInfo, CreateInfo {
 	public String getDescription();
 
 	public void setDescription(String description);
+	
+	public RepositoryEntry getRepositoryEntry();
 
 	public Date getBegin();
 
diff --git a/src/main/java/org/olat/course/assessment/AssessmentModeManager.java b/src/main/java/org/olat/course/assessment/AssessmentModeManager.java
index ff64a3e1c3868dec1f1f2647e62ed0df7bfb03ae..0b295149b8eb25934e0aa0853676dd79f5b9fbc0 100644
--- a/src/main/java/org/olat/course/assessment/AssessmentModeManager.java
+++ b/src/main/java/org/olat/course/assessment/AssessmentModeManager.java
@@ -20,6 +20,7 @@
 package org.olat.course.assessment;
 
 import java.util.List;
+import java.util.Set;
 
 import org.olat.basesecurity.IdentityRef;
 import org.olat.group.BusinessGroup;
@@ -41,11 +42,13 @@ public interface AssessmentModeManager {
 	 */
 	public AssessmentMode createAssessmentMode(RepositoryEntry entry);
 	
+	public AssessmentModeToGroup createAssessmentModeToGroup(AssessmentMode mode, BusinessGroup group);
+	
 	public AssessmentMode save(AssessmentMode assessmentMode);
 	
-	public AssessmentMode loadById(Long key);
+	public AssessmentMode getAssessmentModeById(Long key);
 	
-	public List<AssessmentMode> loadAssessmentMode(RepositoryEntryRef entry);
+	public List<AssessmentMode> getAssessmentModeFor(RepositoryEntryRef entry);
 	
 	/**
 	 * Load the assessment mode for a specific user now.
@@ -53,10 +56,11 @@ public interface AssessmentModeManager {
 	 * @param identity
 	 * @return
 	 */
-	public List<AssessmentMode> loadAssessmentModeFor(IdentityRef identity);
+	public List<AssessmentMode> getAssessmentModeFor(IdentityRef identity);
 	
-	public List<AssessmentMode> loadCurrentAssessmentModes();
+	public List<AssessmentMode> getCurrentAssessmentModes();
+	
+	public Set<Long> getAssessedIdentities(AssessmentMode assessmentMode);
 	
-	public AssessmentModeToGroup createAssessmentModeToGroup(AssessmentMode mode, BusinessGroup group);
 
 }
diff --git a/src/main/java/org/olat/course/assessment/AssessmentModeNotificationEvent.java b/src/main/java/org/olat/course/assessment/AssessmentModeNotificationEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1466cf0546ca7429fd95d598433f974e776907b
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/AssessmentModeNotificationEvent.java
@@ -0,0 +1,59 @@
+/**
+ * <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.course.assessment;
+
+import java.util.Set;
+
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.util.event.MultiUserEvent;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.course.assessment.model.TransientAssessmentMode;
+
+/**
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentModeNotificationEvent extends MultiUserEvent  {
+	
+	public static final String command = "assessment-mode-notification";
+	public static final OLATResourceable ASSESSMENT_MODE_NOTIFICATION = OresHelper.createOLATResourceableType(command);
+
+	private static final long serialVersionUID = 1539360689947584111L;
+
+	private TransientAssessmentMode mode;
+	private Set<Long> assessedIdentityKeys;
+	
+	public AssessmentModeNotificationEvent(TransientAssessmentMode mode, Set<Long> assessedIdentityKeys) {
+		super(command);
+		this.mode = mode;
+		this.assessedIdentityKeys = assessedIdentityKeys;
+	}
+
+	public TransientAssessmentMode getAssessementMode() {
+		return mode;
+	}
+
+
+	public Set<Long> getAssessedIdentityKeys() {
+		return assessedIdentityKeys;
+	}
+}
diff --git a/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java b/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java
index 765eede429b72d1f4fccf734935804945f328715..1c94406d77d48e45ab5e2b82ab3a0ccc63b71cfb 100644
--- a/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java
+++ b/src/main/java/org/olat/course/assessment/AssessmentModeToGroup.java
@@ -1,3 +1,22 @@
+/**
+ * <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.course.assessment;
 
 import org.olat.group.BusinessGroup;
diff --git a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml
index 39b5e21a35b05627f2cfb7a4a937b7d1091e22fb..eeaa6225ea61c9e6ad8f1bd160d15b9ba4023497 100644
--- a/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml
+++ b/src/main/java/org/olat/course/assessment/_spring/assessmentContext.xml
@@ -20,5 +20,15 @@
 		<property name="userManager" ref="userManager"/>
 		<property name="repositoryManager" ref="repositoryManager"/>
 	</bean>
+	
+	<bean id="assessmentNotificationsTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
+	    <property name="jobDetail" ref="assessmentNotificationsJob" />
+	    <property name="cronExpression" value="25 */5 * * * ?" />
+	    <property name="startDelay" value="55000" />
+	</bean>
+	
+	<bean id="assessmentNotificationsJob" class="org.springframework.scheduling.quartz.JobDetailBean" lazy-init="true">
+	  <property name="jobClass" value="org.olat.course.assessment.manager.AssessmentModeNotificationJob" />
+	</bean>
 
 </beans>
diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java
index fcfe9c020c14a1ec1f5178609a85479d6263708f..12d2d7ae06da0d5866bbd31b68cc02cf9f1db917 100644
--- a/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java
+++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeManagerImpl.java
@@ -21,22 +21,28 @@ package org.olat.course.assessment.manager;
 
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.olat.basesecurity.GroupRoles;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
-import org.olat.core.commons.persistence.PersistenceHelper;
 import org.olat.course.assessment.AssessmentMode;
+import org.olat.course.assessment.AssessmentMode.Target;
 import org.olat.course.assessment.AssessmentModeManager;
 import org.olat.course.assessment.AssessmentModeToGroup;
 import org.olat.course.assessment.model.AssessmentModeImpl;
 import org.olat.course.assessment.model.AssessmentModeToGroupImpl;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupImpl;
+import org.olat.group.manager.BusinessGroupRelationDAO;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryRef;
+import org.olat.repository.RepositoryEntryRelationType;
+import org.olat.repository.manager.RepositoryEntryRelationDAO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -51,13 +57,17 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager {
 	
 	@Autowired
 	private DB dbInstance;
+	@Autowired
+	private BusinessGroupRelationDAO businessGroupRelationDao;
+	@Autowired
+	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
 
 	@Override
 	public AssessmentMode createAssessmentMode(RepositoryEntry entry) {
 		AssessmentModeImpl mode = new AssessmentModeImpl();
 		mode.setCreationDate(new Date());
 		mode.setLastModified(new Date());
-		mode.setEntry(entry);
+		mode.setRepositoryEntry(entry);
 		return mode;
 	}
 
@@ -76,7 +86,7 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager {
 	}
 
 	@Override
-	public AssessmentMode loadById(Long key) {
+	public AssessmentMode getAssessmentModeById(Long key) {
 		String q = "select mode from courseassessmentmode mode where mode.key=:modeKey";
 		List<AssessmentMode> modes = dbInstance.getCurrentEntityManager()
 			.createQuery(q, AssessmentMode.class)
@@ -87,7 +97,7 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager {
 	}
 
 	@Override
-	public List<AssessmentMode> loadAssessmentMode(RepositoryEntryRef entry) {
+	public List<AssessmentMode> getAssessmentModeFor(RepositoryEntryRef entry) {
 		return dbInstance.getCurrentEntityManager()
 				.createNamedQuery("assessmentModeByRepoEntry", AssessmentMode.class)
 				.setParameter("entryKey", entry.getKey())
@@ -95,18 +105,20 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager {
 	}
 
 	@Override
-	public List<AssessmentMode> loadAssessmentModeFor(IdentityRef identity) {
-		List<AssessmentMode> currentModes = loadCurrentAssessmentModes();
+	public List<AssessmentMode> getAssessmentModeFor(IdentityRef identity) {
+		List<AssessmentMode> currentModes = getCurrentAssessmentModes();
+		List<AssessmentMode> myModes = null;
 		if(currentModes.size() > 0) {
 			//check permissions, groups, areas, course
-			currentModes = loadAssessmentModeFor(identity, currentModes);
+			myModes = loadAssessmentModeFor(identity, currentModes);
 		}
-		return currentModes;
+		return myModes == null ? Collections.<AssessmentMode>emptyList() : myModes;
 	}
 	
 	private List<AssessmentMode> loadAssessmentModeFor(IdentityRef identity, List<AssessmentMode> currentModes) {
 		StringBuilder sb = new StringBuilder(1000);
 		sb.append("select mode from courseassessmentmode mode ")
+		  .append(" inner join fetch mode.repositoryEntry entry")
 		  .append(" left join mode.groups as modeToGroup")
 		  .append(" where mode.key in (:modeKeys)")
 		  .append("  and ((mode.targetAudienceString in ('").append(AssessmentMode.Target.courseAndGroups.name()).append("','").append(AssessmentMode.Target.groups.name()).append("')")
@@ -116,7 +128,7 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager {
 		  .append("       (mode.applySettingsForCoach=true and membership.role='").append(GroupRoles.coach.name()).append("'))")
 		  .append("  )) or (mode.targetAudienceString in ('").append(AssessmentMode.Target.courseAndGroups.name()).append("','").append(AssessmentMode.Target.course.name()).append("')")
 		  .append("   and exists (select rel from repoentrytogroup as rel,  bgroupmember as membership ")
-		  .append("     where mode.entry=rel.entry and membership.group=rel.group and membership.identity.key=:identityKey")
+		  .append("     where mode.repositoryEntry=rel.entry and membership.group=rel.group and membership.identity.key=:identityKey")
 		  .append("     and (membership.role='").append(GroupRoles.participant.name()).append("' or ")
 		  .append("       (mode.applySettingsForCoach=true and membership.role='").append(GroupRoles.coach.name()).append("'))")
 		  .append("  ))")
@@ -126,15 +138,48 @@ public class AssessmentModeManagerImpl implements AssessmentModeManager {
 		for(AssessmentMode mode:currentModes) {
 			modeKeys.add(mode.getKey());
 		}
-		return dbInstance.getCurrentEntityManager()
+		List<AssessmentMode> modeList = dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), AssessmentMode.class)
 				.setParameter("identityKey", identity.getKey())
 				.setParameter("modeKeys", modeKeys)
 				.getResultList();
+		//quicker than distinct
+		return new ArrayList<AssessmentMode>(new HashSet<AssessmentMode>(modeList));
+	}
+
+	@Override
+	public Set<Long> getAssessedIdentities(AssessmentMode assessmentMode) {
+		Target targetAudience = assessmentMode.getTargetAudience();
+		RepositoryEntry re = assessmentMode.getRepositoryEntry();
+		
+		Set<Long> assessedKeys = new HashSet<>();
+		if(targetAudience == Target.course || targetAudience == Target.courseAndGroups) {
+			List<Long> courseMemberKeys = assessmentMode.isApplySettingsForCoach()
+					? repositoryEntryRelationDao.getMemberKeys(re, RepositoryEntryRelationType.defaultGroup, GroupRoles.coach.name(), GroupRoles.participant.name())
+					: repositoryEntryRelationDao.getMemberKeys(re, RepositoryEntryRelationType.defaultGroup, GroupRoles.participant.name());
+			assessedKeys.addAll(courseMemberKeys);
+		}
+		if(targetAudience == Target.groups || targetAudience == Target.courseAndGroups) {
+			Set<AssessmentModeToGroup> modeToGroups = assessmentMode.getGroups();
+			if(modeToGroups.size() > 0) {
+				List<BusinessGroup> groups = new ArrayList<>(modeToGroups.size());
+				for(AssessmentModeToGroup modeToGroup: modeToGroups) {
+					groups.add(modeToGroup.getBusinessGroup());
+				}
+
+				List<Long> groupMemberKeys = assessmentMode.isApplySettingsForCoach()
+						? businessGroupRelationDao.getMemberKeys(groups, GroupRoles.coach.name(), GroupRoles.participant.name())
+						: businessGroupRelationDao.getMemberKeys(groups, GroupRoles.participant.name());
+				assessedKeys.addAll(groupMemberKeys);		
+			}
+			
+		}
+		
+		return assessedKeys;
 	}
 
 	@Override
-	public List<AssessmentMode> loadCurrentAssessmentModes() {
+	public List<AssessmentMode> getCurrentAssessmentModes() {
 		Calendar cal = Calendar.getInstance();
 		cal.set(Calendar.MILLISECOND, 0);
 		cal.set(Calendar.SECOND, 0);
diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentModeNotificationJob.java b/src/main/java/org/olat/course/assessment/manager/AssessmentModeNotificationJob.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5c147bc231888edd9c9e9b130f7c5c952fd9707
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeNotificationJob.java
@@ -0,0 +1,56 @@
+/**
+ * <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.course.assessment.manager;
+
+import java.util.List;
+import java.util.Set;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.services.scheduler.JobWithDB;
+import org.olat.core.util.coordinate.CoordinatorManager;
+import org.olat.course.assessment.AssessmentMode;
+import org.olat.course.assessment.AssessmentModeManager;
+import org.olat.course.assessment.AssessmentModeNotificationEvent;
+import org.olat.course.assessment.model.TransientAssessmentMode;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+/**
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentModeNotificationJob extends JobWithDB {
+
+	@Override
+	public void executeWithDB(JobExecutionContext context)
+	throws JobExecutionException {
+		AssessmentModeManager assessmentModeManager = CoreSpringFactory.getImpl(AssessmentModeManager.class);
+		List<AssessmentMode> currentModes = assessmentModeManager.getCurrentAssessmentModes();
+		for(AssessmentMode currentMode:currentModes) {
+			Set<Long> assessedIdentityKeys = assessmentModeManager.getAssessedIdentities(currentMode);
+			TransientAssessmentMode transientMode = new TransientAssessmentMode(currentMode);
+			AssessmentModeNotificationEvent event = new AssessmentModeNotificationEvent(transientMode, assessedIdentityKeys);
+			CoordinatorManager.getInstance().getCoordinator().getEventBus()
+				.fireEventToListenersOf(event, AssessmentModeNotificationEvent.ASSESSMENT_MODE_NOTIFICATION);
+		}
+	}
+}
diff --git a/src/main/java/org/olat/course/assessment/manager/IPRangeChecker.java b/src/main/java/org/olat/course/assessment/manager/IPRangeChecker.java
new file mode 100644
index 0000000000000000000000000000000000000000..dec104a2f9d58a6b4865985018829d3696661c39
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/manager/IPRangeChecker.java
@@ -0,0 +1,63 @@
+/**
+ * <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.course.assessment.manager;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * 
+ * Thanks: https://gist.github.com/madan712/6651967
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class IPRangeChecker {
+	
+	public static long ipToLong(InetAddress ip) {
+		byte[] octets = ip.getAddress();
+		long result = 0;
+		for (byte octet : octets) {
+			result <<= 8;
+			result |= octet & 0xff;
+		}
+		return result;
+	}
+ 
+	/**
+	 * TODO replace perhaps with guava, jdk make a round trip to the address.
+	 * @param ipStart
+	 * @param ipEnd
+	 * @param ipToCheck
+	 * @return
+	 */
+	public static boolean isValidRange(String ipStart, String ipEnd, String ipToCheck) {
+		try {
+			long ipLo = ipToLong(InetAddress.getByName(ipStart));
+			long ipHi = ipToLong(InetAddress.getByName(ipEnd));
+			long ipToTest = ipToLong(InetAddress.getByName(ipToCheck));
+			return (ipToTest >= ipLo && ipToTest <= ipHi);
+		} catch (UnknownHostException e) {
+			e.printStackTrace();
+			return false;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java b/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java
index 94e9cce2ac41a20800b6d490e0b93a2d8a0fd2f1..2990d6e55de636693089dd32b3fe72819089bdee 100644
--- a/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java
+++ b/src/main/java/org/olat/course/assessment/model/AssessmentModeImpl.java
@@ -52,7 +52,7 @@ import org.olat.repository.RepositoryEntry;
 @Entity(name="courseassessmentmode")
 @Table(name="o_as_mode_course")
 @NamedQueries({
-	@NamedQuery(name="assessmentModeByRepoEntry", query="select mode from courseassessmentmode mode where mode.entry.key=:entryKey"),
+	@NamedQuery(name="assessmentModeByRepoEntry", query="select mode from courseassessmentmode mode where mode.repositoryEntry.key=:entryKey"),
 	@NamedQuery(name="currentAssessmentModes", query="select mode from courseassessmentmode mode where mode.begin<=:now and mode.end>=:now")
 })
 public class AssessmentModeImpl implements Persistable, AssessmentMode {
@@ -114,7 +114,7 @@ public class AssessmentModeImpl implements Persistable, AssessmentMode {
 	
 	@ManyToOne(targetEntity=RepositoryEntry.class,fetch=FetchType.LAZY,optional=false)
 	@JoinColumn(name="fk_entry", nullable=false, updatable=false)
-	private RepositoryEntry entry;
+	private RepositoryEntry repositoryEntry;
 	
 	
 	@Override
@@ -302,12 +302,13 @@ public class AssessmentModeImpl implements Persistable, AssessmentMode {
 		this.applySettingsForCoach = applySettingsForCoach;
 	}
 
-	public RepositoryEntry getEntry() {
-		return entry;
+	@Override
+	public RepositoryEntry getRepositoryEntry() {
+		return repositoryEntry;
 	}
 
-	public void setEntry(RepositoryEntry entry) {
-		this.entry = entry;
+	public void setRepositoryEntry(RepositoryEntry entry) {
+		this.repositoryEntry = entry;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java b/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java
index 2ce5faab16bbe963b1490c20a131c412c79c6e97..b709392b275ecd9b2c62e74ab9e28a938327b445 100644
--- a/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java
+++ b/src/main/java/org/olat/course/assessment/model/AssessmentModeToGroupImpl.java
@@ -1,3 +1,22 @@
+/**
+ * <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.course.assessment.model;
 
 import javax.persistence.Column;
diff --git a/src/main/java/org/olat/course/assessment/model/TransientAssessmentMode.java b/src/main/java/org/olat/course/assessment/model/TransientAssessmentMode.java
new file mode 100644
index 0000000000000000000000000000000000000000..85b074bdfe0d495b06a83e421aaaee89e5acb45e
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/model/TransientAssessmentMode.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.course.assessment.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.course.assessment.AssessmentMode;
+
+/**
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class TransientAssessmentMode implements Serializable {
+
+	private static final long serialVersionUID = -5738682288044689497L;
+	private String displayName;
+	private Long repositoryEntryKey;
+	private OLATResourceable resource;
+	
+	private String name;
+	private String description;
+	private Date begin;
+	private Date end;
+	private int leadTime;
+	
+	public TransientAssessmentMode(AssessmentMode mode) {
+		displayName = mode.getRepositoryEntry().getDisplayname();
+		resource = OresHelper.clone(mode.getRepositoryEntry().getOlatResource());
+		repositoryEntryKey = mode.getRepositoryEntry().getKey();
+		
+		name = mode.getName();
+		description = mode.getDescription();
+		begin = mode.getBegin();
+		end = mode.getEnd();
+		leadTime = mode.getLeadTime();
+	}
+	
+	public static List<TransientAssessmentMode> create(List<AssessmentMode> modes) {
+		List<TransientAssessmentMode> transientModes = new ArrayList<>(modes.size());
+		for(AssessmentMode mode:modes) {
+			transientModes.add(new TransientAssessmentMode(mode));
+		}
+		return transientModes;
+	}
+
+	public String getDisplayName() {
+		return displayName;
+	}
+
+	public void setDisplayName(String displayName) {
+		this.displayName = displayName;
+	}
+
+	public Long getRepositoryEntryKey() {
+		return repositoryEntryKey;
+	}
+
+	public OLATResourceable getResource() {
+		return resource;
+	}
+
+	public void setResource(OLATResourceable resource) {
+		this.resource = resource;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public String getDescription() {
+		return description;
+	}
+
+	public Date getBegin() {
+		return begin;
+	}
+
+	public void setBegin(Date begin) {
+		this.begin = begin;
+	}
+
+	public Date getEnd() {
+		return end;
+	}
+
+	public void setEnd(Date end) {
+		this.end = end;
+	}
+
+	public int getLeadTime() {
+		return leadTime;
+	}
+
+	public void setLeadTime(int leadTime) {
+		this.leadTime = leadTime;
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
index 91fd337e95ab68c84f69195bf8c1b219c6ace928..5eebeb3df2fd0935fd999329043f15fe148ef268 100644
--- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeEditController.java
@@ -108,7 +108,7 @@ public class AssessmentModeEditController extends FormBasicController {
 		if(assessmentMode.getKey() == null) {
 			this.assessmentMode = assessmentMode;
 		} else {
-			this.assessmentMode = assessmentModeMgr.loadById(assessmentMode.getKey());
+			this.assessmentMode = assessmentModeMgr.getAssessmentModeById(assessmentMode.getKey());
 		}
 		initForm(ureq);
 	}
@@ -152,8 +152,8 @@ public class AssessmentModeEditController extends FormBasicController {
 		
 		String[] audienceKeys = new String[] {
 			AssessmentMode.Target.courseAndGroups.name(),
-			AssessmentMode.Target.groups.name(),
-			AssessmentMode.Target.course.name()
+			AssessmentMode.Target.course.name(),
+			AssessmentMode.Target.groups.name()
 		};
 		String[] audienceValues = new String[] {
 			translate("target.courseAndGroups"),
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java
index 2a76cc70f7ef68bc45f8c8a24eb4b0063abb60df..18d53640bdc4f298dcbc0fd14d5dc1d721a37d58 100644
--- a/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeListController.java
@@ -102,7 +102,7 @@ public class AssessmentModeListController extends FormBasicController {
 	}
 	
 	private void loadModel() {
-		List<AssessmentMode> modes = assessmentModeMgr.loadAssessmentMode(entry);
+		List<AssessmentMode> modes = assessmentModeMgr.getAssessmentModeFor(entry);
 		model.setObjects(modes);
 		tableEl.reloadData();
 	}
diff --git a/src/main/java/org/olat/course/assessment/ui/AssessmentModeUserConfirmationController.java b/src/main/java/org/olat/course/assessment/ui/AssessmentModeUserConfirmationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf727b57c2c03c7a6e197edebd0cda501471291d
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/ui/AssessmentModeUserConfirmationController.java
@@ -0,0 +1,158 @@
+/**
+ * <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.course.assessment.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.olat.NewControllerFactory;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.Windows;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.panel.Panel;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+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.id.OLATResourceable;
+import org.olat.core.util.CodeHelper;
+import org.olat.core.util.Formatter;
+import org.olat.course.assessment.model.TransientAssessmentMode;
+
+/**
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentModeUserConfirmationController extends BasicController {
+
+	private final CloseableModalController cmc;
+	
+	public AssessmentModeUserConfirmationController(UserRequest ureq, WindowControl wControl) {
+		this(ureq, wControl, TransientAssessmentMode.create(ureq.getUserSession().getAssessmentModes()));
+	}
+	
+	public AssessmentModeUserConfirmationController(UserRequest ureq, WindowControl wControl, List<TransientAssessmentMode> modes) {
+		super(ureq, wControl);
+		putInitialPanel(new Panel("assessment-mode-chooser"));
+		
+		VelocityContainer mainVC = createVelocityContainer("choose_mode");
+		List<Mode> modeWrappers = new ArrayList<Mode>();
+		for(TransientAssessmentMode mode:modes) {
+			String name = "go-" + CodeHelper.getRAMUniqueID();
+			Link button = LinkFactory.createCustomLink(name, "go", "current.mode.start", Link.BUTTON, mainVC, this);
+			button.setUserObject(mode);
+			
+			Mode wrapper = new Mode(button, mode, getLocale());
+			modeWrappers.add(wrapper);
+		}
+		mainVC.contextPut("modeWrappers", modeWrappers);
+
+		cmc = new CloseableModalController(getWindowControl(), translate("close"), mainVC, true, translate("current.mode"), false);	
+		cmc.activate();
+		listenTo(cmc);
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if(source instanceof Link) {
+			Link link = (Link)source;
+			if("go".equals(link.getCommand())) {
+				launchAssessmentMode(ureq, (TransientAssessmentMode)link.getUserObject());
+			}
+		}
+	}
+	
+	/**
+	 * Remove thie list of assessment modes and lock the chief controller.
+	 * 
+	 * 
+	 * @param ureq
+	 * @param mode
+	 */
+	private void launchAssessmentMode(UserRequest ureq, TransientAssessmentMode mode) {
+		ureq.getUserSession().setAssessmentModes(null);
+		OLATResourceable resource = mode.getResource();
+		Windows.getWindows(ureq).getChiefController().lockResource(resource);
+		fireEvent(ureq, new ChooseAssessmentModeEvent(mode));
+		
+		String businessPath = "[RepositoryEntry:" + mode.getRepositoryEntryKey() + "]"; //TODO node
+		NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
+	}
+	
+	public static final class Mode {
+		
+		private final Locale locale;
+		private final Link goButton;
+		private final TransientAssessmentMode mode;
+		
+		public Mode(Link goButton, TransientAssessmentMode mode, Locale locale) {
+			this.goButton = goButton;
+			this.mode = mode;
+			this.locale = locale;
+		}
+		
+		public String getName() {
+			return mode.getName();
+		}
+		
+		public String getDescription() {
+			return mode.getDescription();
+		}
+		
+		public String getDisplayName() {
+			return mode.getDisplayName();
+		}
+		
+		public String getBegin() {
+			return Formatter.getInstance(locale).formatDateAndTime(mode.getBegin());
+		}
+		
+		public String getEnd() {
+			return Formatter.getInstance(locale).formatDateAndTime(mode.getEnd());
+		}
+		
+		public String getLeadTime() {
+			String lt = "";
+			if(mode.getLeadTime() > 0) {
+				lt = Integer.toString(mode.getLeadTime());
+			}
+			return lt;
+		}
+
+		public String getButtonName() {
+			return goButton.getComponentName();
+		}
+
+		public TransientAssessmentMode getMode() {
+			return mode;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java b/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc39d2bf801b87d49f5804cee91df794981bda76
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/ui/ChooseAssessmentModeEvent.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.course.assessment.ui;
+
+import org.olat.core.gui.control.Event;
+import org.olat.course.assessment.model.TransientAssessmentMode;
+
+/**
+ * 
+ * Initial date: 18.12.2014<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ChooseAssessmentModeEvent extends Event {
+
+	private static final long serialVersionUID = -3064859162799070354L;
+	private TransientAssessmentMode assessmentMode;
+	
+	public ChooseAssessmentModeEvent(TransientAssessmentMode assessmentMode) {
+		super("choose-assessment-mode");
+		this.assessmentMode = assessmentMode;
+	}
+
+	public TransientAssessmentMode getAssessmentMode() {
+		return assessmentMode;
+	}
+
+}
diff --git a/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html b/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html
new file mode 100644
index 0000000000000000000000000000000000000000..4506849bc6efd9f5e9382715f25430bf8cc74138
--- /dev/null
+++ b/src/main/java/org/olat/course/assessment/ui/_content/choose_mode.html
@@ -0,0 +1,12 @@
+<div class="o_info">$r.translate("current.mode.desc")</div>
+#foreach($mode in $modeWrappers)
+	<h2>$mode.name <small>$r.translate("current.mode.course", $mode.displayName)</small></h2>
+	<p><em>$r.translate("current.mode.datetimes", $mode.begin, $mode.end)</em>
+		#if(!$mode.leadTime.empty)
+			<br/><em>$r.translate("current.mode.leadtime", $mode.leadTime)</em>
+		#end
+	</p>
+	<p>$mode.description</p>
+	<div class="o_button_group">$r.render($mode.buttonName)</div>
+#end
+
diff --git a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties
index eea9b2543d00a7341a62af3ee699bd0e5e3c2e94..a327692a1d9bb5e42fcf50448ac450782df03149 100644
--- a/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/assessment/ui/_i18n/LocalStrings_de.properties
@@ -4,6 +4,12 @@ areas=Lernbereich
 choose.areas=Lernbereich auswählen
 choose.elements=Kursbausteine auswählen
 choose.groups=Gruppen auswählen
+current.mode=Aktuelle Prüfung
+current.mode.desc=Im folgenden Kurs ist für den aktuellen Zeitraum eine Prüfung für Sie vorgesehen. Während dieser Prüfung können keine anderen Funktionen in OpenOLAT verwendet werden:
+current.mode.start=Zur Prüfung
+current.mode.course=in Kurs "{0}"
+current.mode.datetimes=Von {0} bis {1}
+current.mode.leadtime=Ab {0} Minuten vor Prüfungsbeginn können keine andere Kurse mehr geöffnet werden.
 delete.mode=Pr\u00FCfungssetting l\u00F6schen
 elements=Kursbausteine
 form.mode.description=Erstellen Sie ein neues Pr\u00FCfungssetting um f\u00FCr diesen Kurs oder Elemets aus diesem Kurs in einem gesch\u00FCtzten Modus mit einem eingeschr\u00E4nken M\u00F6glichkeiten zu betreiben.
@@ -18,7 +24,7 @@ mode.leadTime=Vorlaufzeit
 mode.name=Title
 mode.ips=Einschränkung auf IP Adressen
 mode.ips.list=Zulässige IP Adressen
-mode.for.coach=Prüfundssettings auch bei Betreuer anwenden
+mode.for.coach=Pr\u00FCfundssettings auch bei Betreuer anwenden
 mode.description=Beschreibung
 mode.safeexambrowser=Safe exam Browser verwenden
 mode.safeexambrowser.key=Browser Exam key
@@ -33,7 +39,7 @@ table.header.name=Pr
 table.header.begin=Von
 table.header.end=Bis
 table.header.leadTime=Vorlauf
-table.header.target=Für
+table.header.target=F\u00FCr
 target.courseAndGroups=Teilnehmer aus kurs und Gruppen
 target.groups=Nur Gruppenteilnehmer
 target.course=Nur Kursteilnehmer
\ No newline at end of file
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
index 1aaa48a646a8a417cfd1fd57771759f8d3f466e4..2ab194a79680556f7b803530c12e72ae4781ba05 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
@@ -214,6 +214,29 @@ public class BusinessGroupRelationDAO {
 		return members;
 	}
 	
+	public List<Long> getMemberKeys(List<? extends BusinessGroupRef> groups, String... roles) {
+		if(groups == null || groups.isEmpty()) return Collections.emptyList();
+		
+		StringBuilder sb = new StringBuilder();
+		sb.append("select membership.identity.key from ").append(BusinessGroupImpl.class.getName()).append(" as bgroup ")
+		  .append(" inner join bgroup.baseGroup as baseGroup")
+		  .append(" inner join baseGroup.members as membership")
+		  .append(" where bgroup.key in (:businessGroupKeys) and membership.role in (:roles)");
+		
+		List<String> roleList = GroupRoles.toList(roles);
+		List<Long> groupKeys = new ArrayList<>(groups.size());
+		for(BusinessGroupRef group:groups) {
+			groupKeys.add(group.getKey());
+		}
+		
+		List<Long> members = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Long.class)
+				.setParameter("businessGroupKeys", groupKeys)
+				.setParameter("roles", roleList)
+				.getResultList();
+		return members;
+	}
+	
 	public List<Identity> getMembersOrderByDate(BusinessGroupRef group, String... roles) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select membership.identity from ").append(BusinessGroupImpl.class.getName()).append(" as bgroup ")
diff --git a/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java b/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java
index c0aa927c461b3e3644ff9c40288a6db7e11c4ee5..9ff13be45bfe6818a0d782f58fb2b328bd8ad4bc 100644
--- a/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java
+++ b/src/main/java/org/olat/gui/control/OlatDmzTopNavController.java
@@ -29,6 +29,7 @@ import org.olat.core.commons.contextHelp.ContextHelpModule;
 import org.olat.core.commons.controllers.impressum.ImpressumDmzMainController;
 import org.olat.core.commons.controllers.impressum.ImpressumInformations;
 import org.olat.core.commons.controllers.impressum.ImpressumModule;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.Windows;
 import org.olat.core.gui.components.Component;
@@ -41,9 +42,10 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.creator.ControllerCreator;
 import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
+import org.olat.core.id.OLATResourceable;
 import org.springframework.beans.factory.annotation.Autowired;
 
-public class OlatDmzTopNavController extends BasicController {
+public class OlatDmzTopNavController extends BasicController implements TopNavController {
 	
 	private static final Boolean contextHelpEnabled = Boolean.valueOf(ContextHelpModule.isContextHelpEnabled());
 	private Link impressumLink;
@@ -79,6 +81,11 @@ public class OlatDmzTopNavController extends BasicController {
 		putInitialPanel(vc);		
 	}
 
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		//
+	}
+
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		if (source == impressumLink) {
diff --git a/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java b/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java
index e55df675d8dc70e40bcaa0f9ad38304c9518b056..b935626b12d0088353736bf57fd9e5a11b39d5d8 100644
--- a/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java
+++ b/src/main/java/org/olat/gui/control/OlatGuestTopNavController.java
@@ -29,6 +29,7 @@ import org.olat.basesecurity.AuthHelper;
 import org.olat.core.commons.controllers.impressum.ImpressumInformations;
 import org.olat.core.commons.controllers.impressum.ImpressumMainController;
 import org.olat.core.commons.controllers.impressum.ImpressumModule;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.commons.fullWebApp.popup.BaseFullWebappPopupLayoutFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.Windows;
@@ -42,6 +43,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.creator.ControllerCreator;
 import org.olat.core.gui.control.generic.popup.PopupBrowserWindow;
+import org.olat.core.id.OLATResourceable;
 import org.olat.course.CourseFactory;
 import org.olat.course.CourseModule;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -52,7 +54,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  * 
  * @author patrickb
  */
-public class OlatGuestTopNavController extends BasicController {
+public class OlatGuestTopNavController extends BasicController implements TopNavController {
 
 	private Link helpLink, loginLink, impressumLink;
 
@@ -86,6 +88,11 @@ public class OlatGuestTopNavController extends BasicController {
 
 		putInitialPanel(vc);
 	}
+	
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		//
+	}
 
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
diff --git a/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java b/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java
index d6d2a37b72ab18e256ad49834f4acb26ada02e0e..fad0eafa4d38ec18aab2c216df0317e4940cea8c 100644
--- a/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java
+++ b/src/main/java/org/olat/gui/control/OlatMinimalTopNavController.java
@@ -24,6 +24,7 @@
 */
 package org.olat.gui.control;
 
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.dispatcher.impl.StaticMediaDispatcher;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.Windows;
@@ -37,6 +38,7 @@ import org.olat.core.gui.control.WindowBackOffice;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.media.RedirectMediaResource;
+import org.olat.core.id.OLATResourceable;
 
 /**
  * Description:<br>
@@ -46,7 +48,7 @@ import org.olat.core.gui.media.RedirectMediaResource;
  * Initial Date:  15.02.2008 <br>
  * @author patrickb
  */
-public class OlatMinimalTopNavController extends BasicController {
+public class OlatMinimalTopNavController extends BasicController implements TopNavController {
 
 	private final Link closeLink;
 
@@ -58,17 +60,16 @@ public class OlatMinimalTopNavController extends BasicController {
 		putInitialPanel(vc);
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#doDispose()
-	 */
 	@Override
 	protected void doDispose() {
 		//
 	}
+	
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		//
+	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
-	 */
 	@Override
 	protected void event(UserRequest ureq, Component source, Event event) {
 		if(source == closeLink){
diff --git a/src/main/java/org/olat/gui/control/OlatTopNavController.java b/src/main/java/org/olat/gui/control/OlatTopNavController.java
index de3e4d95a1a89bf7eafcd0ab80b5ca0d65e5259c..8a3c91aac2f4263cca6fec4882f52da32d1f7d07 100644
--- a/src/main/java/org/olat/gui/control/OlatTopNavController.java
+++ b/src/main/java/org/olat/gui/control/OlatTopNavController.java
@@ -27,6 +27,7 @@ import java.util.Set;
 import org.olat.admin.user.tools.UserTool;
 import org.olat.admin.user.tools.UserToolExtension;
 import org.olat.admin.user.tools.UserToolsModule;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.dispatcher.DispatcherModule;
 import org.olat.core.extensions.ExtManager;
 import org.olat.core.gui.UserRequest;
@@ -39,6 +40,7 @@ import org.olat.core.gui.control.Disposable;
 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.id.OLATResourceable;
 import org.olat.core.id.User;
 import org.olat.core.id.UserConstants;
 import org.olat.core.util.StringHelper;
@@ -54,7 +56,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class OlatTopNavController extends BasicController {
+public class OlatTopNavController extends BasicController implements TopNavController {
 	
 	private Link loginLink;
 	private VelocityContainer topNavVC;
@@ -100,9 +102,15 @@ public class OlatTopNavController extends BasicController {
 			topNavVC.contextPut("myMenuLabel", myMenuText);
 		}
 		
+		topNavVC.contextPut("locked", Boolean.FALSE);
 		putInitialPanel(topNavVC);
 	}
 	
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		topNavVC.contextPut("locked", Boolean.TRUE);
+	}
+	
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		if (source == loginLink) {
diff --git a/src/main/java/org/olat/gui/control/UserToolsMenuController.java b/src/main/java/org/olat/gui/control/UserToolsMenuController.java
index 61e48d9f253e36b0ad79823e3eebc997e74d6161..f4836cd9a3ddf600c0375aba79d659b3c7667257 100644
--- a/src/main/java/org/olat/gui/control/UserToolsMenuController.java
+++ b/src/main/java/org/olat/gui/control/UserToolsMenuController.java
@@ -29,6 +29,7 @@ import org.olat.admin.user.tools.UserToolCategory;
 import org.olat.admin.user.tools.UserToolExtension;
 import org.olat.admin.user.tools.UserToolsModule;
 import org.olat.basesecurity.AuthHelper;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.velocity.VelocityContainer;
@@ -36,6 +37,7 @@ import org.olat.core.gui.control.Disposable;
 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.id.OLATResourceable;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.prefs.Preferences;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,7 +48,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class UserToolsMenuController extends BasicController  {
+public class UserToolsMenuController extends BasicController implements TopNavController  {
 
 	private static final String ACTION_LOGOUT = "logout";
 	
@@ -115,6 +117,12 @@ public class UserToolsMenuController extends BasicController  {
 		menuVC.contextPut("configs", configLinksName);
 		menuVC.contextPut("systems", systemLinksName);
 		menuVC.contextPut("searchs", searchLinksName);
+		menuVC.contextPut("locked", Boolean.FALSE);
+	}
+	
+	@Override
+	public void lockResource(OLATResourceable resource) {
+		menuVC.contextPut("locked", Boolean.TRUE);
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/gui/control/_content/menu.html b/src/main/java/org/olat/gui/control/_content/menu.html
index 4bc8b3133f9021380338ae375736eb92e5246394..0e955e974788f2ad4c235be0500d25e346595f88 100644
--- a/src/main/java/org/olat/gui/control/_content/menu.html
+++ b/src/main/java/org/olat/gui/control/_content/menu.html
@@ -1,29 +1,31 @@
 ## DOM replacement implemented via ID on UL element - bypass standard OO wrapper DIV
 <ul id="$r.getCId()" class="nav o_navbar-nav o_navbar-right o_sel_menu_tools">
-	#foreach($search in $searchs)
-	 	<li>$r.render($search)</li>
-	#end
-	#if($personalTools && $personalTools.size() > 0)
-		<li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.tools")</li>
-		#foreach($personalTool in $personalTools)
-		 	<li>$r.render($personalTool)</li>
+	#if(!$locked)
+		#foreach($search in $searchs)
+		 	<li>$r.render($search)</li>
 		#end
-	#end
-	#if($configs && $configs.size() > 0)
-		<li role="presentation" class="divider"></li>
-		<li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.configurations")</li>
-		#foreach($config in $configs)
-		 	<li>$r.render($config)</li>
+		#if($personalTools && $personalTools.size() > 0)
+			<li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.tools")</li>
+			#foreach($personalTool in $personalTools)
+			 	<li>$r.render($personalTool)</li>
+			#end
 		#end
-	#end
-	#if($systems && $systems.size() > 0)
-		<li role="presentation" class="divider"></li>
-		<li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.systems")</li>
-		#foreach($system in $systems)
-		 	<li>$r.render($system)</li>
+		#if($configs && $configs.size() > 0)
+			<li role="presentation" class="divider"></li>
+			<li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.configurations")</li>
+			#foreach($config in $configs)
+			 	<li>$r.render($config)</li>
+			#end
+		#end
+		#if($systems && $systems.size() > 0)
+			<li role="presentation" class="divider"></li>
+			<li role="presentation" class="dropdown-header">$r.translate("topnav.my.menu.systems")</li>
+			#foreach($system in $systems)
+			 	<li>$r.render($system)</li>
+			#end
 		#end
+		<li role="presentation" class="divider"></li>
 	#end
-	<li role="presentation" class="divider"></li>
 	<li>
 		## make logout link very basic without onClick handler in case javaScript is broken it is still possible to log out
 		## except for the onolatunload() method which must be executed to correctly finish SCORM modules (OLAT-6255)
diff --git a/src/main/java/org/olat/gui/control/_content/topnav.html b/src/main/java/org/olat/gui/control/_content/topnav.html
index 04cbd9a6e90b59b9bf0076db880e0a4336f27fe8..6d496be71440c341cadfe2c75c480686de291d01 100644
--- a/src/main/java/org/olat/gui/control/_content/topnav.html
+++ b/src/main/java/org/olat/gui/control/_content/topnav.html
@@ -1,7 +1,9 @@
 <div id="$r.getCId()" class="o_navbar_tools">
 	<ul id="o_navbar_tools_permanent" class="nav o_navbar-nav o_navbar-right">
-	#foreach($personalTool in $toolSet)
-		 <li #if($personalTool.shortCutCssId) id="$personalTool.shortCutCssId" #end class="o_navbar_tool #if($personalTool.shortCutCssClass) $personalTool.shortCutCssClass #end">$r.render($personalTool.shortCutComponentName)</li>
+	#if(!$locked)
+		#foreach($personalTool in $toolSet)
+			 <li #if($personalTool.shortCutCssId) id="$personalTool.shortCutCssId" #end class="o_navbar_tool #if($personalTool.shortCutCssClass) $personalTool.shortCutCssClass #end">$r.render($personalTool.shortCutComponentName)</li>
+		#end
 	#end
 	#if (!$isGuest && !$isInvitee)
 		<li id="o_navbar_my_menu" class="o_portrait">
diff --git a/src/main/java/org/olat/login/AfterLoginInterceptionController.java b/src/main/java/org/olat/login/AfterLoginInterceptionController.java
index 63533746dee055b34ed480880a6597bcd99d27db..3d1e30d821e97ce9af635bfecaf6bc7a56e8439f 100644
--- a/src/main/java/org/olat/login/AfterLoginInterceptionController.java
+++ b/src/main/java/org/olat/login/AfterLoginInterceptionController.java
@@ -64,7 +64,6 @@ public class AfterLoginInterceptionController extends BasicController {
 	private List<Map<String, Object>> aftctrls;
 	private int actualCtrNr;
 	private List<Property> ctrlPropList;
-	private PropertyManager pm;
 	private boolean actualForceUser;
 	// must match with keys in XML
 	private static final String CONTROLLER_KEY = "controller";
@@ -76,6 +75,8 @@ public class AfterLoginInterceptionController extends BasicController {
 	
 	private static final String PROPERTY_CAT = "afterLogin";
 	
+	@Autowired
+	private PropertyManager pm;
 	@Autowired
 	private AfterLoginInterceptionManager aLIM;
 
@@ -95,7 +96,6 @@ public class AfterLoginInterceptionController extends BasicController {
 		
 		// load all UserProps concerning afterlogin/runOnce workflow => only 1
 		// db-call for all props
-		pm = PropertyManager.getInstance();
 		ctrlPropList = pm.listProperties(ureq.getIdentity(), null, null, null, PROPERTY_CAT, null);
 
 		// loop over possible controllers and check if user already did it before configured timeout
diff --git a/src/main/java/org/olat/login/AuthBFWCParts.java b/src/main/java/org/olat/login/AuthBFWCParts.java
index b312464d14f44ed0d2828823490f24be382ca4f0..11726e0d28054d1bd1bbad3db1b4ec45afe1ef8c 100644
--- a/src/main/java/org/olat/login/AuthBFWCParts.java
+++ b/src/main/java/org/olat/login/AuthBFWCParts.java
@@ -29,6 +29,7 @@ import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
@@ -80,14 +81,14 @@ public class AuthBFWCParts implements BaseFullWebappControllerParts {
 	 * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createTopNavController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
 	 */
 	@Override
-	public Controller createTopNavController(UserRequest ureq, WindowControl wControl) {
+	public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) {
 		Controller topnavCtr = null;
 		// ----------- topnav, optional (e.g. for imprint, logout) ------------------		
 		if (CoreSpringFactory.containsBean("fullWebApp.TopNavControllerCreator")) {
 			ControllerCreator topnavControllerCreator = (ControllerCreator) CoreSpringFactory.getBean("fullWebApp.TopNavControllerCreator");
 			topnavCtr = topnavControllerCreator.createController(ureq, wControl);
 		}
-		return topnavCtr;
+		return (TopNavController)topnavCtr;
 	}
 
 	/**
diff --git a/src/main/java/org/olat/login/DmzBFWCParts.java b/src/main/java/org/olat/login/DmzBFWCParts.java
index 28195534b465a8fac3c7384059a7afd308874a03..5f04f4447d714562f9c648a2d79c147ffee63a3a 100644
--- a/src/main/java/org/olat/login/DmzBFWCParts.java
+++ b/src/main/java/org/olat/login/DmzBFWCParts.java
@@ -28,6 +28,7 @@ import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
@@ -36,10 +37,6 @@ import org.olat.core.gui.control.navigation.SiteInstance;
 import org.olat.gui.control.OlatFooterController;
 
 /**
- * Description:<br>
- * TODO: patrickb Class Description for DmzBFWCParts
- * 
- * <P>
  * Initial Date:  29.01.2008 <br>
  * @author patrickb
  */
@@ -48,9 +45,7 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts {
 	private ControllerCreator contentControllerCreator;
 	private boolean showTopNav = true; // default
 
-	/**
-	 * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createFooterController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
-	 */
+	@Override
 	public Controller createFooterController(UserRequest ureq, WindowControl wControl) {
 		Controller footerCtr = null;
 		// ----------- footer, optional (e.g. for copyright, powered by) ------------------
@@ -63,9 +58,7 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts {
 		return footerCtr;
 	}
 
-	/**
-	 * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createHeaderController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
-	 */
+	@Override
 	public Controller createHeaderController(UserRequest ureq, WindowControl wControl) {
 		Controller headerCtr = null;
 		// ----------- header, optional (e.g. for logo, advertising ) ------------------		
@@ -76,15 +69,13 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts {
 		return headerCtr;
 	}
 
-	/**
-	 * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createTopNavController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
-	 */
-	public Controller createTopNavController(UserRequest ureq, WindowControl wControl) {
+	@Override
+	public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) {
 		if (showTopNav) {
-			Controller topNavCtr = null;
+			TopNavController topNavCtr = null;
 			if (CoreSpringFactory.containsBean("fullWebApp.DMZTopNavControllerCreator")) {
 				ControllerCreator headerControllerCreator = (ControllerCreator)  CoreSpringFactory.getBean("fullWebApp.DMZTopNavControllerCreator");
-				topNavCtr = headerControllerCreator.createController(ureq, wControl);
+				topNavCtr = (TopNavController)headerControllerCreator.createController(ureq, wControl);
 			}
 			return topNavCtr;
 		} else {
@@ -95,14 +86,14 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts {
 	public void setContentControllerCreator(ControllerCreator contentControllerCreator){
 		this.contentControllerCreator = contentControllerCreator;
 	}
-	
+
+	@Override
 	public Controller getContentController(UserRequest ureq, WindowControl wControl) {
 		return contentControllerCreator.createController(ureq, wControl);
 	}
 
-	/**
-	 * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#getSiteInstances(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
-	 */
+
+	@Override
 	public List<SiteInstance> getSiteInstances(UserRequest ureq, WindowControl wControl) {
 		return null;
 	}
@@ -116,5 +107,4 @@ public class DmzBFWCParts implements BaseFullWebappControllerParts {
 	public void showTopNav(boolean showTopNavController) {
 		this.showTopNav = showTopNavController ;
 	}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/login/GuestBFWCParts.java b/src/main/java/org/olat/login/GuestBFWCParts.java
index ebab38669337533d64cf3d87189c756252713acb..adc2be7d853d638181e3622845126fea9e07a381 100644
--- a/src/main/java/org/olat/login/GuestBFWCParts.java
+++ b/src/main/java/org/olat/login/GuestBFWCParts.java
@@ -29,6 +29,7 @@ import java.util.List;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts;
+import org.olat.core.commons.fullWebApp.TopNavController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
@@ -84,12 +85,12 @@ public class GuestBFWCParts implements BaseFullWebappControllerParts {
 	 * @see org.olat.core.commons.fullWebApp.BaseFullWebappControllerParts#createTopNavController(org.olat.core.gui.UserRequest, org.olat.core.gui.control.WindowControl)
 	 */
 	@Override
-	public Controller createTopNavController(UserRequest ureq, WindowControl wControl) {
+	public TopNavController createTopNavController(UserRequest ureq, WindowControl wControl) {
 		if (showTopNav) {
-			Controller topNavCtr = null;
+			TopNavController topNavCtr = null;
 			if (CoreSpringFactory.containsBean("fullWebApp.GuestTopNavControllerCreator")) {
 				ControllerCreator headerControllerCreator = (ControllerCreator)  CoreSpringFactory.getBean("fullWebApp.GuestTopNavControllerCreator");
-				topNavCtr = headerControllerCreator.createController(ureq, wControl);
+				topNavCtr = (TopNavController)headerControllerCreator.createController(ureq, wControl);
 			}
 			return topNavCtr;
 		} else {
diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
index 3b11b3d0ed5cde7f9886dda16ff08f838ce2dfe7..0ca15dd2eaa1f6afc22c90c843ac3299e2c24ba1 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
@@ -288,6 +288,35 @@ public class RepositoryEntryRelationDAO {
 		return query.getResultList();
 	}
 	
+	public List<Long> getMemberKeys(RepositoryEntryRef re, RepositoryEntryRelationType type, String... roles) {
+		List<String> roleList = GroupRoles.toList(roles);
+		
+		String def;
+		switch(type) {
+			case defaultGroup: def = " on relGroup.defaultGroup=true"; break;
+			case notDefaultGroup: def = " on relGroup.defaultGroup=false"; break;
+			default: def = "";
+		}
+		
+		StringBuilder sb = new StringBuilder();
+		sb.append("select members.identity.key from ").append(RepositoryEntry.class.getName()).append(" as v")
+		  .append(" inner join v.groups as relGroup").append(def)
+		  .append(" inner join relGroup.group as baseGroup")
+		  .append(" inner join baseGroup.members as members")
+		  .append(" where v.key=:repoKey");
+		if(roleList.size() > 0) {
+				sb.append(" and members.role in (:roles)");
+		}
+			
+		TypedQuery<Long> query = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Long.class)
+				.setParameter("repoKey", re.getKey());
+		if(roleList.size() > 0) {
+				query.setParameter("roles", roleList);
+		}
+		return query.getResultList();
+	}
+	
 	public boolean removeMembers(RepositoryEntry re, List<Identity> members) {
 		Group group = getDefaultGroup(re);
 		for(Identity member:members) {
diff --git a/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java b/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java
index 144e01d6fb47a9262cf0a2e642b68e28df22bbb2..6eab9fe96a562110c796aea38b61332530e2010d 100644
--- a/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java
+++ b/src/test/java/org/olat/course/assessment/manager/AssessmentModeManagerTest.java
@@ -101,7 +101,7 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(savedMode.getLastModified());
 
 		//reload and check
-		AssessmentMode reloadedMode = assessmentModeMgr.loadById(savedMode.getKey());
+		AssessmentMode reloadedMode = assessmentModeMgr.getAssessmentModeById(savedMode.getKey());
 		Assert.assertNotNull(reloadedMode);
 		Assert.assertEquals(savedMode.getKey(), reloadedMode.getKey());
 		Assert.assertNotNull(reloadedMode.getCreationDate());
@@ -142,7 +142,7 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		Assert.assertNotNull(savedMode);
 		
-		List<AssessmentMode> assessmentModes = assessmentModeMgr.loadAssessmentMode(entry);
+		List<AssessmentMode> assessmentModes = assessmentModeMgr.getAssessmentModeFor(entry);
 		Assert.assertNotNull(assessmentModes);
 		Assert.assertEquals(1, assessmentModes.size());
 		Assert.assertEquals(savedMode, assessmentModes.get(0));
@@ -164,7 +164,7 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		AssessmentMode savedMode = assessmentModeMgr.save(mode);
 		dbInstance.commitAndCloseSession();
 		
-		AssessmentMode reloadedMode = assessmentModeMgr.loadById(mode.getKey());
+		AssessmentMode reloadedMode = assessmentModeMgr.getAssessmentModeById(mode.getKey());
 		Assert.assertEquals(mode, reloadedMode);
 		Assert.assertEquals(savedMode, reloadedMode);
 		Assert.assertNotNull(reloadedMode.getGroups());
@@ -182,7 +182,7 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(mode);
 		
 		//check
-		List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentMode(entry);
+		List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(entry);
 		Assert.assertNotNull(currentModes);
 		Assert.assertEquals(1, currentModes.size());
 		Assert.assertTrue(currentModes.contains(mode));
@@ -197,7 +197,7 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(mode);
 		
 		//check
-		List<AssessmentMode> currentModes = assessmentModeMgr.loadCurrentAssessmentModes();
+		List<AssessmentMode> currentModes = assessmentModeMgr.getCurrentAssessmentModes();
 		Assert.assertNotNull(currentModes);
 		Assert.assertFalse(currentModes.isEmpty());
 		Assert.assertTrue(currentModes.contains(mode));
@@ -229,18 +229,18 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(mode);
 		
 		//check participant
-		List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant);
+		List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant);
 		Assert.assertNotNull(currentModes);
 		Assert.assertEquals(1, currentModes.size());
 		Assert.assertTrue(currentModes.contains(mode));
 		
 		//check coach
-		List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach);
+		List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach);
 		Assert.assertNotNull(currentCoachModes);
 		Assert.assertTrue(currentCoachModes.isEmpty());
 		
 		//check author
-		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author);
+		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author);
 		Assert.assertNotNull(currentAuthorModes);
 		Assert.assertTrue(currentAuthorModes.isEmpty());
 	}
@@ -272,19 +272,19 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(mode);
 		
 		//check participant
-		List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant);
+		List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant);
 		Assert.assertNotNull(currentModes);
 		Assert.assertEquals(1, currentModes.size());
 		Assert.assertTrue(currentModes.contains(mode));
 		
 		//check coach
-		List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach);
+		List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach);
 		Assert.assertNotNull(currentCoachModes);
 		Assert.assertEquals(1, currentCoachModes.size());
 		Assert.assertTrue(currentCoachModes.contains(mode));
 		
 		//check author
-		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author);
+		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author);
 		Assert.assertNotNull(currentAuthorModes);
 		Assert.assertTrue(currentAuthorModes.isEmpty());
 	}
@@ -307,18 +307,18 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(mode);
 		
 		//check participant
-		List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant);
+		List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant);
 		Assert.assertNotNull(currentModes);
 		Assert.assertEquals(1, currentModes.size());
 		Assert.assertTrue(currentModes.contains(mode));
 		
 		//check coach
-		List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach);
+		List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach);
 		Assert.assertNotNull(currentCoachModes);
 		Assert.assertTrue(currentCoachModes.isEmpty());
 		
 		//check author
-		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author);
+		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author);
 		Assert.assertNotNull(currentAuthorModes);
 		Assert.assertTrue(currentAuthorModes.isEmpty());
 	}
@@ -341,19 +341,19 @@ public class AssessmentModeManagerTest extends OlatTestCase {
 		Assert.assertNotNull(mode);
 		
 		//check participant
-		List<AssessmentMode> currentModes = assessmentModeMgr.loadAssessmentModeFor(participant);
+		List<AssessmentMode> currentModes = assessmentModeMgr.getAssessmentModeFor(participant);
 		Assert.assertNotNull(currentModes);
 		Assert.assertEquals(1, currentModes.size());
 		Assert.assertTrue(currentModes.contains(mode));
 		
 		//check coach
-		List<AssessmentMode> currentCoachModes = assessmentModeMgr.loadAssessmentModeFor(coach);
+		List<AssessmentMode> currentCoachModes = assessmentModeMgr.getAssessmentModeFor(coach);
 		Assert.assertNotNull(currentCoachModes);
 		Assert.assertEquals(1, currentCoachModes.size());
 		Assert.assertTrue(currentCoachModes.contains(mode));
 		
 		//check author
-		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.loadAssessmentModeFor(author);
+		List<AssessmentMode> currentAuthorModes = assessmentModeMgr.getAssessmentModeFor(author);
 		Assert.assertNotNull(currentAuthorModes);
 		Assert.assertTrue(currentAuthorModes.isEmpty());
 	}