View Javadoc
1   /*
2    * Copyright (C) 2007-2014 JMPEAX.
3    *
4    *     This program is free software: you can redistribute it and/or modify
5    *     it under the terms of the GNU General Public License as published by
6    *     the Free Software Foundation, either version 3 of the License, or
7    *     (at your option) any later version.
8    *
9    *     This program is distributed in the hope that it will be useful,
10   *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   *     GNU General Public License for more details.
13   *
14   *     You should have received a copy of the GNU General Public License
15   *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  
18  package com.jmpeax.osgi.undertow.http.impl;
19  
20  import io.undertow.Undertow;
21  import io.undertow.server.handlers.PathHandler;
22  import io.undertow.servlet.Servlets;
23  import io.undertow.servlet.api.*;
24  import io.undertow.servlet.util.ImmediateInstanceHandle;
25  import org.osgi.framework.BundleException;
26  import org.osgi.service.http.NamespaceException;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import javax.servlet.Servlet;
31  import javax.servlet.ServletException;
32  import java.util.Dictionary;
33  import java.util.HashSet;
34  import java.util.Set;
35  
36  /**
37   * Manages the undertow server, also is the one who does the actual load/unload of the servlets.
38   *
39   * @author Carlos Ortiz
40   * @since 1.0.0
41   */
42  public class UndertowHttpServer {
43  
44  
45      private final Logger log = LoggerFactory.getLogger(UndertowHttpServer.class);
46      protected Dictionary<String, ?> properties;
47      protected Undertow server;
48      protected PathHandler pathHandler;
49      protected Set<String> registeredPaths;
50  
51      public UndertowHttpServer(Dictionary<String, ?> properties) {
52          this.properties = properties;
53          pathHandler = new PathHandler();
54          registeredPaths = new HashSet<>();
55      }
56  
57      public void startServer() throws BundleException {
58          Undertow.Builder serverBuilder = Undertow.builder();
59          try {
60              int port = Integer.parseInt(properties.get("undertow.server.http.port").toString());
61              String host = properties.get("undertow.server.http.host").toString();
62              log.debug("Starting Http Listener {}:{}", host, port);
63              serverBuilder.addHttpListener(port, host);
64  
65          } catch (NumberFormatException | NullPointerException ex) {
66              log.error("Unable to start Http Server, missing configuration for host and port");
67              log.debug("Reason:", ex);
68              throw new BundleException("Unable to start Http service, configuration invalid!");
69          }
70          serverBuilder.setHandler(pathHandler);
71          server = serverBuilder.build();
72          server.start();
73      }
74  
75  
76      public void addServletHandler(final String url, final Servlet servlet, final Dictionary<String, ?> props) throws NamespaceException, ServletException {
77          log.debug("Adding {} to url {} with properties {}", servlet, url, props);
78          if (registeredPaths.contains(url)) {
79              throw new NamespaceException("Url " + url + " already Exist");
80          }
81          DeploymentInfo servletBuilder = initServetHandler(url, servlet.getClass().getClassLoader());
82  
83          final ServletInfo tobeAdd = Servlets.servlet(url, servlet.getClass(), new InstanceFactory<Servlet>() {
84              // OSGi already provides the instance!
85              @Override
86              public InstanceHandle<Servlet> createInstance() throws InstantiationException {
87                  return new ImmediateInstanceHandle<Servlet>(servlet);
88              }
89          });
90          tobeAdd.addMapping("/*");
91          servletBuilder.setContextPath(url);
92          servletBuilder.setDeploymentName("TEST");
93          servletBuilder.addServlet(tobeAdd);
94          final DeploymentManager manager = Servlets.defaultContainer().addDeployment(servletBuilder);
95          manager.deploy();
96          pathHandler.addExactPath(url, manager.start());
97          log.debug("Servlet {} was added", url);
98          registeredPaths.add(url);
99      }
100 
101     public void addServletHandler(final String url, final Class<? extends Servlet> servlet,
102                                   final Dictionary<String, ?> props) {
103         DeploymentInfo servletBuilder = initServetHandler(url, servlet.getClassLoader());
104         Servlets.servlet(url, servlet);
105     }
106 
107     protected DeploymentInfo initServetHandler(final String url, ClassLoader classloader) {
108         DeploymentInfo servletBuilder = Servlets.deployment();
109         servletBuilder.setClassLoader(classloader);
110         servletBuilder.setContextPath(url);
111         return servletBuilder;
112     }
113 
114     public void removeHandler(final String path) {
115         pathHandler.removeExactPath(path);
116         registeredPaths.remove(path);
117         log.debug("{} was remove from server", path);
118     }
119 
120     public void stopServer() {
121         log.info("Stopping Http Server");
122         log.debug("Clearing all paths");
123         pathHandler.clearPaths();
124         log.debug("Stopping all Http/Ajp services");
125         server.stop();
126         log.info("Http Server was shutdown");
127     }
128 
129 }