001/* 002 * (C) Copyright 2006-2011 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 * Thierry Delprat 018 * Florent Guillaume 019 */ 020 021package org.nuxeo.ecm.platform.ui.web.restAPI; 022 023import java.io.IOException; 024 025import javax.servlet.ServletException; 026import javax.servlet.http.HttpServlet; 027import javax.servlet.http.HttpServletRequest; 028import javax.servlet.http.HttpServletResponse; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.ecm.platform.ui.web.restAPI.service.PluggableRestletService; 033import org.nuxeo.ecm.platform.ui.web.restAPI.service.RestletPluginDescriptor; 034import org.nuxeo.runtime.api.Framework; 035import org.nuxeo.runtime.transaction.TransactionHelper; 036import org.restlet.Filter; 037import org.restlet.Restlet; 038import org.restlet.Route; 039import org.restlet.Router; 040 041import com.noelios.restlet.ext.servlet.ServletConverter; 042 043/** 044 * Servlet used to run a Restlet inside Nuxeo. 045 * <p> 046 * Setup Seam Restlet filter if needed. 047 * <p> 048 * Ensures a transaction is started/committed. 049 */ 050public class RestletServlet extends HttpServlet { 051 052 private static final Log log = LogFactory.getLog(RestletServlet.class); 053 054 private static final long serialVersionUID = 1764653653643L; 055 056 protected ServletConverter converter; 057 058 @Override 059 public synchronized void init() throws ServletException { 060 super.init(); 061 062 converter = new ServletConverter(getServletContext()); 063 064 // init the router 065 Router restletRouter = new Router(); 066 067 // get the service 068 PluggableRestletService service = (PluggableRestletService) Framework.getRuntime().getComponent( 069 PluggableRestletService.NAME); 070 if (service == null) { 071 log.error("Unable to get Service " + PluggableRestletService.NAME); 072 throw new ServletException("Can't initialize Nuxeo Pluggable Restlet Service"); 073 } 074 075 for (String restletName : service.getContributedRestletNames()) { 076 RestletPluginDescriptor plugin = service.getContributedRestletDescriptor(restletName); 077 078 Restlet restletToAdd; 079 if (plugin.getUseSeam()) { 080 Filter seamFilter = new SeamRestletFilter(plugin.getUseConversation()); 081 082 Restlet seamRestlet = service.getContributedRestletByName(restletName); 083 084 seamFilter.setNext(seamRestlet); 085 086 restletToAdd = seamFilter; 087 } else { 088 089 if (plugin.isSingleton()) { 090 restletToAdd = service.getContributedRestletByName(restletName); 091 } else { 092 Filter threadSafeRestletFilter = new ThreadSafeRestletFilter(); 093 094 Restlet restlet = service.getContributedRestletByName(restletName); 095 096 threadSafeRestletFilter.setNext(restlet); 097 restletToAdd = threadSafeRestletFilter; 098 } 099 } 100 101 // force regexp init 102 for (String urlPattern : plugin.getUrlPatterns()) { 103 log.debug("Pre-compiling restlet pattern " + urlPattern); 104 Route route = restletRouter.attach(urlPattern, restletToAdd); 105 route.getTemplate().match(""); 106 } 107 } 108 109 converter.setTarget(restletRouter); 110 } 111 112 @Override 113 protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { 114 boolean tx = false; 115 if (!TransactionHelper.isTransactionActive()) { 116 tx = TransactionHelper.startTransaction(); 117 } 118 try { 119 converter.service(req, res); 120 } catch (ServletException e) { 121 if (tx) { 122 TransactionHelper.setTransactionRollbackOnly(); 123 } 124 throw e; 125 } catch (IOException e) { 126 if (tx) { 127 TransactionHelper.setTransactionRollbackOnly(); 128 } 129 throw e; 130 } finally { 131 if (tx) { 132 if (TransactionHelper.isTransactionActiveOrMarkedRollback()) { 133 // SeamRestletFilter might have done an early commit to 134 // avoid race condition on the core session on restlets 135 // who rely upon the conversation lock to fetch it 136 // thread-safely 137 TransactionHelper.commitOrRollbackTransaction(); 138 } 139 } 140 } 141 } 142 143}