001/* 002 * (C) Copyright 2006-2014 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 * Bogdan Stefanescu 018 * Florent Guillaume 019 */ 020package org.nuxeo.ecm.core.api; 021 022import static org.nuxeo.ecm.core.api.security.SecurityConstants.SYSTEM_USERNAME; 023 024import java.io.Serializable; 025import java.security.Principal; 026import java.util.ArrayList; 027import java.util.Collection; 028import java.util.Map; 029import java.util.function.Consumer; 030import java.util.function.Function; 031 032import org.apache.commons.lang3.mutable.MutableObject; 033import org.nuxeo.ecm.core.api.CoreSessionService.CoreSessionRegistrationInfo; 034import org.nuxeo.ecm.core.api.impl.UserPrincipal; 035import org.nuxeo.ecm.core.api.local.ClientLoginModule; 036import org.nuxeo.ecm.core.api.local.LoginStack; 037import org.nuxeo.ecm.core.api.repository.RepositoryManager; 038import org.nuxeo.ecm.core.api.security.SecurityConstants; 039import org.nuxeo.runtime.api.Framework; 040import org.nuxeo.runtime.api.login.LoginComponent; 041 042/** 043 * The CoreInstance is the main access point to a CoreSession. 044 */ 045public class CoreInstance { 046 047 private static final CoreInstance INSTANCE = new CoreInstance(); 048 049 private CoreInstance() { 050 } 051 052 /** 053 * Gets the CoreInstance singleton. 054 * 055 * @deprecated since 8.4, use {@link CoreSessionService} directly. 056 */ 057 public static CoreInstance getInstance() { 058 return INSTANCE; 059 } 060 061 /** 062 * Opens a {@link CoreSession} for the currently logged-in user. 063 * <p> 064 * The session must be closed using {@link CoreSession#close}. 065 * 066 * @param repositoryName the repository name, or {@code null} for the default repository 067 * @return the session 068 * @since 5.9.3 069 */ 070 public static CoreSession openCoreSession(String repositoryName) { 071 return openCoreSession(repositoryName, getPrincipal((String) null)); 072 } 073 074 /** 075 * MUST ONLY BE USED IN UNIT TESTS to open a {@link CoreSession} for the given user. 076 * <p> 077 * The session must be closed using {@link CoreSession#close}. 078 * 079 * @param repositoryName the repository name, or {@code null} for the default repository 080 * @param username the user name 081 * @return the session 082 * @since 5.9.3 083 */ 084 public static CoreSession openCoreSession(String repositoryName, String username) { 085 return openCoreSession(repositoryName, getPrincipal(username)); 086 } 087 088 /** 089 * Opens a {@link CoreSession} for a system user. 090 * <p> 091 * The session must be closed using {@link CoreSession#close}. 092 * 093 * @param repositoryName the repository name, or {@code null} for the default repository 094 * @return the session 095 * @since 5.9.3 096 */ 097 public static CoreSession openCoreSessionSystem(String repositoryName) { 098 return openCoreSession(repositoryName, getPrincipal((SecurityConstants.SYSTEM_USERNAME))); 099 } 100 101 /** 102 * Opens a {@link CoreSession} for a system user with an optional originating username. 103 * <p> 104 * The session must be closed using {@link CoreSession#close}. 105 * 106 * @param repositoryName the repository name, or {@code null} for the default repository 107 * @param originatingUsername the originating username to set on the SystemPrincipal 108 * @return the session 109 * @since 8.1 110 */ 111 public static CoreSession openCoreSessionSystem(String repositoryName, String originatingUsername) { 112 NuxeoPrincipal principal = getPrincipal((SecurityConstants.SYSTEM_USERNAME)); 113 principal.setOriginatingUser(originatingUsername); 114 return openCoreSession(repositoryName, principal); 115 } 116 117 /** 118 * @deprecated since 5.9.3, use {@link #openCoreSession} instead. 119 */ 120 @Deprecated 121 public CoreSession open(String repositoryName, Map<String, Serializable> context) { 122 return openCoreSession(repositoryName, getPrincipal(context)); 123 } 124 125 /** 126 * NOT PUBLIC, DO NOT CALL. Kept public for compatibility with old code. 127 * <p> 128 * Opens a {@link CoreSession} for the given context. 129 * 130 * @param repositoryName the repository name, or {@code null} for the default repository 131 * @param context the session open context 132 * @return the session 133 */ 134 public static CoreSession openCoreSession(String repositoryName, Map<String, Serializable> context) { 135 return openCoreSession(repositoryName, getPrincipal(context)); 136 } 137 138 /** 139 * MUST ONLY BE USED IN UNIT TESTS to open a {@link CoreSession} for the given principal. 140 * <p> 141 * The session must be closed using {@link CoreSession#close}. 142 * 143 * @param repositoryName the repository name, or {@code null} for the default repository 144 * @param principal the principal 145 * @return the session 146 * @since 5.9.3 147 */ 148 public static CoreSession openCoreSession(String repositoryName, Principal principal) { 149 if (principal instanceof NuxeoPrincipal) { 150 return openCoreSession(repositoryName, (NuxeoPrincipal) principal); 151 } else { 152 return openCoreSession(repositoryName, getPrincipal(principal.getName())); 153 } 154 } 155 156 /** 157 * MUST ONLY BE USED IN UNIT TESTS to open a {@link CoreSession} for the given principal. 158 * <p> 159 * The session must be closed using {@link CoreSession#close}. 160 * 161 * @param repositoryName the repository name, or {@code null} for the default repository 162 * @param principal the principal 163 * @return the session 164 * @since 5.9.3 165 */ 166 public static CoreSession openCoreSession(String repositoryName, NuxeoPrincipal principal) { 167 if (repositoryName == null) { 168 RepositoryManager repositoryManager = Framework.getLocalService(RepositoryManager.class); 169 repositoryName = repositoryManager.getDefaultRepository().getName(); 170 } 171 return Framework.getService(CoreSessionService.class).createCoreSession(repositoryName, principal); 172 } 173 174 /** 175 * Gets an existing open session for the given session id. 176 * <p> 177 * The returned CoreSession must not be closed, as it is owned by someone else. 178 * 179 * @param sessionId the session id 180 * @return the session, which must not be closed 181 */ 182 public CoreSession getSession(String sessionId) { 183 return Framework.getService(CoreSessionService.class).getCoreSession(sessionId); 184 } 185 186 /** 187 * Use {@link CoreSession#close} instead. 188 * 189 * @since 5.9.3 190 */ 191 public static void closeCoreSession(CoreSession session) { 192 Framework.getService(CoreSessionService.class).releaseCoreSession(session); 193 } 194 195 protected static NuxeoPrincipal getPrincipal(Map<String, Serializable> map) { 196 if (map == null) { 197 return getPrincipal((String) null); // logged-in principal 198 } 199 NuxeoPrincipal principal = (NuxeoPrincipal) map.get("principal"); 200 if (principal == null) { 201 principal = getPrincipal((String) map.get("username")); 202 } 203 return principal; 204 } 205 206 protected static NuxeoPrincipal getPrincipal(String username) { 207 if (username != null) { 208 if (SYSTEM_USERNAME.equals(username)) { 209 return new SystemPrincipal(null); 210 } else { 211 return new UserPrincipal(username, new ArrayList<String>(), false, false); 212 } 213 } else { 214 LoginStack.Entry entry = ClientLoginModule.getCurrentLogin(); 215 if (entry != null) { 216 Principal p = entry.getPrincipal(); 217 if (p instanceof NuxeoPrincipal) { 218 return (NuxeoPrincipal) p; 219 } else if (LoginComponent.isSystemLogin(p)) { 220 return new SystemPrincipal(p.getName()); 221 } else { 222 throw new RuntimeException("Unsupported principal: " + p.getClass()); 223 } 224 } else { 225 if (Framework.isTestModeSet()) { 226 return new SystemPrincipal(null); 227 } else { 228 throw new NuxeoException("Cannot create a CoreSession outside a security context, " 229 + " login() missing."); 230 } 231 } 232 } 233 } 234 235 /** 236 * @deprecated since 5.9.3, use {@link CoreSession#close} instead. 237 */ 238 @Deprecated 239 public void close(CoreSession session) { 240 session.close(); // calls back closeCoreSession 241 } 242 243 /** 244 * Gets the number of open sessions. 245 * 246 * @since 5.4.2 247 * @deprecated since 8.4, use {@link CoreSessionService#getNumberOfOpenSessions} directly 248 */ 249 public int getNumberOfSessions() { 250 return Framework.getService(CoreSessionService.class).getNumberOfOpenCoreSessions(); 251 } 252 253 /** 254 * Gets the number of open sessions. 255 * 256 * @since 5.4.2 257 * @deprecated since 8.4, use {@link CoreSessionService#getRegistrationInfos} directly 258 */ 259 public Collection<CoreSessionRegistrationInfo> getRegistrationInfos() { 260 return Framework.getService(CoreSessionService.class).getCoreSessionRegistrationInfos(); 261 } 262 263 /** 264 * Gets the name of the currently logged-in principal. 265 * 266 * @return the principal name, or {@code null} if there was no login 267 * @since 8.4 268 */ 269 protected static String getCurrentPrincipalName() { 270 Principal p = ClientLoginModule.getCurrentPrincipal(); 271 return p == null ? null : p.getName(); 272 } 273 274 /** 275 * Runs the given {@link Function} with a system {@link CoreSession} while logged in as a system user. 276 * 277 * @param repositoryName the repository name for the {@link CoreSession} 278 * @param function the function taking a system {@link CoreSession} and returning a result of type {@code <R>} 279 * @param <R> the function return type 280 * @return the result of the function 281 * @since 8.4 282 */ 283 public static <R> R doPrivileged(String repositoryName, Function<CoreSession, R> function) { 284 MutableObject<R> result = new MutableObject<R>(); 285 new UnrestrictedSessionRunner(repositoryName, getCurrentPrincipalName()) { 286 @Override 287 public void run() { 288 result.setValue(function.apply(session)); 289 } 290 }.runUnrestricted(); 291 return result.getValue(); 292 } 293 294 /** 295 * Runs the given {@link Function} with a system {@link CoreSession} while logged in as a system user. 296 * 297 * @param session an existing session 298 * @param function the function taking a system {@link CoreSession} and returning a result of type {@code <R>} 299 * @param <R> the function return type 300 * @return the result of the function 301 * @since 8.4 302 */ 303 public static <R> R doPrivileged(CoreSession session, Function<CoreSession, R> function) { 304 MutableObject<R> result = new MutableObject<R>(); 305 new UnrestrictedSessionRunner(session) { 306 @Override 307 public void run() { 308 result.setValue(function.apply(session)); 309 } 310 }.runUnrestricted(); 311 return result.getValue(); 312 } 313 314 /** 315 * Runs the given {@link Consumer} with a system {@link CoreSession} while logged in as a system user. 316 * 317 * @param repositoryName the repository name for the {@link CoreSession} 318 * @param consumer the consumer taking a system {@link CoreSession} 319 * @since 8.4 320 */ 321 public static void doPrivileged(String repositoryName, Consumer<CoreSession> consumer) { 322 new UnrestrictedSessionRunner(repositoryName, getCurrentPrincipalName()) { 323 @Override 324 public void run() { 325 consumer.accept(session); 326 } 327 }.runUnrestricted(); 328 } 329 330 /** 331 * Runs the given {@link Consumer} with a system {@link CoreSession} while logged in as a system user. 332 * 333 * @param session an existing session 334 * @param consumer the consumer taking a system {@link CoreSession} 335 * @since 8.4 336 */ 337 public static void doPrivileged(CoreSession session, Consumer<CoreSession> consumer) { 338 new UnrestrictedSessionRunner(session) { 339 @Override 340 public void run() { 341 consumer.accept(session); 342 } 343 }.runUnrestricted(); 344 } 345 346}