001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2016, 2018  Michael N. Lipp
004 *
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.osgi.demo.httpserver;
020
021import java.io.InputStream;
022import java.net.InetSocketAddress;
023import java.security.KeyStore;
024import java.security.SecureRandom;
025
026import javax.net.ssl.KeyManagerFactory;
027import javax.net.ssl.SSLContext;
028
029import org.jgrapes.core.Channel;
030import org.jgrapes.core.Component;
031import org.jgrapes.core.Components;
032import org.jgrapes.core.NamedChannel;
033import org.jgrapes.core.events.Stop;
034import org.jgrapes.http.HttpRequestHandlerFactory;
035import org.jgrapes.http.HttpServer;
036import org.jgrapes.http.InMemorySessionManager;
037import org.jgrapes.http.LanguageSelector;
038import org.jgrapes.http.events.Request;
039import org.jgrapes.io.NioDispatcher;
040import org.jgrapes.io.util.PermitsPool;
041import org.jgrapes.net.SslCodec;
042import org.jgrapes.net.TcpServer;
043import org.jgrapes.osgi.core.ComponentCollector;
044import org.osgi.framework.BundleActivator;
045import org.osgi.framework.BundleContext;
046
047/**
048 * A basic server.
049 */
050public class BasicServer extends Component implements BundleActivator {
051
052    private static BundleContext context;
053    private BasicServer app;
054
055    /**
056     * Returns the context passed to the application.
057     *
058     * @return the bundle context
059     */
060    public static BundleContext context() {
061        return context;
062    }
063
064    /*
065     * (non-Javadoc)
066     * 
067     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.
068     * BundleContext)
069     */
070    @Override
071    public void start(BundleContext context) throws Exception {
072        BasicServer.context = context;
073        // The demo component is the application
074        app = new BasicServer();
075        // Attach a general nio dispatcher
076        app.attach(new NioDispatcher());
077
078        // Create TLS "converter"
079        KeyStore serverStore = KeyStore.getInstance("JKS");
080        try (InputStream storeData
081            = BasicServer.class.getResourceAsStream("/localhost.jks")) {
082            serverStore.load(storeData, "nopass".toCharArray());
083        }
084        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
085            KeyManagerFactory.getDefaultAlgorithm());
086        kmf.init(serverStore, "nopass".toCharArray());
087        SSLContext sslContext = SSLContext.getInstance("TLS");
088        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
089        // Create a TCP server for SSL
090        Channel securedNetwork = app.attach(
091            new TcpServer().setServerAddress(new InetSocketAddress(5443))
092                .setBacklog(3000).setConnectionLimiter(new PermitsPool(50)));
093        // Network level unencrypted channel.
094        Channel httpTransport = new NamedChannel("httpTransport");
095        app.attach(new SslCodec(httpTransport, securedNetwork, sslContext));
096
097        // Create an HTTP server as converter between transport and application
098        // layer.
099        app.attach(new HttpServer(app,
100            httpTransport, Request.In.Get.class, Request.In.Post.class));
101
102        // Build application layer
103        app.attach(new InMemorySessionManager(app.channel()));
104        app.attach(new LanguageSelector(app.channel()));
105        app.attach(new ComponentCollector<>(
106            app.channel(), context, HttpRequestHandlerFactory.class));
107        Components.start(app);
108    }
109
110    /*
111     * (non-Javadoc)
112     * 
113     * @see
114     * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
115     */
116    @Override
117    public void stop(BundleContext context) throws Exception {
118        app.fire(new Stop(), Channel.BROADCAST);
119        Components.awaitExhaustion();
120    }
121
122}