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 */
020package org.nuxeo.ecm.automation.seam.operations;
021
022import javax.faces.context.FacesContext;
023import javax.servlet.http.HttpServletRequest;
024
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.jboss.seam.contexts.Contexts;
028import org.jboss.seam.contexts.ServletLifecycle;
029import org.jboss.seam.core.ConversationPropagation;
030import org.jboss.seam.core.Manager;
031import org.jboss.seam.web.ServletContexts;
032import org.nuxeo.ecm.automation.OperationContext;
033import org.nuxeo.ecm.automation.core.operations.services.GetActions;
034import org.nuxeo.ecm.automation.jsf.OperationHelper;
035import org.nuxeo.ecm.core.api.CoreSession;
036import org.nuxeo.ecm.core.api.NuxeoException;
037import org.nuxeo.ecm.platform.actions.ActionContext;
038import org.nuxeo.ecm.platform.actions.seam.SeamActionContext;
039import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
040import org.nuxeo.ecm.platform.ui.web.util.SeamContextHelper;
041
042/**
043 * Utility class used to manage Seam init and cleanup
044 *
045 * @author Tiry (tdelprat@nuxeo.com)
046 */
047public class SeamOperationFilter {
048
049    protected static final Log log = LogFactory.getLog(SeamOperationFilter.class);
050
051    private SeamOperationFilter() {
052        // Helper class
053    }
054
055    /**
056     * Initialize a workable Seam context as well as a conversion if needed
057     *
058     * @param context
059     * @param conversationId
060     */
061    public static void handleBeforeRun(OperationContext context, String conversationId) {
062
063        CoreSession session = context.getCoreSession();
064
065        // Initialize Seam context if needed
066        if (!OperationHelper.isSeamContextAvailable()) {
067            initializeSeamContext(context, conversationId, session);
068        } else {
069            // Only set Seam Action context
070            setSeamActionContext(context, session);
071        }
072    }
073
074    /**
075     * Manages Seam context and lifecycle cleanup
076     *
077     * @param context
078     * @param conversationId
079     */
080    public static void handleAfterRun(OperationContext context, String conversationId) {
081
082        // Cannot destroy Seam context if it is not initialized
083        if (!OperationHelper.isSeamContextAvailable()) {
084            log.error("Cannot destroy Seam context: it is not initialized");
085            return;
086        }
087
088        HttpServletRequest request = getRequest(context);
089        if (request == null) {
090            log.error("Can not destroy Seam context: no HttpServletRequest was found");
091            return;
092        }
093
094        if (conversationId == null) {
095            conversationId = (String) context.getChainParameter("conversationId");
096        }
097
098        if (conversationId != null) {
099            Contexts.getEventContext().remove("documentManager");
100        }
101        ServletLifecycle.endRequest(request);
102    }
103
104    protected static void initializeSeamContext(OperationContext context, String conversationId, CoreSession session) {
105
106        HttpServletRequest request = getRequest(context);
107        if (request == null) {
108            throw new NuxeoException("Can not init Seam context: no HttpServletRequest was found");
109        }
110        ServletLifecycle.beginRequest(request);
111        ServletContexts.instance().setRequest(request);
112
113        if (conversationId == null) {
114            conversationId = (String) context.getChainParameter("conversationId");
115        }
116
117        if (conversationId != null) {
118            ConversationPropagation.instance().setConversationId(conversationId);
119            Manager.instance().restoreConversation();
120            ServletLifecycle.resumeConversation(request);
121            Contexts.getEventContext().set("documentManager", session);
122            setSeamActionContext(context, session);
123        }
124    }
125
126    /**
127     * Gets the request from the Automation context, fallback on the FacesContext.
128     */
129    protected static HttpServletRequest getRequest(OperationContext context) {
130        HttpServletRequest request = (HttpServletRequest) context.get("request");
131        if (request == null) {
132            FacesContext faces = FacesContext.getCurrentInstance();
133            if (faces != null) {
134                request = (HttpServletRequest) faces.getExternalContext().getRequest();
135            }
136        }
137        return request;
138    }
139
140    protected static void setSeamActionContext(OperationContext context, CoreSession session) {
141        ActionContext seamActionContext = new SeamActionContext();
142        NavigationContext navigationContext = (NavigationContext) Contexts.getConversationContext()
143                                                                          .get("navigationContext");
144        if (navigationContext != null) {
145            seamActionContext.setCurrentDocument(navigationContext.getCurrentDocument());
146        }
147        seamActionContext.setDocumentManager(session);
148        seamActionContext.putLocalVariable("SeamContext", new SeamContextHelper());
149        seamActionContext.setCurrentPrincipal(session.getPrincipal());
150
151        context.put(GetActions.SEAM_ACTION_CONTEXT, seamActionContext);
152    }
153
154}