Skip to content

Commit

Permalink
Fix #205
Browse files Browse the repository at this point in the history
Signed-off-by: Clement Escoffier <clement.escoffier@gmail.com>
  • Loading branch information
cescoffier committed May 13, 2014
1 parent cd934ff commit 28ca4c3
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 32 deletions.
Expand Up @@ -26,17 +26,19 @@
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.wisdom.api.configuration.ApplicationConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wisdom.api.configuration.ApplicationConfiguration;

import java.net.InetAddress;
import java.security.KeyStoreException;
import java.util.Random;

/**
* The Wisdom Server.
*/
public class WisdomServer {

private static final String KEY_HTTP_ADDRESS = "http.address";

private static final Logger LOGGER = LoggerFactory.getLogger("wisdom-engine");
Expand Down Expand Up @@ -76,25 +78,58 @@ public void start() throws InterruptedException {
workerGroup = new NioEventLoopGroup();

try {
//HTTP
if (httpPort != -1) {
// Here we need to start the different channels.
// Negative ports disable the channels. Usually, we use -1.
// 0 indicates a random port.

// HTTP
if (httpPort == 0) {
Random random = new Random();
for (int i = 0; httpPort == 0 && i < 30; i++) {
int port = 9000 + random.nextInt(10000);
try {
LOGGER.debug("Random port lookup - Trying with {}", port);
bind(port, false);
httpPort = port;
LOGGER.info("Wisdom is going to serve HTTP requests on port " + httpPort);
} catch (Exception e) {
LOGGER.debug("Cannot bind on port {} (port already used probably)", port);
}
}

// If the port is still 0, we were not able to bind on any port.
if (httpPort == 0) {
throw new Exception("Cannot find a free port for HTTP after 30 tries");
}
} else if (httpPort >= 0) {
bind(httpPort, false);
LOGGER.info("Wisdom is going to serve HTTP requests on port " + httpPort);
ServerBootstrap http = new ServerBootstrap();
http.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WisdomServerInitializer(accessor, false));
group.add(http.bind(address, httpPort).sync().channel());
}

//HTTPS
if (httpsPort != -1) {
if (httpsPort == 0) {
Random random = new Random();
for (int i = 0; httpsPort == 0 && i < 30; i++) {
int port = 9000 + random.nextInt(10000);
try {
LOGGER.debug("Random port lookup - Trying with {}", port);
bind(port, true);
httpsPort = port;
LOGGER.info("Wisdom is going to serve HTTPS requests on port " + httpsPort);
} catch (Exception e) {
LOGGER.debug("Cannot bind on port {} (port already used probably)", port);
}
}

// If the port is still 0, we were not able to bind on any port.
if (httpsPort == 0) {
throw new Exception("Cannot find a free port for HTTPS after 30 tries");
}
} else if (httpsPort >= 0) {
bind(httpsPort, true);
LOGGER.info("Wisdom is going to serve HTTPS requests on port " + httpsPort);
ServerBootstrap https = new ServerBootstrap();
https.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WisdomServerInitializer(accessor, true));
group.add(https.bind(address, httpsPort).sync().channel());
}

} catch (Exception e) {
LOGGER.error("Cannot initialize Wisdom", e);
group.close().sync();
Expand All @@ -104,6 +139,14 @@ public void start() throws InterruptedException {
}
}

private void bind(int port, boolean secure) throws KeyStoreException, InterruptedException {
ServerBootstrap http = new ServerBootstrap();
http.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WisdomServerInitializer(accessor, secure));
group.add(http.bind(address, port).sync().channel());
}

private void onError() {
System.exit(-1); //NOSONAR
}
Expand Down
Expand Up @@ -57,7 +57,7 @@ private static void load() {
try {
m_properties.load(is);
is.close();
} catch (IOException e) {
} catch (IOException e) { //NOSONAR
throw new IllegalStateException("Cannot load the 'constants' file");
}
}
Expand Down
Expand Up @@ -65,8 +65,8 @@ public void tearDown() {
public void testServerStartSequence() throws InterruptedException, IOException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9101);
when(configuration.getIntegerWithDefault(eq("https.port"), anyInt())).thenReturn(-1);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(0);
when(configuration.getIntegerWithDefault(eq("https.port"), anyInt())).thenReturn(0);

// Prepare an empty router.
Router router = mock(Router.class);
Expand Down Expand Up @@ -117,10 +117,13 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
// Wait for initialization.
Thread.sleep(5000);

int http = dispatcher.httpPort();
int https = dispatcher.httpsPort();

HttpURLConnection connection = null;
int responseCode = 0;
for (int i = 0; i < 10; i++) {
URL url = new URL("http://localhost:9101/test");
URL url = new URL("http://localhost:" + http + "/test");
try {
connection = (HttpURLConnection) url.openConnection();
responseCode = connection.getResponseCode();
Expand All @@ -135,15 +138,15 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
assertThat(responseCode).isEqualTo(404);

assertThat(dispatcher.hostname()).isEqualTo("localhost");
assertThat(dispatcher.httpPort()).isEqualTo(9101);
assertThat(dispatcher.httpsPort()).isEqualTo(-1);
assertThat(dispatcher.httpPort()).isGreaterThan(9000);
assertThat(dispatcher.httpsPort()).isGreaterThan(9001);
}

@Test
public void testWebSocketDispatching() throws InterruptedException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9102);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(-1);
when(configuration.getIntegerWithDefault(eq("https.port"), anyInt())).thenReturn(-1);

// Prepare an empty router.
Expand Down Expand Up @@ -225,7 +228,7 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
public void testWebSocketWithMultiClients() throws InterruptedException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9103);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(-1);
when(configuration.getIntegerWithDefault(eq("https.port"), anyInt())).thenReturn(-1);

// Prepare an empty router.
Expand Down Expand Up @@ -308,7 +311,7 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
public void testWebSocketSending() throws InterruptedException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9104);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(-1);
when(configuration.getIntegerWithDefault(eq("https.port"), anyInt())).thenReturn(-1);

// Prepare an empty router.
Expand Down
Expand Up @@ -51,7 +51,7 @@

/**
* Check the wisdom server behavior.
* This class is listening for http requests on the port 9100.
* This class is listening for http requests on random port.
*/
public class WisdomServerTest {

Expand All @@ -69,7 +69,7 @@ public void tearDown() {
public void testServerStartSequence() throws InterruptedException, IOException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9100);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(0);
when(configuration.getIntegerWithDefault(eq("https.port"), anyInt())).thenReturn(-1);

// Prepare an empty router.
Expand Down Expand Up @@ -123,20 +123,21 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
));

server.start();
URL url = new URL("http://localhost:9100/test");
int port = server.httpPort();
URL url = new URL("http://localhost:" + port + "/test");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
assertThat(connection.getResponseCode()).isEqualTo(404);

assertThat(server.hostname()).isEqualTo("localhost");
assertThat(server.httpPort()).isEqualTo(9100);
assertThat(port).isGreaterThan(9000);
assertThat(server.httpsPort()).isEqualTo(-1);
}

@Test
public void testOk() throws InterruptedException, IOException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9100);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(0);

// Prepare the router with a controller
Controller controller = new DefaultController() {
Expand Down Expand Up @@ -199,7 +200,8 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
));

server.start();
URL url = new URL("http://localhost:9100/");
int port = server.httpPort();
URL url = new URL("http://localhost:" + port + "/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
assertThat(connection.getResponseCode()).isEqualTo(200);
String body = IOUtils.toString(connection.getInputStream());
Expand All @@ -210,7 +212,7 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
public void testInternalError() throws InterruptedException, IOException {
// Prepare the configuration
ApplicationConfiguration configuration = mock(ApplicationConfiguration.class);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(9100);
when(configuration.getIntegerWithDefault(eq("http.port"), anyInt())).thenReturn(0);

// Prepare the router with a controller
Controller controller = new DefaultController() {
Expand Down Expand Up @@ -288,7 +290,8 @@ public boolean shouldEncodeWithHeaders(Map<String, String> headers) {
));

server.start();
URL url = new URL("http://localhost:9100/");
int port = server.httpPort();
URL url = new URL("http://localhost:" + port + "/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
assertThat(connection.getResponseCode()).isEqualTo(500);
}
Expand Down
Expand Up @@ -104,6 +104,13 @@ private void start(File root) throws BundleException, IOException {
Packages.osgihelpers(packages);
configuration.put("org.osgi.framework.system.packages.extra", packages.toString());

// Set the httpPort to 0 to use the random port feature.
// Except if already set explicitly
String port = System.getProperty("http.port");
if (port == null) {
System.setProperty("http.port", "0");
}

chameleon = new Chameleon(configuration);
fixLoggingSystem(root);
chameleon.start();
Expand Down

0 comments on commit 28ca4c3

Please sign in to comment.