org.jboss.as.plugin.common.AbstractServerMojo Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.plugin.common;
import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.security.auth.callback.CallbackHandler;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.client.helpers.domain.DomainClient;
import org.jboss.dmr.ModelNode;
/**
* The default implementation for connecting to a running AS7 instance
*
* @author James R. Perkins
* @author Stuart Douglas
*/
public abstract class AbstractServerMojo extends AbstractMojo implements ConnectionInfo, Closeable {
public static final String DEBUG_MESSAGE_NO_CREDS = "No username and password in settings.xml file - falling back to CLI entry";
public static final String DEBUG_MESSAGE_NO_ID = "No element was found in the POM - Getting credentials from CLI entry";
public static final String DEBUG_MESSAGE_NO_SERVER_SECTION = "No section was found for the specified id";
public static final String DEBUG_MESSAGE_NO_SETTINGS_FILE = "No settings.xml file was found in this Mojo's execution context";
public static final String DEBUG_MESSAGE_POM_HAS_CREDS = "Getting credentials from the POM";
public static final String DEBUG_MESSAGE_SETTINGS_HAS_CREDS = "Found username and password in the settings.xml file";
public static final String DEBUG_MESSAGE_SETTINGS_HAS_ID = "Found the server's id in the settings.xml file";
private volatile InetAddress address = null;
private volatile CallbackHandler handler;
/**
* Specifies the host name of the server where the deployment plan should be executed.
*/
@Parameter(defaultValue = "localhost", property = PropertyNames.HOSTNAME)
private String hostname;
/**
* Specifies the port number the server is listening on.
*/
@Parameter(defaultValue = "9999", property = PropertyNames.PORT)
private int port;
/**
* Specifies the id of the server if the username and password is to be
* retrieved from the settings.xml file
*/
@Parameter(property = PropertyNames.ID)
private String id;
/**
* Provides a reference to the settings file.
*/
@Parameter(property = "settings", readonly = true, required = true, defaultValue = "${settings}")
private Settings settings;
/**
* Specifies the username to use if prompted to authenticate by the server.
*
* If no username is specified and the server requests authentication the user
* will be prompted to supply the username,
*/
@Parameter(property = PropertyNames.USERNAME)
private String username;
/**
* Specifies the password to use if prompted to authenticate by the server.
*
* If no password is specified and the server requests authentication the user
* will be prompted to supply the password,
*/
@Parameter(property = PropertyNames.PASSWORD)
private String password;
/**
* Indicates whether or not the goal should be skipped.
*/
@Parameter(defaultValue = "false", property = PropertyNames.SKIP)
private boolean skip;
/**
* Specifies the timeout to be used when hitting the host. Default is 5000ms.
*/
@Parameter(property = PropertyNames.TIMEOUT)
private int timeout = 5000;
@Component(role = SettingsDecrypter.class)
private DefaultSettingsDecrypter settingsDecrypter;
private ModelControllerClient client;
/**
* The hostname to deploy the archive to. The default is localhost.
*
* @return the hostname of the server.
*/
public final String hostname() {
return hostname;
}
/**
* The port number of the server to deploy to. The default is 9999.
*
* @return the port number to deploy to.
*/
@Override
public final int getPort() {
return port;
}
/**
* Returns {@code true} if the connection is for a domain server, otherwise {@code false}.
*
* @return {@code true} if the connection is for a domain server, otherwise {@code false}
*/
public final boolean isDomainServer() {
return isDomainServer(getClient());
}
/**
* The goal of the deployment.
*
* @return the goal of the deployment.
*/
public abstract String goal();
/**
* Gets or creates a new connection to the server and returns the client.
*
* For a domain server a {@link DomainClient} will be returned.
*
* @return the client
*/
public final synchronized ModelControllerClient getClient() {
ModelControllerClient result = client;
if (result == null) {
try {
result = client = ModelControllerClient.Factory.create(getHostAddress().getHostName(), getPort(), getCallbackHandler(), null, timeout);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(String.format("Host name '%s' is invalid.", hostname), e);
}
if (isDomainServer(result)) {
result = client = DomainClient.Factory.create(result);
}
}
return result;
}
@Override
public final synchronized void close() {
IoUtils.safeClose(client);
client = null;
}
/**
* Creates gets the address to the host name.
*
* @return the address.
*/
@Override
public final synchronized InetAddress getHostAddress() {
InetAddress result = address;
// Lazy load the address
if (result == null) {
try {
result = address = InetAddress.getByName(hostname());
} catch (UnknownHostException e) {
throw new IllegalArgumentException(String.format("Host name '%s' is invalid.", hostname), e);
}
}
return result;
}
@Override
public final synchronized CallbackHandler getCallbackHandler() {
CallbackHandler result = handler;
if (result == null) {
if (username == null && password == null) {
if (id != null) {
getCredentialsFromSettings();
} else {
getLog().debug(DEBUG_MESSAGE_NO_ID);
}
} else {
getLog().debug(DEBUG_MESSAGE_POM_HAS_CREDS);
}
result = handler = new ClientCallbackHandler(username, password);
}
return result;
}
/**
* Indicates whether or not the goal should be skipped.
*
* @return {@code true} to skip the goal, otherwise {@code false}
*/
protected boolean isSkip() {
return skip;
}
private void getCredentialsFromSettings() {
if (settings != null) {
Server server = settings.getServer(id);
if (server != null) {
getLog().debug(DEBUG_MESSAGE_SETTINGS_HAS_ID);
password = decrypt(server);
username = server.getUsername();
if (username != null && password != null) {
getLog().debug(DEBUG_MESSAGE_SETTINGS_HAS_CREDS);
} else {
getLog().debug(DEBUG_MESSAGE_NO_CREDS);
}
} else {
getLog().debug(DEBUG_MESSAGE_NO_SERVER_SECTION);
}
} else {
getLog().debug(DEBUG_MESSAGE_NO_SETTINGS_FILE);
}
}
private String decrypt(final Server server) {
SettingsDecryptionResult decrypt = settingsDecrypter.decrypt(new DefaultSettingsDecryptionRequest(server));
return decrypt.getServer().getPassword();
}
private boolean isDomainServer(final ModelControllerClient client) {
boolean result = false;
// Check this is really a domain server
final ModelNode op = ServerOperations.createReadAttributeOperation(ServerOperations.LAUNCH_TYPE);
try {
final ModelNode opResult = client.execute(op);
if (ServerOperations.isSuccessfulOutcome(opResult)) {
result = ("DOMAIN".equals(ServerOperations.readResultAsString(opResult)));
}
} catch (IOException e) {
if (getLog().isDebugEnabled())
getLog().debug(e);
throw new IllegalStateException(String.format("I/O Error could not execute operation '%s'", op), e);
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy