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