Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #13 from oleg-nenashev/JENKINS-42549
[JENKINS-42549, JENKINS-40621] - Handle fallout after #5
  • Loading branch information
olamy committed Jul 6, 2017
2 parents bcac0b5 + 069e84e commit 9229e4b
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 31 deletions.
12 changes: 12 additions & 0 deletions pom.xml
Expand Up @@ -209,6 +209,18 @@ under the License.
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>test-annotations</artifactId>
<version>1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
Expand Down
27 changes: 27 additions & 0 deletions 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;
}
72 changes: 42 additions & 30 deletions src/main/java/hudson/maven/MavenEmbedderUtils.java
Expand Up @@ -20,6 +20,7 @@
* under the License.
*/

import java.io.Closeable;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
Expand All @@ -32,6 +33,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;
Expand Down Expand Up @@ -179,24 +182,28 @@ 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) {
debugMavenVersion(realm);
}
ClassLoader original = Thread.currentThread().getContextClassLoader();
InputStream inputStream = null;
JarFile jarFile = null;
MavenInformation information = null;
ClassLoader original = null;
ClassRealm realm = null;
try {
realm = buildClassRealm( mavenHome, null, null );
if (debug) {
debugMavenVersion(realm);
}
original = Thread.currentThread().getContextClassLoader();

Thread.currentThread().setContextClassLoader( realm );
// TODO is this really intending to use findResource rather than getResource? Cf. https://github.com/sonatype/plexus-classworlds/pull/8
URL resource = realm.findResource( POM_PROPERTIES_PATH );
Expand All @@ -205,34 +212,39 @@ public static MavenInformation getMavenVersion(File mavenHome) throws MavenEmbed
+ "'. Are you sure that this is a valid maven home?");
}
URLConnection uc = resource.openConnection();
if (uc instanceof JarURLConnection) {
final JarURLConnection connection = (JarURLConnection)uc;
final String entryName = connection.getEntryName();
try {
jarFile = connection.getJarFile();
final JarEntry entry = (entryName != null && jarFile != null) ? jarFile.getJarEntry(entryName) : null;
if (entry != null) {
inputStream = jarFile.getInputStream(entry);
Properties properties = new Properties();
properties.load( inputStream );
information = new MavenInformation( properties.getProperty( "version" ) , resource.toExternalForm() );
}
} finally {
if (jarFile != null) {
jarFile.close();
}
uc.setUseCaches(false);
InputStream istream = uc.getInputStream();
try {
if (preopertiesPreloadHook != null) {
preopertiesPreloadHook.call();
}
}
Properties properties = new Properties();
properties.load( istream );
information = new MavenInformation( properties.getProperty( "version" ) , resource.toExternalForm() );
} finally {
istream.close();
}
} catch ( IOException e ) {
throw new MavenEmbedderException( e.getMessage(), e );
} finally {
IOUtil.close( inputStream );
Thread.currentThread().setContextClassLoader( original );
closeIt(realm);
}

return information;
}

private static final void closeIt(@CheckForNull Closeable obj) throws MavenEmbedderException {
if (obj == null) {
return;
}
try {
obj.close();
} catch(IOException ex) {
throw new MavenEmbedderException("Failed to close " + obj, ex);
}
}

public static boolean isAtLeastMavenVersion(File mavenHome, String version) throws MavenEmbedderException {
ComparableVersion found = new ComparableVersion( getMavenVersion( mavenHome ).getVersion() );
ComparableVersion testedOne = new ComparableVersion( version );
Expand Down
18 changes: 17 additions & 1 deletion src/test/java/hudson/maven/TestMavenEmbedderUtils.java
Expand Up @@ -5,6 +5,7 @@
import org.apache.maven.artifact.versioning.ComparableVersion;

import junit.framework.TestCase;
import org.jvnet.hudson.test.Issue;

/**
* @author Olivier Lamy
Expand Down Expand Up @@ -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);
}
}

0 comments on commit 9229e4b

Please sign in to comment.