aboutsummaryrefslogtreecommitdiffstats
path: root/jdisc_core/src/main/java/com/yahoo/jdisc/client/ClientDriver.java
blob: 8a5c8de92b915d7ce7103d9405560df3e462d142 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.client;

import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.yahoo.jdisc.application.Application;
import com.yahoo.jdisc.application.OsgiFramework;
import com.yahoo.jdisc.core.ApplicationLoader;
import com.yahoo.jdisc.core.FelixFramework;
import com.yahoo.jdisc.core.FelixParams;
import com.yahoo.jdisc.test.NonWorkingOsgiFramework;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>This class provides a unified way to set up and run a {@link ClientApplication}. It provides you with a
 * programmable interface to instantiate and run the whole jDISC framework as if it was started as a Daemon, and it
 * provides you with a thread in which to run your application logic. Once your return from the {@link
 * ClientApplication#run()} method, the ClientProvider will initiate {@link Application} shutdown.</p>
 *
 * <p>A ClientApplication is typically a self-contained JAR file that bundles all of its dependencies, and contains a
 * single "main" method. The typical implementation of that method is:</p>
 * <pre>
 * public static void main(String[] args) throws Exception {
 *     ClientDriver.runApplication(MyApplication.class);
 * }
 * </pre>
 *
 * <p>Alternatively, the ClientApplication can be created up front:</p>
 * <pre>
 * public static void main(String[] args) throws Exception {
 *     MyApplication app = new MyApplication();
 *     (... configure app ...)
 *     ClientDriver.runApplication(app);
 * }
 * </pre>
 *
 * <p>Because all of the dependencies of a ClientApplication is expected to be part of the application JAR, the OSGi
 * framework created by this ClientDriver is disabled. Calling any method on that framework will throw an
 * exception. If you need OSGi support, use either of the runApplicationWithOsgi() methods.</p>
 *
 * @author Simon Thoresen Hult
 */
public abstract class ClientDriver {

    /**
     * <p>Creates and runs the given {@link ClientApplication}.</p>
     *
     * @param app          The ClientApplication to inject.
     * @param guiceModules The Guice {@link Module Modules} to install prior to startup.
     * @throws Exception If an exception was thrown by the ClientApplication.
     */
    public static void runApplication(ClientApplication app, Module... guiceModules)
            throws Exception
    {
        runApplication(newNonWorkingOsgiFramework(), newModuleList(app, guiceModules));
    }

    /**
     * <p>Creates and runs an instance of the given {@link ClientApplication} class.</p>
     *
     * @param appClass     The ClientApplication class to inject.
     * @param guiceModules The Guice {@link Module Modules} to install prior to startup.
     * @throws Exception If an exception was thrown by the ClientApplication.
     */
    public static void runApplication(Class<? extends ClientApplication> appClass, Module... guiceModules)
            throws Exception
    {
        runApplication(newNonWorkingOsgiFramework(), newModuleList(appClass, guiceModules));
    }

    /**
     * <p>Creates and runs an instance of the the given {@link ClientApplication} class with OSGi support.</p>
     *
     * @param cachePath    The path to use for the OSGi bundle cache.
     * @param appClass     The ClientApplication class to inject.
     * @param guiceModules The Guice {@link Module Modules} to install prior to startup.
     * @throws Exception If an exception was thrown by the ClientApplication.
     */
    public static void runApplicationWithOsgi(String cachePath, Class<? extends ClientApplication> appClass,
                                              Module... guiceModules) throws Exception
    {
        runApplication(newOsgiFramework(cachePath), newModuleList(appClass, guiceModules));
    }

    private static OsgiFramework newNonWorkingOsgiFramework() {
        return new NonWorkingOsgiFramework();
    }

    private static FelixFramework newOsgiFramework(String cachePath) {
        return new FelixFramework(new FelixParams().setCachePath(cachePath));
    }

    private static List<Module> newModuleList(final ClientApplication appInstance, Module... guiceModules) {
        List<Module> lst = new LinkedList<>(Arrays.asList(guiceModules));
        lst.add(new AbstractModule() {

            @Override
            protected void configure() {
                bind(Application.class).toInstance(appInstance);
            }
        });
        return lst;
    }

    private static List<Module> newModuleList(final Class<? extends ClientApplication> appClass,
                                              Module... guiceModules)
    {
        List<Module> lst = new LinkedList<>(Arrays.asList(guiceModules));
        lst.add(new AbstractModule() {

            @Override
            protected void configure() {
                bind(Application.class).to(appClass);
            }
        });
        return lst;
    }

    private static void runApplication(OsgiFramework osgi, List<Module> modules) throws Exception {
        ApplicationLoader loader = new ApplicationLoader(osgi, modules);
        loader.init(null, false);
        try {
            loader.start();
            ((ClientApplication)loader.application()).run();
            loader.stop();
        } finally {
            loader.destroy();
        }
    }
}