All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.plugin.provision.AbstractProvisionServerMojo Maven / Gradle / Ivy

Go to download

A maven plugin that allows various management operations to be executed on WildFly Application Server.

There is a newer version: 5.1.1.Final
Show newest version
/*
 * Copyright The WildFly Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package org.wildfly.plugin.provision;

import static org.wildfly.plugin.core.Constants.PLUGIN_PROVISIONING_FILE;
import static org.wildfly.plugin.core.Constants.STANDALONE_XML;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLStreamException;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.repository.RemoteRepository;
import org.jboss.galleon.ProvisioningException;
import org.jboss.galleon.api.GalleonBuilder;
import org.jboss.galleon.api.GalleonFeaturePack;
import org.jboss.galleon.api.Provisioning;
import org.jboss.galleon.api.ProvisioningBuilder;
import org.jboss.galleon.api.config.GalleonProvisioningConfig;
import org.jboss.galleon.maven.plugin.util.MavenArtifactRepositoryManager;
import org.jboss.galleon.maven.plugin.util.MvnMessageWriter;
import org.jboss.galleon.universe.maven.repo.MavenRepoManager;
import org.jboss.galleon.util.IoUtils;
import org.wildfly.channel.UnresolvedMavenArtifactException;
import org.wildfly.plugin.common.PropertyNames;
import org.wildfly.plugin.common.Utils;
import org.wildfly.plugin.core.MavenJBossLogger;
import org.wildfly.plugin.core.MavenRepositoriesEnricher;
import org.wildfly.plugin.tools.GalleonUtils;
import org.wildfly.plugin.tools.PluginProgressTracker;

/**
 * Provision a server
 *
 * @author jfdenise
 */
abstract class AbstractProvisionServerMojo extends AbstractMojo {
    static {
        // This is odd, but if not set we should set the JBoss Logging provider to slf4j as that is what Maven uses
        final String provider = System.getProperty("org.jboss.logging.provider");
        if (provider == null || provider.isBlank()) {
            System.setProperty("org.jboss.logging.provider", "slf4j");
        }
    }

    @Component
    RepositorySystem repoSystem;

    @Component
    MavenProjectHelper projectHelper;

    @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
    RepositorySystemSession repoSession;

