Skip to content

Commit 89e8b75

Browse files
committed
Modify ModularJarArchiver to use the manifest main class as default
If the main class for a module is not explicitly set, lets use the one specified in the manifest file. That would simplify the creation of modular JAR files - clients should just set the manifest main class as in non-modular JAR file and everything will work out of the box. Also it will allow `ModularJarArchiver` to be used as drop-in replacement of `JarArchiver` without any additional configuration. Closes #102, Closes #101
1 parent fcee0af commit 89e8b75

File tree

3 files changed

+121
-4
lines changed

3 files changed

+121
-4
lines changed

Diff for: src/main/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiver.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,14 @@ private String[] getJarToolArguments()
180180
args.add( "--file" );
181181
args.add( getDestFile().getAbsolutePath() );
182182

183-
if ( getModuleMainClass() != null )
183+
String mainClass = getModuleMainClass() != null
184+
? getModuleMainClass()
185+
: getManifestMainClass();
186+
187+
if ( mainClass != null )
184188
{
185189
args.add( "--main-class" );
186-
args.add( getModuleMainClass() );
190+
args.add( mainClass );
187191
}
188192

189193
if ( getModuleVersion() != null )

Diff for: src/main/java/org/codehaus/plexus/archiver/jar/ModularJarArchiver.java

+46
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,22 @@
2727
* they are going to add are part of module
2828
* (contain module descriptor class) or not.
2929
*
30+
* <p>The class allows you to set the
31+
* module main class ({@link #setModuleMainClass(String)}),
32+
* but if it is not set or it is set to {@code null},
33+
* then the {@code Main-Class} attribute of the
34+
* JAR manifest is used (if present) to set
35+
* the module main class.
36+
*
3037
* @since 3.6
3138
*/
3239
public abstract class ModularJarArchiver
3340
extends JarArchiver
3441
{
3542
private String moduleMainClass;
3643

44+
private String manifestMainClass;
45+
3746
private String moduleVersion;
3847

3948
public String getModuleMainClass()
@@ -73,4 +82,41 @@ public void setModuleVersion( String moduleVersion )
7382
this.moduleVersion = moduleVersion;
7483
}
7584

85+
/**
86+
* Returns the "Main-Class" attribute of the
87+
* manifest added to the archive.
88+
*
89+
* {@code null} if there is no manifest
90+
* or the attribute is not set.
91+
*
92+
* @return the "Main-Class" attribute of the manifest
93+
*/
94+
protected String getManifestMainClass()
95+
{
96+
return manifestMainClass;
97+
}
98+
99+
@Override
100+
protected Manifest createManifest()
101+
{
102+
Manifest manifest = super.createManifest();
103+
104+
if ( manifest != null )
105+
{
106+
manifestMainClass = manifest.getMainAttributes()
107+
.getValue( "Main-Class" );
108+
}
109+
110+
return manifest;
111+
}
112+
113+
@Override
114+
public void reset()
115+
{
116+
// We want to be sure that on multiple run
117+
// the latest manifest is used, so lets
118+
// reset it to null
119+
manifestMainClass = null;
120+
super.reset();
121+
}
76122
}

Diff for: src/test/java/org/codehaus/plexus/archiver/jar/JarToolModularJarArchiverTest.java

+69-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@
3030
import org.junit.Before;
3131
import org.junit.Test;
3232

33-
import static org.junit.Assert.assertEquals;
34-
import static org.junit.Assert.assertNotNull;
33+
import static org.junit.Assert.*;
3534
import static org.junit.Assume.assumeFalse;
3635
import static org.junit.Assume.assumeTrue;
3736

@@ -76,6 +75,57 @@ public void testModularJarWithMainClassAndVersion()
7675
"1.0.0", "com.example.app.Main", "com.example.app", "com.example.resources" );
7776
}
7877

78+
/*
79+
* Verify that when both module main class is set and the
80+
* manifest contains main class atribute, the manifest
81+
* value is overridden
82+
*/
83+
@Test
84+
public void testModularJarWithManifestAndModuleMainClass()
85+
throws Exception
86+
{
87+
assumeTrue( modulesAreSupported() );
88+
89+
archiver.addDirectory( new File( "src/test/resources/java-module-descriptor" ) );
90+
Manifest manifest = new Manifest();
91+
manifest.addConfiguredAttribute(
92+
new Manifest.Attribute( "Main-Class", "com.example.app.Main2" ) );
93+
archiver.addConfiguredManifest( manifest );
94+
archiver.setModuleMainClass( "com.example.app.Main" );
95+
96+
archiver.createArchive();
97+
98+
// Verify that the explicitly set module main class
99+
// overrides the manifest main
100+
assertModularJarFile( archiver.getDestFile(),
101+
null, "com.example.app.Main", "com.example.app", "com.example.resources" );
102+
assertManifestMainClass( archiver.getDestFile(), "com.example.app.Main" );
103+
}
104+
105+
/**
106+
* Verify that when the module main class is not explicitly set,
107+
* the manifest main class attribute (if present) is used instead
108+
*/
109+
@Test
110+
public void testModularJarWithManifestMainClassAttribute()
111+
throws Exception
112+
{
113+
assumeTrue( modulesAreSupported() );
114+
115+
archiver.addDirectory( new File( "src/test/resources/java-module-descriptor" ) );
116+
Manifest manifest = new Manifest();
117+
manifest.addConfiguredAttribute(
118+
new Manifest.Attribute( "Main-Class", "com.example.app.Main2" ) );
119+
archiver.addConfiguredManifest( manifest );
120+
121+
archiver.createArchive();
122+
123+
// Verify that the the manifest main class attribute is used as module main class
124+
assertModularJarFile( archiver.getDestFile(),
125+
null, "com.example.app.Main2", "com.example.app", "com.example.resources" );
126+
assertManifestMainClass( archiver.getDestFile(), "com.example.app.Main2" );
127+
}
128+
79129
/*
80130
* Verify that a modular JAR file is created even when no additional attributes are set.
81131
*/
@@ -288,6 +338,23 @@ private void assertModuleDescriptor( InputStream moduleDescriptorInputStream,
288338
assertEquals( expectedPackagesSet, actualPackagesSet );
289339
}
290340

341+
private void assertManifestMainClass( File jarFile, String expectedMainClass )
342+
throws Exception
343+
{
344+
try ( ZipFile resultingArchive = new ZipFile( jarFile ) )
345+
{
346+
ZipEntry manifestEntry = resultingArchive.getEntry( "META-INF/MANIFEST.MF" );
347+
InputStream manifestInputStream = resultingArchive.getInputStream( manifestEntry );
348+
349+
// Get the manifest main class attribute
350+
Manifest manifest = new Manifest( manifestInputStream );
351+
String actualManifestMainClass = manifest.getMainAttributes().getValue( "Main-Class" );
352+
353+
assertEquals( expectedMainClass, actualManifestMainClass );
354+
}
355+
356+
}
357+
291358
/*
292359
* Returns true if the current version of Java does support modules.
293360
*/

0 commit comments

Comments
 (0)