/*
* Copyright (c) 2015 Spotify AB.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.spotify.heroic.shell;
import com.spotify.heroic.lifecycle.LifeCycle;
import com.spotify.heroic.lifecycle.LifeCycleManager;
import dagger.Module;
import dagger.Provides;
import eu.toolchain.async.AsyncFramework;
import eu.toolchain.async.AsyncFuture;
import eu.toolchain.async.Managed;
import eu.toolchain.async.ManagedSetup;
import eu.toolchain.serializer.SerializerFramework;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.Optional;
import java.util.concurrent.Callable;
import javax.inject.Named;
import static java.util.Optional.empty;
import static java.util.Optional.of;
@Slf4j
@RequiredArgsConstructor
@Module
public class ShellServerModule {
public static final String DEFAULT_HOST = "localhost";
public static final int DEFAULT_PORT = 9190;
final Optional<String> host;
final Optional<Integer> port;
@Provides
@ShellServerScope
@Named("shell-protocol")
SerializerFramework serializer() {
return ShellProtocol.setupSerializer();
}
@Provides
@ShellServerScope
Managed<ShellServerState> state(final AsyncFramework async) {
final String host = this.host.orElse(DEFAULT_HOST);
final int port = this.port.orElse(DEFAULT_PORT);
return async.managed(new ManagedSetup<ShellServerState>() {
@Override
public AsyncFuture<ShellServerState> construct() throws Exception {
return async.call(new Callable<ShellServerState>() {
@Override
public ShellServerState call() throws Exception {
log.info("Binding to {}:{}", host, port);
final ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(host, port));
return new ShellServerState(serverSocket);
}
});
}
@Override
public AsyncFuture<Void> destruct(final ShellServerState value) throws Exception {
return async.resolved();
}
});
}
@Provides
@ShellServerScope
@Named("shellServer")
LifeCycle shellServerLife(LifeCycleManager manager, ShellServer shellServer) {
return manager.build(shellServer);
}
public static Builder builder() {
return new Builder();
}
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static class Builder {
private Optional<String> host = empty();
private Optional<Integer> port = empty();
public Builder host(String host) {
this.host = of(host);
return this;
}
public Builder port(int port) {
this.port = of(port);
return this;
}
public ShellServerModule build() {
return new ShellServerModule(host, port);
}
}
}