Publish BP-38 BookieEndpointInfo for BookKeeper Standalone mode

### Motivation

When you run "bin/bookkeeper standalone" the server does not publish BP-38 endpoint info.
This way you cannot use bookieId (BP-41).

### Changes

Fix BookieService in "standalone" package, that is very like to the BookieService in "bookkeeper-server".
The code cannot be reused, even if the name is similar the overall design of the class hierarchy is different.


Reviewers: Jia Zhai <zhaijia@apache.org>

This closes #2484 from eolivelli/fix/standalone-bp38
diff --git a/conf/standalone.conf b/conf/standalone.conf
index 4b52f2b..17dd3c3 100755
--- a/conf/standalone.conf
+++ b/conf/standalone.conf
@@ -16,13 +16,16 @@
 # * limitations under the License.
 # */
 
-# Standalone configuration
+# This file is used by 'bin/bookkeeper standalone' command
+# please copy from bk_server.conf the entries you need
+
+#Bookie configuration
+#bookieId=
+#allowLoopback=false
 
 ##################################################################
-##################################################################
 # stream/table service
 ##################################################################
-##################################################################
 
 ### Storage ###
 
diff --git a/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StorageServer.java b/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StorageServer.java
index fe520e6..278aaf2 100644
--- a/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StorageServer.java
+++ b/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StorageServer.java
@@ -154,12 +154,9 @@
             storageServer = buildStorageServer(
                 conf,
                 grpcPort);
-        } catch (ConfigurationException e) {
+        } catch (Exception e) {
             log.error("Invalid storage configuration", e);
             return ExitCode.INVALID_CONF.code();
-        } catch (UnknownHostException e) {
-            log.error("Unknonw host name", e);
-            return ExitCode.UNKNOWN_HOSTNAME.code();
         }
 
         CompletableFuture<Void> liveFuture =
@@ -178,7 +175,7 @@
 
     public static LifecycleComponent buildStorageServer(CompositeConfiguration conf,
                                                         int grpcPort)
-            throws UnknownHostException, ConfigurationException {
+            throws Exception {
         return buildStorageServer(conf, grpcPort, true, NullStatsLogger.INSTANCE);
     }
 
@@ -186,7 +183,7 @@
                                                         int grpcPort,
                                                         boolean startBookieAndStartProvider,
                                                         StatsLogger externalStatsLogger)
