diff --git a/pom.xml b/pom.xml index 33b7781..1c7933f 100644 --- a/pom.xml +++ b/pom.xml @@ -209,6 +209,18 @@ under the License. 4.12 test + + org.jenkins-ci + test-annotations + 1.2 + test + + + com.google.code.findbugs + jsr305 + 3.0.2 + provided + diff --git a/src/main/java/hudson/maven/MavenEmbedderCallable.java b/src/main/java/hudson/maven/MavenEmbedderCallable.java new file mode 100644 index 0000000..87508d2 --- /dev/null +++ b/src/main/java/hudson/maven/MavenEmbedderCallable.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Oleg Nenashev. + * + * Licensed 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. + */ +package hudson.maven; + +/** + * Callable interface for the Maven Embedder logic. + * + * Used primarily for testing purposes. + * @author Oleg Nenashev + */ +/*package*/ interface MavenEmbedderCallable { + + public void call() throws MavenEmbedderException; +} diff --git a/src/main/java/hudson/maven/MavenEmbedderUtils.java b/src/main/java/hudson/maven/MavenEmbedderUtils.java index 1bc5036..46ab9fd 100644 --- a/src/main/java/hudson/maven/MavenEmbedderUtils.java +++ b/src/main/java/hudson/maven/MavenEmbedderUtils.java @@ -32,6 +32,8 @@ import java.util.Properties; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.tools.ant.AntClassLoader; @@ -179,14 +181,17 @@ private static PlexusContainer buildPlexusContainer(MavenRequest mavenRequest,Co } } - - /** - * @param mavenHome + * @param mavenHome Maven Home directory * @return the maven version - * @throws MavenEmbedderException + * @throws MavenEmbedderException Operation failure */ - public static MavenInformation getMavenVersion(File mavenHome) throws MavenEmbedderException { + public static MavenInformation getMavenVersion(@Nonnull File mavenHome) throws MavenEmbedderException { + return getMavenVersion(mavenHome, null); + } + + /*package*/ static MavenInformation getMavenVersion(@Nonnull File mavenHome, + @CheckForNull MavenEmbedderCallable preopertiesPreloadHook) throws MavenEmbedderException { ClassRealm realm = buildClassRealm( mavenHome, null, null ); if (debug) { @@ -213,6 +218,9 @@ public static MavenInformation getMavenVersion(File mavenHome) throws MavenEmbed final JarEntry entry = (entryName != null && jarFile != null) ? jarFile.getJarEntry(entryName) : null; if (entry != null) { inputStream = jarFile.getInputStream(entry); + if (preopertiesPreloadHook != null) { + preopertiesPreloadHook.call(); + } Properties properties = new Properties(); properties.load( inputStream ); information = new MavenInformation( properties.getProperty( "version" ) , resource.toExternalForm() ); diff --git a/src/test/java/hudson/maven/TestMavenEmbedderUtils.java b/src/test/java/hudson/maven/TestMavenEmbedderUtils.java index a2783c5..148cd11 100644 --- a/src/test/java/hudson/maven/TestMavenEmbedderUtils.java +++ b/src/test/java/hudson/maven/TestMavenEmbedderUtils.java @@ -5,6 +5,7 @@ import org.apache.maven.artifact.versioning.ComparableVersion; import junit.framework.TestCase; +import org.jvnet.hudson.test.Issue; /** * @author Olivier Lamy @@ -48,5 +49,20 @@ public void testGetMavenVersionFromInvalidLocation() { public void testisAtLeastMavenVersion() throws Exception { assertTrue( MavenEmbedderUtils.isAtLeastMavenVersion( new File( System.getProperty( "maven.home" ) ), "3.0" ) ); assertFalse( MavenEmbedderUtils.isAtLeastMavenVersion( new File( "src/test/maven-2.2.1" ), "3.0" ) ); - } + } + + @Issue("JENKINS-42549") + public void testIfFailsInTheCaseOfRaceConditions() throws Exception { + final File mvnHome = new File( System.getProperty( "maven.home" )); + final MavenEmbedderCallable nestedLoad = new MavenEmbedderCallable() { + @Override + public void call() throws MavenEmbedderException { + // Here we invoke the nested call in order to emulate the race condition + // between multiple threads. + MavenEmbedderUtils.getMavenVersion(mvnHome); + } + }; + + MavenEmbedderUtils.getMavenVersion(mvnHome, nestedLoad); + } }