UndertowHttpServer.java
/*
* Copyright (C) 2007-2014 JMPEAX.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jmpeax.osgi.undertow.http.impl;
import io.undertow.Undertow;
import io.undertow.server.handlers.PathHandler;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.*;
import io.undertow.servlet.util.ImmediateInstanceHandle;
import org.osgi.framework.BundleException;
import org.osgi.service.http.NamespaceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Set;
/**
* Manages the undertow server, also is the one who does the actual load/unload of the servlets.
*
* @author Carlos Ortiz
* @since 1.0.0
*/
public class UndertowHttpServer {
private final Logger log = LoggerFactory.getLogger(UndertowHttpServer.class);
protected Dictionary<String, ?> properties;
protected Undertow server;
protected PathHandler pathHandler;
protected Set<String> registeredPaths;
public UndertowHttpServer(Dictionary<String, ?> properties) {
this.properties = properties;
pathHandler = new PathHandler();
registeredPaths = new HashSet<>();
}
public void startServer() throws BundleException {
Undertow.Builder serverBuilder = Undertow.builder();
try {
int port = Integer.parseInt(properties.get("undertow.server.http.port").toString());
String host = properties.get("undertow.server.http.host").toString();
log.debug("Starting Http Listener {}:{}", host, port);
serverBuilder.addHttpListener(port, host);
} catch (NumberFormatException | NullPointerException ex) {
log.error("Unable to start Http Server, missing configuration for host and port");
log.debug("Reason:", ex);
throw new BundleException("Unable to start Http service, configuration invalid!");
}
serverBuilder.setHandler(pathHandler);
server = serverBuilder.build();
server.start();
}
public void addServletHandler(final String url, final Servlet servlet, final Dictionary<String, ?> props) throws NamespaceException, ServletException {
log.debug("Adding {} to url {} with properties {}", servlet, url, props);
if (registeredPaths.contains(url)) {
throw new NamespaceException("Url " + url + " already Exist");
}
DeploymentInfo servletBuilder = initServetHandler(url, servlet.getClass().getClassLoader());
final ServletInfo tobeAdd = Servlets.servlet(url, servlet.getClass(), new InstanceFactory<Servlet>() {
// OSGi already provides the instance!
@Override
public InstanceHandle<Servlet> createInstance() throws InstantiationException {
return new ImmediateInstanceHandle<Servlet>(servlet);
}
});
tobeAdd.addMapping("/*");
servletBuilder.setContextPath(url);
servletBuilder.setDeploymentName("TEST");
servletBuilder.addServlet(tobeAdd);
final DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder);
manager.deploy();
pathHandler.addExactPath(url, manager.start());
log.debug("Servlet {} was added", url);
registeredPaths.add(url);
}
public void addServletHandler(final String url, final Class<? extends Servlet> servlet,
final Dictionary<String, ?> props) {
DeploymentInfo servletBuilder = initServetHandler(url, servlet.getClassLoader());
Servlets.servlet(url, servlet);
}
protected DeploymentInfo initServetHandler(final String url, ClassLoader classloader) {
DeploymentInfo servletBuilder = Servlets.deployment();
servletBuilder.setClassLoader(classloader);
servletBuilder.setContextPath(url);
return servletBuilder;
}
public void removeHandler(final String path) {
pathHandler.removeExactPath(path);
registeredPaths.remove(path);
log.debug("{} was remove from server", path);
}
public void stopServer() {
log.info("Stopping Http Server");
log.debug("Clearing all paths");
pathHandler.clearPaths();
log.debug("Stopping all Http/Ajp services");
server.stop();
log.info("Http Server was shutdown");
}
}