Java tutorial
/******************************************************************************* * Copyright (c) 2014 Gunnar Wagenknecht and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Wagenknecht - initial API and implementation * Sonatype Inc. - methods for reading OSGi I10N properties from Tycho * Brian de Alwis - handle artifacts that lack source *******************************************************************************/ package org.eclipse.ebr.maven; import static java.lang.String.format; import static org.twdata.maven.mojoexecutor.MojoExecutor.artifactId; import static org.twdata.maven.mojoexecutor.MojoExecutor.configuration; import static org.twdata.maven.mojoexecutor.MojoExecutor.element; import static org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo; import static org.twdata.maven.mojoexecutor.MojoExecutor.executionEnvironment; import static org.twdata.maven.mojoexecutor.MojoExecutor.goal; import static org.twdata.maven.mojoexecutor.MojoExecutor.groupId; import static org.twdata.maven.mojoexecutor.MojoExecutor.name; import static org.twdata.maven.mojoexecutor.MojoExecutor.plugin; import static org.twdata.maven.mojoexecutor.MojoExecutor.version; import java.io.File; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Model; import org.apache.maven.model.building.ModelBuilder; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.BuildPluginManager; 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.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.apache.maven.repository.RepositorySystem; import org.apache.maven.settings.Settings; import org.apache.maven.settings.crypto.SettingsDecrypter; import org.twdata.maven.mojoexecutor.MojoExecutor.Element; import com.google.common.base.Strings; /** * A Maven plug-on for collecting Eclipse IP information. * * <pre> * <build> * <plugins> * <plugin> * <groupId>org.eclipse.ebr</groupId> * <artifactId>ebr-maven-plugin</artifactId> * <executions> * <execution> * <goals> * <goal>eclipse-ip-info</goal> * </goals> * <configuration> * <force>true</force> * <licenseMappings> * <logback-core>Eclipse Public License</logback-core> * </licenseMappings> * <localLicenseFiles> * <SLF4J-LICENSE.txt>MIT License</SLF4J-LICENSE.txt> * </localLicenseFiles> * </configuration> * </execution> * </executions> * </plugin> * </plugins> * </build> * </pre> */ @Mojo(name = "eclipse-ip-info", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME, defaultPhase = LifecyclePhase.PREPARE_PACKAGE) public class EclipseIpInfoMojo extends AbstractMojo { private static final String CLASSIFIER_SOURCES = "sources"; /** * The project output directory where all sources and licenses will be * collected for generating the ip info. */ @Parameter(defaultValue = "${project.build.directory}/sources-for-eclipse-ipzilla", readonly = true, required = true) protected File outputDirectory; @Parameter(defaultValue = "${project}", readonly = true, required = true) protected MavenProject project; @Parameter(defaultValue = "${session}", readonly = true, required = true) protected MavenSession mavenSession; @Parameter(defaultValue = "${settings}", readonly = true) protected Settings settings; @Parameter(defaultValue = "${project.remoteArtifactRepositories}", readonly = true) protected List<ArtifactRepository> remoteRepositories; @Component private RepositorySystem repositorySystem; @Component private RepositoryMetadataManager repositoryMetadataManager; @Component private ModelBuilder modelBuilder; @Component private BuildPluginManager pluginManager; @Component private MavenProjectHelper projectHelper; /** * A comma separated list of artifactIds which should be exclude completely * from the processing. TEST dependencies will always be excluded. */ @Parameter(defaultValue = "${excludeDependencies}") protected String excludeDependencies; @Parameter(defaultValue = "2.6", property = "maven-resource-plugin.version", required = true) protected String mavenResourcesPluginVersion = "2.6"; @Parameter(defaultValue = "2.8", property = "maven-dependency-plugin.version", required = true) protected String mavenDependencyPluginVersion = "2.8"; @Parameter(defaultValue = "false", property = "force") private boolean force; @Parameter(defaultValue = "false", property = "forceDownload") private boolean forceDownload; @Parameter(defaultValue = "true", property = "failBuildIfIpLogIsIncomplete") private boolean failBuildIfIpLogIsIncomplete; @Parameter(property = "submitCqsToProject") protected String submitCqsToProject; @Parameter(property = "cqCryptography") protected String cqCryptography; @Component private SettingsDecrypter settingsDecrypter; /** * Custom license mappings (key is artifactId and value is the license used * at Eclipse.org) */ @Parameter protected Map<String, String> licenseMappings = new LinkedHashMap<String, String>(); /** * Custom about_files mappings (key is the local license file name within * the about_files folder, value is the license name it represents) */ @Parameter protected Map<String, String> localLicenseFiles = new LinkedHashMap<String, String>(); private void collectSources(final Set<Artifact> dependencies) throws MojoExecutionException { // collect sources getLog().info("Gathering sources archives"); // @formatter:off final List<Element> copyConfigurationSource = getCopyConfiguration(outputDirectory.getAbsolutePath(), dependencies, CLASSIFIER_SOURCES); try { executeMojo( plugin(groupId("org.apache.maven.plugins"), artifactId("maven-dependency-plugin"), version(mavenDependencyPluginVersion)), goal("copy"), configuration(copyConfigurationSource.toArray(new Element[copyConfigurationSource.size()])), executionEnvironment(project, mavenSession, pluginManager)); } catch (final MojoExecutionException e) { getLog().warn("Unable to resolve source jar; skipping Eclipse IP information"); getLog().debug(e); return; } // @formatter:on // rename all jars to zip for (final File file : outputDirectory.listFiles()) { final String absolutePath = file.getAbsolutePath(); if (absolutePath.endsWith(".jar")) { final File newFile = new File(StringUtils.removeEnd(absolutePath, ".jar") + ".zip"); getLog().debug(format("Renaming '%s' to '%s'.", file.getName(), newFile.getName())); file.renameTo(newFile); } } } private void discoverLicenseFromExistingIpLog(final Set<Artifact> dependencies) throws MojoExecutionException { getLog().info("Discovering license information from existing ip_log.xml"); // find license information final EclipseIpLogUtil ipLogUtil = new EclipseIpLogUtil(getLog(), mavenSession, settings, force); final String licenseName = ipLogUtil.getLicenseNameFromIpLogXmlFile(getIpLogXmlDirectory()); // populate license mappings if (!Strings.isNullOrEmpty(licenseName)) { for (final Artifact artifact : dependencies) { if (!licenseMappings.containsKey(artifact.getArtifactId())) { getLog().info(format("Discovered license '%s' for artifact %s:%s:%s.", licenseName, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion())); licenseMappings.put(artifact.getArtifactId(), licenseName); } } } } @Override public void execute() throws MojoExecutionException, MojoFailureException { if (!BundleMojo.isRecipeProject(project)) { getLog().debug( format("Skipping execution for project with packaging type \"%s\"", project.getPackaging())); return; } final Set<Artifact> dependencies = getDependenciesToInclude(); discoverLicenseFromExistingIpLog(dependencies); collectSources(dependencies); refreshAboutFiles(dependencies); refreshIpLog(dependencies); } private List<Element> getCopyConfiguration(final String outputDirectory, final Set<Artifact> dependencies, final String classifier) throws MojoExecutionException { final List<Element> copyConfiguration = new ArrayList<Element>(); copyConfiguration.add(element(name("outputDirectory"), outputDirectory)); final List<Element> artifactItems = new ArrayList<Element>(); for (final Artifact artifact : dependencies) { // @formatter:off if (classifier != null) { artifactItems.add(element("artifactItem", element("groupId", artifact.getGroupId()), element("artifactId", artifact.getArtifactId()), element("version", artifact.getVersion()), element("classifier", classifier))); } else { artifactItems.add(element("artifactItem", element("groupId", artifact.getGroupId()), element("artifactId", artifact.getArtifactId()), element("version", artifact.getVersion()))); // @formatter:on } } copyConfiguration.add(element("artifactItems", artifactItems.toArray(new Element[artifactItems.size()]))); return copyConfiguration; } private Set<Artifact> getDependenciesToInclude() { final DependencyUtil dependencyUtil = new DependencyUtil(getLog(), mavenSession); dependencyUtil.initializeExcludeDependencies(excludeDependencies); return dependencyUtil.getDependenciesToInclude(project); } private File getIpLogXmlDirectory() throws MojoExecutionException { return new File(getProjectDir(), "src/eclipse"); } private ModelUtil getModelUtil() { return new ModelUtil(getLog(), mavenSession, repositorySystem, repositoryMetadataManager, modelBuilder, remoteRepositories); } private File getProjectDir() throws MojoExecutionException { final File projectDir = project.getBasedir(); if (projectDir == null) throw new MojoExecutionException("Unable to determine project directory for project: " + project); return projectDir; } private void populateLicenseInformation(final LicenseProcessingUtility licenseProcessingUtility, final Set<Artifact> dependencies) throws MojoExecutionException { for (final Artifact artifact : dependencies) { final String license = licenseMappings.get(artifact.getArtifactId()); getLog().debug(format("License mapping for artifact %s:%s:%s: %s", license, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), license)); if (license != null) { licenseProcessingUtility.setLicense(artifact, license); } } for (final Entry<String, String> e : localLicenseFiles.entrySet()) { licenseProcessingUtility.setLicenseFile(e.getValue(), e.getKey()); } } private void refreshAboutFiles(final Set<Artifact> dependencies) throws MojoExecutionException { getLog().info("Refreshing about files and about.html"); // build models final SortedMap<Artifact, Model> effectiveModels = getModelUtil().buildEffectiveModels(dependencies); // populate license information final AboutFilesUtil aboutFilesUtil = new AboutFilesUtil(getLog(), mavenSession, force, forceDownload); populateLicenseInformation(aboutFilesUtil, dependencies); // generate about files final File resourcesDir = new File(getProjectDir(), "src/main/resources"); aboutFilesUtil.generateAboutHtmlFile(effectiveModels, resourcesDir); } private void refreshIpLog(final Set<Artifact> dependencies) throws MojoExecutionException, MojoFailureException { getLog().info("Refreshing ip_log.xml"); // build models final SortedMap<Artifact, Model> effectiveModels = getModelUtil().buildEffectiveModels(dependencies); // populate license information final EclipseIpLogUtil ipLogUtil = new EclipseIpLogUtil(getLog(), mavenSession, settings, force); populateLicenseInformation(ipLogUtil, dependencies); // enable submission of CQs if (null != submitCqsToProject) { ipLogUtil.enableSubmissionOfCqs(submitCqsToProject, cqCryptography, settings, settingsDecrypter, outputDirectory); } // generate ip_log.xml final Model recipePom = getModelUtil().buildEffectiveModel(project.getFile()); final File eclipseDir = getIpLogXmlDirectory(); final File ipLogXmlFile = ipLogUtil.generateIpLogXmlFile(recipePom, effectiveModels, eclipseDir); // verify ipLogUtil.verifyIpLogXmlFile(eclipseDir, failBuildIfIpLogIsIncomplete); // attach ip_log.xml to project projectHelper.attachArtifact(project, "xml", "ip_log", ipLogXmlFile); } }