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.Restlet; 037import org.restlet.ext.servlet.ServletAdapter; 038import org.restlet.routing.Filter; 039import org.restlet.routing.Router; 040import org.restlet.routing.Template; 041 042/** 043 * Servlet used to run a Restlet inside Nuxeo. 044 * <p> 045 * Setup Seam Restlet filter if needed. 046 * <p> 047 * Ensures a transaction is started/committed. 048 */ 049public class RestletServlet extends HttpServlet { 050 051 private static final Log log = LogFactory.getLog(RestletServlet.class); 052 053 private static final long serialVersionUID = 1764653653643L; 054 055 protected ServletAdapter adapter; 056 057 @Override 058 public synchronized void init() throws ServletException { 059 super.init(); 060 061 adapter = new ServletAdapter(getServletContext()); 062 063 // init the router 064 Router restletRouter = new Router(); 065 066 // get the service 067 PluggableRestletService service = (PluggableRestletService) Framework.getRuntime().getComponent( 068 PluggableRestletService.NAME); 069 if (service == null) { 070 log.error("Unable to get Service " + PluggableRestletService.NAME); 071 throw new ServletException("Can't initialize Nuxeo Pluggable Restlet Service"); 072 } 073 074 for (String restletName : service.getContributedRestletNames()) { 075 RestletPluginDescriptor plugin = service.getContributedRestletDescriptor(restletName); 076 077 Restlet restletToAdd; 078 if (plugin.getUseSeam()) { 079 Filter seamFilter = new SeamRestletFilter(plugin.getUseConversation()); 080 081 Restlet seamRestlet = service.getContributedRestletByName(restletName); 082 083 seamFilter.setNext(seamRestlet); 084 085 restletToAdd = seamFilter; 086 } else { 087 088 if (plugin.isSingleton()) { 089 restletToAdd = service.getContributedRestletByName(restletName); 090 } else { 091 Filter threadSafeRestletFilter = new ThreadSafeRestletFilter(); 092 093 Restlet restlet = service.getContributedRestletByName(restletName); 094 095 threadSafeRestletFilter.setNext(restlet); 096 restletToAdd = threadSafeRestletFilter; 097 } 098 } 099 100 for (String urlPattern : plugin.getUrlPatterns()) { 101 restletRouter.attach(urlPattern, restletToAdd, Template.MODE_STARTS_WITH); 102 } 103 } 104 105 adapter.setNext(restletRouter); 106 } 107 108 @Override 109 protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { 110 boolean tx = false; 111 if (!TransactionHelper.isTransactionActive()) { 112 tx = TransactionHelper.startTransaction(); 113 } 114 boolean ok = false; 115 try { 116 adapter.service(req, res); 117 ok = true; 118 } finally { 119 if (!ok) { 120 TransactionHelper.setTransactionRollbackOnly(); 121 } 122 if (tx) { 123 if (TransactionHelper.isTransactionActiveOrMarkedRollback()) { 124 // SeamRestletFilter might have done an early commit to 125 // avoid race condition on the core session on restlets 126 // who rely upon the conversation lock to fetch it 127 // thread-safely 128 TransactionHelper.commitOrRollbackTransaction(); 129 } 130 } 131 } 132 } 133 134}