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

de.smartics.maven.plugin.jboss.modules.JBossModulesArchiveMojo Maven / Gradle / Ivy

Go to download

Generates an archive of modules based on information in a POM to be copied to an JBoss 7 installation.

The newest version!
/*
 * Copyright 2013-2018 smartics, Kronseder & Reiner GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.smartics.maven.plugin.jboss.modules;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiver.MavenArchiveConfiguration;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.util.graph.selector.AndDependencySelector;
import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector;
import org.eclipse.aether.util.graph.selector.OptionalDependencySelector;
import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.jdom2.Namespace;

import de.smartics.maven.plugin.jboss.modules.aether.Mapper;
import de.smartics.maven.plugin.jboss.modules.aether.MavenRepository;
import de.smartics.maven.plugin.jboss.modules.aether.MojoRepositoryBuilder;
import de.smartics.maven.plugin.jboss.modules.aether.filter.DefaultTransitiveDependencyResolver;
import de.smartics.maven.plugin.jboss.modules.aether.filter.ExclusionFilter;
import de.smartics.maven.plugin.jboss.modules.aether.filter.GaExclusionFilter;
import de.smartics.maven.plugin.jboss.modules.aether.filter.TestScopeFilter;
import de.smartics.maven.plugin.jboss.modules.descriptor.ArtifactClusion;
import de.smartics.maven.plugin.jboss.modules.descriptor.ModuleDescriptor;
import de.smartics.maven.plugin.jboss.modules.descriptor.ModulesDescriptor;
import de.smartics.maven.plugin.jboss.modules.domain.ExecutionContext;
import de.smartics.maven.plugin.jboss.modules.domain.ModuleBuilder;
import de.smartics.maven.plugin.jboss.modules.domain.ModuleMap;
import de.smartics.maven.plugin.jboss.modules.domain.PrunerGenerator;
import de.smartics.maven.plugin.jboss.modules.domain.SlotStrategy;
import de.smartics.maven.plugin.jboss.modules.domain.TransitiveDependencyResolver;
import de.smartics.maven.plugin.jboss.modules.parser.ModulesXmlLocator;
import de.smartics.maven.plugin.jboss.modules.xml.ModuleXmlBuilder;

/**
 * Generates a archive containing modules from a BOM project.
 *
 * @since 1.0
 * @description Generates a archive containing modules from a BOM project.
 */
@Mojo(name = "create-modules-archive", threadSafe = true,
    requiresProject = true,
    requiresDependencyResolution = ResolutionScope.TEST,
    defaultPhase = LifecyclePhase.PACKAGE)
public final class JBossModulesArchiveMojo extends AbstractMojo
{
  // ********************************* Fields *********************************

  // --- constants ------------------------------------------------------------

  // --- members --------------------------------------------------------------

  /**
   * An immutable variant of {@link #dependencyExcludes}, initialized in {@link #execute()}.
   */
  private List dependencyExcludesInternal;

  // ... Mojo infrastructure ..................................................

  /**
   * The Maven project.
   *
   * @since 1.0
   */
  @Parameter(defaultValue = "${project}", readonly=true)
  private MavenProject project;

  /**
   * The Maven session.
   */
  @Parameter(defaultValue = "${session}", readonly=true)
  private MavenSession session;

  /**
   * Resolver for artifact repositories.
   *
   * @since 1.0
   */
  @Component
  private RepositorySystem repositorySystem;

  /**
   * The current repository/network configuration of Maven.
   */
  @Parameter(defaultValue = "${repositorySystemSession}")
  private RepositorySystemSession repositorySession;

  /**
   * The project's remote repositories to use for the resolution of
   * dependencies.
   */
  @Parameter(defaultValue = "${project.remoteProjectRepositories}")
  private List remoteRepos;

  /**
   * Helper to add attachments to the build.
   *
   * @since 1.0
   */
  @Component
  private MavenProjectHelper projectHelper;

  /**
   * Helper to create an archive.
   *
   * @since 1.0
   */
  @Component(role = Archiver.class, hint = "jar")
  private JarArchiver jarArchiver;

  /**
   * The archive configuration to use. See Maven
   * Archiver Reference.
   *
   * @since 1.0
   */
  @Parameter
  private final MavenArchiveConfiguration archive =
      new MavenArchiveConfiguration();

