Skip to content

Modify ModularJarArchiver to use the manifest main class as default #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,14 @@ private String[] getJarToolArguments()
args.add( "--file" );
args.add( getDestFile().getAbsolutePath() );

if ( getModuleMainClass() != null )
String mainClass = getModuleMainClass() != null
? getModuleMainClass()
: getManifestMainClass();

if ( mainClass != null )
{
args.add( "--main-class" );
args.add( getModuleMainClass() );
args.add( mainClass );
}

if ( getModuleVersion() != null )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,22 @@
* they are going to add are part of module
* (contain module descriptor class) or not.
*
* <p>The class allows you to set the
* module main class ({@link #setModuleMainClass(String)}),
* but if it is not set or it is set to {@code null},
* then the {@code Main-Class} attribute of the
* JAR manifest is used (if present) to set
* the module main class.
*
* @since 3.6
*/
public abstract class ModularJarArchiver
extends JarArchiver
{
private String moduleMainClass;

private String manifestMainClass;

private String moduleVersion;

public String getModuleMainClass()
Expand Down Expand Up @@ -73,4 +82,41 @@ public void setModuleVersion( String moduleVersion )
this.moduleVersion = moduleVersion;
}

/**
* Returns the "Main-Class" attribute of the
* manifest added to the archive.
*
* {@code null} if there is no manifest
* or the attribute is not set.
*
* @return the "Main-Class" attribute of the manifest
*/
protected String getManifestMainClass()
{
return manifestMainClass;
}

@Override
protected Manifest createManifest()
{
Manifest manifest = super.createManifest();

if ( manifest != null )
{
manifestMainClass = manifest.getMainAttributes()
.getValue( "Main-Class" );
}

return manifest;
}

@Override
public void reset()
{
// We want to be sure that on multiple run
// the latest manifest is used, so lets
// reset it to null
manifestMainClass = null;
super.reset();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

Expand Down Expand Up @@ -76,6 +75,57 @@ public void testModularJarWithMainClassAndVersion()
"1.0.0", "com.example.app.Main", "com.example.app", "com.example.resources" );
}

/*
* Verify that when both module main class is set and the
* manifest contains main class atribute, the manifest
* value is overridden
*/
@Test
public void testModularJarWithManifestAndModuleMainClass()
throws Exception
{
assumeTrue( modulesAreSupported() );

archiver.addDirectory( new File( "src/test/resources/java-module-descriptor" ) );
Manifest manifest = new Manifest();
manifest.addConfiguredAttribute(
new Manifest.Attribute( "Main-Class", "com.example.app.Main2" ) );
archiver.addConfiguredManifest( manifest );
archiver.setModuleMainClass( "com.example.app.Main" );

archiver.createArchive();

// Verify that the explicitly set module main class
// overrides the manifest main
assertModularJarFile( archiver.getDestFile(),
null, "com.example.app.Main", "com.example.app", "com.example.resources" );
assertManifestMainClass( archiver.getDestFile(), "com.example.app.Main" );
}

/**
* Verify that when the module main class is not explicitly set,
* the manifest main class attribute (if present) is used instead
*/
@Test
public void testModularJarWithManifestMainClassAttribute()
throws Exception
{
assumeTrue( modulesAreSupported() );

archiver.addDirectory( new File( "src/test/resources/java-module-descriptor" ) );
Manifest manifest = new Manifest();
manifest.addConfiguredAttribute(
new Manifest.Attribute( "Main-Class", "com.example.app.Main2" ) );
archiver.addConfiguredManifest( manifest );

archiver.createArchive();

// Verify that the the manifest main class attribute is used as module main class
assertModularJarFile( archiver.getDestFile(),
null, "com.example.app.Main2", "com.example.app", "com.example.resources" );
assertManifestMainClass( archiver.getDestFile(), "com.example.app.Main2" );
}

/*
* Verify that a modular JAR file is created even when no additional attributes are set.
*/
Expand Down Expand Up @@ -288,6 +338,23 @@ private void assertModuleDescriptor( InputStream moduleDescriptorInputStream,
assertEquals( expectedPackagesSet, actualPackagesSet );
}

private void assertManifestMainClass( File jarFile, String expectedMainClass )
throws Exception
{
try ( ZipFile resultingArchive = new ZipFile( jarFile ) )
{
ZipEntry manifestEntry = resultingArchive.getEntry( "META-INF/MANIFEST.MF" );
InputStream manifestInputStream = resultingArchive.getInputStream( manifestEntry );

// Get the manifest main class attribute
Manifest manifest = new Manifest( manifestInputStream );
String actualManifestMainClass = manifest.getMainAttributes().getValue( "Main-Class" );

assertEquals( expectedMainClass, actualManifestMainClass );
}

}

/*
* Returns true if the current version of Java does support modules.
*/
Expand Down