/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.http.server.reactive.bootstrap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.http.server.reactive.ContextPathCompositeHandler;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.Assert;
/**
* @author Rossen Stoyanchev
*/
public abstract class AbstractHttpServer implements HttpServer {
private String host = "0.0.0.0";
private int port = 0;
private HttpHandler httpHandler;
private Map<String, HttpHandler> handlerMap;
private boolean running;
private final Object lifecycleMonitor = new Object();
@Override
public void setHost(String host) {
this.host = host;
}
public String getHost() {
return host;
}
@Override
public void setPort(int port) {
this.port = port;
}
@Override
public int getPort() {
return this.port;
}
@Override
public void setHandler(HttpHandler handler) {
this.httpHandler = handler;
}
public HttpHandler getHttpHandler() {
return this.httpHandler;
}
public void registerHttpHandler(String contextPath, HttpHandler handler) {
if (this.handlerMap == null) {
this.handlerMap = new LinkedHashMap<>();
}
this.handlerMap.put(contextPath, handler);
}
public Map<String, HttpHandler> getHttpHandlerMap() {
return this.handlerMap;
}
protected HttpHandler resolveHttpHandler() {
return getHttpHandlerMap() != null ?
new ContextPathCompositeHandler(getHttpHandlerMap()) : getHttpHandler();
}
// InitializingBean
@Override
public final void afterPropertiesSet() throws Exception {
Assert.notNull(this.host, "Host must not be null");
Assert.isTrue(this.port >= 0, "Port must not be a negative number");
Assert.isTrue(this.httpHandler != null || this.handlerMap != null, "No HttpHandler configured");
Assert.state(!this.running, "Cannot reconfigure while running");
synchronized (this.lifecycleMonitor) {
initServer();
}
}
protected abstract void initServer() throws Exception;
// Lifecycle
@Override
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return this.running;
}
}
@Override
public final void start() {
synchronized (this.lifecycleMonitor) {
if (!isRunning()) {
this.running = true;
try {
startInternal();
}
catch (Throwable ex) {
throw new IllegalStateException(ex);
}
}
}
}
protected abstract void startInternal() throws Exception;
@Override
public final void stop() {
synchronized (this.lifecycleMonitor) {
if (isRunning()) {
this.running = false;
try {
stopInternal();
}
catch (Throwable ex) {
throw new IllegalStateException(ex);
}
finally {
reset();
}
}
}
}
protected abstract void stopInternal() throws Exception;
private void reset() {
this.host = "0.0.0.0";
this.port = 0;
this.httpHandler = null;
this.handlerMap = null;
resetInternal();
}
protected abstract void resetInternal();
}