diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/AbstractHostControllerBootstrap.java b/host-controller/src/main/java/org/jboss/as/host/controller/AbstractHostControllerBootstrap.java
new file mode 100644
index 00000000000..8e6ff12831a
--- /dev/null
+++ b/host-controller/src/main/java/org/jboss/as/host/controller/AbstractHostControllerBootstrap.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright The WildFly Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.jboss.as.host.controller;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+
+import org.jboss.as.controller.ControlledProcessState;
+import org.jboss.as.controller.ControlledProcessStateService;
+import org.jboss.as.controller.ProcessStateNotifier;
+import org.jboss.as.server.FutureServiceContainer;
+import org.jboss.as.server.jmx.RunningStateJmx;
+import org.jboss.msc.service.ServiceActivator;
+import org.jboss.msc.service.ServiceContainer;
+import org.jboss.msc.service.ServiceTarget;
+
+/**
+ * Base class for bootstrapping embedded and non-embedded Host Controllers.
+ *
+ * @author Emanuel Muckenhuber
+ * @author Darran Lofthouse
+ * @author Brian Stansberry (c) 2011 Red Hat Inc.
+ * @author Ken Wills (c) 2015 Red Hat Inc.
+ */
+public abstract class AbstractHostControllerBootstrap {
+
+ private final ShutdownHook shutdownHook;
+ private final ServiceContainer serviceContainer;
+ private final HostControllerEnvironment environment;
+ private final String authCode;
+
+ protected AbstractHostControllerBootstrap(final HostControllerEnvironment environment, final String authCode,
+ final ShutdownHook shutdownHook) {
+ this.environment = environment;
+ this.authCode = authCode;
+ this.shutdownHook = shutdownHook;
+ this.serviceContainer = shutdownHook.register();
+ }
+
+ /**
+ * Bootstrap the host controller.
+ *
+ * @param embedded {@code true} if the host controller is embedded in another process
+ * @param extraServices any extra services to launch as part of bootstrap
+ * @return future that will provide the MSC {@link ServiceContainer} for the host controller
+ */
+ protected final Future bootstrap(boolean embedded, ServiceActivator... extraServices) {
+ final HostRunningModeControl runningModeControl = environment.getRunningModeControl();
+ final ControlledProcessState processState = new ControlledProcessState(true, embedded);
+ shutdownHook.setControlledProcessState(processState);
+ ServiceTarget target = serviceContainer.subTarget();
+
+ final ProcessStateNotifier processStateNotifier = ControlledProcessStateService.addService(target, processState);
+ RunningStateJmx.registerMBean(processStateNotifier, null, runningModeControl, false);
+
+ final FutureServiceContainer futureServiceContainer = new FutureServiceContainer();
+ final HostControllerService hcs = new HostControllerService(environment, runningModeControl, authCode,
+ processState, futureServiceContainer, extraServices);
+ target.addService(HostControllerService.HC_SERVICE_NAME, hcs).install();
+ return futureServiceContainer;
+ }
+
+ /**
+ * {@link Runtime#addShutdownHook JVM shutdown hook} thread that cleans up the
+ * Host Controller services.
+ */
+ public static final class ShutdownHook extends Thread {
+
+ private final Runnable processExitingCallback;
+ private boolean down;
+ private ControlledProcessState processState;
+ private ServiceContainer container;
+
+ /**
+ * Creates a new {@code ShutdownHook} thread.
+ */
+ public ShutdownHook() {
+ this(null);
+ }
+
+ /**
+ * Creates a new {@code ShutdownHook} thread.
+ *
+ * @param processExitingCallback runnable to invoke after the {@code ControlledProcessState} has been
+ * {@link ControlledProcessState#setStopping() set as stopping} but before
+ * the MSC {@link ServiceContainer} has been {@link ServiceContainer#shutdown() shut down}.
+ * May be {@code null}.
+ */
+ public ShutdownHook(Runnable processExitingCallback) {
+ this.processExitingCallback = processExitingCallback;
+ }
+
+ private ServiceContainer register() {
+
+ Runtime.getRuntime().addShutdownHook(this);
+ synchronized (this) {
+ if (!down) {
+ container = ServiceContainer.Factory.create("host-controller", false);
+ return container;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ private synchronized void setControlledProcessState(final ControlledProcessState ps) {
+ this.processState = ps;
+ }
+
+ /**
+ * Calls {@link #shutdown()}.
+ */
+ @Override
+ public void run() {
+ shutdown();
+ }
+
+ /**
+ * Notifies the {@code ControlledProcessState} for the Host Controller that
+ * {@link ControlledProcessState#setStopping() it is stopping}, invokes any {@link Runnable}
+ * provided to our {@link ShutdownHook#ShutdownHook(Runnable) constructor}, and
+ * {@link ServiceContainer#shutdown() shuts down} the Host Controller's {@link ServiceContainer}.
+ */
+ public void shutdown() {
+ final ServiceContainer sc;
+ final ControlledProcessState ps;
+ synchronized (this) {
+ down = true;
+ sc = container;
+ ps = processState;
+ }
+ try {
+ if (ps != null) {
+ ps.setStopping();
+ }
+ } finally {
+ if (sc != null) {
+ if (processExitingCallback != null) {
+ processExitingCallback.run();
+ }
+ final CountDownLatch latch = new CountDownLatch(1);
+ sc.addTerminateListener(new ServiceContainer.TerminateListener() {
+ @Override
+ public void handleTermination(Info info) {
+ latch.countDown();
+ }
+ });
+ sc.shutdown();
+ // wait for all services to finish.
+ for (;;) {
+ try {
+ latch.await();
+ break;
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerBootstrap.java b/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerBootstrap.java
index dc23ce74e6e..c4e1e3c69a7 100644
--- a/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerBootstrap.java
+++ b/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerBootstrap.java
@@ -5,110 +5,31 @@
package org.jboss.as.host.controller;
-import java.util.concurrent.CountDownLatch;
-
-import org.jboss.as.controller.ControlledProcessState;
-import org.jboss.as.controller.ProcessStateNotifier;
-import org.jboss.as.controller.ControlledProcessStateService;
import org.jboss.as.host.controller.logging.HostControllerLogger;
-import org.jboss.as.server.jmx.RunningStateJmx;
-import org.jboss.msc.service.ServiceContainer;
-import org.jboss.msc.service.ServiceTarget;
/**
- * Bootstrap of the HostController process.
+ * Bootstrap of a non-embedded HostController process.
*
* @author Emanuel Muckenhuber
* @author Darran Lofthouse
* @author Brian Stansberry (c) 2011 Red Hat Inc.
*/
-public class HostControllerBootstrap {
-
- private final ShutdownHook shutdownHook;
- private final ServiceContainer serviceContainer;
- private final HostControllerEnvironment environment;
- private final String authCode;
+public final class HostControllerBootstrap extends AbstractHostControllerBootstrap {
public HostControllerBootstrap(final HostControllerEnvironment environment, final String authCode) {
- this.environment = environment;
- this.authCode = authCode;
- this.shutdownHook = new ShutdownHook();
- this.serviceContainer = shutdownHook.register();
+ super(environment, authCode,
+ new ShutdownHook(HostControllerBootstrap::handleProcessExiting));
}
/**
* Start the host controller services.
- *
- * @throws Exception
*/
- public void bootstrap() throws Exception {
- final HostRunningModeControl runningModeControl = environment.getRunningModeControl();
- final ControlledProcessState processState = new ControlledProcessState(true, false);
- shutdownHook.setControlledProcessState(processState);
- ServiceTarget target = serviceContainer.subTarget();
- ProcessStateNotifier processStateNotifier = ControlledProcessStateService.addService(target, processState);
- RunningStateJmx.registerMBean(processStateNotifier, null, runningModeControl, false);
- final HostControllerService hcs = new HostControllerService(environment, runningModeControl, authCode, processState);
- target.addService(HostControllerService.HC_SERVICE_NAME, hcs).install();
+ public void bootstrap() {
+ bootstrap(false);
}
- private static class ShutdownHook extends Thread {
- private boolean down;
- private ControlledProcessState processState;
- private ServiceContainer container;
-
- private ServiceContainer register() {
-
- Runtime.getRuntime().addShutdownHook(this);
- synchronized (this) {
- if (!down) {
- container = ServiceContainer.Factory.create("host-controller", false);
- return container;
- } else {
- throw new IllegalStateException();
- }
- }
- }
-
- private synchronized void setControlledProcessState(final ControlledProcessState ps) {
- this.processState = ps;
- }
-
- @Override
- public void run() {
- final ServiceContainer sc;
- final ControlledProcessState ps;
- synchronized (this) {
- down = true;
- sc = container;
- ps = processState;
- }
- try {
- if (ps != null) {
- ps.setStopping();
- }
- } finally {
- if (sc != null) {
- SystemExiter.logBeforeExit(HostControllerLogger.ROOT_LOGGER::shutdownHookInvoked);
- final CountDownLatch latch = new CountDownLatch(1);
- sc.addTerminateListener(new ServiceContainer.TerminateListener() {
- @Override
- public void handleTermination(Info info) {
- latch.countDown();
- }
- });
- sc.shutdown();
- // wait for all services to finish.
- for (;;) {
- try {
- latch.await();
- break;
- } catch (InterruptedException e) {
- }
- }
- }
- }
- }
+ private static void handleProcessExiting() {
+ SystemExiter.logBeforeExit(HostControllerLogger.ROOT_LOGGER::shutdownHookInvoked);
}
}
diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/embedded/EmbeddedHostControllerBootstrap.java b/host-controller/src/main/java/org/jboss/as/host/controller/embedded/EmbeddedHostControllerBootstrap.java
index b1038293990..ae76e97bbcf 100644
--- a/host-controller/src/main/java/org/jboss/as/host/controller/embedded/EmbeddedHostControllerBootstrap.java
+++ b/host-controller/src/main/java/org/jboss/as/host/controller/embedded/EmbeddedHostControllerBootstrap.java
@@ -6,120 +6,51 @@
package org.jboss.as.host.controller.embedded;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
-import org.jboss.as.controller.ControlledProcessState;
-import org.jboss.as.controller.ControlledProcessStateService;
+import org.jboss.as.host.controller.AbstractHostControllerBootstrap;
import org.jboss.as.host.controller.HostControllerEnvironment;
-import org.jboss.as.host.controller.HostControllerService;
-import org.jboss.as.host.controller.HostRunningModeControl;
-import org.jboss.as.server.FutureServiceContainer;
-import org.jboss.as.server.jmx.RunningStateJmx;
import org.jboss.msc.service.ServiceActivator;
import org.jboss.msc.service.ServiceContainer;
-import org.jboss.msc.service.ServiceTarget;
/**
- * Embedded variant of {@link org.jboss.as.host.controller.HostControllerBootstrap}. TODO WFCORE-7143 see if these can be better unified.
+ * Embedded variant of {@link org.jboss.as.host.controller.AbstractHostControllerBootstrap}.
*
* @author Ken Wills (c) 2015 Red Hat Inc.
*/
-public class EmbeddedHostControllerBootstrap {
+public final class EmbeddedHostControllerBootstrap extends AbstractHostControllerBootstrap {
private final ShutdownHook shutdownHook;
- private final ServiceContainer serviceContainer;
- private final HostControllerEnvironment environment;
- private final String authCode;
-
public EmbeddedHostControllerBootstrap(final HostControllerEnvironment environment, final String authCode) {
- this.environment = environment;
- this.authCode = authCode;
- this.shutdownHook = new ShutdownHook();
- this.serviceContainer = shutdownHook.register();
+ this(environment, authCode, new ShutdownHook());
}
- public Future bootstrap(ServiceActivator... extraServices) throws Exception {
- try {
- final HostRunningModeControl runningModeControl = environment.getRunningModeControl();
- final ControlledProcessState processState = new ControlledProcessState(true, true);
- shutdownHook.setControlledProcessState(processState);
- ServiceTarget target = serviceContainer.subTarget();
-
- final org.jboss.as.controller.ProcessStateNotifier processStateNotifier = ControlledProcessStateService.addService(target, processState);
- RunningStateJmx.registerMBean(processStateNotifier, null, runningModeControl, false);
+ private EmbeddedHostControllerBootstrap(final HostControllerEnvironment environment, final String authCode,
+ final ShutdownHook shutdownHook) {
+ super(environment, authCode, shutdownHook);
+ this.shutdownHook = shutdownHook;
+ }
- final FutureServiceContainer futureServiceContainer = new FutureServiceContainer();
- final HostControllerService hcs = new HostControllerService(environment, runningModeControl, authCode,
- processState, futureServiceContainer, extraServices);
- target.addService(HostControllerService.HC_SERVICE_NAME, hcs).install();
- return futureServiceContainer;
+ /**
+ * Start the host controller services.
+ *
+ * @param extraServices any extra services to launch as part of bootstrap
+ */
+ public Future bootstrap(ServiceActivator... extraServices) {
+ try {
+ return bootstrap(true, extraServices);
} catch (RuntimeException | Error e) {
- shutdownHook.run();
+ shutdownHook.shutdown();
throw e;
}
}
+ /**
+ * Notification that overall embedded Host Controller startup of which a call
+ * to {@link #bootstrap(ServiceActivator...)} was a part has failed.
+ */
public void failed() {
- shutdownHook.run();
- }
-
- private static class ShutdownHook extends Thread {
- private boolean down;
- private ControlledProcessState processState;
- private ServiceContainer container;
-
- private ServiceContainer register() {
-
- Runtime.getRuntime().addShutdownHook(this);
- synchronized (this) {
- if (!down) {
- container = ServiceContainer.Factory.create("host-controller", false);
- return container;
- } else {
- throw new IllegalStateException();
- }
- }
- }
-
- private synchronized void setControlledProcessState(final ControlledProcessState ps) {
- this.processState = ps;
- }
-
- @Override
- public void run() {
- final ServiceContainer sc;
- final ControlledProcessState ps;
- synchronized (this) {
- down = true;
- sc = container;
- ps = processState;
- }
- try {
- if (ps != null) {
- ps.setStopping();
- }
- } finally {
- if (sc != null) {
- final CountDownLatch latch = new CountDownLatch(1);
- sc.addTerminateListener(new ServiceContainer.TerminateListener() {
- @Override
- public void handleTermination(Info info) {
- latch.countDown();
- }
- });
- sc.shutdown();
- // wait for all services to finish.
- for (;;) {
- try {
- latch.await();
- break;
- } catch (InterruptedException e) {
- }
- }
- }
- }
- }
+ shutdownHook.shutdown();
}
}