001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * bstefanescu 011 */ 012package org.nuxeo.ecm.automation; 013 014import java.util.ArrayList; 015import java.util.List; 016 017import javax.security.auth.login.LoginContext; 018import javax.security.auth.login.LoginException; 019 020import org.nuxeo.ecm.core.api.CoreInstance; 021import org.nuxeo.ecm.core.api.CoreSession; 022 023/** 024 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 025 */ 026public class LoginStack { 027 028 protected List<Entry> stack = new ArrayList<Entry>(); 029 030 protected CoreSession originalSession; 031 032 protected CoreSession currentSession; 033 034 public LoginStack(CoreSession session) { 035 setSession(session); 036 } 037 038 public void setSession(CoreSession session) { 039 originalSession = session; 040 currentSession = session; 041 } 042 043 /** 044 * Get the current session 045 * 046 * @return 047 */ 048 public CoreSession getSession() { 049 return currentSession; 050 } 051 052 public void push(LoginContext lc) { 053 Entry entry = new Entry(lc); 054 String repositoryName; 055 if (originalSession != null) { 056 repositoryName = originalSession.getRepositoryName(); 057 } else { 058 repositoryName = null; // default repository 059 } 060 entry.session = CoreInstance.openCoreSession(repositoryName); 061 currentSession = entry.session; 062 stack.add(entry); 063 } 064 065 public Entry peek() { 066 if (!stack.isEmpty()) { 067 return stack.get(stack.size() - 1); 068 } 069 return null; 070 } 071 072 /** 073 * Remove the current login context from the stack. 074 * <p> 075 * If no login context in in the stack nothing is done. If the login context has an associated CoreSession the 076 * session will be destroyed and the previous session is restored as the active session of the operation context. 077 */ 078 public void pop() throws OperationException { 079 if (!stack.isEmpty()) { 080 Entry entry = stack.remove(stack.size() - 1); 081 entry.dispose(); 082 entry = peek(); 083 if (entry != null) { 084 currentSession = entry.session; 085 } else { 086 currentSession = originalSession; 087 } 088 if (currentSession != null) { 089 refreshSession(currentSession); 090 } 091 } 092 } 093 094 protected void refreshSession(CoreSession session) throws OperationException { 095 if (session != null && !session.isStateSharedByAllThreadSessions()) { 096 // this will indirectly process refresh the session 097 session.save(); 098 } 099 } 100 101 /** 102 * Remove the stacked logins if any. This is called when chain execution is done. 103 */ 104 protected void clear() throws OperationException { 105 if (!stack.isEmpty()) { 106 for (int i = stack.size() - 1; i > -1; i--) { 107 stack.get(i).dispose(); 108 } 109 stack.clear(); 110 currentSession = originalSession; 111 if (currentSession != null) { 112 refreshSession(currentSession); 113 } 114 stack.clear(); 115 } 116 } 117 118 public static class Entry { 119 public LoginContext lc; 120 121 public CoreSession session; 122 123 public Entry(LoginContext lc) { 124 this(lc, null); 125 } 126 127 public Entry(LoginContext lc, CoreSession session) { 128 this.lc = lc; 129 this.session = session; 130 } 131 132 public final boolean hasSession() { 133 return session != null; 134 } 135 136 public final void dispose() throws OperationException { 137 try { 138 if (session != null) { 139 try { 140 session.save(); 141 } finally { 142 session.close(); 143 } 144 } 145 } finally { 146 try { 147 session = null; 148 lc.logout(); 149 lc = null; 150 } catch (LoginException e) { 151 throw new OperationException(e); 152 } 153 } 154 } 155 } 156 157}