001/* 002 * (C) Copyright 2006-2016 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 * bstefanescu 018 */ 019package org.nuxeo.runtime.test.runner; 020 021import static org.nuxeo.launcher.config.ConfigurationGenerator.PARAM_HTTP_PORT; 022 023import java.io.IOException; 024import java.net.ServerSocket; 025 026import org.apache.logging.log4j.LogManager; 027import org.apache.logging.log4j.Logger; 028import org.nuxeo.runtime.server.ServerComponent; 029 030/** 031 * Runs an embedded servlet container. 032 */ 033@Deploy("org.nuxeo.runtime.server") 034@Features(RuntimeFeature.class) 035public class ServletContainerFeature implements RunnerFeature { 036 037 private static final Logger log = LogManager.getLogger(ServletContainerFeature.class); 038 039 protected static final int RETRIES = 1000; 040 041 protected int port; 042 043 @SuppressWarnings("deprecation") 044 @Override 045 public void initialize(FeaturesRunner runner) throws Exception { 046 ServletContainer conf = runner.getConfig(ServletContainer.class); 047 int port = conf == null ? 0 : conf.port(); 048 if (port <= 0) { 049 port = findFreePort(); 050 } 051 this.port = port; 052 System.setProperty(ServerComponent.PORT_SYSTEM_PROP, String.valueOf(port)); 053 System.setProperty(PARAM_HTTP_PORT, String.valueOf(port)); 054 } 055 056 protected int findFreePort() { 057 for (int i = 0; i < RETRIES; i++) { 058 try (ServerSocket socket = new ServerSocket(0)) { 059 socket.setReuseAddress(true); 060 return socket.getLocalPort(); 061 } catch (IOException e) { 062 log.trace("Failed to allocate port", e); 063 } 064 } 065 throw new RuntimeException("Unable to find free port after " + RETRIES + " retries"); 066 } 067 068 /** 069 * Returns the port allocated for this servlet container. 070 * 071 * @since 10.10 072 */ 073 public int getPort() { 074 return port; 075 } 076 077}