001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.restAPI; 021 022import javax.faces.event.PhaseId; 023import javax.servlet.http.HttpServletRequest; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.jboss.seam.contexts.FacesLifecycle; 028import org.jboss.seam.contexts.Lifecycle; 029import org.jboss.seam.contexts.ServletLifecycle; 030import org.jboss.seam.core.ConversationPropagation; 031import org.jboss.seam.core.Manager; 032import org.jboss.seam.servlet.ServletRequestSessionMap; 033import org.jboss.seam.web.ServletContexts; 034import org.nuxeo.ecm.platform.ui.web.util.SeamComponentCallHelper; 035import org.nuxeo.runtime.transaction.TransactionHelper; 036import org.restlet.Filter; 037import org.restlet.Restlet; 038import org.restlet.data.MediaType; 039import org.restlet.data.Request; 040import org.restlet.data.Response; 041import org.restlet.data.Status; 042 043import com.noelios.restlet.ext.servlet.ServletCall; 044import com.noelios.restlet.http.HttpCall; 045import com.noelios.restlet.http.HttpRequest; 046 047/** 048 * Restlet Filter to initialized Seam context 049 * 050 * @author <a href="mailto:td@nuxeo.com">Thierry Delprat</a> 051 * @author Florent Guillaume 052 */ 053public class SeamRestletFilter extends Filter { 054 055 private static final Log log = LogFactory.getLog(SeamRestletFilter.class); 056 057 private boolean useConversation = false; 058 059 public SeamRestletFilter() { 060 this(false); 061 } 062 063 public SeamRestletFilter(boolean needConversation) { 064 useConversation = needConversation; 065 } 066 067 @Override 068 protected void beforeHandle(Request request, Response response) { 069 FacesLifecycle.setPhaseId(PhaseId.INVOKE_APPLICATION); 070 if (useConversation && (request instanceof HttpRequest)) { 071 // Complete HTTP call with conversation 072 HttpCall httpCall = ((HttpRequest) request).getHttpCall(); 073 if (httpCall instanceof ServletCall) { 074 HttpServletRequest httpServletRequest = ((ServletCall) httpCall).getRequest(); 075 076 // see ContextualHttpServletRequest / SOAPRequestHandler 077 ServletLifecycle.beginRequest(httpServletRequest); 078 ServletContexts.instance().setRequest(httpServletRequest); 079 ConversationPropagation.instance().restoreConversationId(httpServletRequest.getParameterMap()); 080 Manager.instance().restoreConversation(); 081 ServletLifecycle.resumeConversation(httpServletRequest); 082 Manager.instance().handleConversationPropagation(httpServletRequest.getParameterMap()); 083 return; 084 } 085 } 086 // Standard call without conversation 087 Lifecycle.beginCall(); 088 } 089 090 @Override 091 protected void afterHandle(Request request, Response response) { 092 FacesLifecycle.setPhaseId(null); 093 if (useConversation && request instanceof HttpRequest) { 094 HttpCall httpCall = ((HttpRequest) request).getHttpCall(); 095 if (httpCall instanceof ServletCall) { 096 if (TransactionHelper.isTransactionActive()) { 097 // early commit of the transaction before releasing the 098 // conversation lock to avoid a race condition on concurrent 099 // access to the same documentManager instance by threads / 100 // requests sharing the same conversation and triggering 101 // StorageException "closed connection handle" on the RA 102 // pool 103 TransactionHelper.commitOrRollbackTransaction(); 104 } 105 HttpServletRequest httpServletRequest = ((ServletCall) httpCall).getRequest(); 106 // see ContextualHttpServletRequest / SOAPRequestHandler 107 Manager.instance().endRequest(new ServletRequestSessionMap(httpServletRequest)); 108 ServletLifecycle.endRequest(httpServletRequest); 109 return; 110 } 111 } 112 Lifecycle.endCall(); 113 } 114 115 @Override 116 protected void doHandle(Request request, Response response) { 117 if (getNext() != null) { 118 // get the Seam Wrapper from the instance 119 Restlet next = getNext(); 120 Restlet seamRestlet = (Restlet) SeamComponentCallHelper.getSeamComponentByRef(next); 121 if (seamRestlet == null) { 122 final String errMsg = "Cannot get Seam component for restlet "; 123 log.error(errMsg + next); 124 response.setEntity(errMsg, MediaType.TEXT_PLAIN); 125 } else { 126 try { 127 seamRestlet.handle(request, response); 128 } catch (RuntimeException e) { 129 log.error("Restlet handling error", e); 130 response.setEntity("Error while calling Seam aware Restlet: " + e.getMessage(), 131 MediaType.TEXT_PLAIN); 132 } 133 } 134 } else { 135 response.setStatus(Status.CLIENT_ERROR_NOT_FOUND); 136 } 137 } 138 139}