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.platform.ui.web.restAPI;
023
024import javax.faces.event.PhaseId;
025import javax.servlet.http.HttpServletRequest;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.jboss.seam.contexts.FacesLifecycle;
030import org.jboss.seam.contexts.Lifecycle;
031import org.jboss.seam.contexts.ServletLifecycle;
032import org.jboss.seam.core.ConversationPropagation;
033import org.jboss.seam.core.Manager;
034import org.jboss.seam.servlet.ServletRequestSessionMap;
035import org.jboss.seam.web.ServletContexts;
036import org.nuxeo.ecm.platform.ui.web.util.SeamComponentCallHelper;
037import org.nuxeo.runtime.transaction.TransactionHelper;
038import org.restlet.Filter;
039import org.restlet.Restlet;
040import org.restlet.data.MediaType;
041import org.restlet.data.Request;
042import org.restlet.data.Response;
043import org.restlet.data.Status;
044
045import com.noelios.restlet.ext.servlet.ServletCall;
046import com.noelios.restlet.http.HttpCall;
047import com.noelios.restlet.http.HttpRequest;
048
049/**
050 * Restlet Filter to initialized Seam context
051 *
052 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a>
053 * @author Florent Guillaume
054 */
055public class SeamRestletFilter extends Filter {
056
057    private static final Log log = LogFactory.getLog(SeamRestletFilter.class);
058
059    private boolean useConversation = false;
060
061    public SeamRestletFilter() {
062        this(false);
063    }
064
065    public SeamRestletFilter(boolean needConversation) {
066        useConversation = needConversation;
067    }
068
069    @Override
070    protected void beforeHandle(Request request, Response response) {
071        FacesLifecycle.setPhaseId(PhaseId.INVOKE_APPLICATION);
072        if (useConversation && (request instanceof HttpRequest)) {
073            // Complete HTTP call with conversation
074            HttpCall httpCall = ((HttpRequest) request).getHttpCall();
075            if (httpCall instanceof ServletCall) {
076                HttpServletRequest httpServletRequest = ((ServletCall) httpCall).getRequest();
077
078                // see ContextualHttpServletRequest / SOAPRequestHandler
079                ServletLifecycle.beginRequest(httpServletRequest);
080                ServletContexts.instance().setRequest(httpServletRequest);
081                ConversationPropagation.instance().restoreConversationId(httpServletRequest.getParameterMap());
082                Manager.instance().restoreConversation();
083                ServletLifecycle.resumeConversation(httpServletRequest);
084                Manager.instance().handleConversationPropagation(httpServletRequest.getParameterMap());
085                return;
086            }
087        }
088        // Standard call without conversation
089        Lifecycle.beginCall();
090    }
091
092    @Override
093    protected void afterHandle(Request request, Response response) {
094        FacesLifecycle.setPhaseId(null);
095        if (useConversation && request instanceof HttpRequest) {
096            HttpCall httpCall = ((HttpRequest) request).getHttpCall();
097            if (httpCall instanceof ServletCall) {
098                if (TransactionHelper.isTransactionActive()) {
099                    // early commit of the transaction before releasing the
100                    // conversation lock to avoid a race condition on concurrent
101                    // access to the same documentManager instance by threads /
102                    // requests sharing the same conversation and triggering
103                    // StorageException "closed connection handle" on the RA
104                    // pool
105                    TransactionHelper.commitOrRollbackTransaction();
106                }
107                HttpServletRequest httpServletRequest = ((ServletCall) httpCall).getRequest();
108                // see ContextualHttpServletRequest / SOAPRequestHandler
109                Manager.instance().endRequest(new ServletRequestSessionMap(httpServletRequest));
110                ServletLifecycle.endRequest(httpServletRequest);
111                return;
112            }
113        }
114        Lifecycle.endCall();
115    }
116
117    @Override
118    protected void doHandle(Request request, Response response) {
119        if (getNext() != null) {
120            // get the Seam Wrapper from the instance
121            Restlet next = getNext();
122            Restlet seamRestlet = (Restlet) SeamComponentCallHelper.getSeamComponentByRef(next);
123            if (seamRestlet == null) {
124                final String errMsg = "Cannot get Seam component for restlet ";
125                log.error(errMsg + next);
126                response.setEntity(errMsg, MediaType.TEXT_PLAIN);
127            } else {
128                try {
129                    seamRestlet.handle(request, response);
130                } catch (RuntimeException e) {
131                    log.error("Restlet handling error", e);
132                    response.setEntity("Error while calling Seam aware Restlet: " + e.getMessage(),
133                            MediaType.TEXT_PLAIN);
134                }
135            }
136        } else {
137            response.setStatus(Status.CLIENT_ERROR_NOT_FOUND);
138        }
139    }
140
141}