001/*
002 * (C) Copyright 2006-2016 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 java.security.Principal;
023import java.util.ArrayList;
024import java.util.function.Consumer;
025import java.util.function.Function;
026
027import org.apache.commons.lang3.mutable.MutableObject;
028import org.nuxeo.ecm.core.api.impl.UserPrincipal;
029import org.nuxeo.ecm.core.api.repository.RepositoryManager;
030import org.nuxeo.runtime.api.Framework;
031import org.nuxeo.runtime.api.login.LoginComponent;
032
033/**
034 * The CoreInstance is the main access point to a CoreSession.
035 */
036public class CoreInstance {
037
038    private CoreInstance() {
039    }
040
041    /**
042     * Gets a {@link CoreSession} for the currently logged-in user.
043     *
044     * @param repositoryName the repository name, or {@code null} for the default repository
045     * @return the session
046     * @since 11.1
047     */
048    public static CoreSession getCoreSession(String repositoryName) {
049        return getCoreSession(repositoryName, getPrincipal(null));
050    }
051
052    /**
053     * MUST ONLY BE USED IN UNIT TESTS to get a {@link CoreSession} for the given user.
054     *
055     * @param repositoryName the repository name, or {@code null} for the default repository
056     * @param username the user name
057     * @return the session
058     * @since 11.1
059     */
060    public static CoreSession getCoreSession(String repositoryName, String username) {
061        return getCoreSession(repositoryName, getPrincipal(username));
062    }
063
064    /**
065     * Gets a {@link CoreSession} for a system user.
066     *
067     * @param repositoryName the repository name, or {@code null} for the default repository
068     * @return the session
069     * @since 11.1
070     */
071    public static CoreSession getCoreSessionSystem(String repositoryName) {
072        return getCoreSession(repositoryName, new SystemPrincipal(null));
073    }
074
075    /**
076     * Gets a {@link CoreSession} for a system user with an optional originating username.
077     *
078     * @param repositoryName the repository name, or {@code null} for the default repository
079     * @param originatingUsername the originating username to set on the SystemPrincipal
080     * @return the session
081     * @since 11.1
082     */
083    public static CoreSession getCoreSessionSystem(String repositoryName, String originatingUsername) {
084        return getCoreSession(repositoryName, new SystemPrincipal(originatingUsername));
085    }
086
087    /**
088     * Gets a {@link CoreSession} for the given principal.
089     *
090     * @param repositoryName the repository name, or {@code null} for the default repository
091     * @param principal the principal
092     * @return the session
093     * @since 11.1
094     */
095    public static CoreSession getCoreSession(String repositoryName, NuxeoPrincipal principal) {
096        if (repositoryName == null) {
097            RepositoryManager repositoryManager = Framework.getService(RepositoryManager.class);
098            repositoryName = repositoryManager.getDefaultRepositoryName();
099        }
100        return Framework.getService(CoreSessionService.class).createCoreSession(repositoryName, principal);
101    }
102
103    /**
104     * Opens a {@link CoreSession} for the currently logged-in user.
105     *
106     * @param repositoryName the repository name, or {@code null} for the default repository
107     * @return the session
108     * @since 5.9.3
109     * @deprecated since 11.1, use {@link #getCoreSession(String)} instead
110     */
111    @Deprecated
112    public static CloseableCoreSession openCoreSession(String repositoryName) {
113        return (CloseableCoreSession) getCoreSession(repositoryName);
114    }
115
116    /**
117     * MUST ONLY BE USED IN UNIT TESTS to open a {@link CoreSession} for the given user.
118     *
119     * @param repositoryName the repository name, or {@code null} for the default repository
120     * @param username the user name
121     * @return the session
122     * @since 5.9.3
123     * @deprecated since 11.1, use {@link #getCoreSession(String, String)} instead
124     */
125    @Deprecated
126    public static CloseableCoreSession openCoreSession(String repositoryName, String username) {
127        return (CloseableCoreSession) getCoreSession(repositoryName, username);
128    }
129
130    /**
131     * Opens a {@link CoreSession} for a system user.
132     *
133     * @param repositoryName the repository name, or {@code null} for the default repository
134     * @return the session
135     * @since 5.9.3
136     * @deprecated since 11.1, use {@link #getCoreSessionSystem(String)} instead
137     */
138    @Deprecated
139    public static CloseableCoreSession openCoreSessionSystem(String repositoryName) {
140        return (CloseableCoreSession) getCoreSessionSystem(repositoryName);
141    }
142
143    /**
144     * Opens a {@link CoreSession} for a system user with an optional originating username.
145     *
146     * @param repositoryName the repository name, or {@code null} for the default repository
147     * @param originatingUsername the originating username to set on the SystemPrincipal
148     * @return the session
149     * @since 8.1
150     * @deprecated since 11.1, use {@link #getCoreSessionSystem(String, String)} instead
151     */
152    @Deprecated
153    public static CloseableCoreSession openCoreSessionSystem(String repositoryName, String originatingUsername) {
154        return (CloseableCoreSession) getCoreSessionSystem(repositoryName, originatingUsername);
155    }
156
157    /**
158     * Opens a {@link CoreSession} for the given principal.
159     *
160     * @param repositoryName the repository name, or {@code null} for the default repository
161     * @param principal the principal
162     * @return the session
163     * @since 5.9.3
164     * @deprecated since 11.1, use {@link #getCoreSession(String, NuxeoPrincipal)} instead
165     */
166    @Deprecated
167    public static CloseableCoreSession openCoreSession(String repositoryName, NuxeoPrincipal principal) {
168        return (CloseableCoreSession) getCoreSession(repositoryName, principal);
169    }
170
171    /**
172     * Does nothing.
173     *
174     * @since 5.9.3
175     * @deprecated since 11.1, does nothing
176     */
177    @Deprecated
178    public static void closeCoreSession(CloseableCoreSession session) {
179        // nothing (the session holds no resources to close)
180    }
181
182    protected static NuxeoPrincipal getPrincipal(String username) {
183        if (username != null) {
184            return new UserPrincipal(username, new ArrayList<>(), false, false);
185        } else {
186            Principal p = LoginComponent.getCurrentPrincipal();
187            if (p != null) {
188                if (p instanceof NuxeoPrincipal) {
189                    return (NuxeoPrincipal) p;
190                } else if (LoginComponent.isSystemLogin(p)) {
191                    return new SystemPrincipal(p.getName());
192                } else {
193                    throw new RuntimeException("Unsupported principal: " + p.getClass());
194                }
195            } else {
196                if (Framework.isTestModeSet()) {
197                    return new SystemPrincipal(null);
198                } else {
199                    throw new NuxeoException(
200                            "Cannot create a CoreSession outside a security context, " + " login() missing.");
201                }
202            }
203        }
204    }
205
206    /**
207     * Gets the name of the currently logged-in principal.
208     *
209     * @return the principal name, or {@code null} if there was no login
210     * @since 8.4
211     */
212    protected static String getCurrentPrincipalName() {
213        NuxeoPrincipal p = NuxeoPrincipal.getCurrent();
214        return p == null ? null : p.getName();
215    }
216
217    /**
218     * Runs the given {@link Function} with a system {@link CoreSession} while logged in as a system user.
219     *
220     * @param repositoryName the repository name for the {@link CoreSession}
221     * @param function the function taking a system {@link CoreSession} and returning a result of type {@code <R>}
222     * @param <R> the function return type
223     * @return the result of the function
224     * @since 8.4
225     */
226    public static <R> R doPrivileged(String repositoryName, Function<CoreSession, R> function) {
227        MutableObject<R> result = new MutableObject<>();
228        new UnrestrictedSessionRunner(repositoryName, getCurrentPrincipalName()) {
229            @Override
230            public void run() {
231                result.setValue(function.apply(session));
232            }
233        }.runUnrestricted();
234        return result.getValue();
235    }
236
237    /**
238     * Runs the given {@link Function} with a system {@link CoreSession} while logged in as a system user.
239     *
240     * @param session an existing session
241     * @param function the function taking a system {@link CoreSession} and returning a result of type {@code <R>}
242     * @param <R> the function return type
243     * @return the result of the function
244     * @since 8.4
245     */
246    public static <R> R doPrivileged(CoreSession session, Function<CoreSession, R> function) {
247        MutableObject<R> result = new MutableObject<>();
248        new UnrestrictedSessionRunner(session) {
249            @Override
250            public void run() {
251                result.setValue(function.apply(session));
252            }
253        }.runUnrestricted();
254        return result.getValue();
255    }
256
257    /**
258     * Runs the given {@link Consumer} with a system {@link CoreSession} while logged in as a system user.
259     *
260     * @param repositoryName the repository name for the {@link CoreSession}
261     * @param consumer the consumer taking a system {@link CoreSession}
262     * @since 8.4
263     */
264    public static void doPrivileged(String repositoryName, Consumer<CoreSession> consumer) {
265        new UnrestrictedSessionRunner(repositoryName, getCurrentPrincipalName()) {
266            @Override
267            public void run() {
268                consumer.accept(session);
269            }
270        }.runUnrestricted();
271    }
272
273    /**
274     * Runs the given {@link Consumer} with a system {@link CoreSession} while logged in as a system user.
275     *
276     * @param session an existing session
277     * @param consumer the consumer taking a system {@link CoreSession}
278     * @since 8.4
279     */
280    public static void doPrivileged(CoreSession session, Consumer<CoreSession> consumer) {
281        new UnrestrictedSessionRunner(session) {
282            @Override
283            public void run() {
284                consumer.accept(session);
285            }
286        }.runUnrestricted();
287    }
288
289}