diff --git a/README.md b/README.md index a22a66f0..fd606a01 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,12 @@ The full list of all the parameters is available [here](src/main/resources/MOJO. # Version Notes +## Version notes 2.3.0 - 2022-12-30 +- provides default values for plugin configuration, especially for ``, see Issue [#98](../../issues/98) +- adds a `disableVersionInfoDefaults` parameter to be able to disable provided defaults, see PR [#205](../../pull/205) +- adds documentation notes regarding a new defaults, see [VERSIONINFO.md](src/main/resources/VERSIONINFO.md) +- throwing exceptions with detailed description of default values formula, when cannot fulfill default values (no configuration data for formula), it helps plugin user with debugging what is wrong + ## Version notes 2.2.0 - 2022-11-24 - upgrades Launch4j to version 3.50 and adopts config to the bew requirements, see Issue [#199](../../issues/199) and PR [#200](../../pull/200) for more details what has to be changed diff --git a/pom.xml b/pom.xml index 9ae0e5bd..e0c56189 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ com.akathist.maven.plugins.launch4j launch4j-maven-plugin maven-plugin - 2.2.1-SNAPSHOT + 2.3.0-SNAPSHOT Maven Launch4j Plugin This plugin creates Windows executables from Java jar files using the Launch4j utility. @@ -119,12 +119,29 @@ maven-artifact-transfer 0.13.1 + + org.apache.commons + commons-lang3 + 3.12.0 + junit junit 4.13.2 test + + pl.pragmatists + JUnitParams + 1.1.1 + test + + + org.mockito + mockito-core + 4.11.0 + test + org.apache.maven.plugin-testing maven-plugin-testing-harness diff --git a/src/main/java/com/akathist/maven/plugins/launch4j/Launch4jMojo.java b/src/main/java/com/akathist/maven/plugins/launch4j/Launch4jMojo.java index f84add38..354e91db 100644 --- a/src/main/java/com/akathist/maven/plugins/launch4j/Launch4jMojo.java +++ b/src/main/java/com/akathist/maven/plugins/launch4j/Launch4jMojo.java @@ -174,7 +174,7 @@ public class Launch4jMojo extends AbstractMojo { * like if java can't be found. If this is a console app and not a gui, then this value * is used to prefix any error messages, as in ${errTitle}: ${errorMessage}. */ - @Parameter + @Parameter(defaultValue = "${project.name}") private String errTitle; /** @@ -262,7 +262,7 @@ public class Launch4jMojo extends AbstractMojo { * Details about the classpath your application should have. * This is required if you are not wrapping a jar. */ - @Parameter() + @Parameter private ClassPath classPath; /** @@ -283,6 +283,12 @@ public class Launch4jMojo extends AbstractMojo { @Parameter private VersionInfo versionInfo; + /** + * If set to true, it will prevent filling out the VersionInfo params with default values. + */ + @Parameter(defaultValue = "false") + private boolean disableVersionInfoDefaults; + /** * Various messages you can display. */ @@ -340,6 +346,17 @@ private void doExecute() throws MojoExecutionException { return; } + if (!disableVersionInfoDefaults) { + try { + if(versionInfo == null) { + versionInfo = new VersionInfo(); + } + versionInfo.tryFillOutByDefaults(project, outfile); + } catch (RuntimeException exception) { + throw new MojoExecutionException("Cannot fill out VersionInfo by defaults", exception); + } + } + final File workDir = setupBuildEnvironment(); if (infile != null) { if (infile.exists()) { @@ -834,6 +851,7 @@ public String toString() { ", singleInstance=" + singleInstance + ", splash=" + splash + ", versionInfo=" + versionInfo + + ", disableVersionInfoDefaults=" + disableVersionInfoDefaults + ", messages=" + messages + ", manifest=" + manifest + ", saveConfig=" + saveConfig + diff --git a/src/main/java/com/akathist/maven/plugins/launch4j/VersionInfo.java b/src/main/java/com/akathist/maven/plugins/launch4j/VersionInfo.java index 88e8116e..8adfc363 100644 --- a/src/main/java/com/akathist/maven/plugins/launch4j/VersionInfo.java +++ b/src/main/java/com/akathist/maven/plugins/launch4j/VersionInfo.java @@ -18,9 +18,15 @@ */ package com.akathist.maven.plugins.launch4j; +import com.akathist.maven.plugins.launch4j.generators.CopyrightGenerator; +import com.akathist.maven.plugins.launch4j.generators.Launch4jFileVersionGenerator; import net.sf.launch4j.config.LanguageID; +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.model.Organization; import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import java.io.File; import java.util.HashMap; import java.util.Map; @@ -28,7 +34,6 @@ * Information that appears in the Windows Explorer. */ public class VersionInfo { - private static final Map LANGUAGE_TO_LANGUAGE_ID; static { @@ -110,6 +115,27 @@ public class VersionInfo { @Parameter String trademarks; + public VersionInfo() { + } + + public VersionInfo(String fileVersion, String txtFileVersion, String fileDescription, + String copyright, String productVersion, String txtProductVersion, + String productName, String companyName, String internalName, + String originalFilename, String language, String trademarks) { + this.fileVersion = fileVersion; + this.txtFileVersion = txtFileVersion; + this.fileDescription = fileDescription; + this.copyright = copyright; + this.productVersion = productVersion; + this.txtProductVersion = txtProductVersion; + this.productName = productName; + this.companyName = companyName; + this.internalName = internalName; + this.originalFilename = originalFilename; + this.language = language; + this.trademarks = trademarks; + } + net.sf.launch4j.config.VersionInfo toL4j() { net.sf.launch4j.config.VersionInfo ret = new net.sf.launch4j.config.VersionInfo(); @@ -137,6 +163,75 @@ private void setLanguage(net.sf.launch4j.config.VersionInfo ret) { ret.setLanguage(languageID); } + void tryFillOutByDefaults(MavenProject project, File outfile) { + if (project == null) { + throw new IllegalArgumentException("'project' is required, but it is null."); + } + if (outfile == null) { + throw new IllegalArgumentException("'outfile' is required, but it is null."); + } + + String version = project.getVersion(); + Organization organization = project.getOrganization(); + + tryFillOutByDefaultVersionInL4jFormat(version); + tryFillOutCopyrightByDefaults(project.getInceptionYear(), organization); + tryFillOutOrganizationRelatedDefaults(organization); + tryFillOutSimpleValuesByDefaults( + version, + project.getName(), + project.getArtifactId(), + project.getDescription() + ); + + originalFilename = getDefaultWhenOriginalIsBlank(originalFilename, outfile.getName(), "originalFilename", "${project.version}"); + } + + private void tryFillOutByDefaultVersionInL4jFormat(String version) { + final String defaultFileVersion = Launch4jFileVersionGenerator.generate(version); + fileVersion = getDefaultWhenOriginalIsBlank(fileVersion, defaultFileVersion, "fileVersion", "${project.version}"); + productVersion = getDefaultWhenOriginalIsBlank(productVersion, defaultFileVersion, "productVersion", "${project.version}"); + } + + private void tryFillOutCopyrightByDefaults(String inceptionYear, Organization organization) { + final String defaultCopyright = CopyrightGenerator.generate(inceptionYear, organization); + copyright = getDefaultWhenOriginalIsBlank(copyright, defaultCopyright, "copyright", "${project.inceptionYear},${project.organization.name}"); + } + + private void tryFillOutOrganizationRelatedDefaults(Organization organization) { + if (organization != null) { + companyName = getDefaultWhenOriginalIsBlank(companyName, organization.getName(), "companyName", "${project.organization.name}"); + trademarks = getDefaultWhenOriginalIsBlank(trademarks, organization.getName(), "trademarks", "${project.organization.name}"); + } + } + + private void tryFillOutSimpleValuesByDefaults(String version, + String name, + String artifactId, + String description) { + txtFileVersion = getDefaultWhenOriginalIsBlank(txtFileVersion, version, "txtFileVersion", "${project.version}"); + txtProductVersion = getDefaultWhenOriginalIsBlank(txtProductVersion, version, "txtProductVersion", "${project.version}"); + productName = getDefaultWhenOriginalIsBlank(productName, name, "productName", "${project.name}"); + internalName = getDefaultWhenOriginalIsBlank(internalName, artifactId, "internalName", "${project.artifactId}"); + fileDescription = getDefaultWhenOriginalIsBlank(fileDescription, description, "fileDescription", "${project.description}"); + } + + private String getDefaultWhenOriginalIsBlank(final String originalValue, + final String defaultValue, + final String originalParameterName, + final String defaultValueFormulaParams) { + if (StringUtils.isBlank(originalValue)) { + if(StringUtils.isNotBlank(defaultValue)) { + return defaultValue; + } + + throw new IllegalStateException("Please fill the missing configuration values. " + + "Error when trying to fulfill default value for VersionInfo parameter:'" + originalParameterName + "' with formula params:'" + defaultValueFormulaParams + "'."); + } + + return originalValue; + } + @Override public String toString() { return "VersionInfo{" + diff --git a/src/main/java/com/akathist/maven/plugins/launch4j/generators/CopyrightGenerator.java b/src/main/java/com/akathist/maven/plugins/launch4j/generators/CopyrightGenerator.java new file mode 100644 index 00000000..7e9df9a5 --- /dev/null +++ b/src/main/java/com/akathist/maven/plugins/launch4j/generators/CopyrightGenerator.java @@ -0,0 +1,40 @@ +package com.akathist.maven.plugins.launch4j.generators; + +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.model.Organization; + +import java.time.LocalDate; + +public class CopyrightGenerator { + private CopyrightGenerator() { + } + + /** + * Parameters should be taken from MavenProject properties: + * @param projectInceptionYear as ${project.inceptionYear} + * @param projectOrganization as ${project.organization} + */ + public static String generate(String projectInceptionYear, Organization projectOrganization) { + String inceptionYear = generateInceptionYear(projectInceptionYear); + int buildYear = LocalDate.now().getYear(); + String organizationName = generateOrganizationName(projectOrganization); + + return String.format("Copyright © %s%d%s. All rights reserved.", inceptionYear, buildYear, organizationName); + } + + private static String generateInceptionYear(String projectInceptionYear) { + if(StringUtils.isNotBlank(projectInceptionYear)) { + return projectInceptionYear + "-"; + } + + return ""; + } + + private static String generateOrganizationName(Organization projectOrganization) { + if(projectOrganization != null && StringUtils.isNotBlank(projectOrganization.getName())) { + return " " + projectOrganization.getName(); + } + + return ""; + } +} diff --git a/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java b/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java new file mode 100644 index 00000000..40f3a43c --- /dev/null +++ b/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java @@ -0,0 +1,72 @@ +package com.akathist.maven.plugins.launch4j.generators; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +public class Launch4jFileVersionGenerator { + private static final int REQUIRED_NESTED_VERSION_LEVELS = 4; + private static final String SIMPLE_PROJECT_VERSION_REGEX = "^((\\d(\\.)?)*\\d+)(-\\w+)?$"; + private static final Pattern simpleProjectVersionPattern = Pattern.compile( + SIMPLE_PROJECT_VERSION_REGEX, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE + ); + + private Launch4jFileVersionGenerator() { + } + + /** + * Converts projectVersion into a format "x.x.x.x" ('x' as a number), which is required by Launch4j. + * + * For shorter versions like "x.x.x" it will append zeros (to the 4th level) at the end like "x.x.x.0". + * Every text flag like "-SNAPSHOT" or "-alpha" will be cut off. + * Too many nested numbers (more than 4 levels) will be cut off as well: "1.2.3.4.5.6" -> "1.2.3.4". + * + * Param should be taken from MavenProject property: + * @param projectVersion as ${project.version} + */ + public static String generate(String projectVersion) { + if(projectVersion == null) { + return null; + } + if(!simpleProjectVersionPattern.matcher(projectVersion).matches()) { + throw new IllegalArgumentException("'project.version' is in invalid format. Regex pattern: " + SIMPLE_PROJECT_VERSION_REGEX); + } + + String versionLevels = removeTextFlags(projectVersion); + String limitedVersionLevels = cutOffTooManyNestedLevels(versionLevels); + + return appendMissingNestedLevelsByZeros(limitedVersionLevels); + } + + private static String removeTextFlags(String version) { + if(version.contains("-")) { + String[] parts = version.split("-"); + return parts[0]; + } + + return version; + } + + private static String cutOffTooManyNestedLevels(String versionLevels) { + String[] levels = versionLevels.split("\\."); + + if(levels.length > REQUIRED_NESTED_VERSION_LEVELS) { + List limitedLevels = Arrays.asList(levels) + .subList(0, REQUIRED_NESTED_VERSION_LEVELS); + return String.join(".", limitedLevels); + } + + return versionLevels; + } + + private static String appendMissingNestedLevelsByZeros(String versionLevels) { + String[] levels = versionLevels.split("\\."); + + StringBuilder filledLevels = new StringBuilder(versionLevels); + for (int i = levels.length; i < REQUIRED_NESTED_VERSION_LEVELS; i++) { + filledLevels.append(".0"); + } + + return filledLevels.toString(); + } +} diff --git a/src/main/resources/MOJO.md b/src/main/resources/MOJO.md index 89ff68e4..befd5fa5 100644 --- a/src/main/resources/MOJO.md +++ b/src/main/resources/MOJO.md @@ -13,7 +13,7 @@ Wraps a jar in a Windows executable. ### Parameter Details -#### **** +#### **\** Changes to the given directory, relative to the executable, before running your jar. If set to `.` the current directory will be where the executable is. If omitted, the directory will not be changed. @@ -22,7 +22,7 @@ Changes to the given directory, relative to the executable, before running your * * * -#### **** +#### **\** Details about the classpath your application should have. This is required if you are not wrapping a jar. @@ -31,7 +31,7 @@ Details about the classpath your application should have. This is required if yo * * * -#### **** +#### **\** Constant command line arguments to pass to your program's main method. Actual command line arguments entered by the user will appear after these. @@ -40,7 +40,7 @@ Constant command line arguments to pass to your program's main method. Actual co * * * -#### **** +#### **\** If `saveConfig` is set to true, config will be written to this file @@ -50,7 +50,7 @@ If `saveConfig` is set to true, config will be written to this file * * * -#### **** +#### **\** Whether the executable should wrap the jar or not. @@ -60,7 +60,7 @@ Whether the executable should wrap the jar or not. * * * -#### **** +#### **\** downloadUrl (?). @@ -69,16 +69,17 @@ downloadUrl (?). * * * -#### **** +#### **\** The title of the error popup if something goes wrong trying to run your program, like if java can't be found. If this is a console app and not a gui, then this value is used to prefix any error messages, as in ${errTitle}: ${errorMessage}. * **Type**: `java.lang.String` * **Required**: `No` +* **Default**: `${project.name}` * * * -#### **** +#### **\** Whether you want a gui or console app. Valid values are "gui" and "console." If you say gui, then launch4j will run your app from javaw instead of java in order to avoid opening a DOS window. Choosing gui also enables other options like taskbar icon and a splash screen. @@ -87,7 +88,7 @@ Whether you want a gui or console app. Valid values are "gui" and "console." If * * * -#### **** +#### **\** The icon to use in the taskbar. Must be in ico format. @@ -96,7 +97,7 @@ The icon to use in the taskbar. Must be in ico format. * * * -#### **** +#### **\** The name of the Launch4j native configuration file The path, if relative, is relative to the pom.xml. @@ -105,7 +106,7 @@ The name of the Launch4j native configuration file The path, if relative, is rel * * * -#### **** +#### **\** The jar to bundle inside the executable. The path, if relative, is relative to the pom.xml. If you don't want to wrap the jar, then this value should be the runtime path to the jar relative to the executable. You should also set dontWrapJar to true. You can only bundle a single jar. Therefore, you should either create a jar that contains your own code plus all your dependencies, or you should distribute your dependencies alongside the executable. @@ -115,7 +116,7 @@ The jar to bundle inside the executable. The path, if relative, is relative to t * * * -#### **** +#### **\** Details about the supported jres. @@ -124,7 +125,7 @@ Details about the supported jres. * * * -#### **** +#### **\** Win32 libraries to include. Used for custom headers only. @@ -133,7 +134,7 @@ Win32 libraries to include. Used for custom headers only. * * * -#### **** +#### **\** Windows manifest file (a XML file) with the same name as .exe file (myapp.exe.manifest) @@ -142,7 +143,7 @@ Windows manifest file (a XML file) with the same name as .exe file (myapp.exe.ma * * * -#### **** +#### **\** Various messages you can display. @@ -151,7 +152,7 @@ Various messages you can display. * * * -#### **** +#### **\** Object files to include. Used for custom headers only. @@ -160,7 +161,7 @@ Object files to include. Used for custom headers only. * * * -#### **** +#### **\** The name of the executable you want launch4j to produce. The path, if relative, is relative to the pom.xml. @@ -170,7 +171,7 @@ The name of the executable you want launch4j to produce. The path, if relative, * * * -#### **** +#### **\** If set to true, a synchronized block will be used to protect resources @@ -180,7 +181,7 @@ If set to true, a synchronized block will be used to protect resources * * * -#### **** +#### **\** The dependencies of this plugin. Used to get the Launch4j artifact version. @@ -190,7 +191,7 @@ The dependencies of this plugin. Used to get the Launch4j artifact version. * * * -#### **** +#### **\** Priority class of windows process. Valid values are "normal" (default), "idle" and "high". @@ -200,7 +201,7 @@ Priority class of windows process. Valid values are "normal" (default), "idle" a * * * -#### **** +#### **\** If true, when the application exits, any exit code other than 0 is considered a crash and the application will be started again. @@ -210,7 +211,7 @@ If true, when the application exits, any exit code other than 0 is considered a * * * -#### **** +#### **\** If set to true it will save final config into a XML file @@ -220,7 +221,7 @@ If set to true it will save final config into a XML file * * * -#### **** +#### **\** Details about whether to run as a single instance. @@ -229,7 +230,7 @@ Details about whether to run as a single instance. * * * -#### **** +#### **\** If set to true, execution of the plugin will be skipped @@ -239,7 +240,7 @@ If set to true, execution of the plugin will be skipped * * * -#### **** +#### **\** Details about the splash screen. @@ -248,7 +249,7 @@ Details about the splash screen. * * * -#### **** +#### **\** If true, the executable waits for the java application to finish before returning its exit code. Defaults to false for gui applications. Has no effect for console applications, which always wait. @@ -258,7 +259,7 @@ If true, the executable waits for the java application to finish before returnin * * * -#### **** +#### **\** supportUrl (?). @@ -267,7 +268,7 @@ supportUrl (?). * * * -#### **** +#### **\** Variables to set. @@ -276,9 +277,23 @@ Variables to set. * * * -#### **** +#### **\** Lots of information you can attach to the windows process. * **Type**: `com.akathist.maven.plugins.launch4j.VersionInfo` * **Required**: `No` + +The full list of all the `VersionInfo` parameters is available [here](./VERSIONINFO.md). + +* * * + +#### **\** + +If `disableVersionInfoDefaults` is set to true, it will prevent filling out the VersionInfo params with default values. + +* **Type**: `boolean` +* **Required**: `No` +* **Default**: `false` + +* * * \ No newline at end of file diff --git a/src/main/resources/VERSIONINFO.md b/src/main/resources/VERSIONINFO.md new file mode 100644 index 00000000..6141e2ec --- /dev/null +++ b/src/main/resources/VERSIONINFO.md @@ -0,0 +1,143 @@ +# VersionInfo parameters + +### Description. + +This file describes the `VersionInfo` parameters. + +* **Type**: `com.akathist.maven.plugins.launch4j.VersionInfo` + +Every parameter (including their parent `VersionInfo`) have a default value defined. +To fulfill them by default values you need to make sure that **\** inside plugin configuration is set to `false`. + +### Parameter Details + +#### **\** + +Version number in `x.x.x.x` format. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.version}` converted into a `x.x.x.x` format. + +Conversion into a `x.x.x.x` format have specific constraints: +* `x` as a number +* shorter project versions like `x.x.x` will have appended zeros (to the 4th level) like `x.x.x.0` +* every text flag like "-SNAPSHOT" or "-alpha" will be cut off +* too many nested levels (>4) will be cut off as well. Example input: `1.2.3.4.5.6`, output: `1.2.3.4`. + +* * * + +#### **\** + +Free-form version number, like "1.20.RC1." + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.version}` + +* * * + +#### **\** + +File description shown to the user. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.description}` + +* * * + +#### **\** + +Legal copyright. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `Copyright © ${project.inceptionYear}-${currentYear} ${project.organization.name}. All rights reserved.`. + +Where: +* `${project.inceptionYear}` is not mandatory. +* `${currentYear}` is generated programmatically. +* `${project.organization.name}` is not mandatory. + +* * * + +#### **\** + +Version number in `x.x.x.x` format. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.version}` converted into a `x.x.x.x` format. The same conversion such the one described regarding `fileVersion` parameter above. + +* * * + +#### **\** + +Free-form version number, like "1.20.RC1." + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.version}` + +* * * + +#### **\** + +The product name. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.name}` + +* * * + +#### **\** + +The company name. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.organization.name}` + +* * * + +#### **\** + +The internal name. For instance, you could use the filename without extension or the module name. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.artifactId}` + +* * * + +#### **\** + +The original filename without path. Setting this lets you determine whether a user has renamed the file. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: last path segment of the `${outfile}` configuration + +* * * + +#### **\** + +Language to be used during installation. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `ENGLISH_US` + +* * * + +#### **\** + +Trademarks of author. + +* **Type**: `java.lang.String` +* **Required**: `Yes` +* **Default**: `${project.organization.name}` + +* * * \ No newline at end of file diff --git a/src/test/java/com/akathist/maven/plugins/launch4j/Launch4jMojoTest.java b/src/test/java/com/akathist/maven/plugins/launch4j/Launch4jMojoTest.java index 0e9bee22..6c6134ee 100644 --- a/src/test/java/com/akathist/maven/plugins/launch4j/Launch4jMojoTest.java +++ b/src/test/java/com/akathist/maven/plugins/launch4j/Launch4jMojoTest.java @@ -5,9 +5,8 @@ import java.io.File; public class Launch4jMojoTest extends AbstractMojoTestCase { - - public void testMojoGoal() throws Exception { - File testPom = new File(getBasedir(), "src/test/resources/unit/launch4j-default/launch4j-default-plugin-config.xml"); + public void testPrintOutFulfilledConfiguration() throws Exception { + File testPom = new File(getBasedir(), "src/test/resources/unit/launch4j-config/launch4j-full-plugin-config.xml"); Launch4jMojo mojo = (Launch4jMojo) lookupMojo("launch4j", testPom); @@ -66,6 +65,7 @@ public void testMojoGoal() throws Exception { "language='ENGLISH_US', " + "trademarks='Luk ™'" + "}, " + + "disableVersionInfoDefaults=true, " + "messages=Messages{" + "startupErr='null', " + "jreVersionErr='null', " + @@ -80,5 +80,4 @@ public void testMojoGoal() throws Exception { "skip=false" + "}", mojo.toString()); } - -} +} \ No newline at end of file diff --git a/src/test/java/com/akathist/maven/plugins/launch4j/VersionInfoTest.java b/src/test/java/com/akathist/maven/plugins/launch4j/VersionInfoTest.java new file mode 100644 index 00000000..e8eaa883 --- /dev/null +++ b/src/test/java/com/akathist/maven/plugins/launch4j/VersionInfoTest.java @@ -0,0 +1,358 @@ +package com.akathist.maven.plugins.launch4j; + +import net.sf.launch4j.config.LanguageID; +import org.apache.maven.model.Organization; +import org.apache.maven.project.MavenProject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.io.File; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.doReturn; + +@RunWith(MockitoJUnitRunner.class) +public class VersionInfoTest { + // VersionInfo test params + private String fileVersion = "1.0.0.0"; + private String txtFileVersion = "1.0.0.0"; + private String fileDescription = "Launch4j Test Application"; + private String copyright = "Copyright Orphan OSS"; + private String productVersion = "1.0.0.0"; + private String txtProductVersion = "1.0.0.0"; + private String productName = "Test App"; + private String companyName = "Orphan OSS Company"; + private String internalName = "app"; + private String originalFilename = "app.exe"; + private String language = LanguageID.ENGLISH_US.name(); + private String trademarks = "Test ™"; + + // Mocks + @Mock + Organization organization; + @Mock + MavenProject project; + @Mock + File outfile; + + // Subject + private VersionInfo versionInfo; + + @Before + public void buildVersionInfoFromTestParams() { + versionInfo = new VersionInfo(fileVersion, txtFileVersion, fileDescription, + copyright, productVersion, txtProductVersion, + productName, companyName, internalName, + originalFilename, language, trademarks); + } + + @Test + public void shouldConvertIntoL4jFormatProperly() { + // when + net.sf.launch4j.config.VersionInfo l4jVersionInfo = versionInfo.toL4j(); + + // then + assertEquals(versionInfo.fileVersion, l4jVersionInfo.getFileVersion()); + assertEquals(versionInfo.txtFileVersion, l4jVersionInfo.getTxtFileVersion()); + assertEquals(versionInfo.fileDescription, l4jVersionInfo.getFileDescription()); + assertEquals(versionInfo.copyright, l4jVersionInfo.getCopyright()); + assertEquals(versionInfo.productVersion, l4jVersionInfo.getProductVersion()); + assertEquals(versionInfo.txtProductVersion, l4jVersionInfo.getTxtProductVersion()); + assertEquals(versionInfo.productName, l4jVersionInfo.getProductName()); + assertEquals(versionInfo.companyName, l4jVersionInfo.getCompanyName()); + assertEquals(versionInfo.internalName, l4jVersionInfo.getInternalName()); + assertEquals(versionInfo.originalFilename, l4jVersionInfo.getOriginalFilename()); + assertEquals(versionInfo.trademarks, l4jVersionInfo.getTrademarks()); + assertEquals(versionInfo.language, l4jVersionInfo.getLanguage().name()); + } + + @Test + public void shouldConvertIntoL4jFormat_For_All_Languages() { + for (LanguageID languageId : LanguageID.values()) { + // given + versionInfo.language = languageId.name(); + + // when + net.sf.launch4j.config.VersionInfo l4jVersionInfo = versionInfo.toL4j(); + + // then + assertEquals(languageId, l4jVersionInfo.getLanguage()); + } + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowException_WhenTryingToFillOutDefaults_WithEmptyProject() { + // expect throws + versionInfo.tryFillOutByDefaults(null, outfile); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowException_WhenTryingToFillOutDefaults_WithEmptyOutfile() { + // expect throws + versionInfo.tryFillOutByDefaults(project, null); + } + + @Test + public void should_Not_FillOut_ByDefaultVersion_InL4jFormat_When_VersionInfoPropsWere_Filled() { + // given + String projectVersion = "4.3.2.1"; + doReturn(projectVersion).when(project).getVersion(); + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNotEquals(projectVersion, versionInfo.fileVersion); + assertEquals(fileVersion, versionInfo.fileVersion); + assertNotEquals(projectVersion, versionInfo.productVersion); + assertEquals(productVersion, versionInfo.productVersion); + } + + @Test + public void shouldFillOut_ByDefaultVersion_InL4jFormat_When_VersionInfoPropsWere_Empty() { + // given + String projectVersion = "1.2.3.4"; + doReturn(projectVersion).when(project).getVersion(); + + versionInfo.fileVersion = null; + versionInfo.productVersion = null; + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertEquals(projectVersion, versionInfo.fileVersion); + assertNotEquals(fileVersion, versionInfo.fileVersion); + assertEquals(projectVersion, versionInfo.productVersion); + assertNotEquals(productVersion, versionInfo.productVersion); + } + + @Test + public void should_Not_FillOut_Copyright_ByDefault_When_ItWas_Filled() { + // given + String projectInceptionYear = "2017"; + doReturn(projectInceptionYear).when(project).getInceptionYear(); + + String organizationName = "Another OSS"; + doReturn(organizationName).when(organization).getName(); + doReturn(organization).when(project).getOrganization(); + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNotNull(versionInfo.copyright); + assertEquals(copyright, versionInfo.copyright); + assertFalse(versionInfo.copyright.contains(projectInceptionYear)); + assertFalse(versionInfo.copyright.contains(organizationName)); + } + + @Test + public void shouldFillOut_Copyright_ByDefault_When_ItWas_Empty() { + // given + String projectInceptionYear = "2019"; + doReturn(projectInceptionYear).when(project).getInceptionYear(); + + String organizationName = "Some OSS"; + doReturn(organizationName).when(organization).getName(); + doReturn(organization).when(project).getOrganization(); + + versionInfo.copyright = null; + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNotNull(versionInfo.copyright); + assertNotEquals(copyright, versionInfo.copyright); + assertTrue(versionInfo.copyright.contains(projectInceptionYear)); + assertTrue(versionInfo.copyright.contains(organizationName)); + } + + @Test + public void should_Not_FillOutByDefaults_From_MavenProject_OrganizationName_When_OrganizationWas_Empty() { + // given + versionInfo.companyName = null; + versionInfo.trademarks = null; + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNull(versionInfo.companyName); + assertNull(versionInfo.trademarks); + } + + @Test + public void should_Not_FillOutByDefaults_From_OrganizationName_When_VersionInfoPropsWere_Filled() { + // given + String organizationName = "Example OSS"; + doReturn(organizationName).when(organization).getName(); + doReturn(organization).when(project).getOrganization(); + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNotEquals(organizationName, versionInfo.companyName); + assertEquals(companyName, versionInfo.companyName); + assertNotEquals(organizationName, versionInfo.trademarks); + assertEquals(trademarks, versionInfo.trademarks); + } + + @Test + public void shouldFillOutByDefaults_From_OrganizationName_When_OrganizationWas_Filled() { + // given + String organizationName = "Other OSS"; + doReturn(organizationName).when(organization).getName(); + doReturn(organization).when(project).getOrganization(); + + versionInfo.companyName = null; + versionInfo.trademarks = null; + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertEquals(organizationName, versionInfo.companyName); + assertEquals(organizationName, versionInfo.trademarks); + } + + @Test(expected = IllegalStateException.class) + public void should_Not_FillOutByDefaults_SimpleValues_From_MavenProject_When_ProjectPropsWere_Empty() { + // given + doReturn(null).when(project).getVersion(); + versionInfo.txtFileVersion = null; + versionInfo.txtProductVersion = null; + + doReturn(null).when(project).getName(); + versionInfo.productName = null; + + doReturn(null).when(project).getArtifactId(); + versionInfo.internalName = null; + + doReturn(null).when(project).getDescription(); + versionInfo.fileDescription = null; + + // expect throws + versionInfo.tryFillOutByDefaults(project, outfile); + } + + @Test + public void should_Not_FillOutByDefaults_SimpleValues_From_MavenProject_When_VersionInfoPropsWere_Filled() { + // given + String projectVersion = "1.21.1"; + doReturn(projectVersion).when(project).getVersion(); + + String projectName = "launch4j-test-app"; + doReturn(projectName).when(project).getName(); + + String projectArtifactId = "launch4j-test"; + doReturn(projectArtifactId).when(project).getArtifactId(); + + String projectDescription = "Launch4j Test App"; + doReturn(projectDescription).when(project).getDescription(); + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNotEquals(projectVersion, versionInfo.txtFileVersion); + assertEquals(txtFileVersion, versionInfo.txtFileVersion); + assertNotEquals(projectVersion, versionInfo.txtProductVersion); + assertEquals(txtProductVersion, versionInfo.txtProductVersion); + assertNotEquals(projectName, versionInfo.productName); + assertEquals(productName, versionInfo.productName); + assertNotEquals(projectArtifactId, versionInfo.internalName); + assertEquals(internalName, versionInfo.internalName); + assertNotEquals(projectDescription, versionInfo.fileDescription); + assertEquals(fileDescription, versionInfo.fileDescription); + } + + @Test + public void shouldFillOutByDefaults_SimpleValues_From_MavenProject_When_VersionInfoPropsWere_Empty() { + // given + String projectVersion = "1.21.1"; + doReturn(projectVersion).when(project).getVersion(); + versionInfo.txtFileVersion = null; + versionInfo.txtProductVersion = null; + + String projectName = "launch4j-test-app"; + doReturn(projectName).when(project).getName(); + versionInfo.productName = null; + + String projectArtifactId = "launch4j-test"; + doReturn(projectArtifactId).when(project).getArtifactId(); + versionInfo.internalName = null; + + String projectDescription = "Launch4j Test App"; + doReturn(projectDescription).when(project).getDescription(); + versionInfo.fileDescription = null; + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertEquals(projectVersion, versionInfo.txtFileVersion); + assertEquals(projectVersion, versionInfo.txtProductVersion); + assertEquals(projectName, versionInfo.productName); + assertEquals(projectArtifactId, versionInfo.internalName); + assertEquals(projectDescription, versionInfo.fileDescription); + } + + @Test + public void should_Not_FillOut_ByDefault_LastSegmentOfOutfilePath_When_OriginalFilenameWas_Filled() { + // given + String outfileName = "testApp.exe"; + doReturn(outfileName).when(outfile).getName(); + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertNotEquals(outfileName, versionInfo.originalFilename); + assertEquals(originalFilename, versionInfo.originalFilename); + } + + @Test + public void shouldFillOut_ByDefault_LastSegmentOfOutfilePath_When_OriginalFilenameWas_Empty() { + // given + String outfileName = "testApp.exe"; + doReturn(outfileName).when(outfile).getName(); + versionInfo.originalFilename = null; + + // when + versionInfo.tryFillOutByDefaults(project, outfile); + + // then + assertEquals(outfileName, versionInfo.originalFilename); + } + + @Test + public void shouldGenerateString_WithTestParams() { + // when + String result = versionInfo.toString(); + + // then + assertNotNull(result); + assertTrue(containsParam(result, "fileVersion", fileVersion)); + assertTrue(containsParam(result, "txtFileVersion", txtFileVersion)); + assertTrue(containsParam(result, "fileDescription", fileDescription)); + assertTrue(containsParam(result, "copyright", copyright)); + assertTrue(containsParam(result, "productVersion", productVersion)); + assertTrue(containsParam(result, "txtProductVersion", txtProductVersion)); + assertTrue(containsParam(result, "productName", productName)); + assertTrue(containsParam(result, "companyName", companyName)); + assertTrue(containsParam(result, "internalName", internalName)); + assertTrue(containsParam(result, "originalFilename", originalFilename)); + assertTrue(containsParam(result, "language", language)); + assertTrue(containsParam(result, "trademarks", trademarks)); + } + + private boolean containsParam(String result, String paramName, String paramValue) { + return result.contains(paramName + "='" + paramValue + "'"); + } +} \ No newline at end of file diff --git a/src/test/java/com/akathist/maven/plugins/launch4j/generators/CopyrightGeneratorTest.java b/src/test/java/com/akathist/maven/plugins/launch4j/generators/CopyrightGeneratorTest.java new file mode 100644 index 00000000..734725f8 --- /dev/null +++ b/src/test/java/com/akathist/maven/plugins/launch4j/generators/CopyrightGeneratorTest.java @@ -0,0 +1,97 @@ +package com.akathist.maven.plugins.launch4j.generators; + +import org.apache.maven.model.Organization; +import org.junit.Before; +import org.junit.Test; + +import java.time.LocalDate; + +import static org.junit.Assert.*; + +public class CopyrightGeneratorTest { + private static final String COPYRIGHT_PREFIX = "Copyright © "; + private static final String COPYRIGHT_POSTFIX = ". All rights reserved."; + + private String buildYear; + + @Before + public void initializeBuildYear() { + buildYear = String.valueOf( + LocalDate.now().getYear() + ); + } + + @Test + public void shouldContain_BuildYear() { + // when + final String copyright = CopyrightGenerator.generate(null, null); + + // then + String expected = concatAndWrapWithCopyright(buildYear); + assertEquals(expected, copyright); + } + + @Test + public void shouldContain_InceptionYear_And_BuildYear() { + // given + final String projectInceptionYear = "2019"; + + // when + final String copyright = CopyrightGenerator.generate(projectInceptionYear, null); + + // then + String expected = concatAndWrapWithCopyright( + projectInceptionYear, "-", buildYear + ); + assertEquals(expected, copyright); + } + + @Test + public void shouldContain_BuildYear_And_OrganizationName() { + // given + final String organizationName = "SoftwareMill"; + + Organization projectOrganization = new Organization(); + projectOrganization.setName(organizationName); + + // when + final String copyright = CopyrightGenerator.generate(null, projectOrganization); + + // then + String expected = concatAndWrapWithCopyright( + buildYear, " ", organizationName + ); + assertEquals(expected, copyright); + } + + @Test + public void shouldContain_InceptionYear_And_BuildYear_And_OrganizationName() { + // given + final String projectInceptionYear = "2020"; + final String organizationName = "Orphan OSS"; + + Organization projectOrganization = new Organization(); + projectOrganization.setName(organizationName); + + // when + final String copyright = CopyrightGenerator.generate(projectInceptionYear, projectOrganization); + + // then + String expected = concatAndWrapWithCopyright( + projectInceptionYear, "-", buildYear, " ", organizationName + ); + assertEquals(expected, copyright); + } + + private String concatAndWrapWithCopyright(String... elements) { + StringBuilder builder = new StringBuilder(COPYRIGHT_PREFIX); + + for (String element : elements) { + builder.append(element); + } + + builder.append(COPYRIGHT_POSTFIX); + + return builder.toString(); + } +} \ No newline at end of file diff --git a/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java b/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java new file mode 100644 index 00000000..962275ee --- /dev/null +++ b/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java @@ -0,0 +1,85 @@ +package com.akathist.maven.plugins.launch4j.generators; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +@RunWith(JUnitParamsRunner.class) +public class Launch4jFileVersionGeneratorTest { + @Test + public void shouldReturnNull_WhenProjectVersionIsNull() { + // given + String projectVersion = null; + + // expect + assertNull(Launch4jFileVersionGenerator.generate(projectVersion)); + } + + @Test(expected = IllegalArgumentException.class) + @Parameters({ + "", + " ", + "null", + "alpha-1.2.3", + "1a.2.3", + "1.X.3", + "1.2.3_11", + "1.2.3;4", + "1.2.3.4SNAPSHOT", + "1.2.3.4.SNAPSHOT" + }) + public void shouldThrowException_WhenProjectVersion_HaveWrongFormat(String projectVersion) { + // expect throws + Launch4jFileVersionGenerator.generate(projectVersion); + } + + @Test + @Parameters({ + "0, 0.0.0.0", + "1, 1.0.0.0", + "2, 2.0.0.0", + "3.14, 3.14.0.0", + "4.0.1, 4.0.1.0", + "55.44.33, 55.44.33.0" + }) + public void shouldFillMissingPlacesByZeros(String projectVersion, String expected) { + // when + final String launch4jFileVersion = Launch4jFileVersionGenerator.generate(projectVersion); + + // then + assertEquals(expected, launch4jFileVersion); + } + + @Test + @Parameters({ + "1-SNAPSHOT, 1.0.0.0", + "1.2.1-alpha, 1.2.1.0", + "1.2.3.4-beta, 1.2.3.4", + "0.0.1-snapshot, 0.0.1.0", + }) + public void shouldCutOffTextFlags(String projectVersion, String expected) { + // when + final String launch4jFileVersion = Launch4jFileVersionGenerator.generate(projectVersion); + + // then + assertEquals(expected, launch4jFileVersion); + } + + @Test + @Parameters({ + "0.0.0.0.1, 0.0.0.0", + "1.22.333.4444.55555.666666, 1.22.333.4444", + "9.8.7.6.5-SNAPSHOT, 9.8.7.6", + "3.0.1.12.44.62.1.0.0.0.1-alpha, 3.0.1.12", + }) + public void shouldCutOffTooManyNestedDigits(String projectVersion, String expected) { + // when + final String launch4jFileVersion = Launch4jFileVersionGenerator.generate(projectVersion); + + // then + assertEquals(expected, launch4jFileVersion); + } +} \ No newline at end of file diff --git a/src/test/resources/unit/launch4j-default/launch4j-default-plugin-config.xml b/src/test/resources/unit/launch4j-config/launch4j-full-plugin-config.xml similarity index 95% rename from src/test/resources/unit/launch4j-default/launch4j-default-plugin-config.xml rename to src/test/resources/unit/launch4j-config/launch4j-full-plugin-config.xml index 7f38dba9..45136800 100644 --- a/src/test/resources/unit/launch4j-default/launch4j-default-plugin-config.xml +++ b/src/test/resources/unit/launch4j-config/launch4j-full-plugin-config.xml @@ -7,7 +7,7 @@ 1.0-SNAPSHOT jar - launch4j-default + launch4j-full @@ -35,6 +35,7 @@ -Dname=Lukasz + true Test bundledJreErr @@ -54,7 +55,6 @@ - - + \ No newline at end of file