  /**
   * A simple flag to skip the execution of this MOJO. If set on the command
   * line use -Dsmartics-jboss-modules.skip.
   *
   * @since 1.0
   */
  @Parameter(property = "smartics-jboss-modules.skip", defaultValue = "false")
  private boolean skip;

  /**
   * The verbose level. If set on the command line use
   * -Dsmartics-jboss-modules.verbose.
   *
   * @since 1.0
   */
  @Parameter(property = "smartics-jboss-modules.verbose",
      defaultValue = "false")
  private boolean verbose;

  /**
   * Allows to attach the generated modules as a ZIP archive to the build.
   *
   * @since 1.0
   */
  @Parameter(defaultValue = "true")
  private boolean attach;

  /**
   * Controls the system to act as being offline (true) or not (
   * false).
   *
   * @since 1.0
   */
  @Parameter(defaultValue = "${offline}")
  private boolean offline;

  /**
   * Controls the update policy according the access of the remote repositories.
   * 

* Allowed values are never, always, and * daily. *

* * @since 1.0 */ @Parameter(property = "smartics-jboss-modules.update", defaultValue = "never") private String updatePolicy; /** * Controls whether or not optional dependencies should be followed. * * @since 1.0 */ @Parameter(property = "smartics-jboss-modules.followOptionalDependencies", defaultValue = "false") private boolean followOptionalDependencies; /** * Allows to globally ignore exclusions declared in Maven dependencies. * * @since 1.0 */ @Parameter(defaultValue = "false") private boolean ignoreDependencyExclusions; /** * The name of the default slot to write to. See slotStrategy. * * @since 1.0 * @see #slotStrategy */ @Parameter(defaultValue = "main") private String defaultSlot; /** * The name of the slot strategy to us. If not specified, the major version of * the dependency will be used as slot value. *

* Possible values are: *

* * * * * * * * * * * * * *
valuedescription
version-majorThe slot has the major number of the version. The * defaultSlot is prepended, if not set to main * (e.g. defaultSlot=prodx and version 1.2.3 then the slot will * be named prodx1.
mainThe slot has the name as given with defaultSlot.
* * @since 1.0 */ @Parameter(defaultValue = "main") private String slotStrategy; /** * A list of dependencies to be excluded from the transitive dependency * collection process. * *
   *  <dependencyExcludes>
   *    <exclude>
   *      <groupId>com.sun</groupId>
   *      <artifactId>tools</artifactId>
   *    </exclude>
   *  </dependencyExcludes>
   * 
*/ @Parameter private List dependencyExcludes; // see also dependencyExcludesInternal /** * The root directories to search for modules XML files that contain module * descriptors. *

* If not specified, the default locations * src/main/config/jboss-modules, * src/main/resources/META-INF/jboss-modules, and * src/etc/jboss-modules is probed and - if exists - are * appended. *

*

* You may want to use only one of the locations given above. Use * config if you do not want to have the configuration files * included. Use resources/META-INF if they should and use * etc if they should not, but be stored outside the * main folder. *

* *
   * <modules>
   *   <dir>src/etc/jboss-modules</dir>
   * </modules>
   * 
* * @since 1.0 */ @Parameter private List modules; /** * The folder to write the module structure to. * * @since 1.0 */ @Parameter(defaultValue = "${project.build.directory}/jboss-modules") private File targetFolder; /** * The file to attach, containing the JBoss modules. * * @since 1.0 */ @Parameter( defaultValue = "${project.build.directory}/${project.artifactId}-${project.version}-jboss-modules.jar") private File modulesArchive; /** * The modules declared in the POM and the modules declared on the classpath * (in that order). */ private List modulesDescriptors; /** * The linear list of all modules from {@link #modulesDescriptors}. */ private List allModules; /** * Exclude the dependencies in the dependency management block if the project * is a POM project. If the project is not a POM project, these dependencies * are never included. *

* For BOM projects the default of false is usually appropriate. * In case of a multi module POM, the property usually is set to * true. *

* * @since 1.0 */ @Parameter(defaultValue = "false") private boolean excludeDependencyManagementDependenciesInPomProject; /** * Exclude any dependencies or transitive dependencies that are marked as * optional = true. * * @since 2.1.0 */ @Parameter(defaultValue = "false") private boolean ignoreOptionalDependencies; /** * Whether to generate a feature pack definition (true) or not * (false). Refer to * Provide camel subsystem as feature pack * for details. * * @since 2.1.0 */ @Parameter(defaultValue = "false") private boolean generateFeaturePackDefinition; /** * The namespace to use in the generated module.xml files. * * @since 2.1.4 */ @Parameter(defaultValue = ModuleXmlBuilder.MODULE_NS_1_1_URI) private String targetNamespace; // ****************************** Initializer ******************************* // ****************************** Constructors ****************************** // ****************************** Inner Classes ***************************** // ********************************* Methods ******************************** // --- init ----------------------------------------------------------------- // --- get&set -------------------------------------------------------------- // --- business ------------------------------------------------------------- @Override public void execute() throws MojoExecutionException, MojoFailureException { final Log log = getLog(); if (skip) { log.info("Skipping creating archive for JBoss modules since skip='true'."); return; } this.dependencyExcludesInternal = ArtifactClusion.buildList(dependencyExcludes); this.modulesDescriptors = initModulesDescriptors(); this.allModules = initModules(); this.repositorySession = adjustSession(); final List rootDependencies = calcRootDependencies(); final List dependencies = resolve(rootDependencies); logDependencies(rootDependencies, dependencies); runModuleCreation(dependencies); attach(); } private List initModules() { final List modules = new ArrayList(); for (final ModulesDescriptor descriptor : modulesDescriptors) { modules.addAll(descriptor.getDescriptors()); } return modules; } private List initModulesDescriptors() throws MojoExecutionException { try { final ModulesXmlLocator locator = new ModulesXmlLocator(defaultSlot); final ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); final List rootDirectories = calcModulesRootDirectories(); final List descriptors = locator.discover(parentClassLoader, rootDirectories); return descriptors; } catch (final IOException e) { throw new MojoExecutionException("Cannot read modules from class path.", e); } } private List calcModulesRootDirectories() { if (modules == null) { addDefaultDirIfExists("src/etc/jboss-modules"); addDefaultDirIfExists("src/main/config/jboss-modules"); addDefaultDirIfExists("src/main/resources/META-INF/jboss-modules"); } if (modules != null) { final List rootDirectories = new ArrayList(modules.size()); for (final String dir : modules) { final File rootDirectory = new File(project.getBasedir(), dir); if (rootDirectory.isDirectory()) { rootDirectories.add(rootDirectory); } else { getLog().warn( String.format( "Modules directory '%s' does not exist. Skipping ...", rootDirectory.getAbsolutePath())); } } return rootDirectories; } return new ArrayList(0); } private void addDefaultDirIfExists(final String defaultDir) { if (modules == null) { modules = new ArrayList(2); } final File rootDirectory = new File(project.getBasedir(), defaultDir); if (rootDirectory.isDirectory()) { modules.add(defaultDir); } } private void runModuleCreation(final List dependencies) throws MojoExecutionException { final boolean isPomProject = "pom".equals(project.getPackaging()); if (!isPomProject || excludeDependencyManagementDependenciesInPomProject) { final Mapper mapper = new Mapper(); final Artifact projectArtifact = mapper.map(project.getArtifact()); final Dependency projectAsDependency = new Dependency(projectArtifact, "compile"); dependencies.add(0, projectAsDependency); } final ExecutionContext context = createContext(dependencies); for (final Entry> entry : context .getModuleMap().toMap().entrySet()) { final ModuleDescriptor module = entry.getKey(); final Collection moduleDependencies = new HashSet(entry.getValue()); final ModuleBuilder builder = new ModuleBuilder(context, module, moduleDependencies); try { builder.create(); } catch (final IOException e) { throw new MojoExecutionException("Cannot write module '" + entry.getKey().getName() + "'.", e); } } } private void logDependencies(final Collection rootDependencies, final Collection dependencies) throws MojoExecutionException { if (verbose) { try { FileUtils.writeStringToFile(new File(project.getBasedir(), "target/root-dependencies.txt"), rootDependencies.toString()); FileUtils.writeStringToFile(new File(project.getBasedir(), "target/resolved-dependencies.txt"), dependencies.toString()); } catch (final IOException e) { throw new MojoExecutionException("dependencies", e); } } } private DefaultRepositorySystemSession adjustSession() { final DefaultRepositorySystemSession session = new DefaultRepositorySystemSession(repositorySession); final Set selectors = new HashSet(); selectors.add(new ScopeDependencySelector("test")); if (!followOptionalDependencies) { selectors.add(new OptionalDependencySelector()); } selectors.add(new ExclusionDependencySelector()); final AndDependencySelector selector = new AndDependencySelector(selectors); session.setDependencySelector(selector); session.setUpdatePolicy(updatePolicy); session.setOffline(offline); return session; } private void attach() throws MojoExecutionException { if (!attach) { return; } if (!targetFolder.isDirectory()) { getLog().info("Nothing to attach."); return; } try { jarArchiver.addDirectory(targetFolder); final MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); archiver.setOutputFile(modulesArchive); archiver.createArchive(session, project, archive); projectHelper.attachArtifact(project, "jar", "jboss-modules", modulesArchive); } catch (final Exception e) { final String message = String.format("Cannot create archive '%s'.: %s", modulesArchive.getAbsolutePath(), e.getMessage()); throw new MojoExecutionException(message, e); } } private ExecutionContext createContext(final List dependencies) { final ExecutionContext.Builder builder = new ExecutionContext.Builder(); builder.with(getLog()); builder.withTargetFolder(targetFolder); final TransitiveDependencyResolver resolver = createResolver(dependencies); builder.with(resolver); final SlotStrategy slotStrategy = SlotStrategy.fromString(this.slotStrategy); builder.with(slotStrategy); builder.withDefaultSlot(defaultSlot); final ModuleMap moduleMap = new ModuleMap(allModules, dependencies); builder.with(moduleMap); builder.withIgnoreOptionalDependencies(ignoreOptionalDependencies); builder.withGenerateFeaturePackDefinition(generateFeaturePackDefinition); builder.withTargetNamespaceUri(targetNamespace); if (verbose) { getLog().info("Modules:\n" + moduleMap.toString()); } return builder.build(); } @SuppressWarnings("unchecked") private List calcRootDependencies() throws MojoExecutionException { final List rootDependencies = new ArrayList(); final List projectDependencies = project.getDependencies(); addMappedDependencies(rootDependencies, projectDependencies); final boolean isPomProject = "pom".equals(project.getPackaging()); if (isPomProject) { if (!excludeDependencyManagementDependenciesInPomProject) { final DependencyManagement management = project.getDependencyManagement(); if (management != null) { final List managedDependencies = management.getDependencies(); addMappedDependencies(rootDependencies, managedDependencies); } } } return rootDependencies; } private static void addMappedDependencies( final List rootDependencies, final List newDependencies) { if (newDependencies != null && !newDependencies.isEmpty()) { final Mapper mapper = new Mapper(); for (final org.apache.maven.model.Dependency mavenDependency : newDependencies) { final Dependency dependency = mapper.map(mavenDependency); rootDependencies.add(dependency); } } } private List resolve(final List rootDependencies) throws MojoExecutionException { final TransitiveDependencyResolver resolver = createResolver(null); try { final List dependencies = resolver.resolve(rootDependencies); return dependencies; } catch (final DependencyResolutionException e) { final String message = "Cannot resolve dependency: " + e.getMessage() + "\nYou may use 'dependencyExcludes' to exclude broken dependencies from examination."; throw new MojoExecutionException(message, e); } } private TransitiveDependencyResolver createResolver( final List managedDependencies) { final PrunerGenerator prunerGenerator = new PrunerGenerator(dependencyExcludesInternal, allModules, ignoreDependencyExclusions); final List dependencyFilters = createDependencyFilters(); final MojoRepositoryBuilder builder = new MojoRepositoryBuilder(); builder.with(repositorySystem).with(repositorySession).with(remoteRepos) .withDependencyFilters(dependencyFilters) .withManagedDependencies(managedDependencies).withOffline(offline) .withTraverserGenerator(prunerGenerator).build(); final MavenRepository repository = builder.build(); return new DefaultTransitiveDependencyResolver(repository); } private List createDependencyFilters() { final List dependencyFilters = new ArrayList(); dependencyFilters.add(TestScopeFilter.INSTANCE); if (!ignoreDependencyExclusions) { dependencyFilters.add(ExclusionFilter.INSTANCE); } if (dependencyExcludes != null && !dependencyExcludes.isEmpty()) { final GaExclusionFilter filter = new GaExclusionFilter(dependencyExcludesInternal); dependencyFilters.add(filter); } return dependencyFilters; } // --- object basics -------------------------------------------------------- }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy