1 package org.apache.maven.it;
2
3 import com.google.common.io.ByteStreams;
4 import org.eclipse.jetty.security.ConstraintMapping;
5 import org.eclipse.jetty.security.ConstraintSecurityHandler;
6 import org.eclipse.jetty.security.HashLoginService;
7 import org.eclipse.jetty.security.authentication.BasicAuthenticator;
8 import org.eclipse.jetty.server.Connector;
9 import org.eclipse.jetty.server.NetworkConnector;
10 import org.eclipse.jetty.server.Request;
11 import org.eclipse.jetty.server.Server;
12 import org.eclipse.jetty.server.ServerConnector;
13 import org.eclipse.jetty.server.handler.AbstractHandler;
14 import org.eclipse.jetty.util.security.Constraint;
15 import org.eclipse.jetty.util.security.Password;
16 import org.eclipse.jetty.util.thread.QueuedThreadPool;
17 import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
18
19 import javax.servlet.ServletException;
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.net.URL;
28 import java.util.Collections;
29
30
31
32
33
34
35
36
37 public class HttpServer
38 {
39
40 private final Server server;
41
42 private final StreamSource source;
43
44 private final String username;
45
46 private final String password;
47
48 public HttpServer( int port, String username, String password, StreamSource source )
49 {
50 this.username = username;
51 this.password = password;
52 this.source = source;
53 this.server = server( port );
54 }
55
56 public void start()
57 throws Exception
58 {
59 server.start();
60
61 }
62
63 public void stop()
64 throws Exception
65 {
66 server.stop();
67 }
68
69 public int port()
70 {
71 return ( (NetworkConnector) server.getConnectors()[0] ).getLocalPort();
72 }
73
74 private Server server( int port )
75 {
76 QueuedThreadPool threadPool = new QueuedThreadPool();
77 threadPool.setMaxThreads( 500 );
78 Server server = new Server( threadPool );
79 server.setConnectors( new Connector[]{ new ServerConnector( server ) } );
80 server.addBean( new ScheduledExecutorScheduler() );
81
82 ServerConnector connector = (ServerConnector) server.getConnectors()[0];
83 connector.setIdleTimeout( 30_000L );
84 connector.setPort( port );
85
86 StreamSourceHandler handler = new StreamSourceHandler( source );
87
88 if ( username != null && password != null )
89 {
90 HashLoginService loginService = new HashLoginService( "Test Server" );
91 loginService.putUser( username, new Password( password ), new String[]{ "user" } );
92 server.addBean( loginService );
93
94 ConstraintSecurityHandler security = new ConstraintSecurityHandler();
95 server.setHandler( security );
96
97 Constraint constraint = new Constraint();
98 constraint.setName( "auth" );
99 constraint.setAuthenticate( true );
100 constraint.setRoles( new String[]{ "user", "admin" } );
101
102 ConstraintMapping mapping = new ConstraintMapping();
103 mapping.setPathSpec( "/*" );
104 mapping.setConstraint( constraint );
105
106 security.setConstraintMappings( Collections.singletonList( mapping ) );
107 security.setAuthenticator( new BasicAuthenticator() );
108 security.setLoginService( loginService );
109 security.setHandler( handler );
110 }
111 else
112 {
113 server.setHandler( handler );
114 }
115 return server;
116 }
117
118 public static HttpServerBuilder builder()
119 {
120 return new HttpServerBuilder();
121 }
122
123 public static class HttpServerBuilder
124 {
125
126 private int port;
127
128 private String username;
129
130 private String password;
131
132 private StreamSource source;
133
134 public HttpServerBuilder port( int port )
135 {
136 this.port = port;
137 return this;
138 }
139
140 public HttpServerBuilder username( String username )
141 {
142 this.username = username;
143 return this;
144 }
145
146 public HttpServerBuilder password( String password )
147 {
148 this.password = password;
149 return this;
150 }
151
152 public HttpServerBuilder source( final String source )
153 {
154 this.source = new StreamSource()
155 {
156 @Override
157 public InputStream stream( String path )
158 throws IOException
159 {
160 return new URL( String.format( "%s/%s", source, path ) ).openStream();
161 }
162 };
163 return this;
164 }
165
166 public HttpServerBuilder source( final File source )
167 {
168 this.source = new StreamSource()
169 {
170 @Override
171 public InputStream stream( String path )
172 throws IOException
173 {
174 return new FileInputStream( new File( source, path ) );
175 }
176 };
177 return this;
178 }
179
180 public HttpServer build()
181 {
182 return new HttpServer( port, username, password, source );
183 }
184 }
185
186 public interface StreamSource
187 {
188 InputStream stream( String path )
189 throws IOException;
190 }
191
192 public static class StreamSourceHandler
193 extends AbstractHandler
194 {
195
196 private final StreamSource source;
197
198 public StreamSourceHandler( StreamSource source )
199 {
200 this.source = source;
201 }
202
203 @Override
204 public void handle( String target, Request baseRequest, HttpServletRequest request,
205 HttpServletResponse response )
206 throws IOException, ServletException
207 {
208 response.setContentType( "application/octet-stream" );
209 response.setStatus( HttpServletResponse.SC_OK );
210 try ( InputStream in = source.stream(
211 target.substring( 1 ) ); OutputStream out = response.getOutputStream() )
212 {
213 ByteStreams.copy( in, out );
214 }
215 baseRequest.setHandled( true );
216 }
217 }
218
219 public static void main( String[] args )
220 throws Exception
221 {
222 HttpServer server = HttpServer.builder()
223 .port( 0 )
224 .username( "maven" )
225 .password( "secret" )
226 .source( new File( "/tmp/repo" ) )
227 .build();
228 server.start();
229 }
230 }