package org.wildfly.swarm.jmx.runtime;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import org.jboss.logging.Logger;
import org.wildfly.swarm.config.ManagementCoreService;
import org.wildfly.swarm.config.Undertow;
import org.wildfly.swarm.config.jmx.JMXRemotingConnector;
import org.wildfly.swarm.jmx.JMXFraction;
import org.wildfly.swarm.jmx.JMXProperties;
import org.wildfly.swarm.remoting.RemotingFraction;
import org.wildfly.swarm.spi.api.Customizer;
import org.wildfly.swarm.spi.runtime.annotations.ConfigurationValue;
import org.wildfly.swarm.spi.runtime.annotations.Pre;
/**
* Picks and/or verifies the remote JMX connector to use.
*
* <p>If a user has not specified <b>any</b> {@link JMXFraction#jmxRemotingConnector(JMXRemotingConnector)},
* then nothing is done as JMX remains purely available only inside the process.</p>
*
* <p>If a user has specified a generic, unconfigured {@link JMXRemotingConnector}, then his selector
* will pick the "best" connector available, given the following priority:</p>
*
* <ul>
* <li>Management Interface (typically port 9990) if <code>org.wildfly.swarm:management</code> is present</li>
* <li>Remoting over HTTP (typically normal web-port, 8080) if <code>org.wildfly.swarm:undertow</code> is present</li>
* <li>Else, the legacy remoting port (typically port 4777)</li>
* </ul>
*
* <p>A user who does not explicitly configure a {@link JMXRemotingConnector} can still activate
* a connector using configuation values (through properties or project-stages.yml), using
* the key of <code>swarm.jmx.remote</code></p>.
*
* <p>A non-null value (such as "true") will cause the above logic to be followed in selecting
* an endpoint. If the value is <code>management</code>, then the management endpoint will
* be considered to be explicitly selected. If management is available but the user would
* rather use the standard HTTP interface, then a value of <code>http></code> may be used.</p>
*
* <p>In the event a user has specifically {@link JMXRemotingConnector#useManagementEndpoint(Boolean)} to
* <code>true<</code>, then in the event <code>org.wildfly.swarm:management</code> is not present,
* then the remote connector for JMX will be <b>completely disabled</b>.</p>
*
* @author Bob McWhirter
*/
@Pre
@ApplicationScoped
public class JMXRemotingConnectorEndpointSelector implements Customizer {
private static Logger LOG = Logger.getLogger("org.wildfly.swarm.jmx");
@Inject
private JMXFraction jmx;
@Inject
private Instance<ManagementCoreService> management;
@Inject
private Instance<Undertow> undertow;
@Inject
private RemotingFraction remoting;
@Inject
@ConfigurationValue(JMXProperties.REMOTE)
private String remote;
@Override
public void customize() {
JMXRemotingConnector remotingConnector = this.jmx.subresources().jmxRemotingConnector();
if (remotingConnector == null) {
if (this.remote == null) {
LOG.info("JMX not configured for remote access");
return;
}
this.jmx.jmxRemotingConnector();
remotingConnector = this.jmx.subresources().jmxRemotingConnector();
if (this.remote.equals("http")) {
remotingConnector.useManagementEndpoint(false);
} else if (this.remote.equals("management")) {
remotingConnector.useManagementEndpoint(true);
}
}
boolean requiresLegacyRemoting = false;
if (remotingConnector.useManagementEndpoint() == null) {
if (!this.management.isUnsatisfied()) {
LOG.info("JMX configured for remote connector: implicitly using management interface");
remotingConnector.useManagementEndpoint(true);
} else if (!this.undertow.isUnsatisfied()) {
LOG.info("JMX configured for remote connector: implicitly using standard interface");
remotingConnector.useManagementEndpoint(false);
} else {
requiresLegacyRemoting = true;
}
} else if (remotingConnector.useManagementEndpoint() && this.management.isUnsatisfied()) {
LOG.warn("JMX configured to use management endpoint, but org.wildfly.swarm:management not available. Disabling");
this.jmx.jmxRemotingConnector(() -> null);
} else if (this.undertow.isUnsatisfied()) {
requiresLegacyRemoting = true;
}
if (requiresLegacyRemoting) {
remotingConnector.useManagementEndpoint(false);
LOG.info("JMX configured for remote connector but neither management nor http interfaces available. Using legacy remoting.");
this.remoting.requireLegacyConnector(true);
}
}
}