diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 5d5c583..0000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,67 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ master ] - schedule: - - cron: '25 17 * * 1' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - language: [ 'java' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 8c20619..7efdcbe 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: os: [ubuntu-latest,windows-latest, macOS-latest] - java: [8, 11, 14, 15, 16, 17-ea] + java: [8, 11, 16, 17-ea] jdk: [adopt-hotspot, zulu, adopt-openj9] fail-fast: false @@ -45,7 +45,7 @@ jobs: maven-${{ matrix.os }}- - name: Set up JDK - uses: actions/setup-java@v2.1.0 + uses: actions/setup-java@v2.2.0 with: distribution: ${{ matrix.jdk }} java-version: ${{ matrix.java }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 27e418a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: java -jdk: - - openjdk8 - - openjdk9 - - openjdk11 - - openjdk12 - - openjdk13 - - openjdk-ea - -dist: trusty - -script: "mvn --show-version --errors --batch-mode -Prun-its clean verify" - -cache: - directories: - - $HOME/.m2 -branches: - except: - - gh-pages -notifications: - email: - - rfscholte@apache.org diff --git a/README.md b/README.md index 38b376c..b965e90 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Plexus Language -[![Build Status](https://travis-ci.org/codehaus-plexus/plexus-languages.svg?branch=master)](https://travis-ci.org/codehaus-plexus/plexus-languages) +![Build Status](https://github.com/codehaus-plexus/plexus-languages/workflows/GitHub%20CI/badge.svg) Plexus Languages: diff --git a/plexus-java/pom.xml b/plexus-java/pom.xml index ea0b014..423257b 100644 --- a/plexus-java/pom.xml +++ b/plexus-java/pom.xml @@ -81,6 +81,18 @@ true + + org.hamcrest + hamcrest + 2.2 + test + + + org.hamcrest + hamcrest-library + 2.2 + test + junit junit @@ -90,7 +102,7 @@ org.mockito mockito-core - 3.11.2 + 3.12.1 test 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/AsmModuleInfoParser.java index 2f6d606..d20ba74 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/AsmModuleInfoParser.java @@ -25,7 +25,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; @@ -60,10 +62,19 @@ public ModuleVisitor visitModule( String name, int arg1, String arg2 ) @Override public void visitRequire( String module, int access, String version ) { - if ( ( access & Opcodes.ACC_STATIC_PHASE ) != 0 ) + if ( ( access & ( Opcodes.ACC_STATIC_PHASE | Opcodes.ACC_TRANSITIVE ) ) != 0 ) { - wrapper.builder.requires​( Collections.singleton( JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), - module ); + Set modifiers = new LinkedHashSet<>(); + if ( ( access & Opcodes.ACC_STATIC_PHASE ) != 0 ) + { + modifiers.add( JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ); + } + if ( ( access & Opcodes.ACC_TRANSITIVE ) != 0 ) + { + modifiers.add( JavaModuleDescriptor.JavaRequires.JavaModifier.TRANSITIVE ); + } + + wrapper.builder.requires​( modifiers, module ); } else { 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 4e861fe..d4a7f82 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 @@ -26,7 +26,7 @@ import java.util.Set; /** - * Simple representation of a Module containing info required by this plugin. + * Simple representation of a ModuleDescriptor containing info required by this plugin. * It will provide only methods matching Java 9 ModuleDescriptor, so once Java 9 is required, we can easily switch * * @author Robert Scholte @@ -231,7 +231,7 @@ public JavaModuleDescriptor build() } /** - * Represents Module.Requires + * Represents ModuleDescriptor.Requires * * @author Robert Scholte * @since 1.0.0 @@ -265,14 +265,14 @@ public String name() } /** - * Represents Module.Requires.Modifier + * Represents ModuleDescriptor.Requires.Modifier * * @author Robert Scholte * @since 1.0.0 */ public static enum JavaModifier { - STATIC + STATIC, TRANSITIVE } @Override @@ -311,7 +311,7 @@ public boolean equals( Object obj ) } /** - * Represents Module.Requires + * Represents ModuleDescriptor.Exports * * @author Robert Scholte * @since 1.0.0 @@ -380,7 +380,7 @@ public boolean equals( Object obj ) } /** - * Represents Module.Provides + * Represents ModuleDescriptor.Provides * * @author Robert Scholte * @since 1.0.0 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 94c094c..3ec20e8 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 @@ -261,6 +261,7 @@ public String extract( Path path ) Collections.unmodifiableMap( availableNamedModules ), Collections.unmodifiableMap( availableProviders ), requiredNamedModules, + true, true ); } @@ -270,7 +271,8 @@ public String extract( Path path ) Collections.unmodifiableMap( availableNamedModules ), Collections.unmodifiableMap( availableProviders ), requiredNamedModules, - request.isIncludeStatic() ); + request.isIncludeStatic(), + true ); } // in case of identical module names, first one wins @@ -398,13 +400,19 @@ private void selectRequires( JavaModuleDescriptor module, Map availableModules, Map> availableProviders, Set namedModules, - boolean includeStatic ) + boolean includeStatic, + boolean includeTransitive ) { for ( JavaModuleDescriptor.JavaRequires requires : module.requires() ) { + // includeTransitive is one level deeper compared to includeStatic if ( includeStatic || !requires.modifiers​().contains( JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ) ) { - selectModule( requires.name(), availableModules, availableProviders, namedModules, false ); + selectModule( requires.name(), availableModules, availableProviders, namedModules, false, includeStatic ); + } + else if ( includeTransitive && requires.modifiers​().contains( JavaModuleDescriptor.JavaRequires.JavaModifier.TRANSITIVE ) ) + { + selectModule( requires.name(), availableModules, availableProviders, namedModules, false, includeStatic ); } } @@ -418,7 +426,7 @@ private void selectRequires( JavaModuleDescriptor module, if ( requiredModule != null && namedModules.add( providerModule ) ) { - selectRequires( requiredModule, availableModules, availableProviders, namedModules, false ); + selectRequires( requiredModule, availableModules, availableProviders, namedModules, false, includeStatic ); } } } @@ -426,13 +434,13 @@ private void selectRequires( JavaModuleDescriptor module, } private void selectModule( String module, Map availableModules, Map> availableProviders, - Set namedModules, boolean includeStatic ) + Set namedModules, boolean includeStatic, boolean includeTransitive ) { JavaModuleDescriptor requiredModule = availableModules.get( module ); if ( requiredModule != null && namedModules.add( module ) ) { - selectRequires( requiredModule, availableModules, availableProviders, namedModules, includeStatic ); + selectRequires( requiredModule, availableModules, availableProviders, namedModules, includeStatic, includeTransitive ); } } diff --git a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java index 248ef9a..56508f9 100644 --- a/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java +++ b/plexus-java/src/main/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParser.java @@ -24,6 +24,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -56,10 +57,19 @@ public org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor fromSourcePa for ( JavaModuleDescriptor.JavaRequires requires : descriptor.getRequires() ) { - if ( requires.isStatic() ) + if ( requires.isStatic() || requires.isTransitive() ) { - builder.requires​( Collections.singleton( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), - requires.getModule().getName() ); + Set modifiers = + new LinkedHashSet<>( 2 ); + if ( requires.isStatic() ) + { + modifiers.add( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ); + } + if ( requires.isTransitive() ) + { + modifiers.add( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.TRANSITIVE ); + } + builder.requires​( modifiers , requires.getModule().getName() ); } else { 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 index b3a7007..a6752e7 100644 --- 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 @@ -24,6 +24,8 @@ import java.lang.module.ModuleDescriptor; import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.Builder; @@ -38,10 +40,19 @@ JavaModuleDescriptor parse( InputStream in ) throws IOException for ( ModuleDescriptor.Requires requires : descriptor.requires() ) { - if ( requires.modifiers().contains( ModuleDescriptor.Requires.Modifier.STATIC ) ) + if ( requires.modifiers().contains( ModuleDescriptor.Requires.Modifier.STATIC ) + || requires.modifiers().contains( ModuleDescriptor.Requires.Modifier.TRANSITIVE ) ) { - builder.requires​( Collections.singleton( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), - requires.name() ); + Set modifiers = new LinkedHashSet<>(); + if ( requires.modifiers().contains( ModuleDescriptor.Requires.Modifier.STATIC ) ) + { + modifiers.add( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ); + } + if ( requires.modifiers().contains( ModuleDescriptor.Requires.Modifier.TRANSITIVE ) ) + { + modifiers.add( org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier.TRANSITIVE ); + } + builder.requires​( modifiers, requires.name() ); } else { diff --git a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java index 9279540..a25bfcd 100644 --- a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java +++ b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/BinaryModuleInfoParserTest.java @@ -1,6 +1,5 @@ package org.codehaus.plexus.languages.java.jpms; -import static org.junit.Assert.assertArrayEquals; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -21,9 +20,12 @@ * under the License. */ +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; import java.io.IOException; import java.io.InputStream; @@ -177,4 +179,26 @@ public void testProvides() throws Exception } + @Test + public void testRequires() throws Exception + { + try ( InputStream is = Files.newInputStream( Paths.get( "src/test/resources/dir.descriptor.requires/out/module-info.class" ) ) ) + { + JavaModuleDescriptor descriptor = parser.parse( is ); + + assertNotNull( descriptor); + assertThat( descriptor.requires().size(), is( 5 ) ); + + Set expectedRequires = JavaModuleDescriptor.newAutomaticModule( "_" ) + .requires( "java.base" ) + .requires( "mod_r" ) + .requires​( Collections.singleton( JavaRequires.JavaModifier.STATIC ), "mod_r_s" ) + .requires​( Collections.singleton( JavaRequires.JavaModifier.TRANSITIVE ), "mod_r_t" ) + .requires​( new HashSet( Arrays.asList( JavaRequires.JavaModifier.STATIC, JavaRequires.JavaModifier.TRANSITIVE ) ), "mod_r_s_t" ) + .build() + .requires(); + + assertEquals( expectedRequires, descriptor.requires() ); + } + } } 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 10c5961..1ed6d0b 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 @@ -30,6 +30,9 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; + +import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaRequires.JavaModifier; import org.junit.Before; import org.junit.Test; @@ -377,7 +380,7 @@ public void testTransitiveStatic() throws Exception when( qdoxParser.fromSourcePath( moduleA ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleA" ) .requires( "moduleB" ).build() ); when( asmParser.getModuleDescriptor( moduleB ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleB" ) - .requires​( Collections.singleton( JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), "moduleC" ).build() ); + .requires​( Collections.singleton( JavaModifier.STATIC ), "moduleC" ).build() ); when( asmParser.getModuleDescriptor( moduleC ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleC" ).build() ); @@ -399,10 +402,10 @@ public void testDirectStatic() throws Exception when( qdoxParser.fromSourcePath( moduleA ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleA" ) .requires( "moduleB" ) - .requires​( Collections.singleton( JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), "moduleD") + .requires​( Collections.singleton( JavaModifier.STATIC ), "moduleD") .build() ); when( asmParser.getModuleDescriptor( moduleB ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleB" ) - .requires​( Collections.singleton( JavaModuleDescriptor.JavaRequires.JavaModifier.STATIC ), "moduleC" ) + .requires​( Collections.singleton( JavaModifier.STATIC ), "moduleC" ) .build() ); when( asmParser.getModuleDescriptor( moduleC ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleC" ).build() ); when( asmParser.getModuleDescriptor( moduleD ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleD" ).build() ); @@ -443,5 +446,37 @@ public void testDuplicateModule() throws Exception assertThat( result.getClasspathElements().size(), is( 0 ) ); assertThat( result.getPathExceptions().size(), is( 0 ) ); } + + @Test + public void testStaticTransitive() throws Exception + { + Path moduleA = Paths.get( "src/test/resources/mock/module-info.java" ); // some file called module-info.java + Path moduleB = Paths.get( "src/test/resources/mock/jar0.jar" ); // any existing file + Path moduleC = Paths.get( "src/test/resources/mock/jar1.jar" ); // any existing file + Path moduleD = Paths.get( "src/test/resources/mock/jar2.jar" ); // any existing file + ResolvePathsRequest request = ResolvePathsRequest.ofPaths( moduleB, moduleC, moduleD ).setMainModuleDescriptor( moduleA ); + + when( qdoxParser.fromSourcePath( moduleA ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleA" ) + .requires( "moduleB" ) + .build() ); + when( asmParser.getModuleDescriptor( moduleB ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleB" ) + .requires​( new HashSet( Arrays.asList( JavaModifier.STATIC,JavaModifier.TRANSITIVE ) ), "moduleC" ) + .build() ); + when( asmParser.getModuleDescriptor( moduleC ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleC" ) + .requires​( new HashSet( Arrays.asList( JavaModifier.STATIC,JavaModifier.TRANSITIVE ) ), "moduleD" ) + .build() ); + when( asmParser.getModuleDescriptor( moduleD ) ).thenReturn( JavaModuleDescriptor.newModule( "moduleD" ).build() ); + + + ResolvePathsResult result = locationManager.resolvePaths( request ); + assertThat( result.getPathElements().size(), is( 3 ) ); + assertThat( result.getModulepathElements().size(), is( 2 ) ); + assertThat( result.getModulepathElements().containsKey( moduleB ), is( true ) ); + assertThat( result.getModulepathElements().containsKey( moduleC ), is( true ) ); + assertThat( result.getClasspathElements().size(), is( 1 ) ); + assertThat( result.getClasspathElements().contains( moduleD ), is( true ) ); + assertThat( result.getPathExceptions().size(), is( 0 ) ); + } + } diff --git a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java index bf34c72..36037fa 100644 --- a/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java +++ b/plexus-java/src/test/java/org/codehaus/plexus/languages/java/jpms/SourceModuleInfoParserTest.java @@ -50,10 +50,22 @@ public void test() throws Exception JavaRequires requires = requiresIter.next(); assertEquals( "d.e", requires.name() ); assertFalse( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); + assertFalse( requires.modifiers​().contains( JavaRequires.JavaModifier.TRANSITIVE ) ); requires = requiresIter.next(); assertEquals( "s.d.e", requires.name() ); assertTrue( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); + assertFalse( requires.modifiers​().contains( JavaRequires.JavaModifier.TRANSITIVE ) ); + + requires = requiresIter.next(); + assertEquals( "t.d.e", requires.name() ); + assertFalse( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); + assertTrue( requires.modifiers​().contains( JavaRequires.JavaModifier.TRANSITIVE ) ); + + requires = requiresIter.next(); + assertEquals( "s.t.d.e", requires.name() ); + assertTrue( requires.modifiers​().contains( JavaRequires.JavaModifier.STATIC ) ); + assertTrue( requires.modifiers​().contains( JavaRequires.JavaModifier.TRANSITIVE ) ); Iterator exportsIter = moduleDescriptor.exports().iterator(); diff --git a/plexus-java/src/test/resources/dir.descriptor.requires/out/module-info.class b/plexus-java/src/test/resources/dir.descriptor.requires/out/module-info.class new file mode 100644 index 0000000..004ba1a Binary files /dev/null and b/plexus-java/src/test/resources/dir.descriptor.requires/out/module-info.class differ diff --git a/plexus-java/src/test/resources/src.dir/module-info.java b/plexus-java/src/test/resources/src.dir/module-info.java index d950a65..34fca79 100644 --- a/plexus-java/src/test/resources/src.dir/module-info.java +++ b/plexus-java/src/test/resources/src.dir/module-info.java @@ -5,6 +5,8 @@ { requires d.e; requires static s.d.e; + requires transitive t.d.e; + requires static transitive s.t.d.e; exports f.g; exports f.g.h to i.j, k.l.m;