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.portal;
020
021import java.io.InputStream;
022import java.net.InetSocketAddress;
023import java.net.URI;
024import java.net.URISyntaxException;
025import java.security.KeyStore;
026import java.security.SecureRandom;
027
028import javax.net.ssl.KeyManagerFactory;
029import javax.net.ssl.SSLContext;
030
031import org.jgrapes.core.Channel;
032import org.jgrapes.core.Component;
033import org.jgrapes.core.Components;
034import org.jgrapes.core.NamedChannel;
035import org.jgrapes.core.events.Stop;
036import org.jgrapes.http.HttpServer;
037import org.jgrapes.http.InMemorySessionManager;
038import org.jgrapes.http.LanguageSelector;
039import org.jgrapes.http.events.Request;
040import org.jgrapes.io.FileStorage;
041import org.jgrapes.io.NioDispatcher;
042import org.jgrapes.io.util.PermitsPool;
043import org.jgrapes.net.SslCodec;
044import org.jgrapes.net.TcpServer;
045import org.jgrapes.osgi.core.ComponentCollector;
046import org.jgrapes.portal.base.KVStoreBasedPortalPolicy;
047import org.jgrapes.portal.base.PageResourceProviderFactory;
048import org.jgrapes.portal.base.Portal;
049import org.jgrapes.portal.base.PortalLocalBackedKVStore;
050import org.jgrapes.portal.base.PortalWeblet;
051import org.jgrapes.portal.base.PortletComponentFactory;
052import org.jgrapes.portal.jqueryui.JQueryUiWeblet;
053import org.osgi.framework.BundleActivator;
054import org.osgi.framework.BundleContext;
055
056/**
057 *
058 */
059public class Application extends Component implements BundleActivator {
060
061    private static BundleContext context;
062    private Application app;
063
064    /**
065     * Returns the context passed to the application.
066     *
067     * @return the bundle context
068     */
069    public static BundleContext context() {
070        return context;
071    }
072
073    /*
074     * (non-Javadoc)
075     * 
076     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.
077     * BundleContext)
078     */
079    @Override
080    @SuppressWarnings("PMD.DataflowAnomalyAnalysis")
081    public void start(BundleContext context) throws Exception {
082        Application.context = context;
083        // The demo component is the application
084        app = new Application();
085        // Attach a general nio dispatcher
086        app.attach(new NioDispatcher());
087
088        // Create TLS "converter"
089        KeyStore serverStore = KeyStore.getInstance("JKS");
090        try (InputStream storeData
091            = Application.class.getResourceAsStream("/localhost.jks")) {
092            serverStore.load(storeData, "nopass".toCharArray());
093        }
094        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
095            KeyManagerFactory.getDefaultAlgorithm());
096        kmf.init(serverStore, "nopass".toCharArray());
097        SSLContext sslContext = SSLContext.getInstance("TLS");
098        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
099        // Create a TCP server for SSL
100        Channel securedNetwork = app.attach(
101            new TcpServer().setServerAddress(new InetSocketAddress(6443))
102                .setBacklog(3000).setConnectionLimiter(new PermitsPool(50)));
103        // Network level unencrypted channel.
104        Channel httpTransport = new NamedChannel("httpTransport");
105        app.attach(new SslCodec(httpTransport, securedNetwork, sslContext));
106
107        // Create an HTTP server as converter between transport and application
108        // layer.
109        app.attach(new HttpServer(app,
110            httpTransport, Request.In.Get.class, Request.In.Post.class));
111
112        // Build application layer
113        app.attach(new InMemorySessionManager(app.channel()));
114        app.attach(new LanguageSelector(app.channel()));
115        app.attach(new FileStorage(app.channel(), 65536));
116
117        createJQueryUiPortal(context);
118        createBootstrap4Portal(context);
119        Components.start(app);
120    }
121
122    private void createJQueryUiPortal(BundleContext context)
123            throws URISyntaxException {
124        PortalWeblet portalWeblet
125            = app.attach(new JQueryUiWeblet(app.channel(), Channel.SELF,
126                new URI("/jqportal/")))
127                .prependResourceBundleProvider(getClass());
128        Portal portal = portalWeblet.portal();
129        portal.attach(new PortalLocalBackedKVStore(
130            portal, portalWeblet.prefix().getPath()));
131        portal.attach(new KVStoreBasedPortalPolicy(portal));
132        portal.attach(new NewPortalSessionPolicy(portal));
133        portal.attach(new ComponentCollector<>(
134            portal, context, PageResourceProviderFactory.class));
135        portal.attach(new ComponentCollector<>(
136            portal, context, PortletComponentFactory.class));
137    }
138
139    private void createBootstrap4Portal(BundleContext context)
140            throws URISyntaxException {
141        PortalWeblet portalWeblet
142            = app.attach(new DemoPortalWeblet(app.channel(), Channel.SELF,
143                new URI("/b4portal/")));
144        Portal portal = portalWeblet.portal();
145        portal.attach(new PortalLocalBackedKVStore(
146            portal, portalWeblet.prefix().getPath()));
147        portal.attach(new KVStoreBasedPortalPolicy(portal));
148        portal.attach(new NewPortalSessionPolicy(portal));
149        portal.attach(new ComponentCollector<>(
150            portal, context, PageResourceProviderFactory.class));
151        portal.attach(new ComponentCollector<>(
152            portal, context, PortletComponentFactory.class));
153    }
154
155    /*
156     * (non-Javadoc)
157     * 
158     * @see
159     * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
160     */
161    @Override
162    public void stop(BundleContext context) throws Exception {
163        app.fire(new Stop(), Channel.BROADCAST);
164        Components.awaitExhaustion();
165    }
166}