diff --git a/distribution-core/pom.xml b/distribution-core/pom.xml index a69bf7eac5f..8900ca8011c 100644 --- a/distribution-core/pom.xml +++ b/distribution-core/pom.xml @@ -509,6 +509,14 @@ powsybl-ucte-util ${project.version} + + + + ${project.groupId} + powsybl-itools-packager-maven-plugin + ${project.version} + provided + diff --git a/itools-packager/README.md b/itools-packager/README.md index bfcdd975dc4..b2b5f08831c 100644 --- a/itools-packager/README.md +++ b/itools-packager/README.md @@ -39,6 +39,7 @@ Here is how to configure itools package Maven plugin in your project powsybl powsybl-x-y-x + zip 8G 2 @@ -68,6 +69,7 @@ Here is how to configure itools package Maven plugin in your project - packageName is optional, project final name is used as default value. - archiveName is optional, packageName is used as default value. +- packageType is optional, "zip" is the default value. It can be either zip or tgz. - javaXmx, mpiTasks and mpiHosts are used to generate itools.conf, are all optional and default values are respectively 8G, 2 and localhost. - additional binaries, libraries and configurations file can be added to the package using optional copyToBin, copyToLib and copyToEtc tags. - all of the jars with compile and runtime scope will be included in the package diff --git a/itools-packager/pom.xml b/itools-packager/pom.xml index f003cbe19db..cb554c17b3f 100644 --- a/itools-packager/pom.xml +++ b/itools-packager/pom.xml @@ -67,6 +67,34 @@ ${maven.plugin.annotations.version} provided + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + ${maven.plugin.testing.harness.version} + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.slf4j + log4j-over-slf4j + test + + + org.slf4j + slf4j-simple + test + + + org.apache.maven + maven-compat + ${maven.compat} + test + diff --git a/itools-packager/src/main/java/com/powsybl/itools/ItoolsPackagerMojo.java b/itools-packager/src/main/java/com/powsybl/itools/ItoolsPackagerMojo.java index f9e0962f989..d56348fb95c 100644 --- a/itools-packager/src/main/java/com/powsybl/itools/ItoolsPackagerMojo.java +++ b/itools-packager/src/main/java/com/powsybl/itools/ItoolsPackagerMojo.java @@ -7,8 +7,11 @@ */ package com.powsybl.itools; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugins.annotations.Mojo; @@ -64,6 +67,9 @@ public void setFiles(File[] files) { } } + @Parameter(defaultValue = "zip") + private String packageType; + @Parameter private CopyTo copyToBin; @@ -73,7 +79,8 @@ public void setFiles(File[] files) { @Parameter private CopyTo copyToEtc; - private static void zip(Path dir, Path baseDir, Path zipFilePath) throws IOException { + private void zip(Path dir, Path baseDir, Path zipFilePath) throws IOException { + getLog().info("Zip package"); try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(Files.newOutputStream(zipFilePath))) { Files.walkFileTree(dir, new SimpleFileVisitor() { @Override @@ -100,6 +107,38 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th } } + private void targz(Path dir, Path baseDir, Path zipFilePath) throws IOException { + getLog().info("Targz package"); + try (TarArchiveOutputStream zos = + new TarArchiveOutputStream(new GzipCompressorOutputStream(Files.newOutputStream(zipFilePath)))) { + zos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX); // allow long file paths + zos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX); // allow large numbers (for instance a big GID) + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + TarArchiveEntry entry = new TarArchiveEntry(file.toFile(), baseDir.relativize(file).toString()); + if (Files.isExecutable(file)) { + entry.setMode(0100770); + } else { + entry.setMode(0100660); + } + zos.putArchiveEntry(entry); + Files.copy(file, zos); + zos.closeArchiveEntry(); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + zos.putArchiveEntry(new TarArchiveEntry(baseDir.relativize(dir).toString() + "/")); + zos.closeArchiveEntry(); + return FileVisitResult.CONTINUE; + } + }); + } + + } + private void copyFiles(CopyTo copyTo, Path destDir) { if (copyTo != null) { for (File file : copyTo.getFiles()) { @@ -179,9 +218,14 @@ public void execute() { Files.createDirectories(libDir); copyFiles(copyToLib, libDir); - getLog().info("Zip package"); String archiveNameNotNull = archiveName != null ? archiveName : packageNameNotNull; - zip(packageDir, targetDir, targetDir.resolve(archiveNameNotNull + ".zip")); + if (packageType.equalsIgnoreCase("zip")) { + zip(packageDir, targetDir, targetDir.resolve(archiveNameNotNull + ".zip")); + } else if (packageType.equalsIgnoreCase("tgz")) { + targz(packageDir, targetDir, targetDir.resolve(archiveNameNotNull + ".tgz")); + } else { + throw new IllegalArgumentException("Unknown filetype '" + packageType + "': should be either zip or tgz"); + } } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/itools-packager/src/test/java/com/powsybl/itools/ItoolsPackagerMojoTest.java b/itools-packager/src/test/java/com/powsybl/itools/ItoolsPackagerMojoTest.java new file mode 100644 index 00000000000..245544a7583 --- /dev/null +++ b/itools-packager/src/test/java/com/powsybl/itools/ItoolsPackagerMojoTest.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2024, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * SPDX-License-Identifier: MPL-2.0 + */ +package com.powsybl.itools; + +import org.apache.commons.io.FileUtils; +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.testing.AbstractMojoTestCase; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.project.ProjectBuildingRequest; +import org.codehaus.plexus.configuration.DefaultPlexusConfiguration; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.eclipse.aether.DefaultRepositorySystemSession; + +import java.io.File; + +/** + * @author Damien Jeandemange {@literal } + */ +public class ItoolsPackagerMojoTest extends AbstractMojoTestCase { + + private static final File BASEDIR = new File("src/test/resources/test-maven-project/"); + private static final File POM_XML = new File(BASEDIR, "pom.xml"); + private static final File TARGET = new File(BASEDIR, "target"); + public static final String DEFAULT_PACKAGE_NAME = "itools-packager-test-project-1.0.0-SNAPSHOT"; + + ItoolsPackagerMojo mojo; + PlexusConfiguration configuration; + + @Override + protected void setUp() + throws Exception { + // required + super.setUp(); + MavenProject project = readMavenProject(); + MavenSession session = newMavenSession(project); + MojoExecution execution = newMojoExecution("package-zip"); + mojo = (ItoolsPackagerMojo) lookupConfiguredMojo(session, execution); + configuration = new DefaultPlexusConfiguration("configuration"); + } + + @Override + protected void tearDown() + throws Exception { + // required + super.tearDown(); + FileUtils.deleteDirectory(TARGET); // cleanup + } + + protected MavenProject readMavenProject() throws Exception { + MavenExecutionRequest request = new DefaultMavenExecutionRequest(); + request.setBaseDirectory(BASEDIR); + ProjectBuildingRequest projectBuildingRequest = request.getProjectBuildingRequest(); + projectBuildingRequest.setRepositorySession(new DefaultRepositorySystemSession()); + MavenProject project = lookup(ProjectBuilder.class).build(POM_XML, projectBuildingRequest).getProject(); + assertNotNull(project); + return project; + } + + public void testDefaultConfiguration() throws Exception { + super.configureMojo(mojo, configuration); + assertNotNull(mojo); + mojo.execute(); + assertTrue(new File(TARGET, DEFAULT_PACKAGE_NAME + ".zip").exists()); + } + + public void testPackageTypeTgz() throws Exception { + configuration.addChild("packageType", "tgz"); + super.configureMojo(mojo, configuration); + assertNotNull(mojo); + mojo.execute(); + assertTrue(new File(TARGET, DEFAULT_PACKAGE_NAME + ".tgz").exists()); + } +} diff --git a/itools-packager/src/test/resources/test-maven-project/pom.xml b/itools-packager/src/test/resources/test-maven-project/pom.xml new file mode 100644 index 00000000000..f543d09b336 --- /dev/null +++ b/itools-packager/src/test/resources/test-maven-project/pom.xml @@ -0,0 +1,36 @@ + + + + 4.0.0 + + pom + com.powsybl + itools-packager-test-project + 1.0.0-SNAPSHOT + + + + + powsybl-itools-packager-maven-plugin + + + package + + package-zip + + + + + + + + diff --git a/pom.xml b/pom.xml index fa348543fdb..5ed3b8d8695 100644 --- a/pom.xml +++ b/pom.xml @@ -123,8 +123,10 @@ 1.3.0 5.10.2 1.5.6 + 3.9.9 3.8.5 3.13.0 + 3.3.0 0.5.15 5.12.0 2.5.0 @@ -926,6 +928,12 @@ ${junit-jupiter.version} test + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + org.assertj assertj-core