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    /**
053     * Initialize a workable Seam context as well as a conversion if needed
054     *
055     * @param context
056     * @param conversationId
057     */
058    public static void handleBeforeRun(OperationContext context, String conversationId) {
059
060        CoreSession session = context.getCoreSession();
061
062        // Initialize Seam context if needed
063        if (!OperationHelper.isSeamContextAvailable()) {
064            initializeSeamContext(context, conversationId, session);
065        } else {
066            // Only set Seam Action context
067            setSeamActionContext(context, session);
068        }
069    }
070
071    /**
072     * Manages Seam context and lifecycle cleanup
073     *
074     * @param context
075     * @param conversationId
076     */
077    public static void handleAfterRun(OperationContext context, String conversationId) {
078
079        // Cannot destroy Seam context if it is not initialized
080        if (!OperationHelper.isSeamContextAvailable()) {
081            log.error("Cannot destroy Seam context: it is not initialized");
082            return;
083        }
084
085        HttpServletRequest request = getRequest(context);
086        if (request == null) {
087            log.error("Can not destroy Seam context: no HttpServletRequest was found");
088            return;
089        }
090
091        if (conversationId == null) {
092            conversationId = (String) context.get("conversationId");
093        }
094
095        if (conversationId != null) {
096            // CoreSession seamDocumentManager = (CoreSession)
097            // Contexts.getConversationContext().get("seamDocumentManager");
098            Contexts.getEventContext().remove("documentManager");
099            // Manager.instance().endConversation(true);
100        }
101        ServletLifecycle.endRequest(request);
102    }
103
104    protected static void initializeSeamContext(OperationContext context, String conversationId, CoreSession session)
105            {
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.get("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().get(
144                "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}