diff --git a/plexus-java/pom.xml b/plexus-java/pom.xml index ccf069e..a317713 100644 --- a/plexus-java/pom.xml +++ b/plexus-java/pom.xml @@ -22,7 +22,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.20 + 2.21.0 @@ -31,6 +31,30 @@ org.codehaus.plexus plexus-component-metadata 1.7.1 + + + source + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.21.0 + + + + integration-test + verify + + + + + + **/*Test.java + + @@ -44,7 +68,7 @@ com.thoughtworks.qdox qdox - 2.0-M7 + 2.0-M8 @@ -69,7 +93,7 @@ org.mockito mockito-core - 2.15.0 + 2.18.3 test @@ -80,4 +104,55 @@ + + + jdk9 + + [9,) + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + + jdk9 + + compile + + + 9 + + ${project.basedir}/src/main/java9 + + ${project.build.outputDirectory}/META-INF/versions/9 + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + default-jar + + + + true + + + + + + + + + + + + diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AbstractBinaryModuleInfoParser.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AbstractBinaryModuleInfoParser.java new file mode 100644 index 0000000..a58a043 --- /dev/null +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AbstractBinaryModuleInfoParser.java @@ -0,0 +1,77 @@ +package org.codehaus.plexus.languages.java.jpms; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.regex.Pattern; + +public abstract class AbstractBinaryModuleInfoParser implements ModuleInfoParser +{ + private static final Pattern MRJAR_DESCRIPTOR = Pattern.compile( "META-INF/versions/[^/]+/module-info.class" ); + + @Override + public JavaModuleDescriptor getModuleDescriptor( Path modulePath ) + throws IOException + { + JavaModuleDescriptor descriptor; + if ( Files.isDirectory( modulePath ) ) + { + try ( InputStream in = Files.newInputStream( modulePath.resolve( "module-info.class" ) ) ) + { + descriptor = parse( in ); + } + } + else + { + try ( JarFile jarFile = new JarFile( modulePath.toFile() ) ) + { + JarEntry moduleInfo; + if ( modulePath.toString().toLowerCase().endsWith( ".jmod" ) ) + { + moduleInfo = jarFile.getJarEntry( "classes/module-info.class" ); + } + else + { + moduleInfo = jarFile.getJarEntry( "module-info.class" ); + + if ( moduleInfo == null ) + { + Manifest manifest = jarFile.getManifest(); + + if ( manifest != null && "true".equalsIgnoreCase( manifest.getMainAttributes().getValue( "Multi-Release" ) ) ) + { + // look for multirelease descriptor + Enumeration entryIter = jarFile.entries(); + while ( entryIter.hasMoreElements() ) + { + JarEntry entry = entryIter.nextElement(); + if ( MRJAR_DESCRIPTOR.matcher( entry.getName() ).matches() ) + { + moduleInfo = entry; + break; + } + } + } + } + } + + if ( moduleInfo != null ) + { + descriptor = parse( jarFile.getInputStream( moduleInfo ) ); + } + else + { + descriptor = null; + } + } + } + return descriptor; + } + + abstract JavaModuleDescriptor parse( InputStream in ) throws IOException; +} diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AsmModuleInfoParser.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParser.java similarity index 55% rename from plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AsmModuleInfoParser.java rename to plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParser.java index b0ee733..ab04621 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/AsmModuleInfoParser.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParser.java @@ -21,16 +21,9 @@ import java.io.IOException; import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; -import java.util.Enumeration; import java.util.HashSet; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.regex.Pattern; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; @@ -40,74 +33,14 @@ /** * Extract information from module with ASM * + * * @author Robert Scholte * @since 1.0.0 */ -public class AsmModuleInfoParser - implements ModuleInfoParser +class BinaryModuleInfoParser extends AbstractBinaryModuleInfoParser { - private static final Pattern MRJAR_DESCRIPTOR = Pattern.compile( "META-INF/versions/[^/]+/module-info.class" ); - @Override - public JavaModuleDescriptor getModuleDescriptor( Path modulePath ) - throws IOException - { - JavaModuleDescriptor descriptor; - if ( Files.isDirectory( modulePath ) ) - { - try ( InputStream in = Files.newInputStream( modulePath.resolve( "module-info.class" ) ) ) - { - descriptor = parse( in ); - } - } - else - { - try ( JarFile jarFile = new JarFile( modulePath.toFile() ) ) - { - JarEntry moduleInfo; - if ( modulePath.toString().toLowerCase().endsWith( ".jmod" ) ) - { - moduleInfo = jarFile.getJarEntry( "classes/module-info.class" ); - } - else - { - moduleInfo = jarFile.getJarEntry( "module-info.class" ); - - if ( moduleInfo == null ) - { - Manifest manifest = jarFile.getManifest(); - - if ( manifest != null && "true".equalsIgnoreCase( manifest.getMainAttributes().getValue( "Multi-Release" ) ) ) - { - // look for multirelease descriptor - Enumeration entryIter = jarFile.entries(); - while ( entryIter.hasMoreElements() ) - { - JarEntry entry = entryIter.nextElement(); - if ( MRJAR_DESCRIPTOR.matcher( entry.getName() ).matches() ) - { - moduleInfo = entry; - break; - } - } - } - } - } - - if ( moduleInfo != null ) - { - descriptor = parse( jarFile.getInputStream( moduleInfo ) ); - } - else - { - descriptor = null; - } - } - } - return descriptor; - } - - private JavaModuleDescriptor parse( InputStream in ) + JavaModuleDescriptor parse( InputStream in ) throws IOException { final JavaModuleDescriptorWrapper wrapper = new JavaModuleDescriptorWrapper(); diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/JavaModuleDescriptor.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/JavaModuleDescriptor.java index 2fa1538..1293910 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/JavaModuleDescriptor.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/JavaModuleDescriptor.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.LinkedHashSet; +import java.util.Objects; import java.util.Set; /** @@ -171,6 +172,40 @@ public static enum JavaModifier { STATIC } + + @Override + public int hashCode() + { + return Objects.hash( modifiers, name ); + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( obj == null ) + { + return false; + } + if ( getClass() != obj.getClass() ) + { + return false; + } + + JavaRequires other = (JavaRequires) obj; + if ( !Objects.equals( modifiers, other.modifiers ) ) + { + return false; + } + if ( !Objects.equals( name, other.name ) ) + { + return false; + } + return true; + } } /** @@ -206,5 +241,41 @@ public Set targets() { return targets; } + + @Override + public int hashCode() + { + return Objects.hash( source, targets ); + } + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( obj == null ) + { + return false; + } + if ( getClass() != obj.getClass() ) + { + return false; + } + + JavaExports other = (JavaExports) obj; + if ( !Objects.equals( source, other.source ) ) + { + return false; + } + if ( !Objects.equals( targets, other.targets ) ) + { + return false; + } + return true; + } + + } } diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java index 547ca2c..724b225 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/LocationManager.java @@ -45,20 +45,20 @@ @Component( role = LocationManager.class ) public class LocationManager { - private ModuleInfoParser asmParser; + private ModuleInfoParser binaryParser; - private QDoxModuleInfoParser qdoxParser; + private SourceModuleInfoParser sourceParser; public LocationManager() { - this.asmParser = new AsmModuleInfoParser(); - this.qdoxParser = new QDoxModuleInfoParser(); + this.binaryParser = new BinaryModuleInfoParser(); + this.sourceParser = new SourceModuleInfoParser(); } - LocationManager( ModuleInfoParser asmParser, QDoxModuleInfoParser qdoxParser ) + LocationManager( ModuleInfoParser binaryParser, SourceModuleInfoParser sourceParser ) { - this.asmParser = asmParser; - this.qdoxParser = qdoxParser; + this.binaryParser = binaryParser; + this.sourceParser = sourceParser; } /** @@ -84,11 +84,11 @@ public ResolvePathsResult resolvePaths( ResolvePathsRequest request ) { if ( descriptorPath.endsWith( "module-info.java" ) ) { - mainModuleDescriptor = qdoxParser.fromSourcePath( descriptorPath ); + mainModuleDescriptor = sourceParser.fromSourcePath( descriptorPath ); } else if ( descriptorPath.endsWith( "module-info.class" ) ) { - mainModuleDescriptor = asmParser.getModuleDescriptor( descriptorPath.getParent() ); + mainModuleDescriptor = binaryParser.getModuleDescriptor( descriptorPath.getParent() ); } else { @@ -124,7 +124,7 @@ else if ( descriptorPath.endsWith( "module-info.class" ) ) { try { - moduleDescriptor = asmParser.getModuleDescriptor( path ); + moduleDescriptor = binaryParser.getModuleDescriptor( path ); } catch( IOException e ) { diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ManifestModuleNameExtractor.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ManifestModuleNameExtractor.java index 9affa58..16d0984 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ManifestModuleNameExtractor.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ManifestModuleNameExtractor.java @@ -33,7 +33,7 @@ * @author Robert Scholte * @since 1.0.0 */ -public class ManifestModuleNameExtractor implements ModuleNameExtractor +class ManifestModuleNameExtractor implements ModuleNameExtractor { @Override public String extract( Path file ) diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleInfoParser.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleInfoParser.java index 671bcb4..572d916 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleInfoParser.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleInfoParser.java @@ -28,10 +28,8 @@ * @author Robert Scholte * @since 1.0.0 */ -public interface ModuleInfoParser +interface ModuleInfoParser { - - /** * Extracts the name from the module-info file * diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleNameExtractor.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleNameExtractor.java index 28e5473..541f8c3 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleNameExtractor.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/ModuleNameExtractor.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.nio.file.Path; -public interface ModuleNameExtractor +interface ModuleNameExtractor { String extract( Path path ) throws IOException; } diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/QDoxModuleInfoParser.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java similarity index 98% rename from plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/QDoxModuleInfoParser.java rename to plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java index 3765848..48f8e1e 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/QDoxModuleInfoParser.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java @@ -36,7 +36,7 @@ * @author Robert Scholte * @since 1.0.0 */ -public class QDoxModuleInfoParser +class SourceModuleInfoParser { public org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor fromSourcePath( Path modulePath ) diff --git a/plexus-java/src/main/java9/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParser.java b/plexus-java/src/main/java9/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParser.java new file mode 100644 index 0000000..2bb36d9 --- /dev/null +++ b/plexus-java/src/main/java9/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParser.java @@ -0,0 +1,66 @@ +package org.codehaus.plexus.languages.java.jpms; + +/* + * 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.IOException; +import java.io.InputStream; + +import java.lang.module.ModuleDescriptor; +import java.util.Collections; + +import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.Builder; + +class BinaryModuleInfoParser extends AbstractBinaryModuleInfoParser +{ + @Override + JavaModuleDescriptor parse( InputStream in ) throws IOException + { + ModuleDescriptor descriptor = ModuleDescriptor.read( in ); + + Builder builder = JavaModuleDescriptor.newModule( descriptor.name() ); + + for ( ModuleDescriptor.Requires requires : descriptor.requires() ) + { + if ( requires.modifiers().contains( ModuleDescriptor.Requires.Modifier.STATIC ) ) + { + builder.requires​( Collections.singleton( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), + requires.name() ); + } + else + { + builder.requires( requires.name() ); + } + } + + for ( ModuleDescriptor.Exports exports : descriptor.exports() ) + { + if ( exports.targets().isEmpty() ) + { + builder.exports( exports.source() ); + } + else + { + builder.exports( exports.source(), exports.targets() ); + } + } + + return builder.build(); + } +} diff --git a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/AsmModuleInfoParserTest.java b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java similarity index 81% rename from plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/AsmModuleInfoParserTest.java rename to plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java index fcc42f6..41bc6f9 100644 --- a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/AsmModuleInfoParserTest.java +++ b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java @@ -28,14 +28,19 @@ import java.io.IOException; import java.nio.file.NoSuchFileException; import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaExports; import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires; import org.junit.Test; -public class AsmModuleInfoParserTest +public class BinaryModuleInfoParserTest { - private ModuleInfoParser parser = new AsmModuleInfoParser(); + private BinaryModuleInfoParser parser = new BinaryModuleInfoParser(); @Test public void testJarDescriptor() throws Exception @@ -49,8 +54,12 @@ public void testJarDescriptor() throws Exception assertEquals( 1, descriptor.requires().size() ); assertEquals( "java.base", descriptor.requires().iterator().next().name() ); - assertEquals( 2, descriptor.exports().size() ); - assertEquals( "org.objectweb.asm", descriptor.exports().iterator().next().source() ); + Set expectedExports = JavaModuleDescriptor.newAutomaticModule( "_" ) + .exports( "org.objectweb.asm" ) + .exports( "org.objectweb.asm.signature" ) + .build() + .exports(); + assertEquals( expectedExports, descriptor.exports() ); } @Test @@ -93,19 +102,14 @@ public void testOutputDirectoryDescriptor() assertEquals( 3, descriptor.requires().size() ); - Iterator requiresIter = descriptor.requires().iterator(); + Set expectedRequires = JavaModuleDescriptor.newAutomaticModule( "_" ) + .requires​( "java.base" ) + .requires( "java.xml" ) + .requires​( Collections.singleton( JavaRequires.JavaModifier.STATIC ), "com.google.common" ) + .build() + .requires(); - JavaRequires requires = requiresIter.next(); - assertEquals( "java.base", requires.name() ); - assertFalse( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); - - requires = requiresIter.next(); - assertEquals( "java.xml", requires.name() ); - assertFalse( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); - - requires = requiresIter.next(); - assertEquals( "com.google.common", requires.name() ); - assertTrue( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); + assertEquals( expectedRequires, descriptor.requires() ); } @Test( expected = NoSuchFileException.class ) diff --git a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java index 7292c0c..a5c0fcc 100644 --- a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java +++ b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/LocationManagerTest.java @@ -45,10 +45,10 @@ public class LocationManagerTest { @Mock - private ModuleInfoParser asmParser; + private BinaryModuleInfoParser asmParser; @Mock - private QDoxModuleInfoParser qdoxParser; + private SourceModuleInfoParser qdoxParser; private LocationManager locationManager; diff --git a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/QDoxModuleInfoParserTest.java b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java similarity index 95% rename from plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/QDoxModuleInfoParserTest.java rename to plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java index 7ace474..f7e4ead 100644 --- a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/QDoxModuleInfoParserTest.java +++ b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java @@ -32,9 +32,9 @@ import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires; import org.junit.Test; -public class QDoxModuleInfoParserTest +public class SourceModuleInfoParserTest { - private QDoxModuleInfoParser parser = new QDoxModuleInfoParser(); + private SourceModuleInfoParser parser = new SourceModuleInfoParser(); @Test public void test() throws Exception diff --git a/pom.xml b/pom.xml index ebbb5ed..b0960ed 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,16 @@ true + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + @@ -67,4 +77,34 @@ + + + + plexus-release + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-java + + enforce + + + + + 9 + + + + + + + + + +