summaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/container/osgi/ContainerRpcAdaptor.java
blob: 64a75df57707e3424f37a472b9e7975050f75127 (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
134
135
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.osgi;

import com.yahoo.jrt.Acceptor;
import com.yahoo.jrt.ErrorCode;
import com.yahoo.jrt.ListenFailedException;
import com.yahoo.jrt.Method;
import com.yahoo.jrt.Request;
import com.yahoo.jrt.Spec;
import com.yahoo.jrt.StringValue;
import com.yahoo.jrt.Supervisor;
import com.yahoo.jrt.Transport;
import com.yahoo.jrt.slobrok.api.Register;
import com.yahoo.jrt.slobrok.api.SlobrokList;
import com.yahoo.net.LinuxInetAddress;
import com.yahoo.log.LogLevel;
import com.yahoo.osgi.Osgi;
import com.yahoo.yolean.Exceptions;
import org.osgi.framework.Bundle;

import java.net.UnknownHostException;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;

/**
 * An rpc adaptor to container Osgi commands.
 *
 * @author bratseth
 */
public class ContainerRpcAdaptor extends AbstractRpcAdaptor {

    private static final Logger log = Logger.getLogger(ContainerRpcAdaptor.class.getName());

    private Acceptor acceptor;
    private final Supervisor supervisor;

    private final Osgi osgi;
    private final String hostname;

    private Optional<String> slobrokId = Optional.empty();
    private Optional<Register> slobrokRegistrator = Optional.empty();

    public ContainerRpcAdaptor(Osgi osgi) {
        this.osgi = osgi;
        supervisor = new Supervisor(new Transport());

        try {
            this.hostname = LinuxInetAddress.getLocalHost().getCanonicalHostName();
        } catch (UnknownHostException e) {
            throw new RuntimeException("Failed gettting local hostname", e);
        }

        bindCommands(supervisor);
    }

    public void list(Request request) {
        try {
            StringBuilder buffer=new StringBuilder("Installed bundles:");
            for (Bundle bundle : osgi.getBundles()) {
                if (bundle.getSymbolicName().equals("system.bundle")) continue;
                buffer.append("\n");
                buffer.append(bundle.getSymbolicName());
                buffer.append(" (");
                buffer.append(bundle.getLocation());
                buffer.append(")");
            }
            request.returnValues().add(new StringValue(buffer.toString()));
        }
        catch (Exception e) {
            request.setError(ErrorCode.METHOD_FAILED,Exceptions.toMessageString(e));
        }
    }

    public void bindCommands(Supervisor supervisor) {
        supervisor.addMethod(new Method("list","","s",this,"list"));
    }

    public synchronized void listen(int port) {
        Spec spec = new Spec(port);
        try {
            acceptor = supervisor.listen(spec);
            log.log(LogLevel.DEBUG, "Added new rpc server listening at" + " port '" + port + "'.");
        } catch (ListenFailedException e) {
            throw new RuntimeException("Could not create rpc server listening on " + spec, e);
        }
    }

    public synchronized void setSlobrokId(String slobrokId) {
        this.slobrokId = Optional.of(slobrokId);
    }

    public synchronized void registerInSlobrok(List<String> slobrokConnectionSpecs) {
        shutdownSlobrokRegistrator();

        if (slobrokConnectionSpecs.isEmpty()) {
            return;
        }

        if (!slobrokId.isPresent()) {
            throw new AssertionError("Slobrok id must be set first");
        }

        SlobrokList slobrokList = new SlobrokList();
        slobrokList.setup(slobrokConnectionSpecs.stream().toArray(String[]::new));

        Spec mySpec = new Spec(hostname, acceptor.port());

        Register register = new Register(supervisor, slobrokList, mySpec);
        register.registerName(slobrokId.get());
        slobrokRegistrator = Optional.of(register);

        log.log(LogLevel.INFO, "Registered name '" + slobrokId.get() + "' at " + mySpec + " with: " + slobrokList);
    }

    private synchronized void shutdownSlobrokRegistrator() {
        slobrokRegistrator.ifPresent(Register::shutdown);
        slobrokRegistrator = Optional.empty();
    }

    public synchronized void shutdown() {
        shutdownSlobrokRegistrator();

        if (acceptor != null) {
            acceptor.shutdown().join();
        }
        supervisor.transport().shutdown().join();
    }


    public synchronized void bindRpcAdaptor(AbstractRpcAdaptor adaptor) {
        adaptor.bindCommands(supervisor);
    }

}