001/*
002 * (C) Copyright 2006-2008 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 *     Razvan Caraghin
018 *     Olivier Grisel
019 *     Thierry Delprat
020 *     Florent Guillaume
021 */
022
023package org.nuxeo.ecm.webapp.delegate;
024
025import static org.jboss.seam.ScopeType.CONVERSATION;
026
027import java.io.Serializable;
028import java.util.HashMap;
029import java.util.Map;
030import java.util.Map.Entry;
031
032import javax.annotation.security.PermitAll;
033import javax.security.auth.login.LoginContext;
034import javax.security.auth.login.LoginException;
035
036import org.apache.commons.logging.Log;
037import org.apache.commons.logging.LogFactory;
038import org.jboss.seam.Component;
039import org.jboss.seam.annotations.Destroy;
040import org.jboss.seam.annotations.Name;
041import org.jboss.seam.annotations.Scope;
042import org.jboss.seam.annotations.Unwrap;
043import org.jboss.seam.contexts.Lifecycle;
044import org.nuxeo.ecm.core.api.CloseableCoreSession;
045import org.nuxeo.ecm.core.api.CoreInstance;
046import org.nuxeo.ecm.core.api.CoreSession;
047import org.nuxeo.ecm.core.api.repository.Repository;
048import org.nuxeo.ecm.platform.util.RepositoryLocation;
049import org.nuxeo.runtime.api.Framework;
050
051/**
052 * Acquires a {@link CoreSession} connection.
053 *
054 * @author Razvan Caraghin
055 * @author Olivier Grisel
056 * @author Thierry Delprat
057 * @author Florent Guillaume
058 */
059@Name("documentManager")
060@Scope(CONVERSATION)
061public class DocumentManagerBusinessDelegate implements Serializable {
062
063    private static final long serialVersionUID = 1L;
064
065    private static final Log log = LogFactory.getLog(DocumentManagerBusinessDelegate.class);
066
067    /**
068     * Map holding the open session for each repository location.
069     */
070    protected final Map<RepositoryLocation, CloseableCoreSession> sessions = new HashMap<>();
071
072    public void initialize() {
073        log.debug("Seam component initialized...");
074    }
075
076    @Unwrap
077    public CoreSession getDocumentManager() {
078        /*
079         * Explicit lookup, as this method is the only user of the Seam component. Also, in some cases (Seam remoting),
080         * it seems that the injection is not done correctly.
081         */
082        RepositoryLocation currentServerLocation = (RepositoryLocation) Component.getInstance("currentServerLocation");
083        return getDocumentManager(currentServerLocation);
084    }
085
086    public CoreSession getDocumentManager(RepositoryLocation serverLocation) {
087
088        if (serverLocation == null) {
089            /*
090             * currentServerLocation (factory in ServerContextBean) is set through navigationContext, which itself
091             * injects documentManager, so it will be null the first time.
092             */
093            return null;
094        }
095
096        CloseableCoreSession session = sessions.get(serverLocation);
097        if (session == null) {
098            if (Lifecycle.isDestroying()) {
099                /*
100                 * During Seam component destroy phases, we don't want to recreate a core session just for injection.
101                 * This happens during logout when the session context is destroyed; we don't want to cause EJB calls in
102                 * this case as the authentication wouldn't work.
103                 */
104                return null;
105            }
106            String serverName = serverLocation.getName();
107            session = CoreInstance.openCoreSession(serverName);
108            log.debug("Opened session for repository " + serverName);
109            sessions.put(serverLocation, session);
110        }
111        return session;
112    }
113
114    @Destroy
115    @PermitAll
116    public void remove() {
117        LoginContext lc = null;
118        try {
119            try {
120                if (Framework.getRuntime() != null) {
121                    lc = Framework.login();
122                }
123            } catch (LoginException le) {
124                log.error("Unable to login as System", le);
125                log.warn("...try to feed CoreSession(s) without system login ...");
126            }
127            for (Entry<RepositoryLocation, CloseableCoreSession> entry : sessions.entrySet()) {
128                String serverName = entry.getKey().getName();
129                CloseableCoreSession session = entry.getValue();
130                session.close();
131                log.debug("Closed session for repository " + serverName);
132            }
133        } finally {
134            if (lc != null) {
135                try {
136                    lc.logout();
137                } catch (LoginException lo) {
138                    log.error("Error when logout", lo);
139                }
140            }
141            sessions.clear();
142        }
143    }
144}