-        throws ConfigurationException, UnknownHostException {
+        throws Exception {
         final ComponentInfoPublisher componentInfoPublisher = new ComponentInfoPublisher();
 
         final Supplier<BookieServiceInfo> bookieServiceInfoProvider =
diff --git a/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StreamStorageLifecycleComponent.java b/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StreamStorageLifecycleComponent.java
index 6cf73b0..60c60a3 100644
--- a/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StreamStorageLifecycleComponent.java
+++ b/stream/server/src/main/java/org/apache/bookkeeper/stream/server/StreamStorageLifecycleComponent.java
@@ -18,13 +18,11 @@
 
 package org.apache.bookkeeper.stream.server;
 
-import java.net.UnknownHostException;
 import org.apache.bookkeeper.common.component.LifecycleComponent;
 import org.apache.bookkeeper.server.component.ServerLifecycleComponent;
 import org.apache.bookkeeper.server.conf.BookieConfiguration;
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.bookkeeper.stream.server.conf.StorageServerConfiguration;
-import org.apache.commons.configuration.ConfigurationException;
 
 /**
  * This is a {@link ServerLifecycleComponent} to allow run stream storage component as part of bookie server.
@@ -34,7 +32,7 @@
     private final LifecycleComponent streamStorage;
 
     public StreamStorageLifecycleComponent(BookieConfiguration conf, StatsLogger statsLogger)
-            throws UnknownHostException, ConfigurationException {
+            throws Exception {
         super("stream-storage", conf, statsLogger);
 
         StorageServerConfiguration ssConf = StorageServerConfiguration.of(conf.getUnderlyingConf());
diff --git a/stream/server/src/main/java/org/apache/bookkeeper/stream/server/service/BookieService.java b/stream/server/src/main/java/org/apache/bookkeeper/stream/server/service/BookieService.java
index 2a41421..4b8080c 100644
--- a/stream/server/src/main/java/org/apache/bookkeeper/stream/server/service/BookieService.java
+++ b/stream/server/src/main/java/org/apache/bookkeeper/stream/server/service/BookieService.java
@@ -13,18 +13,20 @@
  */
 package org.apache.bookkeeper.stream.server.service;
 
-import java.io.File;
 import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.function.Supplier;
 import lombok.Getter;
 import lombok.experimental.Accessors;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.bookkeeper.common.component.AbstractLifecycleComponent;
+import org.apache.bookkeeper.common.component.ComponentInfoPublisher;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.discover.BookieServiceInfo;
+import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.proto.BookieServer;
 import org.apache.bookkeeper.stats.StatsLogger;
 import org.apache.bookkeeper.stream.server.conf.BookieConfiguration;
@@ -40,34 +42,27 @@
     @Getter
     private final ServerConfiguration serverConf;
     private BookieServer bs;
-    private final Supplier<BookieServiceInfo> bookieServiceInfoProvider;
-
 
     public BookieService(BookieConfiguration conf, StatsLogger statsLogger,
-                         Supplier<BookieServiceInfo> bookieServiceInfoProvider) {
+                         Supplier<BookieServiceInfo> bookieServiceInfoProvider) throws Exception {
         super("bookie-server", conf, statsLogger);
         this.serverConf = new ServerConfiguration();
         this.serverConf.loadConf(conf.getUnderlyingConf());
-        this.bookieServiceInfoProvider = bookieServiceInfoProvider;
+        String hello = String.format(
+            "Hello, I'm your bookie, bookieId is %1$s, listening on port %2$s. Metadata service uri is %3$s."
+                + " Journals are in %4$s. Ledgers are stored in %5$s.",
+            serverConf.getBookieId() != null ? serverConf.getBookieId() : "<not-set>",
+            serverConf.getBookiePort(),
+            serverConf.getMetadataServiceUriUnchecked(),
+            Arrays.asList(serverConf.getJournalDirNames()),
+            Arrays.asList(serverConf.getLedgerDirNames()));
+        log.info(hello);
+        this.bs = new BookieServer(serverConf, statsLogger, bookieServiceInfoProvider);
     }
 
     @Override
     protected void doStart() {
-        List<File> indexDirs;
-        if (null == serverConf.getIndexDirs()) {
-            indexDirs = Collections.emptyList();
-        } else {
-            indexDirs = Arrays.asList(serverConf.getIndexDirs());
-        }
-        log.info("Hello, I'm your bookie, listening on port {} :"
-                + " metadata service uri = {}, journals = {}, ledgers = {}, index = {}",
-            serverConf.getBookiePort(),
-            serverConf.getMetadataServiceUriUnchecked(),
-            Arrays.asList(serverConf.getJournalDirNames()),
-            Arrays.asList(serverConf.getLedgerDirs()),
-            indexDirs);
         try {
-            this.bs = new BookieServer(serverConf, statsLogger, bookieServiceInfoProvider);
             bs.start();
             log.info("Started bookie server successfully.");
         } catch (Exception e) {
@@ -86,4 +81,23 @@
     protected void doClose() throws IOException {
         // no-op
     }
+
+    @Override
+    public void publishInfo(ComponentInfoPublisher componentInfoPublisher) {
+        try {
+            BookieSocketAddress localAddress = bs.getLocalAddress();
+            List<String> extensions = new ArrayList<>();
+            if (serverConf.getTLSProviderFactoryClass() != null) {
+                extensions.add("tls");
+            }
+            ComponentInfoPublisher.EndpointInfo endpoint = new ComponentInfoPublisher.EndpointInfo("bookie",
+                    localAddress.getPort(),
+                    localAddress.getHostName(),
+                    "bookie-rpc", null, extensions);
+            componentInfoPublisher.publishEndpoint(endpoint);
+
+        } catch (UnknownHostException err) {
+            log.error("Cannot compute local address", err);
+        }
+    }
 }