diff --git a/its/core-it-suite/pom.xml b/its/core-it-suite/pom.xml index 6b1050b425..2a41415f56 100644 --- a/its/core-it-suite/pom.xml +++ b/its/core-it-suite/pom.xml @@ -1,25 +1,18 @@ - - 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. ---> - - + 4.0.0 @@ -33,40 +26,31 @@ under the License. Maven ITs The effective Maven Integration Tests suite. - + -Xmx384m -XX:MaxPermSize=192m ${maven.home} - + ${mavenHome} http://repo1.maven.org/maven2 @@ -77,6 +61,7 @@ under the License. 1.6.1 + 9.0.4.v20130625 @@ -85,7 +70,7 @@ under the License. junit 4.8.2 - + org.codehaus.plexus plexus-utils @@ -96,34 +81,63 @@ under the License. org.apache.maven.its maven-it-helper 2.1-SNAPSHOT - + org.apache.maven.shared maven-verifier - + - + org.mortbay.jetty jetty 6.1.14 - + + + + servlet-api-2.5 + org.mortbay.jetty + + org.apache.maven.shared maven-shared-utils 0.6 - + + + + + org.eclipse.jetty + jetty-server + ${jetty9Version} + + + org.eclipse.jetty + jetty-security + ${jetty9Version} + + + org.eclipse.jetty + jetty-util + ${jetty9Version} + + + org.eclipse.jetty.orbit + javax.servlet + 3.0.0.v201112011016 + + + com.google.guava + guava + 16.0 + @@ -178,19 +192,19 @@ under the License. - parallel - - - - org.apache.maven.plugins - maven-surefire-plugin - - classes - 6 - - - - + parallel + + + + org.apache.maven.plugins + maven-surefire-plugin + + classes + 6 + + + + run-its @@ -241,7 +255,8 @@ under the License. - + maven.repo.local ${maven.repo.local} @@ -265,7 +280,8 @@ under the License. - + maven.repo.local.layout ${maven.repo.local.layout} @@ -284,8 +300,10 @@ under the License. false once - ${surefireMemory} -Dcom.sun.management.jmxremote=true - + ${surefireMemory} + -Dcom.sun.management.jmxremote=true + false @@ -360,11 +378,14 @@ under the License. - - - + + + - + @@ -404,11 +425,13 @@ under the License. - + - + - + @@ -444,11 +467,12 @@ under the License. - + - + - + diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/HttpServer.java b/its/core-it-suite/src/test/java/org/apache/maven/it/HttpServer.java new file mode 100644 index 0000000000..e94780ac15 --- /dev/null +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/HttpServer.java @@ -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(); + } +} diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng5771CoreExtensionsTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng5771CoreExtensionsTest.java index 29f011905d..41dad74506 100644 --- a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng5771CoreExtensionsTest.java +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng5771CoreExtensionsTest.java @@ -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 { diff --git a/its/core-it-suite/src/test/resources/mng-5771-core-extensions/settings-template-mirror-auth.xml b/its/core-it-suite/src/test/resources/mng-5771-core-extensions/settings-template-mirror-auth.xml new file mode 100644 index 0000000000..60b8305de5 --- /dev/null +++ b/its/core-it-suite/src/test/resources/mng-5771-core-extensions/settings-template-mirror-auth.xml @@ -0,0 +1,41 @@ + + + + repoman + maven + secret + + + + + + repoman + Mirror + http://localhost:@port@ + external:* + + + + + + development + + + central + http://central + + + + + central + http://central + + + + + + + development + + + diff --git a/its/pom.xml b/its/pom.xml index 9d8f3faa50..a5b83ed162 100644 --- a/its/pom.xml +++ b/its/pom.xml @@ -63,6 +63,8 @@ under the License. core-its ${user.home}/maven-sites true + 1.7 + 1.7