io.bdeploy.bhive.cli.ServeTool Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of api Show documentation
Show all versions of api Show documentation
Public API including dependencies, ready to be used for integrations and plugins.
package io.bdeploy.bhive.cli;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.util.Map;
import java.util.TreeMap;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import io.bdeploy.bhive.BHive;
import io.bdeploy.bhive.cli.ServeTool.ServeConfig;
import io.bdeploy.bhive.remote.jersey.BHiveJacksonModule;
import io.bdeploy.bhive.remote.jersey.BHiveLocatorImpl;
import io.bdeploy.bhive.remote.jersey.BHiveRegistry;
import io.bdeploy.common.cfg.Configuration.Help;
import io.bdeploy.common.cfg.Configuration.Validator;
import io.bdeploy.common.cfg.ExistingPathValidator;
import io.bdeploy.common.cli.ToolBase.CliTool.CliName;
import io.bdeploy.common.cli.ToolBase.ConfiguredCliTool;
import io.bdeploy.common.cli.ToolCategory;
import io.bdeploy.common.cli.data.RenderableResult;
import io.bdeploy.common.security.SecurityHelper;
import io.bdeploy.jersey.JerseyServer;
import io.bdeploy.jersey.JerseySessionConfiguration;
import io.bdeploy.jersey.ws.change.ObjectChangeBroadcaster;
import io.bdeploy.jersey.ws.change.ObjectChangeWebSocket;
/**
* Starts a HTTP(S) server which serves given {@link BHive}s other the network.
*/
@Help("Serve given BHives over the network.")
@ToolCategory(BHiveCli.SERVER_TOOLS)
@CliName("serve")
public class ServeTool extends ConfiguredCliTool {
public @interface ServeConfig {
@Help("Mapping from context path to BHive directory, ':' separated. E.g. 'myhive:/path/to/hive' will serve on 'https://host:port/api/hives/myhive'")
String[] serve();
@Help("Private KeyStore containing the server certificate and private key")
@Validator(ExistingPathValidator.class)
String keystore();
@Help("Passphrase for the private KeyStore")
String passphrase();
@Help("Port to serve on")
short port() default 7700;
}
public ServeTool() {
super(ServeConfig.class);
}
@Override
protected RenderableResult run(ServeConfig config) {
helpAndFailIfMissing(config.serve(), "Missing --serve");
helpAndFailIfMissing(config.keystore(), "Missing --keystore");
Map hives = new TreeMap<>();
try {
for (String s : config.serve()) {
int index = s.indexOf(':');
String path = s.substring(0, index);
String hive = s.substring(index + 1);
Path hPath = Paths.get(hive);
if (!Files.isDirectory(hPath)) {
out().println("WARNING: Skipping non-existant: " + hPath);
continue;
}
hives.put(path, new BHive(hPath.toUri(), getAuditorFactory().apply(hPath), getActivityReporter()));
}
Path storePath = Paths.get(config.keystore());
char[] passphrase = config.passphrase() == null ? null : config.passphrase().toCharArray();
KeyStore ks = SecurityHelper.getInstance().loadPrivateKeyStore(storePath, passphrase);
out().println("Serving " + hives.size() + " hive" + (hives.size() == 1 ? "" : "s") + " on port " + config.port());
runServer(config.port(), hives, ks, passphrase);
} catch (Exception e) {
throw new IllegalStateException("Error while preparing or running server", e);
} finally {
hives.forEach((k, v) -> v.close());
}
return null; // usually not reached.
}
private void runServer(short port, Map hives, KeyStore ks, char[] passphrase) {
try (JerseyServer server = new JerseyServer(port, ks, null, passphrase, JerseySessionConfiguration.noSessions())) {
BHiveRegistry reg = new BHiveRegistry(getActivityReporter());
for (Map.Entry entry : hives.entrySet()) {
reg.register(entry.getKey(), entry.getValue());
}
// WebSocket activity reporter bridge
ObjectChangeWebSocket ocws = new ObjectChangeWebSocket(server.getKeyStore());
server.registerWebsocketApplication(ObjectChangeWebSocket.OCWS_PATH, ocws);
// locator will create nested resources on demand.
server.registerResource(reg);
server.register(reg.binder());
server.register(new BHiveJacksonModule().binder());
server.register(BHiveLocatorImpl.class);
server.register(new AbstractBinder() {
@Override
protected void configure() {
bind(ocws).to(ObjectChangeBroadcaster.class);
}
});
server.start();
server.join();
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy