Skip to content
Commits on Source (5)
......@@ -31,9 +31,9 @@ Getting Started
+ Make sure you have a [JIRA account](https://issues.apache.org/jira/).
+ Make sure you have a [GitHub account](https://github.com/signup/free).
+ If you're planning to implement a new feature, it makes sense to discuss your changes
on the [dev list](https://maven.apache.org/mail-lists.html) first.
This way you can make sure you're not wasting your time on something that isn't
+ If you're planning to implement a new feature, it makes sense to discuss your changes
on the [dev list](https://maven.apache.org/mail-lists.html) first.
This way you can make sure you're not wasting your time on something that isn't
considered to be in Apache Maven's scope.
+ Submit a ticket for your issue, assuming one does not already exist.
+ Clearly describe the issue, including steps to reproduce when it is a bug.
......@@ -44,7 +44,7 @@ Making and Submitting Changes
--------------
We accept Pull Requests via GitHub. The [developer mailing list][dev-ml-list] is the
main channel of communication for contributors.
main channel of communication for contributors.
There are some guidelines which will make applying PRs easier for us:
+ Create a topic branch from where you want to base your work (this is usually the master branch).
Push your changes to a topic branch in your fork of the repository.
......@@ -52,7 +52,7 @@ There are some guidelines which will make applying PRs easier for us:
+ Respect the original code style: by using the same [codestyle][code-style],
patches should only highlight the actual difference, not being disturbed by any formatting issues:
+ Only use spaces for indentation.
+ Create minimal diffs - disable on save actions like reformat source code or organize imports.
+ Create minimal diffs - disable on save actions like reformat source code or organize imports.
If you feel the source code should be reformatted, create a separate PR for this change.
+ Check for unnecessary whitespace with `git diff --check` before committing.
+ Make sure your commit messages are in the proper format. Your commit message should contain the key of the JIRA issue.
......@@ -85,7 +85,7 @@ Additional Resources
+ [Apache Maven Twitter Account](https://twitter.com/ASFMavenProject)
+ #Maven IRC channel on freenode.org
[dev-ml-list]: https://maven.apache.org/mail-lists.html
[dev-ml-list]: https://maven.apache.org/mailing-lists.html
[code-style]: https://maven.apache.org/developers/conventions/code.html
[cla]: https://www.apache.org/licenses/#clas
[maven-wiki]: https://cwiki.apache.org/confluence/display/MAVEN/Index
maven-jar-plugin (3.1.2-1) unstable; urgency=medium
* Team upload.
* New upstream release
- Refreshed the patch
- New dependency on libmaven-file-management-java
-- Emmanuel Bourg <ebourg@apache.org> Sun, 07 Jul 2019 13:15:52 +0200
maven-jar-plugin (3.1.1-1) unstable; urgency=medium
* Team upload.
......
......@@ -9,6 +9,7 @@ Build-Depends:
junit4,
libcommons-lang-java,
libmaven-archiver-java,
libmaven-file-management-java,
libmaven-install-plugin-java,
libmaven-invoker-plugin-java,
libmaven-plugin-testing-java,
......
......@@ -5,7 +5,7 @@ Forwarded: no
Bug: https://issues.apache.org/jira/browse/MJAR-198
--- a/src/main/java/org/apache/maven/plugins/jar/AbstractJarMojo.java
+++ b/src/main/java/org/apache/maven/plugins/jar/AbstractJarMojo.java
@@ -262,7 +262,7 @@
@@ -300,7 +300,7 @@
{
if ( projectHasAlreadySetAnArtifact() )
{
......
......@@ -30,7 +30,7 @@
</parent>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
<version>3.1.2</version>
<packaging>maven-plugin</packaging>
<name>Apache Maven JAR Plugin</name>
......@@ -57,7 +57,7 @@
<connection>scm:git:https://gitbox.apache.org/repos/asf/maven-jar-plugin.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-jar-plugin.git</developerConnection>
<url>https://github.com/apache/maven-jar-plugin/tree/${project.scm.tag}</url>
<tag>maven-jar-plugin-3.1.1</tag>
<tag>maven-jar-plugin-3.1.2</tag>
</scm>
<issueManagement>
<system>JIRA</system>
......@@ -75,7 +75,8 @@
</distributionManagement>
<properties>
<mavenArchiverVersion>3.3.0</mavenArchiverVersion>
<mavenFileManagementVersion>3.0.0</mavenFileManagementVersion>
<mavenArchiverVersion>3.4.0</mavenArchiverVersion>
<mavenVersion>3.0</mavenVersion>
<javaVersion>7</javaVersion>
</properties>
......@@ -96,6 +97,11 @@
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>file-management</artifactId>
<version>${mavenFileManagementVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-archiver</artifactId>
......@@ -112,16 +118,28 @@
! so we define it here explicit to make sure we get the
! correct version for plexus-archiver and plexus-utils.
-->
<!--
! maven-shared-utils is pulled by file-management
! Need to use a more recent version otherwise
! the build will fail. This needed to be kept
! here until a new version of file-management
! has been made.
-->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-archiver</artifactId>
<version>3.7.0</version>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-shared-utils</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.1.0</version>
<artifactId>plexus-archiver</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
......
......@@ -45,12 +45,6 @@ try
Attributes manifest = jar.getManifest().getMainAttributes();
if ( !manifest.getValue( new Attributes.Name( "Created-By" ) ).startsWith( "Apache Maven" ) )
{
System.err.println( "Created-By not equals Apache Maven" );
return false;
}
if ( !"myproject.HelloWorld".equals( manifest.get( Attributes.Name.MAIN_CLASS ) ) )
{
System.err.println( Attributes.Name.MAIN_CLASS.toString() + " not equals myproject.HelloWorld" );
......
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
invoker.java.version = 9+
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>mjar-238-modular-jar-main-class</artifactId>
<name>mjar-238-modular-jar-main-class</name>
<description>Verifies that the modular descriptor main class is set for modular Jar files</description>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>@project.version@</version>
<configuration>
<archive>
<manifest>
<mainClass>myproject.HelloWorld</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.9</source>
<target>1.9</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
module myproject {
exports myproject;
}
package myproject;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* The classic Hello World App.
*/
public class HelloWorld {
/**
* Main method.
*
* @param args Not used
*/
public static void main( String[] args )
{
System.out.println( "Hi!" );
}
}
\ No newline at end of file
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.*;
import java.lang.module.*;
import java.util.jar.*;
boolean result = true;
JarFile jar;
try
{
File target = new File( basedir, "target" );
if ( !target.exists() || !target.isDirectory() )
{
System.err.println( "target file is missing or not a directory." );
return false;
}
File artifact = new File( target, "mjar-238-modular-jar-main-class-1.0-SNAPSHOT.jar" );
if ( !artifact.exists() || artifact.isDirectory() )
{
System.err.println( "artifact file is missing or a directory." );
return false;
}
jar = new JarFile( artifact );
Attributes manifest = jar.getManifest().getMainAttributes();
if ( !"myproject.HelloWorld".equals( manifest.get( Attributes.Name.MAIN_CLASS ) ) )
{
System.err.println( "Manifest main class attribute not equals myproject.HelloWorld" );
return false;
}
InputStream moduleDescriptorInputStream = jar.getInputStream( jar.getEntry( "module-info.class" ) );
ModuleDescriptor moduleDescriptor = ModuleDescriptor.read( moduleDescriptorInputStream );
if ( !"myproject.HelloWorld".equals( moduleDescriptor.mainClass().orElse( null ) ) )
{
System.err.println( "Module descriptor main class not equals myproject.HelloWorld" );
return false;
}
}
catch( Throwable e )
{
e.printStackTrace();
result = false;
}
finally
{
if ( jar != null )
{
jar.close();
}
}
return result;
......@@ -25,6 +25,7 @@ import org.codehaus.plexus.util.*;
boolean result = true;
try
{
File target = new File( basedir, "target" );
......@@ -45,13 +46,6 @@ try
Attributes manifest = jar.getManifest().getMainAttributes();
if ( !manifest.getValue( new Attributes.Name( "Created-By" ) ).startsWith( "Apache Maven" ) )
{
System.err.println( "Created-By not equals Apache Maven" );
return false;
}
if ( !"manifest-content-it".equals( manifest.get( Attributes.Name.SPECIFICATION_TITLE ) ) )
{
System.err.println( Attributes.Name.SPECIFICATION_TITLE.toString() + " not equals manifest-content-it" );
......@@ -84,12 +78,6 @@ try
return false;
}
if ( !"org.apache.maven.plugins".equals( manifest.get( Attributes.Name.IMPLEMENTATION_VENDOR_ID ) ) )
{
System.err.println( Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString() + " not equals org.apache.maven.plugins" );
return false;
}
if ( !"jar plugin it".equals( manifest.get( Attributes.Name.IMPLEMENTATION_VENDOR ) ) )
{
System.err.println( Attributes.Name.IMPLEMENTATION_VENDOR.toString() + " not equals jar plugin it" );
......
......@@ -28,10 +28,14 @@ import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.shared.model.fileset.FileSet;
import org.apache.maven.shared.model.fileset.util.FileSetManager;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.jar.JarArchiver;
import java.io.File;
import java.util.Arrays;
import java.util.Map;
/**
* Base class for creating a jar from project classes.
......@@ -47,6 +51,8 @@ public abstract class AbstractJarMojo
private static final String[] DEFAULT_INCLUDES = new String[] { "**/**" };
private static final String MODULE_DESCRIPTOR_FILE_NAME = "module-info.class";
/**
* List of files to include. Specified as fileset patterns which are relative to the input directory whose contents
* is being packaged into the JAR.
......@@ -76,8 +82,8 @@ public abstract class AbstractJarMojo
/**
* The Jar archiver.
*/
@Component( role = Archiver.class, hint = "jar" )
private JarArchiver jarArchiver;
@Component
private Map<String, Archiver> archivers;
/**
* The {@link {MavenProject}.
......@@ -201,9 +207,41 @@ public abstract class AbstractJarMojo
{
File jarFile = getJarFile( outputDirectory, finalName, getClassifier() );
FileSetManager fileSetManager = new FileSetManager();
FileSet jarContentFileSet = new FileSet();
jarContentFileSet.setDirectory( getClassesDirectory().getAbsolutePath() );
jarContentFileSet.setIncludes( Arrays.asList( getIncludes() ) );
jarContentFileSet.setExcludes( Arrays.asList( getExcludes() ) );
boolean containsModuleDescriptor = false;
String[] includedFiles = fileSetManager.getIncludedFiles( jarContentFileSet );
for ( String includedFile : includedFiles )
{
// May give false positives if the files is named as module descriptor
// but is not in the root of the archive or in the versioned area
// (and hence not actually a module descriptor).
// That is fine since the modular Jar archiver will gracefully
// handle such case.
// And also such case is unlikely to happen as file ending
// with "module-info.class" is unlikely to be included in Jar file
// unless it is a module descriptor.
if ( includedFile.endsWith( MODULE_DESCRIPTOR_FILE_NAME ) )
{
containsModuleDescriptor = true;
break;
}
}
MavenArchiver archiver = new MavenArchiver();
archiver.setArchiver( jarArchiver );
if ( containsModuleDescriptor )
{
archiver.setArchiver( (JarArchiver) archivers.get( "mjar" ) );
}
else
{
archiver.setArchiver( (JarArchiver) archivers.get( "jar" ) );
}
archiver.setOutputFile( jarFile );
......
......@@ -78,3 +78,22 @@ mvn package
the {{{/guides/introduction/introduction-to-the-lifecycle.html}Maven Build Life Cycle}}.
For full documentation, click {{{./plugin-info.html}here}}.
* Modular JAR files
The {{{https://openjdk.java.net/projects/jigsaw/spec/}Java Platform Module System (JPMS)}} introduced
{{{https://cr.openjdk.java.net/~mr/jigsaw/spec/jar.html}changes in the JAR file specifications}}
as well - Modular JAR files. Modular JAR files are JAR files with <<<module-info.class>>> file in the root directory
(or in the versioned area for multi-release JAR files). If the project contains <<<module-info.class>>>
the resulting JAR will be a Modular JAR without a need for any configuration regardless of the plugin version used.
Starting with version 3.1.2, if the JAR file contains <<<module-info.class>>>, this plugin will update
the modular descriptor (<<<module-info.class>>>) with additional attributes such as the list of packages included
and will validate the resulting modular descriptor (for example if all services provided by the module are actually
included in the JAR file). The most notable additional attribute added is the module main class.
If the JAR manifest contains <<<Main-Class>>> attribute this plugin will set the module main class to the same value
(for example how to set it read {{{../../shared/maven-archiver/examples/classpath.html}Make The Jar Executable}}).
Internally the plugin uses the JDK <<<jar>>> tool so in order to add the additional attributes and to
verify the modular descriptor Maven should be run with JDK version 9 or newer. If version 8 or earlier is used
the resulting JAR still will be Modular JAR (as it contains <<<module-info.class>>>) but no additional attributes
will be added and no validation will be performed.
package org.apache.maven.plugins.jar;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.artifact.versioning.VersionRange;
/**
* @todo move to maven-artifact-test
*/
class MockArtifact
implements Artifact
{
private String groupId;
private String artifactId;
private String version;
private File file;
private String scope;
private String type;
private String classifier;
private String baseVersion;
public String getGroupId()
{
return groupId;
}
public String getArtifactId()
{
return artifactId;
}
public String getVersion()
{
return version;
}
public void setVersion( String string )
{
this.version = string;
}
public String getScope()
{
return scope;
}
public String getType()
{
return type;
}
public String getClassifier()
{
return classifier;
}
public boolean hasClassifier()
{
return classifier != null;
}
public File getFile()
{
return file;
}
public void setFile( File file )
{
this.file = file;
}
public String getBaseVersion()
{
return baseVersion;
}
public void setBaseVersion( String string )
{
this.baseVersion = string;
}
public String getId()
{
return null;
}
public String getDependencyConflictId()
{
return null;
}
public void addMetadata( ArtifactMetadata artifactMetadata )
{
// intentionally empty.
}
public Collection getMetadataList()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setRepository( ArtifactRepository artifactRepository )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public ArtifactRepository getRepository()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void updateVersion( String string, ArtifactRepository artifactRepository )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public String getDownloadUrl()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setDownloadUrl( String string )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public ArtifactFilter getDependencyFilter()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setDependencyFilter( ArtifactFilter artifactFilter )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public ArtifactHandler getArtifactHandler()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public List getDependencyTrail()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setDependencyTrail( List list )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public void setScope( String string )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public VersionRange getVersionRange()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setVersionRange( VersionRange versionRange )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public void selectVersion( String string )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public boolean isSnapshot()
{
return false; //To change body of implemented methods use File | Settings | File Templates.
}
public void setResolved( boolean b )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public boolean isResolved()
{
return false; //To change body of implemented methods use File | Settings | File Templates.
}
public void setResolvedVersion( String string )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public void setArtifactHandler( ArtifactHandler artifactHandler )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public boolean isRelease()
{
return false; //To change body of implemented methods use File | Settings | File Templates.
}
public void setRelease( boolean b )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public List getAvailableVersions()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public void setAvailableVersions( List list )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public boolean isOptional()
{
return false; //To change body of implemented methods use File | Settings | File Templates.
}
public void setOptional( boolean b )
{
//To change body of implemented methods use File | Settings | File Templates.
}
public ArtifactVersion getSelectedVersion()
throws OverConstrainedVersionException
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public boolean isSelectedVersionKnown()
throws OverConstrainedVersionException
{
return false; //To change body of implemented methods use File | Settings | File Templates.
}
public void setGroupId( String groupId )
{
this.groupId = groupId;
}
public void setArtifactId( String artifactId )
{
this.artifactId = artifactId;
}
public void setType( String type )
{
this.type = type;
}
public void setClassifier( String classifier )
{
this.classifier = classifier;
}
public int compareTo( Artifact o )
{
return 0;
}
public ArtifactMetadata getMetadata( Class<?> metadataClass )
{
return null;
}
}