001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * bstefanescu 018 */ 019package org.nuxeo.ecm.automation; 020 021import java.util.ArrayList; 022import java.util.List; 023 024import javax.security.auth.login.LoginContext; 025import javax.security.auth.login.LoginException; 026 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.ecm.core.api.CoreInstance; 030import org.nuxeo.ecm.core.api.CoreSession; 031 032/** 033 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 034 */ 035public class LoginStack { 036 037 protected List<Entry> stack = new ArrayList<>(); 038 039 protected CoreSession originalSession; 040 041 protected CoreSession currentSession; 042 043 public LoginStack(CoreSession session) { 044 setSession(session); 045 } 046 047 public void setSession(CoreSession session) { 048 originalSession = session; 049 currentSession = session; 050 } 051 052 /** 053 * Get the current session 054 */ 055 public CoreSession getSession() { 056 return currentSession; 057 } 058 059 public void push(LoginContext lc) { 060 Entry entry = new Entry(lc); 061 String repositoryName; 062 if (originalSession != null) { 063 repositoryName = originalSession.getRepositoryName(); 064 } else { 065 repositoryName = null; // default repository 066 } 067 entry.session = CoreInstance.getCoreSession(repositoryName); 068 currentSession = entry.session; 069 stack.add(entry); 070 } 071 072 public Entry peek() { 073 if (!stack.isEmpty()) { 074 return stack.get(stack.size() - 1); 075 } 076 return null; 077 } 078 079 /** 080 * Remove the current login context from the stack. 081 * <p> 082 * If no login context in in the stack nothing is done. If the login context has an associated CoreSession the 083 * session will be destroyed and the previous session is restored as the active session of the operation context. 084 */ 085 public void pop() { 086 if (!stack.isEmpty()) { 087 Entry entry = stack.remove(stack.size() - 1); 088 entry.dispose(); 089 entry = peek(); 090 if (entry != null) { 091 currentSession = entry.session; 092 } else { 093 currentSession = originalSession; 094 } 095 } 096 } 097 098 /** 099 * Remove the stacked logins if any. This is called when chain execution is done. 100 */ 101 protected void clear() { 102 if (!stack.isEmpty()) { 103 for (int i = stack.size() - 1; i > -1; i--) { 104 stack.get(i).dispose(); 105 } 106 stack.clear(); 107 currentSession = originalSession; 108 stack.clear(); 109 } 110 } 111 112 public static class Entry { 113 114 private static final Log log = LogFactory.getLog(Entry.class); 115 116 public LoginContext lc; 117 118 public CoreSession session; 119 120 public Entry(LoginContext lc) { 121 this.lc = lc; 122 } 123 124 public final boolean hasSession() { 125 return session != null; 126 } 127 128 public final void dispose() { 129 try { 130 if (session != null) { 131 session.save(); 132 } 133 } finally { 134 try { 135 session = null; 136 lc.logout(); 137 lc = null; 138 } catch (LoginException e) { 139 log.error(e); // don't rethrow inside finally 140 } 141 } 142 } 143 } 144 145}