151e2646dSJens Baumgart /* 25c5f7c6bSMatthias Sohn * Copyright (C) 2010, 2017 Google Inc. and others 351e2646dSJens Baumgart * 45c5f7c6bSMatthias Sohn * This program and the accompanying materials are made available under the 55c5f7c6bSMatthias Sohn * terms of the Eclipse Distribution License v. 1.0 which is available at 65c5f7c6bSMatthias Sohn * https://www.eclipse.org/org/documents/edl-v10.php. 751e2646dSJens Baumgart * 85c5f7c6bSMatthias Sohn * SPDX-License-Identifier: BSD-3-Clause 951e2646dSJens Baumgart */ 1051e2646dSJens Baumgart 1151e2646dSJens Baumgart package org.eclipse.jgit.junit.http; 1251e2646dSJens Baumgart 13d9e07a57SRobin Rosenberg import static org.junit.Assert.assertFalse; 14d9e07a57SRobin Rosenberg import static org.junit.Assert.assertTrue; 15d9e07a57SRobin Rosenberg 16e17bfc96SThomas Wolf import java.io.File; 17e17bfc96SThomas Wolf import java.io.IOException; 1851e2646dSJens Baumgart import java.net.InetAddress; 1951e2646dSJens Baumgart import java.net.URI; 2051e2646dSJens Baumgart import java.net.URISyntaxException; 2151e2646dSJens Baumgart import java.net.UnknownHostException; 22e17bfc96SThomas Wolf import java.nio.file.Files; 2351e2646dSJens Baumgart import java.util.ArrayList; 2451e2646dSJens Baumgart import java.util.List; 257ac1bfc8SThomas Wolf import java.util.Locale; 26*0f442d70SThomas Wolf import java.util.Map; 2733bbbc3cSMat Booth import java.util.concurrent.ConcurrentHashMap; 2851e2646dSJens Baumgart 29e17bfc96SThomas Wolf import org.eclipse.jetty.http.HttpVersion; 3033bbbc3cSMat Booth import org.eclipse.jetty.security.AbstractLoginService; 3151e2646dSJens Baumgart import org.eclipse.jetty.security.Authenticator; 3251e2646dSJens Baumgart import org.eclipse.jetty.security.ConstraintMapping; 3351e2646dSJens Baumgart import org.eclipse.jetty.security.ConstraintSecurityHandler; 3451e2646dSJens Baumgart import org.eclipse.jetty.security.authentication.BasicAuthenticator; 3551e2646dSJens Baumgart import org.eclipse.jetty.server.Connector; 36a24b7c3cSMatthias Sohn import org.eclipse.jetty.server.HttpConfiguration; 37a24b7c3cSMatthias Sohn import org.eclipse.jetty.server.HttpConnectionFactory; 3851e2646dSJens Baumgart import org.eclipse.jetty.server.Server; 39a24b7c3cSMatthias Sohn import org.eclipse.jetty.server.ServerConnector; 40e17bfc96SThomas Wolf import org.eclipse.jetty.server.SslConnectionFactory; 4151e2646dSJens Baumgart import org.eclipse.jetty.server.handler.ContextHandlerCollection; 4251e2646dSJens Baumgart import org.eclipse.jetty.servlet.ServletContextHandler; 4324a0f47eSMatthias Sohn import org.eclipse.jetty.util.security.Constraint; 44da6fa14fSDavid Pursehouse import org.eclipse.jetty.util.security.Password; 45e17bfc96SThomas Wolf import org.eclipse.jetty.util.ssl.SslContextFactory; 4651e2646dSJens Baumgart import org.eclipse.jgit.transport.URIish; 4751e2646dSJens Baumgart 4851e2646dSJens Baumgart /** 4951e2646dSJens Baumgart * Tiny web application server for unit testing. 5051e2646dSJens Baumgart * <p> 5151e2646dSJens Baumgart * Tests should start the server in their {@code setUp()} method and stop the 5251e2646dSJens Baumgart * server in their {@code tearDown()} method. Only while started the server's 5351e2646dSJens Baumgart * URL and/or port number can be obtained. 5451e2646dSJens Baumgart */ 5551e2646dSJens Baumgart public class AppServer { 5651e2646dSJens Baumgart /** Realm name for the secure access areas. */ 5751e2646dSJens Baumgart public static final String realm = "Secure Area"; 5851e2646dSJens Baumgart 5951e2646dSJens Baumgart /** Username for secured access areas. */ 6051e2646dSJens Baumgart public static final String username = "agitter"; 6151e2646dSJens Baumgart 6251e2646dSJens Baumgart /** Password for {@link #username} in secured access areas. */ 6351e2646dSJens Baumgart public static final String password = "letmein"; 6451e2646dSJens Baumgart 65e17bfc96SThomas Wolf /** SSL keystore password; must have at least 6 characters. */ 66e17bfc96SThomas Wolf private static final String keyPassword = "mykeys"; 67e17bfc96SThomas Wolf 687ac1bfc8SThomas Wolf /** Role for authentication. */ 697ac1bfc8SThomas Wolf private static final String authRole = "can-access"; 707ac1bfc8SThomas Wolf 7151e2646dSJens Baumgart static { 7251e2646dSJens Baumgart // Install a logger that throws warning messages. 7351e2646dSJens Baumgart // 7451e2646dSJens Baumgart final String prop = "org.eclipse.jetty.util.log.class"; System.setProperty(prop, RecordingLogger.class.getName())7551e2646dSJens Baumgart System.setProperty(prop, RecordingLogger.class.getName()); 7651e2646dSJens Baumgart } 7751e2646dSJens Baumgart 7851e2646dSJens Baumgart private final Server server; 7951e2646dSJens Baumgart 80e17bfc96SThomas Wolf private final HttpConfiguration config; 81e17bfc96SThomas Wolf 82a24b7c3cSMatthias Sohn private final ServerConnector connector; 8351e2646dSJens Baumgart 84e17bfc96SThomas Wolf private final HttpConfiguration secureConfig; 85e17bfc96SThomas Wolf 86e17bfc96SThomas Wolf private final ServerConnector secureConnector; 87e17bfc96SThomas Wolf 8851e2646dSJens Baumgart private final ContextHandlerCollection contexts; 8951e2646dSJens Baumgart 9051e2646dSJens Baumgart private final TestRequestLog log; 9151e2646dSJens Baumgart 92e17bfc96SThomas Wolf private List<File> filesToDelete = new ArrayList<>(); 93e17bfc96SThomas Wolf 940b131b73SMatthias Sohn /** 950b131b73SMatthias Sohn * Constructor for <code>AppServer</code>. 960b131b73SMatthias Sohn */ AppServer()9751e2646dSJens Baumgart public AppServer() { 98e17bfc96SThomas Wolf this(0, -1); 993bae524fSMatthias Sohn } 1003bae524fSMatthias Sohn 1013bae524fSMatthias Sohn /** 1020b131b73SMatthias Sohn * Constructor for <code>AppServer</code>. 1030b131b73SMatthias Sohn * 1043bae524fSMatthias Sohn * @param port 105e17bfc96SThomas Wolf * the http port number; may be zero to allocate a port 106e17bfc96SThomas Wolf * dynamically 1073bae524fSMatthias Sohn * @since 4.2 1083bae524fSMatthias Sohn */ AppServer(int port)1093bae524fSMatthias Sohn public AppServer(int port) { 110e17bfc96SThomas Wolf this(port, -1); 111e17bfc96SThomas Wolf } 112e17bfc96SThomas Wolf 113e17bfc96SThomas Wolf /** 1140b131b73SMatthias Sohn * Constructor for <code>AppServer</code>. 1150b131b73SMatthias Sohn * 116e17bfc96SThomas Wolf * @param port 1177ac1bfc8SThomas Wolf * for http, may be zero to allocate a port dynamically 118e17bfc96SThomas Wolf * @param sslPort 119e17bfc96SThomas Wolf * for https,may be zero to allocate a port dynamically. If 1207ac1bfc8SThomas Wolf * negative, the server will be set up without https support. 121e17bfc96SThomas Wolf * @since 4.9 122e17bfc96SThomas Wolf */ AppServer(int port, int sslPort)123e17bfc96SThomas Wolf public AppServer(int port, int sslPort) { 124a24b7c3cSMatthias Sohn server = new Server(); 125a24b7c3cSMatthias Sohn 126e17bfc96SThomas Wolf config = new HttpConfiguration(); 127e17bfc96SThomas Wolf config.setSecureScheme("https"); 128e17bfc96SThomas Wolf config.setSecurePort(0); 129e17bfc96SThomas Wolf config.setOutputBufferSize(32768); 130a24b7c3cSMatthias Sohn 131a24b7c3cSMatthias Sohn connector = new ServerConnector(server, 132e17bfc96SThomas Wolf new HttpConnectionFactory(config)); 1333bae524fSMatthias Sohn connector.setPort(port); 134e17bfc96SThomas Wolf String ip; 135e17bfc96SThomas Wolf String hostName; 13651e2646dSJens Baumgart try { 13751e2646dSJens Baumgart final InetAddress me = InetAddress.getByName("localhost"); 138e17bfc96SThomas Wolf ip = me.getHostAddress(); 139e17bfc96SThomas Wolf connector.setHost(ip); 140e17bfc96SThomas Wolf hostName = InetAddress.getLocalHost().getCanonicalHostName(); 14151e2646dSJens Baumgart } catch (UnknownHostException e) { 14251e2646dSJens Baumgart throw new RuntimeException("Cannot find localhost", e); 14351e2646dSJens Baumgart } 14451e2646dSJens Baumgart 145e17bfc96SThomas Wolf if (sslPort >= 0) { 146e17bfc96SThomas Wolf SslContextFactory sslContextFactory = createTestSslContextFactory( 147e17bfc96SThomas Wolf hostName); 148e17bfc96SThomas Wolf secureConfig = new HttpConfiguration(config); 149e17bfc96SThomas Wolf secureConnector = new ServerConnector(server, 150e17bfc96SThomas Wolf new SslConnectionFactory(sslContextFactory, 151e17bfc96SThomas Wolf HttpVersion.HTTP_1_1.asString()), 152e17bfc96SThomas Wolf new HttpConnectionFactory(secureConfig)); 153e17bfc96SThomas Wolf secureConnector.setPort(sslPort); 154e17bfc96SThomas Wolf secureConnector.setHost(ip); 155e17bfc96SThomas Wolf } else { 156e17bfc96SThomas Wolf secureConfig = null; 157e17bfc96SThomas Wolf secureConnector = null; 158e17bfc96SThomas Wolf } 159e17bfc96SThomas Wolf 16051e2646dSJens Baumgart contexts = new ContextHandlerCollection(); 16151e2646dSJens Baumgart 16251e2646dSJens Baumgart log = new TestRequestLog(); 16351e2646dSJens Baumgart log.setHandler(contexts); 16451e2646dSJens Baumgart 165e17bfc96SThomas Wolf if (secureConnector == null) { 16651e2646dSJens Baumgart server.setConnectors(new Connector[] { connector }); 167e17bfc96SThomas Wolf } else { 168e17bfc96SThomas Wolf server.setConnectors( 169e17bfc96SThomas Wolf new Connector[] { connector, secureConnector }); 170e17bfc96SThomas Wolf } 17151e2646dSJens Baumgart server.setHandler(log); 17251e2646dSJens Baumgart } 17351e2646dSJens Baumgart createTestSslContextFactory(String hostName)174e17bfc96SThomas Wolf private SslContextFactory createTestSslContextFactory(String hostName) { 1758e356fc4SDavid Pursehouse SslContextFactory.Client factory = new SslContextFactory.Client(true); 176e17bfc96SThomas Wolf 177e17bfc96SThomas Wolf String dName = "CN=,OU=,O=,ST=,L=,C="; 178e17bfc96SThomas Wolf 179e17bfc96SThomas Wolf try { 180e17bfc96SThomas Wolf File tmpDir = Files.createTempDirectory("jks").toFile(); 181e17bfc96SThomas Wolf tmpDir.deleteOnExit(); 182e17bfc96SThomas Wolf makePrivate(tmpDir); 183e17bfc96SThomas Wolf File keyStore = new File(tmpDir, "keystore.jks"); 184e17bfc96SThomas Wolf Runtime.getRuntime().exec( 185e17bfc96SThomas Wolf new String[] { 186e17bfc96SThomas Wolf "keytool", // 187e17bfc96SThomas Wolf "-keystore", keyStore.getAbsolutePath(), // 188e17bfc96SThomas Wolf "-storepass", keyPassword, 189e17bfc96SThomas Wolf "-alias", hostName, // 190e17bfc96SThomas Wolf "-genkeypair", // 191e17bfc96SThomas Wolf "-keyalg", "RSA", // 192e17bfc96SThomas Wolf "-keypass", keyPassword, // 193e17bfc96SThomas Wolf "-dname", dName, // 194e17bfc96SThomas Wolf "-validity", "2" // 195e17bfc96SThomas Wolf }).waitFor(); 196e17bfc96SThomas Wolf keyStore.deleteOnExit(); 197e17bfc96SThomas Wolf makePrivate(keyStore); 198e17bfc96SThomas Wolf filesToDelete.add(keyStore); 199e17bfc96SThomas Wolf filesToDelete.add(tmpDir); 200e17bfc96SThomas Wolf factory.setKeyStorePath(keyStore.getAbsolutePath()); 201e17bfc96SThomas Wolf factory.setKeyStorePassword(keyPassword); 202e17bfc96SThomas Wolf factory.setKeyManagerPassword(keyPassword); 203e17bfc96SThomas Wolf factory.setTrustStorePath(keyStore.getAbsolutePath()); 204e17bfc96SThomas Wolf factory.setTrustStorePassword(keyPassword); 205e17bfc96SThomas Wolf } catch (InterruptedException | IOException e) { 206e17bfc96SThomas Wolf throw new RuntimeException("Cannot create ssl key/certificate", e); 207e17bfc96SThomas Wolf } 208e17bfc96SThomas Wolf return factory; 209e17bfc96SThomas Wolf } 210e17bfc96SThomas Wolf makePrivate(File file)211e17bfc96SThomas Wolf private void makePrivate(File file) { 212e17bfc96SThomas Wolf file.setReadable(false); 213e17bfc96SThomas Wolf file.setWritable(false); 214e17bfc96SThomas Wolf file.setExecutable(false); 215e17bfc96SThomas Wolf file.setReadable(true, true); 216e17bfc96SThomas Wolf file.setWritable(true, true); 217e17bfc96SThomas Wolf if (file.isDirectory()) { 218e17bfc96SThomas Wolf file.setExecutable(true, true); 219e17bfc96SThomas Wolf } 220e17bfc96SThomas Wolf } 221e17bfc96SThomas Wolf 22251e2646dSJens Baumgart /** 22351e2646dSJens Baumgart * Create a new servlet context within the server. 22451e2646dSJens Baumgart * <p> 22551e2646dSJens Baumgart * This method should be invoked before the server is started, once for each 22651e2646dSJens Baumgart * context the caller wants to register. 22751e2646dSJens Baumgart * 22851e2646dSJens Baumgart * @param path 22951e2646dSJens Baumgart * path of the context; use "/" for the root context if binding 23051e2646dSJens Baumgart * to the root is desired. 23151e2646dSJens Baumgart * @return the context to add servlets into. 23251e2646dSJens Baumgart */ addContext(String path)23351e2646dSJens Baumgart public ServletContextHandler addContext(String path) { 23451e2646dSJens Baumgart assertNotYetSetUp(); 23551e2646dSJens Baumgart if ("".equals(path)) 23651e2646dSJens Baumgart path = "/"; 23751e2646dSJens Baumgart 23851e2646dSJens Baumgart ServletContextHandler ctx = new ServletContextHandler(); 23951e2646dSJens Baumgart ctx.setContextPath(path); 24051e2646dSJens Baumgart contexts.addHandler(ctx); 24151e2646dSJens Baumgart 24251e2646dSJens Baumgart return ctx; 24351e2646dSJens Baumgart } 24451e2646dSJens Baumgart 2450b131b73SMatthias Sohn /** 2460b131b73SMatthias Sohn * Configure basic authentication. 2470b131b73SMatthias Sohn * 2480b131b73SMatthias Sohn * @param ctx 2490b131b73SMatthias Sohn * @param methods 2500b131b73SMatthias Sohn * @return servlet context handler 2510b131b73SMatthias Sohn */ authBasic(ServletContextHandler ctx, String... methods)2527ac1bfc8SThomas Wolf public ServletContextHandler authBasic(ServletContextHandler ctx, 2537ac1bfc8SThomas Wolf String... methods) { 25451e2646dSJens Baumgart assertNotYetSetUp(); 2557ac1bfc8SThomas Wolf auth(ctx, new BasicAuthenticator(), methods); 25651e2646dSJens Baumgart return ctx; 25751e2646dSJens Baumgart } 25851e2646dSJens Baumgart 25933bbbc3cSMat Booth static class TestMappedLoginService extends AbstractLoginService { 2609a4e8de4SMatthias Sohn private String role; 26151e2646dSJens Baumgart 262*0f442d70SThomas Wolf protected final Map<String, UserPrincipal> users = new ConcurrentHashMap<>(); 26333bbbc3cSMat Booth TestMappedLoginService(String role)264da6fa14fSDavid Pursehouse TestMappedLoginService(String role) { 2659a4e8de4SMatthias Sohn this.role = role; 2669a4e8de4SMatthias Sohn } 26751e2646dSJens Baumgart 26851e2646dSJens Baumgart @Override doStart()26933bbbc3cSMat Booth protected void doStart() throws Exception { 27033bbbc3cSMat Booth UserPrincipal p = new UserPrincipal(username, 27133bbbc3cSMat Booth new Password(password)); 27233bbbc3cSMat Booth users.put(username, p); 27333bbbc3cSMat Booth super.doStart(); 27451e2646dSJens Baumgart } 27551e2646dSJens Baumgart 27651e2646dSJens Baumgart @Override loadRoleInfo(UserPrincipal user)27733bbbc3cSMat Booth protected String[] loadRoleInfo(UserPrincipal user) { 27898cdca9bSDavid Pursehouse if (users.get(user.getName()) == null) { 27933bbbc3cSMat Booth return null; 28098cdca9bSDavid Pursehouse } 28133bbbc3cSMat Booth return new String[] { role }; 28251e2646dSJens Baumgart } 2839aa3748eSMatthias Sohn 284fc24c5e1SMatthias Sohn @Override loadUserInfo(String user)28533bbbc3cSMat Booth protected UserPrincipal loadUserInfo(String user) { 28633bbbc3cSMat Booth return users.get(user); 28751e2646dSJens Baumgart } 2889a4e8de4SMatthias Sohn } 28951e2646dSJens Baumgart createConstraintMapping()2907ac1bfc8SThomas Wolf private ConstraintMapping createConstraintMapping() { 29151e2646dSJens Baumgart ConstraintMapping cm = new ConstraintMapping(); 29251e2646dSJens Baumgart cm.setConstraint(new Constraint()); 29351e2646dSJens Baumgart cm.getConstraint().setAuthenticate(true); 29451e2646dSJens Baumgart cm.getConstraint().setDataConstraint(Constraint.DC_NONE); 2957ac1bfc8SThomas Wolf cm.getConstraint().setRoles(new String[] { authRole }); 29651e2646dSJens Baumgart cm.setPathSpec("/*"); 2977ac1bfc8SThomas Wolf return cm; 2987ac1bfc8SThomas Wolf } 2997ac1bfc8SThomas Wolf auth(ServletContextHandler ctx, Authenticator authType, String... methods)3007ac1bfc8SThomas Wolf private void auth(ServletContextHandler ctx, Authenticator authType, 3017ac1bfc8SThomas Wolf String... methods) { 3027ac1bfc8SThomas Wolf AbstractLoginService users = new TestMappedLoginService(authRole); 3037ac1bfc8SThomas Wolf List<ConstraintMapping> mappings = new ArrayList<>(); 3047ac1bfc8SThomas Wolf if (methods == null || methods.length == 0) { 3057ac1bfc8SThomas Wolf mappings.add(createConstraintMapping()); 3067ac1bfc8SThomas Wolf } else { 3077ac1bfc8SThomas Wolf for (String method : methods) { 3087ac1bfc8SThomas Wolf ConstraintMapping cm = createConstraintMapping(); 3097ac1bfc8SThomas Wolf cm.setMethod(method.toUpperCase(Locale.ROOT)); 3107ac1bfc8SThomas Wolf mappings.add(cm); 3117ac1bfc8SThomas Wolf } 3127ac1bfc8SThomas Wolf } 31351e2646dSJens Baumgart 31451e2646dSJens Baumgart ConstraintSecurityHandler sec = new ConstraintSecurityHandler(); 31551e2646dSJens Baumgart sec.setRealmName(realm); 31651e2646dSJens Baumgart sec.setAuthenticator(authType); 31751e2646dSJens Baumgart sec.setLoginService(users); 3187ac1bfc8SThomas Wolf sec.setConstraintMappings( 3192fc00af4SMichael Keppler mappings.toArray(new ConstraintMapping[0])); 32051e2646dSJens Baumgart sec.setHandler(ctx); 32151e2646dSJens Baumgart 32251e2646dSJens Baumgart contexts.removeHandler(ctx); 32351e2646dSJens Baumgart contexts.addHandler(sec); 32451e2646dSJens Baumgart } 32551e2646dSJens Baumgart 32651e2646dSJens Baumgart /** 32751e2646dSJens Baumgart * Start the server on a random local port. 32851e2646dSJens Baumgart * 32951e2646dSJens Baumgart * @throws Exception 33051e2646dSJens Baumgart * the server cannot be started, testing is not possible. 33151e2646dSJens Baumgart */ setUp()33251e2646dSJens Baumgart public void setUp() throws Exception { 33351e2646dSJens Baumgart RecordingLogger.clear(); 33451e2646dSJens Baumgart log.clear(); 33551e2646dSJens Baumgart server.start(); 336e17bfc96SThomas Wolf config.setSecurePort(getSecurePort()); 337e17bfc96SThomas Wolf if (secureConfig != null) { 338e17bfc96SThomas Wolf secureConfig.setSecurePort(getSecurePort()); 339e17bfc96SThomas Wolf } 34051e2646dSJens Baumgart } 34151e2646dSJens Baumgart 34251e2646dSJens Baumgart /** 34351e2646dSJens Baumgart * Shutdown the server. 34451e2646dSJens Baumgart * 34551e2646dSJens Baumgart * @throws Exception 34651e2646dSJens Baumgart * the server refuses to halt, or wasn't running. 34751e2646dSJens Baumgart */ tearDown()34851e2646dSJens Baumgart public void tearDown() throws Exception { 34951e2646dSJens Baumgart RecordingLogger.clear(); 35051e2646dSJens Baumgart log.clear(); 35151e2646dSJens Baumgart server.stop(); 352e17bfc96SThomas Wolf for (File f : filesToDelete) { 353e17bfc96SThomas Wolf f.delete(); 354e17bfc96SThomas Wolf } 355e17bfc96SThomas Wolf filesToDelete.clear(); 35651e2646dSJens Baumgart } 35751e2646dSJens Baumgart 35851e2646dSJens Baumgart /** 35951e2646dSJens Baumgart * Get the URI to reference this server. 36051e2646dSJens Baumgart * <p> 36151e2646dSJens Baumgart * The returned URI includes the proper host name and port number, but does 36251e2646dSJens Baumgart * not contain a path. 36351e2646dSJens Baumgart * 36451e2646dSJens Baumgart * @return URI to reference this server's root context. 36551e2646dSJens Baumgart */ getURI()36651e2646dSJens Baumgart public URI getURI() { 36751e2646dSJens Baumgart assertAlreadySetUp(); 36851e2646dSJens Baumgart String host = connector.getHost(); 36951e2646dSJens Baumgart if (host.contains(":") && !host.startsWith("[")) 37051e2646dSJens Baumgart host = "[" + host + "]"; 37151e2646dSJens Baumgart final String uri = "http://" + host + ":" + getPort(); 37251e2646dSJens Baumgart try { 37351e2646dSJens Baumgart return new URI(uri); 37451e2646dSJens Baumgart } catch (URISyntaxException e) { 37551e2646dSJens Baumgart throw new RuntimeException("Unexpected URI error on " + uri, e); 37651e2646dSJens Baumgart } 37751e2646dSJens Baumgart } 37851e2646dSJens Baumgart 3790b131b73SMatthias Sohn /** 3800b131b73SMatthias Sohn * Get port. 3810b131b73SMatthias Sohn * 3820b131b73SMatthias Sohn * @return the local port number the server is listening on. 3830b131b73SMatthias Sohn */ getPort()38451e2646dSJens Baumgart public int getPort() { 38551e2646dSJens Baumgart assertAlreadySetUp(); 386a24b7c3cSMatthias Sohn return connector.getLocalPort(); 38751e2646dSJens Baumgart } 38851e2646dSJens Baumgart 3890b131b73SMatthias Sohn /** 3900b131b73SMatthias Sohn * Get secure port. 3910b131b73SMatthias Sohn * 3920b131b73SMatthias Sohn * @return the HTTPS port or -1 if not configured. 3930b131b73SMatthias Sohn */ getSecurePort()394e17bfc96SThomas Wolf public int getSecurePort() { 395e17bfc96SThomas Wolf assertAlreadySetUp(); 396e17bfc96SThomas Wolf return secureConnector != null ? secureConnector.getLocalPort() : -1; 397e17bfc96SThomas Wolf } 398e17bfc96SThomas Wolf 3990b131b73SMatthias Sohn /** 4000b131b73SMatthias Sohn * Get requests. 4010b131b73SMatthias Sohn * 4020b131b73SMatthias Sohn * @return all requests since the server was started. 4030b131b73SMatthias Sohn */ getRequests()40451e2646dSJens Baumgart public List<AccessEvent> getRequests() { 4053b444863SDavid Pursehouse return new ArrayList<>(log.getEvents()); 40651e2646dSJens Baumgart } 40751e2646dSJens Baumgart 40851e2646dSJens Baumgart /** 4090b131b73SMatthias Sohn * Get requests. 4100b131b73SMatthias Sohn * 41151e2646dSJens Baumgart * @param base 41251e2646dSJens Baumgart * base URI used to access the server. 41351e2646dSJens Baumgart * @param path 41451e2646dSJens Baumgart * the path to locate requests for, relative to {@code base}. 41551e2646dSJens Baumgart * @return all requests which match the given path. 41651e2646dSJens Baumgart */ getRequests(URIish base, String path)41751e2646dSJens Baumgart public List<AccessEvent> getRequests(URIish base, String path) { 41851e2646dSJens Baumgart return getRequests(HttpTestCase.join(base, path)); 41951e2646dSJens Baumgart } 42051e2646dSJens Baumgart 42151e2646dSJens Baumgart /** 4220b131b73SMatthias Sohn * Get requests. 4230b131b73SMatthias Sohn * 42451e2646dSJens Baumgart * @param path 42551e2646dSJens Baumgart * the path to locate requests for. 42651e2646dSJens Baumgart * @return all requests which match the given path. 42751e2646dSJens Baumgart */ getRequests(String path)42851e2646dSJens Baumgart public List<AccessEvent> getRequests(String path) { 4293b444863SDavid Pursehouse ArrayList<AccessEvent> r = new ArrayList<>(); 43051e2646dSJens Baumgart for (AccessEvent event : log.getEvents()) { 43151e2646dSJens Baumgart if (event.getPath().equals(path)) { 43251e2646dSJens Baumgart r.add(event); 43351e2646dSJens Baumgart } 43451e2646dSJens Baumgart } 43551e2646dSJens Baumgart return r; 43651e2646dSJens Baumgart } 43751e2646dSJens Baumgart assertNotYetSetUp()43851e2646dSJens Baumgart private void assertNotYetSetUp() { 439d9e07a57SRobin Rosenberg assertFalse("server is not running", server.isRunning()); 44051e2646dSJens Baumgart } 44151e2646dSJens Baumgart assertAlreadySetUp()44251e2646dSJens Baumgart private void assertAlreadySetUp() { 443d9e07a57SRobin Rosenberg assertTrue("server is running", server.isRunning()); 44451e2646dSJens Baumgart } 44551e2646dSJens Baumgart } 446