    @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true, required = true)
    List repositories;

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    MavenProject project;

    @Parameter(defaultValue = "${session}", readonly = true, required = true)
    MavenSession session;

    /**
     * Arbitrary Galleon options used when provisioning the server. In case you
     * are building a large amount of server in the same maven session, it
     * is strongly advised to set 'jboss-fork-embedded' option to 'true' in
     * order to fork Galleon provisioning and CLI scripts execution in dedicated
     * processes. For example:
     *
     * 
     *   <galleon-options>
     *     <jboss-fork-embedded>true</jboss-fork-embedded>
     *   </galleon-options>
     * 
*/ @Parameter(required = false, alias = "galleon-options") Map galleonOptions = Collections.emptyMap(); /** * Whether to use offline mode when the plugin resolves an artifact. In * offline mode the plugin will only use the local Maven repository for an * artifact resolution. */ @Parameter(alias = "offline-provisioning", defaultValue = "false", property = PropertyNames.WILDFLY_PROVISIONING_OFFLINE) boolean offlineProvisioning; /** * Whether to log provisioning time at the end */ @Parameter(alias = "log-provisioning-time", defaultValue = "false", property = PropertyNames.WILDFLY_PROVISIONING_LOG_TIME) boolean logProvisioningTime; /** * Whether to record provisioning state in .galleon directory. */ @Parameter(alias = "record-provisioning-state", defaultValue = "false", property = PropertyNames.WILDFLY_PROVISIONING_RECORD_STATE) boolean recordProvisioningState; /** * Set to {@code true} if you want the goal to be skipped, otherwise * {@code false}. */ @Parameter(defaultValue = "false", property = PropertyNames.SKIP_PROVISION) private boolean skip; /** * The path to the directory where to provision the server. Can be an absolute path or a path relative to the buildDir. * By default the server is provisioned into the {@code target/server} directory. */ @Parameter(alias = "provisioning-dir", property = PropertyNames.WILDFLY_PROVISIONING_DIR, defaultValue = Utils.WILDFLY_DEFAULT_DIR) protected String provisioningDir; /** * Set to {@code true} if you want to delete the existing server referenced from the {@code provisioningDir} and provision a * new one, * otherwise {@code false}. */ @Parameter(alias = "overwrite-provisioned-server", defaultValue = "false", property = PropertyNames.WILDFLY_PROVISIONING_OVERWRITE_PROVISIONED_SERVER) private boolean overwriteProvisionedServer; /** * A list of feature-pack configurations to install, can be combined with layers. * Use the System property {@code wildfly.provisioning.feature-packs} to provide a comma separated list of feature-packs. */ @Parameter(required = false, alias = "feature-packs", property = PropertyNames.WILDFLY_PROVISIONING_FEATURE_PACKS) List featurePacks = Collections.emptyList(); /** * A list of Galleon layers to provision. Can be used when * feature-pack-location or feature-packs are set. * Use the System property {@code wildfly.provisioning.layers} to provide a comma separated list of layers. */ @Parameter(alias = "layers", required = false, property = PropertyNames.WILDFLY_PROVISIONING_LAYERS) List layers = Collections.emptyList(); /** * A list of Galleon layers to exclude. Can be used when * feature-pack-location or feature-packs are set. * Use the System property {@code wildfly.provisioning.layers.excluded} to provide a comma separated list of layers to * exclude. */ @Parameter(alias = "excluded-layers", required = false, property = PropertyNames.WILDFLY_PROVISIONING_LAYERS_EXCLUDED) List excludedLayers = Collections.emptyList(); /** * The path to the {@code provisioning.xml} file to use. Note that this cannot be used with the {@code feature-packs} * or {@code configurations}. * If the provisioning file is not absolute, it has to be relative to the project base directory. */ @Parameter(alias = "provisioning-file", property = PropertyNames.WILDFLY_PROVISIONING_FILE, defaultValue = "${project.basedir}/galleon/provisioning.xml") private File provisioningFile; /** * The name of the configuration file generated from layers. Default value is {@code standalone.xml}. * If no {@code layers} have been configured, setting this parameter is invalid. */ @Parameter(alias = "layers-configuration-file-name", property = PropertyNames.WILDFLY_LAYERS_CONFIGURATION_FILE_NAME, defaultValue = STANDALONE_XML) String layersConfigurationFileName; /** * A list of channels used for resolving artifacts while provisioning. *

* Defining a channel: * *

     * 
     *     
     *         
     *             org.wildfly.channels
     *             wildfly-30.0
     *         
     *     
     *     
     *         
     *             https://example.example.org/channel/30
     *         
     *     
     * 
     * 
*

*

* The {@code wildfly.channels} property can be used pass a comma delimited string for the channels. The channel * can be a URL or a Maven GAV. If a Maven GAV is used, the groupId and artifactId are required. *
* Examples: * *

     *     -Dwildfly.channels="https://channels.example.org/30"
     *     -Dwildfly.channels="https://channels.example.org/30,org.example.channel:updates-30"
     *     -Dwildfly.channels="https://channels.example.org/30,org.example.channel:updates-30:1.0.2"
     * 
*

*/ @Parameter(alias = "channels", property = PropertyNames.CHANNELS) List channels; /** * Do not actually provision a server but generate the Galleon provisioning configuration * in {@code target/.wildfly-maven-plugin-provisioning.xml} file. * * @since 5.0 */ @Parameter(alias = "dry-run") boolean dryRun; private Path wildflyDir; protected MavenRepoManager artifactResolver; @Override public void execute() throws MojoExecutionException, MojoFailureException { if (skip) { getLog().debug(String.format("Skipping " + getGoal() + " of %s:%s", project.getGroupId(), project.getArtifactId())); return; } if (dryRun) { getLog().info("Dry run execution, no server will be provisioned."); } Path targetPath = Paths.get(project.getBuild().getDirectory()); wildflyDir = targetPath.resolve(provisioningDir).normalize(); if (!overwriteProvisionedServer && Files.exists(wildflyDir)) { getLog().info(String.format("A server already exists in " + wildflyDir + ", skipping " + getGoal() + " of %s:%s", project.getGroupId(), project.getArtifactId())); return; } enrichRepositories(); if (channels == null || channels.isEmpty()) { artifactResolver = offlineProvisioning ? new MavenArtifactRepositoryManager(repoSystem, repoSession) : new MavenArtifactRepositoryManager(repoSystem, repoSession, repositories); } else { try { artifactResolver = new ChannelMavenArtifactRepositoryManager(channels, repoSystem, repoSession, repositories, getLog(), offlineProvisioning); } catch (MalformedURLException | UnresolvedMavenArtifactException ex) { throw new MojoExecutionException(ex.getLocalizedMessage(), ex); } } if (!Paths.get(provisioningDir).isAbsolute() && (targetPath.equals(wildflyDir) || !wildflyDir.startsWith(targetPath))) { throw new MojoExecutionException("provisioning-dir " + provisioningDir + " must be an absolute path or a child directory relative to the project build directory."); } IoUtils.recursiveDelete(wildflyDir); try { try { provisionServer(wildflyDir); if (!dryRun) { if (artifactResolver instanceof ChannelMavenArtifactRepositoryManager) { ((ChannelMavenArtifactRepositoryManager) artifactResolver).done(wildflyDir); } serverProvisioned(wildflyDir); } } catch (ProvisioningException | IOException | XMLStreamException ex) { throw new MojoExecutionException("Provisioning failed", ex); } } finally { // Although cli and embedded are run in their own classloader, // the module.path system property has been set and needs to be cleared for // in same JVM next execution. System.clearProperty("module.path"); } } protected void enrichRepositories() throws MojoExecutionException { MavenRepositoriesEnricher.enrich(session, project, repositories); } protected abstract String getGoal(); protected abstract void serverProvisioned(Path jbossHome) throws MojoExecutionException, MojoFailureException; private void provisionServer(Path home) throws ProvisioningException, MojoExecutionException, IOException, XMLStreamException { GalleonBuilder galleonBuilder = new GalleonBuilder(); galleonBuilder.addArtifactResolver(artifactResolver); GalleonProvisioningConfig config = buildGalleonConfig(galleonBuilder); ProvisioningBuilder builder = galleonBuilder.newProvisioningBuilder(config); try (Provisioning pm = builder .setInstallationHome(home) .setMessageWriter(new MvnMessageWriter(getLog())) .setLogTime(logProvisioningTime) .setRecordState(recordProvisioningState) .build()) { if (dryRun) { Path targetPath = Paths.get(project.getBuild().getDirectory()); Path file = targetPath.resolve(PLUGIN_PROVISIONING_FILE); getLog().info("Dry-run execution, generating provisioning.xml file: " + file); pm.storeProvisioningConfig(config, file); return; } getLog().info("Provisioning server in " + home); PluginProgressTracker.initTrackers(pm, new MavenJBossLogger(getLog())); pm.provision(config); // Check that at least the standalone or domain directories have been generated. if (!Files.exists(home.resolve("standalone")) && !Files.exists(home.resolve("domain"))) { getLog().error("Invalid galleon provisioning, no server provisioned in " + home + ". Make sure " + "that the list of Galleon feature-packs and Galleon layers are properly configured."); throw new MojoExecutionException("Invalid plugin configuration, no server provisioned."); } if (!recordProvisioningState) { Path file = home.resolve(PLUGIN_PROVISIONING_FILE); pm.storeProvisioningConfig(config, file); } } } protected GalleonProvisioningConfig buildGalleonConfig(GalleonBuilder galleonBuilder) throws MojoExecutionException, ProvisioningException { GalleonProvisioningConfig config; Path resolvedProvisioningFile = resolvePath(project, provisioningFile.toPath()); boolean provisioningFileExists = Files.exists(resolvedProvisioningFile); if (featurePacks.isEmpty()) { if (provisioningFileExists) { getLog().info("Provisioning server using " + resolvedProvisioningFile + " file."); try (Provisioning p = galleonBuilder.newProvisioningBuilder(resolvedProvisioningFile).build()) { config = p.loadProvisioningConfig(resolvedProvisioningFile); } } else { config = getDefaultConfig(); if (config == null) { throw new MojoExecutionException("No feature-pack has been configured, can't provision a server."); } } } else { if (provisioningFileExists) { getLog().warn( "Galleon provisioning file " + provisioningFile + " is ignored, plugin configuration is used."); } if (layers.isEmpty() && !STANDALONE_XML.equals(layersConfigurationFileName)) { throw new MojoExecutionException( "layers-configuration-file-name has been set although no layers are defined."); } config = GalleonUtils.buildConfig(galleonBuilder, featurePacks, layers, excludedLayers, galleonOptions, layersConfigurationFileName); } return config; } protected GalleonProvisioningConfig getDefaultConfig() throws ProvisioningException { return GalleonUtils.buildDefaultConfig(); } static Path resolvePath(MavenProject project, Path path) { if (!path.isAbsolute()) { path = Paths.get(project.getBasedir().getAbsolutePath()).resolve(path); } return path; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy