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 protected PluggableRestletService service; 059 060 @Override 061 public synchronized void init() throws ServletException { 062 super.init(); 063 064 if (converter != null) { 065 log.error("RestletServlet initialized several times"); 066 return; 067 } 068 converter = new ServletConverter(getServletContext()); 069 070 // init the router 071 Router restletRouter = new Router(); 072 073 // get the service 074 service = (PluggableRestletService) Framework.getRuntime().getComponent(PluggableRestletService.NAME); 075 if (service == null) { 076 log.error("Unable to get Service " + PluggableRestletService.NAME); 077 throw new ServletException("Can't initialize Nuxeo Pluggable Restlet Service"); 078 } 079 080 for (String restletName : service.getContributedRestletNames()) { 081 RestletPluginDescriptor plugin = service.getContributedRestletDescriptor(restletName); 082 083 Restlet restletToAdd; 084 if (plugin.getUseSeam()) { 085 Filter seamFilter = new SeamRestletFilter(plugin.getUseConversation()); 086 087 Restlet seamRestlet = service.getContributedRestletByName(restletName); 088 089 seamFilter.setNext(seamRestlet); 090 091 restletToAdd = seamFilter; 092 } else { 093 094 if (plugin.isSingleton()) { 095 restletToAdd = service.getContributedRestletByName(restletName); 096 } else { 097 Filter threadSafeRestletFilter = new ThreadSafeRestletFilter(); 098 099 Restlet restlet = service.getContributedRestletByName(restletName); 100 101 threadSafeRestletFilter.setNext(restlet); 102 restletToAdd = threadSafeRestletFilter; 103 } 104 } 105 106 // force regexp init 107 for (String urlPattern : plugin.getUrlPatterns()) { 108 log.debug("Pre-compiling restlet pattern " + urlPattern); 109 Route route = restletRouter.attach(urlPattern, restletToAdd); 110 route.getTemplate().match(""); 111 } 112 } 113 114 converter.setTarget(restletRouter); 115 } 116 117 @Override 118 protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { 119 boolean tx = false; 120 if (!TransactionHelper.isTransactionActive()) { 121 tx = TransactionHelper.startTransaction(); 122 } 123 try { 124 converter.service(req, res); 125 } catch (ServletException e) { 126 if (tx) { 127 TransactionHelper.setTransactionRollbackOnly(); 128 } 129 throw e; 130 } catch (IOException e) { 131 if (tx) { 132 TransactionHelper.setTransactionRollbackOnly(); 133 } 134 throw e; 135 } finally { 136 if (tx) { 137 if (TransactionHelper.isTransactionActiveOrMarkedRollback()) { 138 // SeamRestletFilter might have done an early commit to 139 // avoid race condition on the core session on restlets 140 // who rely upon the conversation lock to fetch it 141 // thread-safely 142 TransactionHelper.commitOrRollbackTransaction(); 143 } 144 } 145 } 146 } 147 148}