/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bstefanescu */ package org.eclipse.ecr.automation; import java.util.ArrayList; import java.util.List; import javax.security.auth.login.LoginContext; import org.eclipse.ecr.core.api.CoreSession; import org.eclipse.ecr.core.api.repository.Repository; import org.eclipse.ecr.core.api.repository.RepositoryManager; import org.eclipse.ecr.runtime.api.Framework; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> * */ public class LoginStack { protected List<Entry> stack = new ArrayList<Entry>(); protected CoreSession originalSession; protected CoreSession currentSession; public LoginStack(CoreSession session) { setSession(session); } public void setSession(CoreSession session) { originalSession = session; currentSession = session; } /** * Get the current session * * @return */ public CoreSession getSession() { return currentSession; } public void push(LoginContext lc) throws OperationException { Entry entry = new Entry(lc); try { if (originalSession != null) { entry.session = Framework.getService(RepositoryManager.class).getRepository( originalSession.getRepositoryName()).open(); currentSession = entry.session; } stack.add(entry); } catch (Exception e) { throw new OperationException( "Failed to create new core session for loginAs", e); } } public Entry peek() { if (!stack.isEmpty()) { return stack.get(stack.size() - 1); } return null; } /** * Remove the current login context from the stack. * <p> * If no login context in in the stack nothing is done. If the login context * has an associated CoreSession the session will be destroyed and the * previous session is restored as the active session of the operation * context. */ public void pop() throws OperationException { if (!stack.isEmpty()) { Entry entry = stack.remove(stack.size() - 1); entry.dispose(); entry = peek(); if (entry != null) { currentSession = entry.session; } else { currentSession = originalSession; } if (currentSession != null) { refreshSession(currentSession); } } } protected void refreshSession(CoreSession session) throws OperationException { if (session != null && !session.isStateSharedByAllThreadSessions()) { try { // this will indirectly process refresh the session session.save(); } catch (Exception e) { throw new OperationException(e); } } } /** * Remove the stacked logins if any. This is called when chain execution is * done. * */ protected void clear() throws OperationException { if (!stack.isEmpty()) { for (int i = stack.size() - 1; i > -1; i--) { stack.get(i).dispose(); } stack.clear(); currentSession = originalSession; if (currentSession != null) { refreshSession(currentSession); } stack.clear(); } } public static class Entry { public LoginContext lc; public CoreSession session; public Entry(LoginContext lc) { this(lc, null); } public Entry(LoginContext lc, CoreSession session) { this.lc = lc; this.session = session; } public final boolean hasSession() { return session != null; } public final void dispose() throws OperationException { try { if (session != null) { session.save(); Repository.close(session); } } catch (Exception e) { throw new OperationException(e); } finally { try { session = null; lc.logout(); lc = null; } catch (Exception e) { throw new OperationException(e); } } } } }