MNG-5795: Verify that core extensions can be retrieved when a mirror is used that requires basic auth.

This commit is contained in:
Jason van Zyl 2015-04-02 00:18:55 -04:00
parent 2fee3bbc73
commit 030eb3cf6f
5 changed files with 387 additions and 90 deletions

View File

@ -1,25 +1,18 @@
<?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
<!-- 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. -->
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/xsd/maven-4.0.0.xsd">
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@ -33,40 +26,31 @@ under the License.
<name>Maven ITs</name>
<description>The effective Maven Integration Tests suite.</description>
<!--
By default, the project just packages the tests in an artifact. To actually run them, activate the profile "run-its":
mvn clean test -Prun-its
This will subject the Maven version running the build to the integration tests. If you would like to test a different
Maven distribution, you can use the system property "mavenHome" to specify the path of the Maven distribution to test:
mvn clean test -Prun-its -DmavenHome=<maven-under-test>
Alternatively, you can just specify the version of a previously installed/deployed Maven distribution which will be
downloaded, unpacked and tested:
mvn clean test -Prun-its -DmavenVersion=2.2.1
It's also possible to point the ITs at an already downloaded Maven distribution:
mvn clean test -Prun-its -DmavenDistro=<path-to-bin-archive>
To run the ITs using embedded Maven 3.x, additionally activate the profile "embedded".
ITs that don't require to fork Maven can also be run from the IDE using the Maven projects from the workspace if the
Maven dependencies are added to the test class path.
If you're behind a proxy, use the system properties proxy.host, proxy.port, proxy.user and proxy.pass to specify the
required proxy setup for the ITs. Alternatively, set the system property maven.it.central to a URL of a local
repository manager that proxies the required artifacts.
-->
<!-- By default, the project just packages the tests in an artifact. To
actually run them, activate the profile "run-its": mvn clean test -Prun-its
This will subject the Maven version running the build to the integration
tests. If you would like to test a different Maven distribution, you can
use the system property "mavenHome" to specify the path of the Maven distribution
to test: mvn clean test -Prun-its -DmavenHome=<maven-under-test> Alternatively,
you can just specify the version of a previously installed/deployed Maven
distribution which will be downloaded, unpacked and tested: mvn clean test
-Prun-its -DmavenVersion=2.2.1 It's also possible to point the ITs at an
already downloaded Maven distribution: mvn clean test -Prun-its -DmavenDistro=<path-to-bin-archive>
To run the ITs using embedded Maven 3.x, additionally activate the profile
"embedded". ITs that don't require to fork Maven can also be run from the
IDE using the Maven projects from the workspace if the Maven dependencies
are added to the test class path. If you're behind a proxy, use the system
properties proxy.host, proxy.port, proxy.user and proxy.pass to specify the
required proxy setup for the ITs. Alternatively, set the system property
maven.it.central to a URL of a local repository manager that proxies the
required artifacts. -->
<properties>
<surefireMemory>-Xmx384m -XX:MaxPermSize=192m</surefireMemory>
<!-- The original Maven distribution to test. -->
<mavenHome>${maven.home}</mavenHome>
<!-- The (possibly instrumented copy of the) Maven distribution we actually use for the tests. -->
<!-- The (possibly instrumented copy of the) Maven distribution we actually
use for the tests. -->
<preparedMavenHome>${mavenHome}</preparedMavenHome>
<!-- default properties used to filter the global settings -->
<maven.it.central>http://repo1.maven.org/maven2</maven.it.central>
@ -77,6 +61,7 @@ under the License.
<proxy.user></proxy.user>
<proxy.pass></proxy.pass>
<slf4jVersion>1.6.1</slf4jVersion>
<jetty9Version>9.0.4.v20130625</jetty9Version>
</properties>
<dependencies>
@ -85,7 +70,7 @@ under the License.
<artifactId>junit</artifactId>
<version>4.8.2</version>
<!-- NOTE: Use compile scope for transitivity. -->
</dependency>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
@ -96,34 +81,63 @@ under the License.
<groupId>org.apache.maven.its</groupId>
<artifactId>maven-it-helper</artifactId>
<version>2.1-SNAPSHOT</version>
<!-- TODO: not transitive in tests artifact, so must be left in main scope
<scope>test</scope>
-->
<!-- TODO: not transitive in tests artifact, so must be left in main
scope <scope>test</scope> -->
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-verifier</artifactId>
<!-- TODO: not transitive in tests artifact, so must be left in main scope
<scope>test</scope>
-->
<!-- TODO: not transitive in tests artifact, so must be left in main
scope <scope>test</scope> -->
</dependency>
<!--
Should be fine to introduce this here, even if we use the embedder as it should be using an isolated classloader
Used to simplify tests that provide a test HTTP server.
-->
<!-- Should be fine to introduce this here, even if we use the embedder
as it should be using an isolated classloader Used to simplify tests that
provide a test HTTP server. -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<version>6.1.14</version>
<!-- TODO: not transitive in tests artifact, so must be left in main scope
<scope>test</scope>
-->
<!-- TODO: not transitive in tests artifact, so must be left in main
scope <scope>test</scope> -->
<exclusions>
<exclusion>
<artifactId>servlet-api-2.5</artifactId>
<groupId>org.mortbay.jetty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-shared-utils</artifactId>
<version>0.6</version>
</dependency>
</dependency>
<!-- Jetty9 server for testing -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty9Version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${jetty9Version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty9Version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet</artifactId>
<version>3.0.0.v201112011016</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0</version>
</dependency>
</dependencies>
<build>
@ -178,19 +192,19 @@ under the License.
<profiles>
<profile>
<id>parallel</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>classes</parallel>
<threadCount>6</threadCount>
</configuration>
</plugin>
</plugins>
</build>
<id>parallel</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>classes</parallel>
<threadCount>6</threadCount>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>run-its</id>
@ -241,7 +255,8 @@ under the License.
<configuration>
<systemProperties combine.children="append">
<property>
<!-- Pass this through to the tests (if set!) to have them pick the right repository -->
<!-- Pass this through to the tests (if set!) to have them
pick the right repository -->
<name>maven.repo.local</name>
<value>${maven.repo.local}</value>
</property>
@ -265,7 +280,8 @@ under the License.
<configuration>
<systemProperties combine.children="append">
<property>
<!-- Pass this through to the tests (if set!) to have them pick the right repository layout -->
<!-- Pass this through to the tests (if set!) to have them
pick the right repository layout -->
<name>maven.repo.local.layout</name>
<value>${maven.repo.local.layout}</value>
</property>
@ -284,8 +300,10 @@ under the License.
<configuration>
<skip>false</skip>
<forkMode>once</forkMode>
<argLine>${surefireMemory} -Dcom.sun.management.jmxremote=true</argLine>
<!-- NOTE: Maven plugins have access to the system class path so keep it clean -->
<argLine>${surefireMemory}
-Dcom.sun.management.jmxremote=true</argLine>
<!-- NOTE: Maven plugins have access to the system class path
so keep it clean -->
<useSystemClassLoader>false</useSystemClassLoader>
<systemProperties combine.children="append">
<property>
@ -360,11 +378,14 @@ under the License.
</goals>
<configuration>
<tasks>
<delete dir="${mavenHome}"/>
<unzip src="${project.build.directory}/maven-bin.zip" dest="${mavenHome}">
<globmapper from="apache-maven-${mavenVersion}/*" to="*" handledirsep="true" />
<delete dir="${mavenHome}" />
<unzip src="${project.build.directory}/maven-bin.zip"
dest="${mavenHome}">
<globmapper from="apache-maven-${mavenVersion}/*"
to="*" handledirsep="true" />
</unzip>
<chmod dir="${mavenHome}/bin" perm="ugo+rx" includes="mvn,mvnDebug"/>
<chmod dir="${mavenHome}/bin" perm="ugo+rx"
includes="mvn,mvnDebug" />
</tasks>
</configuration>
</execution>
@ -404,11 +425,13 @@ under the License.
</goals>
<configuration>
<tasks>
<delete dir="${mavenHome}"/>
<delete dir="${mavenHome}" />
<unzip src="${mavenDistro}" dest="${mavenHome}">
<regexpmapper from="^([^/]+)/(.*)$" to="\2" handledirsep="true" />
<regexpmapper from="^([^/]+)/(.*)$"
to="\2" handledirsep="true" />
</unzip>
<chmod dir="${mavenHome}/bin" perm="ugo+rx" includes="mvn,mvnDebug"/>
<chmod dir="${mavenHome}/bin" perm="ugo+rx"
includes="mvn,mvnDebug" />
</tasks>
</configuration>
</execution>
@ -444,11 +467,12 @@ under the License.
</goals>
<configuration>
<tasks>
<delete dir="${preparedMavenHome}"/>
<delete dir="${preparedMavenHome}" />
<copy todir="${preparedMavenHome}" overwrite="true">
<fileset dir="${mavenHome}"/>
<fileset dir="${mavenHome}" />
</copy>
<chmod dir="${preparedMavenHome}/bin" perm="ugo+rx" includes="mvn,mvnDebug"/>
<chmod dir="${preparedMavenHome}/bin" perm="ugo+rx"
includes="mvn,mvnDebug" />
</tasks>
</configuration>
</execution>

View File

@ -0,0 +1,199 @@
package org.apache.maven.it;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Collections;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
/**
* An HTTP server that handles all requests on a given port from a specified source, optionally secured using BASIC auth by providing a username and password.
*
* The source can either be a URL or a directory. When a request is made the request is satisfied from the provided source.
*
* @author Jason van Zyl
*
*/
public class HttpServer {
private final Server server;
private final StreamSource source;
private final String username;
private final String password;
public HttpServer(int port, String username, String password, StreamSource source) {
this.username = username;
this.password = password;
this.source = source;
this.server = server(port);
}
public void start() throws Exception {
server.start();
//server.join();
}
public void stop() throws Exception {
server.stop();
}
public int port() {
return ((ServerConnector) server.getConnectors()[0]).getLocalPort();
}
private Server server(int port) {
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(500);
Server server = new Server(threadPool);
server.addBean(new ScheduledExecutorScheduler());
ServerConnector http = new ServerConnector(server);
http.setPort(port);
http.setIdleTimeout(30000);
server.addConnector(http);
StreamSourceHandler handler = new StreamSourceHandler(source);
if (username != null && password != null) {
HashLoginService loginService = new HashLoginService("Test Server");
loginService.putUser(username, new Password(password), new String[] {
"user"
});
server.addBean(loginService);
ConstraintSecurityHandler security = new ConstraintSecurityHandler();
server.setHandler(security);
Constraint constraint = new Constraint();
constraint.setName("auth");
constraint.setAuthenticate(true);
constraint.setRoles(new String[] {
"user", "admin"
});
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec("/*");
mapping.setConstraint(constraint);
security.setConstraintMappings(Collections.singletonList(mapping));
security.setAuthenticator(new BasicAuthenticator());
security.setLoginService(loginService);
security.setHandler(handler);
} else {
server.setHandler(handler);
}
return server;
}
public static HttpServerBuilder builder() {
return new HttpServerBuilder();
}
public static class HttpServerBuilder {
private int port;
private String username;
private String password;
private StreamSource source;
public HttpServerBuilder port(int port) {
this.port = port;
return this;
}
public HttpServerBuilder username(String username) {
this.username = username;
return this;
}
public HttpServerBuilder password(String password) {
this.password = password;
return this;
}
public HttpServerBuilder source(final String source) {
this.source = new StreamSource() {
public InputStream stream(String path) throws IOException {
return new URL(String.format("%s/%s", source, path)).openStream();
}
};
return this;
}
public HttpServerBuilder source(final File source) {
this.source = new StreamSource() {
public InputStream stream(String path) throws IOException {
return new FileInputStream(new File(source, path));
}
};
return this;
}
public HttpServer build() {
return new HttpServer(port, username, password, source);
}
}
public static interface StreamSource {
InputStream stream(String path) throws IOException;
}
public static class StreamSourceHandler extends AbstractHandler {
private final StreamSource source;
public StreamSourceHandler(StreamSource source) {
this.source = source;
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setContentType("application/octet-stream");
response.setStatus(HttpServletResponse.SC_OK);
Closer closer = Closer.create();
try {
// /target --> target
InputStream in = closer.register(source.stream(target.substring(1)));
OutputStream out = closer.register(response.getOutputStream());
ByteStreams.copy(in, out);
} catch (Throwable e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
baseRequest.setHandled(true);
}
}
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.builder() //
.port(0) //
.username("maven") //
.password("secret") //
.source(new File("/tmp/repo")) //
.build();
server.start();
}
}

View File

@ -1,6 +1,7 @@
package org.apache.maven.it;
import java.io.File;
import java.util.Properties;
import org.apache.maven.it.util.ResourceExtractor;
@ -30,6 +31,36 @@ public class MavenITmng5771CoreExtensionsTest
verifier.resetStreams();
}
public void testCoreExtensionRetrievedFromAMirrorWithBasicAuthentication()
throws Exception
{
File testDir = ResourceExtractor.simpleExtractResources( getClass(), "/mng-5771-core-extensions" );
HttpServer server = HttpServer.builder() //
.port(0) //
.username("maven") //
.password("secret") //
.source(new File(testDir, "repo")) //
.build();
server.start();
Verifier verifier = newVerifier( testDir.getAbsolutePath() );
Properties properties = verifier.newDefaultFilterProperties();
properties.setProperty("@port@", Integer.toString(server.port()));
verifier.filterFile( "settings-template-mirror-auth.xml", "settings.xml", "UTF-8", properties );
verifier = newVerifier( new File( testDir, "client" ).getAbsolutePath() );
verifier.deleteDirectory( "target" );
verifier.deleteArtifacts( "org.apache.maven.its.it-core-extensions" );
verifier.getCliOptions().add( "-s" );
verifier.getCliOptions().add( new File( testDir, "settings.xml" ).getAbsolutePath() );
verifier.executeGoal( "validate" );
verifier.verifyErrorFreeLog();
verifier.resetStreams();
server.stop();
}
public void testCoreExtensionNoDescriptor()
throws Exception
{

View File

@ -0,0 +1,41 @@
<settings>
<servers>
<server>
<id>repoman</id>
<username>maven</username>
<password>secret</password>
</server>
</servers>
<mirrors>
<mirror>
<id>repoman</id>
<name>Mirror</name>
<url>http://localhost:@port@</url>
<mirrorOf>external:*</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>development</id>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>development</activeProfile>
</activeProfiles>
</settings>

View File

@ -63,6 +63,8 @@ under the License.
<maven.site.path>core-its</maven.site.path>
<maven.site.cache>${user.home}/maven-sites</maven.site.cache>
<rat.ignoreErrors>true</rat.ignoreErrors>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<modules>