| /******************************************************************************* |
| * Copyright (c) 2008, 2017 Sonatype Inc. 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: |
| * Sonatype Inc. - initial API and implementation |
| * Bachmann electronic GmbH. - #519941 Copy the shared license info |
| *******************************************************************************/ |
| package org.eclipse.tycho.packaging; |
| |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.nio.file.Files; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipFile; |
| |
| import org.apache.maven.archiver.MavenArchiveConfiguration; |
| import org.apache.maven.archiver.MavenArchiver; |
| 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.codehaus.plexus.archiver.Archiver; |
| import org.codehaus.plexus.archiver.FileSet; |
| import org.codehaus.plexus.archiver.jar.JarArchiver; |
| import org.codehaus.plexus.component.repository.exception.ComponentLookupException; |
| import org.codehaus.plexus.util.IOUtil; |
| import org.eclipse.tycho.artifacts.TargetPlatform; |
| import org.eclipse.tycho.core.osgitools.DefaultReactorProject; |
| import org.eclipse.tycho.core.shared.BuildProperties; |
| import org.eclipse.tycho.core.shared.BuildPropertiesParser; |
| import org.eclipse.tycho.core.utils.TychoProjectUtils; |
| import org.eclipse.tycho.model.Feature; |
| |
| @Mojo(name = "package-feature", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.RUNTIME) |
| public class PackageFeatureMojo extends AbstractTychoPackagingMojo { |
| |
| private static final String FEATURE_PROPERTIES = "feature.properties"; |
| |
| /** |
| * The <a href="http://maven.apache.org/shared/maven-archiver/">maven archiver</a> to use. One |
| * of the archiver properties is the <code>addMavenDescriptor</code> flag, which indicates |
| * whether the generated archive will contain the pom.xml and pom.properties file. If no archive |
| * configuration is specified, the default value is <code>false</code>. If the maven descriptor |
| * should be added to the artifact, use the following configuration: |
| * |
| * <pre> |
| * <plugin> |
| * <groupId>org.eclipse.tycho</groupId> |
| * <artifactId>tycho-packaging-plugin</artifactId> |
| * <version>${tycho-version}</version> |
| * <configuration> |
| * <archive> |
| * <addMavenDescriptor>true</addMavenDescriptor> |
| * </archive> |
| * </configuration> |
| * </plugin> |
| * </pre> |
| */ |
| @Parameter |
| private MavenArchiveConfiguration archive; |
| |
| /** |
| * The output directory of the jar file |
| * |
| * By default this is the Maven <tt>target/</tt> directory. |
| */ |
| @Parameter(property = "project.build.directory") |
| private File outputDirectory; |
| |
| @Parameter(property = "project.basedir") |
| private File basedir; |
| |
| /** |
| * Name of the generated JAR. |
| */ |
| @Parameter(property = "project.build.finalName", alias = "jarName", required = true) |
| private String finalName; |
| |
| /** |
| * If set to <code>true</code>, standard eclipse update site directory with feature content will |
| * be created under target folder. |
| */ |
| @Parameter(defaultValue = "false") |
| private boolean deployableFeature = false; |
| |
| @Parameter(defaultValue = "${project.build.directory}/site") |
| private File target; |
| |
| @Component |
| private FeatureXmlTransformer featureXmlTransformer; |
| |
| @Component |
| private LicenseFeatureHelper licenseFeatureHelper; |
| |
| @Component |
| private BuildPropertiesParser buildPropertiesParser; |
| |
| @Override |
| public void execute() throws MojoExecutionException, MojoFailureException { |
| outputDirectory.mkdirs(); |
| |
| Feature feature = Feature.loadFeature(basedir); |
| |
| File licenseFeature = licenseFeatureHelper.getLicenseFeature(feature, project); |
| |
| updateLicenseProperties(feature, licenseFeature); |
| |
| File featureXml = new File(outputDirectory, Feature.FEATURE_XML); |
| try { |
| expandVersionQualifiers(feature); |
| Feature.write(feature, featureXml); |
| } catch (IOException e) { |
| throw new MojoExecutionException("Error updating feature.xml", e); |
| } |
| |
| BuildProperties buildProperties = buildPropertiesParser.parse(project.getBasedir()); |
| checkBinIncludesExist(buildProperties); |
| |
| File featureProperties = getFeatureProperties(licenseFeature, buildProperties); |
| |
| File outputJar = new File(outputDirectory, finalName + ".jar"); |
| outputJar.getParentFile().mkdirs(); |
| |
| MavenArchiver archiver = new MavenArchiver(); |
| JarArchiver jarArchiver = getJarArchiver(); |
| archiver.setArchiver(jarArchiver); |
| archiver.setOutputFile(outputJar); |
| jarArchiver.setDestFile(outputJar); |
| |
| try { |
| archiver.getArchiver().addFileSet(getManuallyIncludedFiles(buildProperties)); |
| if (licenseFeature != null) { |
| archiver.getArchiver() |
| .addArchivedFileSet(licenseFeatureHelper.getLicenseFeatureFileSet(licenseFeature)); |
| } |
| archiver.getArchiver().addFile(featureXml, Feature.FEATURE_XML); |
| if (featureProperties != null) { |
| archiver.getArchiver().addFile(featureProperties, FEATURE_PROPERTIES); |
| } |
| if (archive == null) { |
| archive = new MavenArchiveConfiguration(); |
| archive.setAddMavenDescriptor(false); |
| } |
| archiver.createArchive(session, project, archive); |
| } catch (Exception e) { |
| throw new MojoExecutionException("Error creating feature package", e); |
| } |
| |
| project.getArtifact().setFile(outputJar); |
| |
| if (deployableFeature) { |
| assembleDeployableFeature(); |
| } |
| } |
| |
| private void updateLicenseProperties(Feature feature, File licenseFeatureFile) { |
| // remove license feature id and version from feature.xml |
| feature.setLicenseFeature(null); |
| feature.setLicenseFeatureVersion(null); |
| // copy the license text and URL from the license feature |
| if (licenseFeatureFile != null) { |
| Feature licenseFeature = Feature.loadFeature(licenseFeatureFile); |
| if (licenseFeature.getLicenseURL() != null) { |
| feature.setLicenseURL(licenseFeature.getLicenseURL()); |
| } |
| if (licenseFeature.getLicense() != null) { |
| feature.setLicense(licenseFeature.getLicense()); |
| } |
| } |
| } |
| |
| private File getFeatureProperties(File licenseFeature, BuildProperties buildProperties) |
| throws MojoExecutionException { |
| try { |
| File localFeatureProperties = new File(basedir, FEATURE_PROPERTIES); |
| File targetFeatureProperties = new File(outputDirectory, FEATURE_PROPERTIES); |
| if (targetFeatureProperties.exists() && !targetFeatureProperties.delete()) { |
| throw new MojoExecutionException("Could not delete file " + targetFeatureProperties.getAbsolutePath()); |
| } |
| // copy the feature.properties from the current feature to the target directory |
| if (buildProperties.getBinIncludes().contains(FEATURE_PROPERTIES) && localFeatureProperties.canRead()) { |
| Files.copy(localFeatureProperties.toPath(), targetFeatureProperties.toPath()); |
| } |
| // if there is a license feature, append to the existing feature.properties or create |
| // a new one containing the license features's feature.properties content |
| if (licenseFeature != null) { |
| appendToOrAddFeatureProperties(targetFeatureProperties, licenseFeature); |
| } |
| if (targetFeatureProperties.exists()) { |
| return targetFeatureProperties; |
| } |
| return null; |
| } catch (IOException e) { |
| throw new MojoExecutionException("Could not create feature.properties file for project " + project, e); |
| } |
| } |
| |
| private void appendToOrAddFeatureProperties(File targetFeatureProperties, File licenseFeature) throws IOException { |
| InputStream inputStream = null; |
| FileWriter writer = null; |
| try (ZipFile zip = new ZipFile(licenseFeature)) { |
| ZipEntry entry = zip.getEntry(FEATURE_PROPERTIES); |
| if (entry != null) { |
| inputStream = zip.getInputStream(entry); |
| writer = new FileWriter(targetFeatureProperties.getAbsolutePath(), true); |
| // if we append, first add a new line to be sure that we start |
| // in a new line of the existing file |
| if (targetFeatureProperties.exists()) { |
| IOUtil.copy("\n", writer); |
| } |
| IOUtil.copy(inputStream, writer); |
| } |
| } finally { |
| IOUtil.close(writer); |
| IOUtil.close(inputStream); |
| } |
| } |
| |
| /** |
| * @return A {@link FileSet} including files as configured by the <tt>bin.includes</tt> and |
| * <tt>bin.excludes</tt> properties without the files that are always included |
| * automatically. |
| */ |
| private FileSet getManuallyIncludedFiles(BuildProperties buildProperties) { |
| List<String> binExcludes = new ArrayList<>(buildProperties.getBinExcludes()); |
| binExcludes.add(Feature.FEATURE_XML); // we'll include updated feature.xml |
| binExcludes.add(FEATURE_PROPERTIES); // we'll include updated feature.properties |
| return getFileSet(basedir, buildProperties.getBinIncludes(), binExcludes); |
| } |
| |
| private void assembleDeployableFeature() throws MojoExecutionException { |
| UpdateSiteAssembler assembler = new UpdateSiteAssembler(session, target); |
| getDependencyWalker().walk(assembler); |
| } |
| |
| private void expandVersionQualifiers(Feature feature) throws MojoFailureException { |
| feature.setVersion(DefaultReactorProject.adapt(project).getExpandedVersion()); |
| |
| TargetPlatform targetPlatform = TychoProjectUtils.getTargetPlatformIfAvailable(project); |
| if (targetPlatform == null) { |
| getLog().warn( |
| "Skipping version reference expansion in eclipse-feature project using the deprecated -Dtycho.targetPlatform configuration"); |
| return; |
| } |
| featureXmlTransformer.expandReferences(feature, targetPlatform); |
| } |
| |
| private JarArchiver getJarArchiver() throws MojoExecutionException { |
| try { |
| return (JarArchiver) plexus.lookup(Archiver.ROLE, "jar"); |
| } catch (ComponentLookupException e) { |
| throw new MojoExecutionException("Unable to get JarArchiver", e); |
| } |
| } |
| } |