001/*
002 * (C) Copyright 2006-2007 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 *     Nuxeo - initial API and implementation
018 *
019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
020 */
021
022package org.nuxeo.ecm.webapp.helpers;
023
024import static org.jboss.seam.ScopeType.SESSION;
025
026import java.io.Serializable;
027import java.security.Principal;
028import java.util.Collections;
029import java.util.LinkedHashMap;
030import java.util.List;
031import java.util.Map;
032
033import javax.faces.context.FacesContext;
034
035import org.apache.commons.logging.Log;
036import org.apache.commons.logging.LogFactory;
037import org.jboss.seam.annotations.Begin;
038import org.jboss.seam.annotations.In;
039import org.jboss.seam.annotations.Install;
040import org.jboss.seam.annotations.Name;
041import org.jboss.seam.annotations.Scope;
042import org.jboss.seam.contexts.Context;
043import org.jboss.seam.core.Events;
044import org.nuxeo.ecm.core.api.CoreSession;
045import org.nuxeo.ecm.core.api.DocumentModel;
046import org.nuxeo.ecm.core.api.NuxeoException;
047import org.nuxeo.ecm.core.api.repository.RepositoryManager;
048import org.nuxeo.ecm.core.api.security.SecurityConstants;
049import org.nuxeo.ecm.platform.query.api.PageProvider;
050import org.nuxeo.ecm.platform.query.api.PageProviderService;
051import org.nuxeo.ecm.platform.query.nxql.CoreQueryAndFetchPageProvider;
052import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
053import org.nuxeo.ecm.platform.ui.web.api.WebActions;
054import org.nuxeo.ecm.platform.ui.web.rest.RestHelper;
055import org.nuxeo.ecm.platform.util.RepositoryLocation;
056import org.nuxeo.ecm.webapp.dashboard.DashboardNavigationHelper;
057
058@Name("startupHelper")
059@Scope(SESSION)
060@Install(precedence = Install.FRAMEWORK)
061public class StartupHelper implements Serializable {
062
063    public static final String STARTUP_PAGE_PROVIDER_NAME = "startup_domains";
064
065    public static final String SERVERS_VIEW = "view_servers";
066
067    public static final String DOMAINS_VIEW = "view_domains";
068
069    protected static final String DOMAIN_TYPE = "Domain";
070
071    protected static final String DOCUMENT_MANAGEMENT_TAB = WebActions.MAIN_TABS_CATEGORY + ":"
072            + WebActions.DOCUMENTS_MAIN_TAB_ID;
073
074    private static final long serialVersionUID = 3248972387619873245L;
075
076    private static final Log log = LogFactory.getLog(StartupHelper.class);
077
078    @In(create = true)
079    protected transient RepositoryManager repositoryManager;
080
081    @In(create = true)
082    protected transient NavigationContext navigationContext;
083
084    @In(create = true)
085    protected transient WebActions webActions;
086
087    @In
088    protected transient Context sessionContext;
089
090    @In(create = true)
091    protected DashboardNavigationHelper dashboardNavigationHelper;
092
093    @In(create = true)
094    ConversationIdGenerator conversationIdGenerator;
095
096    @In(create = true, required = false)
097    protected transient CoreSession documentManager;
098
099    @In(create = true)
100    protected transient RestHelper restHelper;
101
102    @In(create = true)
103    protected transient PageProviderService pageProviderService;
104
105    /**
106     * Initializes the context with the principal id, and try to connect to the default server if any. If several
107     * servers are available, let the user choose.
108     *
109     * @return the view_id of the contextually computed startup page
110     */
111    public String initServerAndFindStartupPage() {
112
113        setupCurrentUser();
114
115        // we try to select the server to go to the next screen
116        if (navigationContext.getCurrentServerLocation() == null) {
117            // update location
118            RepositoryLocation repLoc = new RepositoryLocation(repositoryManager.getDefaultRepositoryName());
119            navigationContext.setCurrentServerLocation(repLoc);
120        }
121
122        if (documentManager == null) {
123            documentManager = navigationContext.getOrCreateDocumentManager();
124        }
125
126        if (Events.exists()) {
127            Events.instance().raiseEvent(EventNames.USER_SESSION_STARTED, documentManager);
128        }
129
130        // select home page
131
132        DocumentModel rootDocument = documentManager.getRootDocument();
133        if (!documentManager.hasPermission(rootDocument.getRef(), SecurityConstants.READ_CHILDREN)) {
134            // user cannot see the root but maybe she can see contained
135            // documents thus forwarding her to her dashboard
136            return dashboardNavigationHelper.navigateToDashboard();
137        }
138
139        webActions.setCurrentTabIds(DOCUMENT_MANAGEMENT_TAB);
140        // if more than one repo : display the server selection screen
141        if (repositoryManager.getRepositoryNames().size() > 1) {
142            return SERVERS_VIEW;
143        }
144
145        // the Repository Location is initialized, skip the first screen
146        return DOMAINS_VIEW;
147    }
148
149    /**
150     * Initializes the context with the principal id, and tries to connect to the default server if any then: - if the
151     * server has several domains, redirect to the list of domains - if the server has only one domain, select it and
152     * redirect to viewId - if the server is empty, create a new domain with title 'domainTitle' and redirect to it on
153     * viewId.
154     * <p>
155     * If several servers are available, let the user choose.
156     *
157     * @return the view id of the contextually computed startup page
158     */
159    @Begin(id = "#{conversationIdGenerator.nextMainConversationId}", join = true)
160    public String initDomainAndFindStartupPage(String domainTitle, String viewId) {
161
162        try {
163            // delegate server initialized to the default helper
164            String result = initServerAndFindStartupPage();
165
166            // more than one repo
167            if (SERVERS_VIEW.equals(result)) {
168                return result;
169            }
170
171            Map<String, Serializable> properties = Collections.singletonMap(
172                    CoreQueryAndFetchPageProvider.CORE_SESSION_PROPERTY, (Serializable) documentManager);
173
174            PageProvider<DocumentModel> pageProvider = (PageProvider<DocumentModel>) pageProviderService.getPageProvider(
175                    STARTUP_PAGE_PROVIDER_NAME, null, null, null, properties);
176
177            List<DocumentModel> currentPage = pageProvider.getCurrentPage();
178
179            if (currentPage != null && pageProvider.getResultsCount() == 1) {
180                // select and go to the unique domain
181                webActions.setCurrentTabIds(DOCUMENT_MANAGEMENT_TAB);
182                return navigationContext.navigateToDocument(currentPage.get(0), viewId);
183            }
184
185            // zero or several domains: let the user decide what to do if he has
186            // right on the Root document
187            DocumentModel rootDocument = documentManager.getRootDocument();
188            if (documentManager.hasPermission(rootDocument.getRef(), SecurityConstants.READ_CHILDREN)) {
189                webActions.setCurrentTabIds(DOCUMENT_MANAGEMENT_TAB);
190                navigationContext.navigateToDocument(rootDocument);
191                return DOMAINS_VIEW;
192            }
193
194            return result;
195        } catch (NuxeoException e) {
196            // avoid pages.xml contribution to catch exceptions silently
197            // hiding the cause of the problem to developers
198            // TODO: remove this catch clause if we find a way not to make it
199            // fail silently
200            log.error("error while initializing the Seam context with a CoreSession instance: " + e.getMessage(), e);
201            return null;
202        }
203    }
204
205    public void setupCurrentUser() {
206        Principal currentUser = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
207        sessionContext.set("currentUser", currentUser);
208    }
209
210}