blob: 8d87dd54a586c273865f2b45af154275e398fa32 [file] [log] [blame]
package org.apache.maven.it;
import com.google.common.io.ByteStreams;
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.Connector;
import org.eclipse.jetty.server.NetworkConnector;
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 javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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;
/**
* 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 ( (NetworkConnector) server.getConnectors()[0] ).getLocalPort();
}
private Server server( int port )
{
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads( 500 );
Server server = new Server( threadPool );
server.setConnectors( new Connector[]{ new ServerConnector( server ) } );
server.addBean( new ScheduledExecutorScheduler() );
ServerConnector connector = (ServerConnector) server.getConnectors()[0];
connector.setIdleTimeout( 30_000L );
connector.setPort( port );
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()
{
@Override
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()
{
@Override
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 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;
}
@Override
public void handle( String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response )
throws IOException, ServletException
{
response.setContentType( "application/octet-stream" );
response.setStatus( HttpServletResponse.SC_OK );
try ( InputStream in = source.stream(
target.substring( 1 ) ); OutputStream out = response.getOutputStream() )
{
ByteStreams.copy( in, out );
}
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();
}
}