diff options
Diffstat (limited to 'org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit')
7 files changed, 823 insertions, 496 deletions
diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java index aaccc66f55..36da539e8d 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AccessEvent.java @@ -1,121 +1,112 @@ /* - * Copyright (C) 2010, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.junit.http; import java.util.Collections; -import java.util.Enumeration; import java.util.Map; import java.util.TreeMap; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.util.Fields; -/** A single request made through {@link AppServer}. */ +/** + * A single request made through {@link org.eclipse.jgit.junit.http.AppServer}. + */ public class AccessEvent { private final String method; - private final String uri; + private final HttpURI uri; private final Map<String, String> requestHeaders; private final Map<String, String[]> parameters; - private final int status; + private int status; - private final Map<String, String> responseHeaders; + private Map<String, String> responseHeaders; - AccessEvent(final Request req, final Response rsp) { + AccessEvent(Request req) { method = req.getMethod(); - uri = req.getRequestURI(); + uri = req.getHttpURI(); requestHeaders = cloneHeaders(req); - parameters = clone(req.getParameterMap()); + parameters = cloneParameters(req); + } + void setResponse(Response rsp) { status = rsp.getStatus(); responseHeaders = cloneHeaders(rsp); } - private static Map<String, String> cloneHeaders(final Request req) { - Map<String, String> r = new TreeMap<String, String>(); - Enumeration hn = req.getHeaderNames(); - while (hn.hasMoreElements()) { - String key = (String) hn.nextElement(); + private static Map<String, String> cloneHeaders(Request req) { + Map<String, String> r = new TreeMap<>(); + for (HttpField f : req.getHeaders()) { + String key = f.getName(); if (!r.containsKey(key)) { - r.put(key, req.getHeader(key)); + r.put(key, f.getValue()); } } return Collections.unmodifiableMap(r); } - private static Map<String, String> cloneHeaders(final Response rsp) { - Map<String, String> r = new TreeMap<String, String>(); - Enumeration<String> hn = rsp.getHttpFields().getFieldNames(); - while (hn.hasMoreElements()) { - String key = hn.nextElement(); + private static Map<String, String> cloneHeaders(Response rsp) { + Map<String, String> r = new TreeMap<>(); + for (HttpField f : rsp.getHeaders()) { + String key = f.getName(); if (!r.containsKey(key)) { - Enumeration<String> v = rsp.getHttpFields().getValues(key); - r.put(key, v.nextElement()); + r.put(key, f.getValue()); } } return Collections.unmodifiableMap(r); } - @SuppressWarnings("unchecked") - private static Map<String, String[]> clone(Map parameterMap) { - return new TreeMap<String, String[]>(parameterMap); + private static Map<String, String[]> cloneParameters(Request req) { + Map<String, String[]> r = new TreeMap<>(); + + Fields fields; + try { + fields = Request.getParameters(req); + for (String n : fields.getNames()) { + r.put(n, fields.getValues(n).toArray(new String[0])); + } + } catch (Exception e) { + throw new RuntimeException("Failed to extract request parameters", + e); + } + return r; } - /** @return {@code "GET"} or {@code "POST"} */ + /** + * Get the <code>method</code>. + * + * @return {@code "GET"} or {@code "POST"} + */ public String getMethod() { return method; } - /** @return path of the file on the server, e.g. {@code /git/HEAD}. */ + /** + * Get <code>path</code>. + * + * @return path of the file on the server, e.g. {@code /git/HEAD}. + */ public String getPath() { - return uri; + return uri.getPath(); } /** + * Get request header + * * @param name * name of the request header to read. * @return first value of the request header; null if not sent. @@ -125,6 +116,8 @@ public class AccessEvent { } /** + * Get parameter + * * @param name * name of the request parameter to read. * @return first value of the request parameter; null if not sent. @@ -134,30 +127,41 @@ public class AccessEvent { return r != null && 1 <= r.length ? r[0] : null; } - /** @return all parameters in the request. */ + /** + * Get <code>parameters</code> + * + * @return all parameters in the request. + */ public Map<String, String[]> getParameters() { return parameters; } - /** @return HTTP status code of the response, e.g. 200, 403, 500. */ + /** + * Get the <code>status</code>. + * + * @return HTTP status code of the response, e.g. 200, 403, 500. + */ public int getStatus() { return status; } /** + * Get response header. + * * @param name * name of the response header to read. * @return first value of the response header; null if not sent. */ public String getResponseHeader(String name) { - return responseHeaders.get(name); + return responseHeaders != null ? responseHeaders.get(name) : null; } + @Override public String toString() { StringBuilder b = new StringBuilder(); b.append(method); b.append(' '); - b.append(uri); + b.append(uri.getPath()); if (!parameters.isEmpty()) { b.append('?'); boolean first = true; diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java index ce04bdf2c6..76e437bc3d 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/AppServer.java @@ -1,44 +1,11 @@ /* - * Copyright (C) 2010, 2012 Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, 2017 Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.junit.http; @@ -46,29 +13,39 @@ package org.eclipse.jgit.junit.http; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.nio.file.Files; import java.util.ArrayList; +import java.util.Collections; import java.util.List; - +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.security.ConstraintMapping; +import org.eclipse.jetty.ee10.servlet.security.ConstraintSecurityHandler; +import org.eclipse.jetty.security.AbstractLoginService; import org.eclipse.jetty.security.Authenticator; -import org.eclipse.jetty.security.ConstraintMapping; -import org.eclipse.jetty.security.ConstraintSecurityHandler; -import org.eclipse.jetty.security.MappedLoginService; +import org.eclipse.jetty.security.Constraint; +import org.eclipse.jetty.security.RolePrincipal; +import org.eclipse.jetty.security.UserPrincipal; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.UserIdentity; +import org.eclipse.jetty.server.SslConnectionFactory; import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.util.security.Constraint; import org.eclipse.jetty.util.security.Password; +import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jgit.transport.URIish; /** @@ -88,6 +65,12 @@ public class AppServer { /** Password for {@link #username} in secured access areas. */ public static final String password = "letmein"; + /** SSL keystore password; must have at least 6 characters. */ + private static final String keyPassword = "mykeys"; + + /** Role for authentication. */ + private static final String authRole = "can-access"; + static { // Install a logger that throws warning messages. // @@ -97,39 +80,159 @@ public class AppServer { private final Server server; + private final HttpConfiguration config; + private final ServerConnector connector; + private final HttpConfiguration secureConfig; + + private final ServerConnector secureConnector; + private final ContextHandlerCollection contexts; private final TestRequestLog log; + private List<File> filesToDelete = new ArrayList<>(); + + /** + * Constructor for <code>AppServer</code>. + */ public AppServer() { + this(0, -1); + } + + /** + * Constructor for <code>AppServer</code>. + * + * @param port + * the http port number; may be zero to allocate a port + * dynamically + * @since 4.2 + */ + public AppServer(int port) { + this(port, -1); + } + + /** + * Constructor for <code>AppServer</code>. + * + * @param port + * for http, may be zero to allocate a port dynamically + * @param sslPort + * for https,may be zero to allocate a port dynamically. If + * negative, the server will be set up without https support. + * @since 4.9 + */ + public AppServer(int port, int sslPort) { server = new Server(); - HttpConfiguration http_config = new HttpConfiguration(); - http_config.setSecureScheme("https"); - http_config.setSecurePort(8443); - http_config.setOutputBufferSize(32768); + config = new HttpConfiguration(); + config.setSecureScheme("https"); + config.setSecurePort(0); + config.setOutputBufferSize(32768); connector = new ServerConnector(server, - new HttpConnectionFactory(http_config)); - connector.setPort(0); + new HttpConnectionFactory(config)); + connector.setPort(port); + String ip; + String hostName; try { final InetAddress me = InetAddress.getByName("localhost"); - connector.setHost(me.getHostAddress()); + ip = me.getHostAddress(); + connector.setHost(ip); + hostName = InetAddress.getLocalHost().getCanonicalHostName(); } catch (UnknownHostException e) { throw new RuntimeException("Cannot find localhost", e); } + if (sslPort >= 0) { + SslContextFactory.Server sslContextFactory = createTestSslContextFactory( + hostName, ip); + secureConfig = new HttpConfiguration(config); + secureConfig.addCustomizer(new SecureRequestCustomizer()); + HttpConnectionFactory http11 = new HttpConnectionFactory( + secureConfig); + SslConnectionFactory tls = new SslConnectionFactory( + sslContextFactory, http11.getProtocol()); + secureConnector = new ServerConnector(server, tls, http11); + secureConnector.setPort(sslPort); + secureConnector.setHost(ip); + } else { + secureConfig = null; + secureConnector = null; + } + contexts = new ContextHandlerCollection(); log = new TestRequestLog(); log.setHandler(contexts); - server.setConnectors(new Connector[] { connector }); + if (secureConnector == null) { + server.setConnectors(new Connector[] { connector }); + } else { + server.setConnectors( + new Connector[] { connector, secureConnector }); + } server.setHandler(log); } + private SslContextFactory.Server createTestSslContextFactory( + String hostName, String ip) { + SslContextFactory.Server factory = new SslContextFactory.Server(); + + String dName = "CN=localhost,OU=JGit,O=Eclipse,ST=Ontario,L=Toronto,C=CA"; + + try { + File tmpDir = Files.createTempDirectory("jks").toFile(); + tmpDir.deleteOnExit(); + makePrivate(tmpDir); + File keyStore = new File(tmpDir, "keystore.jks"); + File keytool = new File( + new File(new File(System.getProperty("java.home")), "bin"), + "keytool"); + Runtime.getRuntime().exec( + new String[] { + keytool.getAbsolutePath(), // + "-keystore", keyStore.getAbsolutePath(), // + "-storepass", keyPassword, + "-alias", hostName, // + "-ext", "bc=ca:true", // + "-ext", + String.format( + "san=ip:%s,ip:127.0.0.1,ip:[::1],DNS:%s", + ip, hostName), // + "-genkeypair", // + "-keyalg", "RSA", // + "-keypass", keyPassword, // + "-dname", dName, // + "-validity", "2" // + }).waitFor(); + keyStore.deleteOnExit(); + makePrivate(keyStore); + filesToDelete.add(keyStore); + filesToDelete.add(tmpDir); + factory.setKeyStorePath(keyStore.getAbsolutePath()); + factory.setKeyStorePassword(keyPassword); + factory.setKeyManagerPassword(keyPassword); + factory.setTrustStorePath(keyStore.getAbsolutePath()); + factory.setTrustStorePassword(keyPassword); + } catch (InterruptedException | IOException e) { + throw new RuntimeException("Cannot create ssl key/certificate", e); + } + return factory; + } + + private void makePrivate(File file) { + file.setReadable(false); + file.setWritable(false); + file.setExecutable(false); + file.setReadable(true, true); + file.setWritable(true, true); + if (file.isDirectory()) { + file.setExecutable(true, true); + } + } + /** * Create a new servlet context within the server. * <p> @@ -140,6 +243,7 @@ public class AppServer { * path of the context; use "/" for the root context if binding * to the root is desired. * @return the context to add servlets into. + * @since 7.0 */ public ServletContextHandler addContext(String path) { assertNotYetSetUp(); @@ -153,39 +257,84 @@ public class AppServer { return ctx; } - public ServletContextHandler authBasic(ServletContextHandler ctx) { + /** + * Configure basic authentication. + * + * @param ctx + * servlet context handler + * @param methods + * the methods + * @return servlet context handler + * @since 7.0 + */ + public ServletContextHandler authBasic(ServletContextHandler ctx, + String... methods) { assertNotYetSetUp(); - auth(ctx, new BasicAuthenticator()); + auth(ctx, new BasicAuthenticator(), methods); return ctx; } - private void auth(ServletContextHandler ctx, Authenticator authType) { - final String role = "can-access"; + static class TestMappedLoginService extends AbstractLoginService { + private RolePrincipal role; - MappedLoginService users = new MappedLoginService() { - @Override - protected UserIdentity loadUser(String who) { - return null; - } + protected final Map<String, UserPrincipal> users = new ConcurrentHashMap<>(); + + TestMappedLoginService(String role) { + this.role = new RolePrincipal(role); + } + + @Override + protected void doStart() throws Exception { + UserPrincipal p = new UserPrincipal(username, + new Password(password)); + users.put(username, p); + super.doStart(); + } + + @Override + protected UserPrincipal loadUserInfo(String user) { + return users.get(user); + } - @Override - protected void loadUsers() throws IOException { - putUser(username, new Password(password), new String[] { role }); + @Override + protected List<RolePrincipal> loadRoleInfo(UserPrincipal user) { + if (users.get(user.getName()) == null) { + return null; } - }; + return Collections.singletonList(role); + } + } + private ConstraintMapping createConstraintMapping() { ConstraintMapping cm = new ConstraintMapping(); - cm.setConstraint(new Constraint()); - cm.getConstraint().setAuthenticate(true); - cm.getConstraint().setDataConstraint(Constraint.DC_NONE); - cm.getConstraint().setRoles(new String[] { role }); + Constraint constraint = new Constraint.Builder() + .authorization(Constraint.Authorization.SPECIFIC_ROLE) + .roles(new String[] { authRole }).build(); + cm.setConstraint(constraint); cm.setPathSpec("/*"); + return cm; + } + + private void auth(ServletContextHandler ctx, Authenticator authType, + String... methods) { + AbstractLoginService users = new TestMappedLoginService(authRole); + List<ConstraintMapping> mappings = new ArrayList<>(); + if (methods == null || methods.length == 0) { + mappings.add(createConstraintMapping()); + } else { + for (String method : methods) { + ConstraintMapping cm = createConstraintMapping(); + cm.setMethod(method.toUpperCase(Locale.ROOT)); + mappings.add(cm); + } + } ConstraintSecurityHandler sec = new ConstraintSecurityHandler(); sec.setRealmName(realm); sec.setAuthenticator(authType); sec.setLoginService(users); - sec.setConstraintMappings(new ConstraintMapping[] { cm }); + sec.setConstraintMappings( + mappings.toArray(new ConstraintMapping[0])); sec.setHandler(ctx); contexts.removeHandler(ctx); @@ -202,6 +351,10 @@ public class AppServer { RecordingLogger.clear(); log.clear(); server.start(); + config.setSecurePort(getSecurePort()); + if (secureConfig != null) { + secureConfig.setSecurePort(getSecurePort()); + } } /** @@ -214,6 +367,10 @@ public class AppServer { RecordingLogger.clear(); log.clear(); server.stop(); + for (File f : filesToDelete) { + f.delete(); + } + filesToDelete.clear(); } /** @@ -237,18 +394,38 @@ public class AppServer { } } - /** @return the local port number the server is listening on. */ + /** + * Get port. + * + * @return the local port number the server is listening on. + */ public int getPort() { assertAlreadySetUp(); return connector.getLocalPort(); } - /** @return all requests since the server was started. */ + /** + * Get secure port. + * + * @return the HTTPS port or -1 if not configured. + */ + public int getSecurePort() { + assertAlreadySetUp(); + return secureConnector != null ? secureConnector.getLocalPort() : -1; + } + + /** + * Get requests. + * + * @return all requests since the server was started. + */ public List<AccessEvent> getRequests() { - return new ArrayList<AccessEvent>(log.getEvents()); + return new ArrayList<>(log.getEvents()); } /** + * Get requests. + * * @param base * base URI used to access the server. * @param path @@ -260,12 +437,14 @@ public class AppServer { } /** + * Get requests. + * * @param path * the path to locate requests for. * @return all requests which match the given path. */ public List<AccessEvent> getRequests(String path) { - ArrayList<AccessEvent> r = new ArrayList<AccessEvent>(); + ArrayList<AccessEvent> r = new ArrayList<>(); for (AccessEvent event : log.getEvents()) { if (event.getPath().equals(path)) { r.add(event); diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java index 84bb888619..f399471b39 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/HttpTestCase.java @@ -1,44 +1,11 @@ /* - * Copyright (C) 2009-2010, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2009-2017, Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.junit.http; @@ -54,7 +21,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.AnyObjectId; @@ -67,33 +35,82 @@ import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteRefUpdate; import org.eclipse.jgit.transport.URIish; -/** Base class for HTTP related transport testing. */ +/** + * Base class for HTTP related transport testing. + */ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { + /** Constant <code>master="Constants.R_HEADS + Constants.MASTER"</code> */ protected static final String master = Constants.R_HEADS + Constants.MASTER; /** In-memory application server; subclass must start. */ protected AppServer server; + @Override public void setUp() throws Exception { super.setUp(); - server = new AppServer(); + server = createServer(); } + @Override public void tearDown() throws Exception { server.tearDown(); super.tearDown(); } + /** + * Create the {@link AppServer}.This default implementation creates a server + * without SSLsupport listening for HTTP connections on a dynamically chosen + * port, which can be gotten once the server has been started via its + * {@link org.eclipse.jgit.junit.http.AppServer#getPort()} method. + * Subclasses may override if they need a more specialized server. + * + * @return the {@link org.eclipse.jgit.junit.http.AppServer}. + * @since 4.9 + */ + protected AppServer createServer() { + return new AppServer(); + } + + /** + * Create TestRepository + * + * @return the TestRepository + * @throws IOException + * if an IO error occurred + */ protected TestRepository<Repository> createTestRepository() throws IOException { - return new TestRepository<Repository>(createBareRepository()); + final FileRepository repository = createBareRepository(); + addRepoToClose(repository); + return new TestRepository<>(repository); } + /** + * Convert path to URIish + * + * @param path + * the path + * @return the URIish + * @throws URISyntaxException + * if URI is invalid + */ protected URIish toURIish(String path) throws URISyntaxException { URI u = server.getURI().resolve(path); return new URIish(u.toString()); } + /** + * Convert a path relative to the app's context path to a URIish + * + * @param app + * app name + * @param name + * context path name + * @return the warnings (if any) from the last execution + * @throws URISyntaxException + * if URI is invalid + * @since 7.0 + */ protected URIish toURIish(ServletContextHandler app, String name) throws URISyntaxException { String p = app.getContextPath(); @@ -103,25 +120,68 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { return toURIish(p); } + /** + * Get requests. + * + * @return list of events + */ protected List<AccessEvent> getRequests() { return server.getRequests(); } + /** + * Get requests. + * + * @param base + * base URI + * @param path + * the request path relative to {@code base} + * + * @return list of events + */ protected List<AccessEvent> getRequests(URIish base, String path) { return server.getRequests(base, path); } + /** + * Get requests. + * + * @param path + * request path + * + * @return list of events + */ protected List<AccessEvent> getRequests(String path) { return server.getRequests(path); } + /** + * Run fsck + * + * @param db + * the repository + * @param tips + * tips to start checking from + * @throws Exception + * if an error occurred + */ protected static void fsck(Repository db, RevObject... tips) throws Exception { - new TestRepository(db).fsck(tips); + try (TestRepository<? extends Repository> tr = + new TestRepository<>(db)) { + tr.fsck(tips); + } } + /** + * Mirror refs + * + * @param refs + * the refs + * @return set of RefSpecs + */ protected static Set<RefSpec> mirror(String... refs) { - HashSet<RefSpec> r = new HashSet<RefSpec>(); + HashSet<RefSpec> r = new HashSet<>(); for (String name : refs) { RefSpec rs = new RefSpec(name); rs = rs.setDestination(name); @@ -131,6 +191,17 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { return r; } + /** + * Push a commit + * + * @param from + * repository from which to push + * @param q + * commit to push + * @return collection of RefUpdates + * @throws IOException + * if an IO error occurred + */ protected static Collection<RemoteRefUpdate> push(TestRepository from, RevCommit q) throws IOException { final Repository db = from.getRepository(); @@ -145,6 +216,15 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { return Collections.singleton(u); } + /** + * Create loose object path + * + * @param base + * base URI + * @param id + * objectId + * @return path of the loose object + */ public static String loose(URIish base, AnyObjectId id) { final String objectName = id.name(); final String d = objectName.substring(0, 2); @@ -152,6 +232,15 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { return join(base, "objects/" + d + "/" + f); } + /** + * Join a base URIish and a path + * + * @param base + * base URI + * @param path + * a relative path + * @return the joined path + */ public static String join(URIish base, String path) { if (path.startsWith("/")) fail("Cannot join absolute path " + path + " to URIish " + base); @@ -161,4 +250,59 @@ public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { dir += "/"; return dir + path; } + + /** + * Rewrite a url + * + * @param url + * the URL + * @param newProtocol + * new protocol + * @param newPort + * new port + * @return the rewritten url + */ + protected static String rewriteUrl(String url, String newProtocol, + int newPort) { + String newUrl = url; + if (newProtocol != null && !newProtocol.isEmpty()) { + int schemeEnd = newUrl.indexOf("://"); + if (schemeEnd >= 0) { + newUrl = newProtocol + newUrl.substring(schemeEnd); + } + } + if (newPort > 0) { + newUrl = newUrl.replaceFirst(":\\d+/", ":" + newPort + "/"); + } else { + // Remove the port, if any + newUrl = newUrl.replaceFirst(":\\d+/", "/"); + } + return newUrl; + } + + /** + * Extend a path + * + * @param uri + * the URI + * @param pathComponents + * path components + * @return the extended URIish + * @throws URISyntaxException + * if URI is invalid + */ + protected static URIish extendPath(URIish uri, String pathComponents) + throws URISyntaxException { + String raw = uri.toString(); + String newComponents = pathComponents; + if (!newComponents.startsWith("/")) { + newComponents = '/' + newComponents; + } + if (!newComponents.endsWith("/")) { + newComponents += '/'; + } + int i = raw.lastIndexOf('/'); + raw = raw.substring(0, i) + newComponents + raw.substring(i + 1); + return new URIish(raw); + } } diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java index 0b4530ded2..808b076943 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/MockServletConfig.java @@ -1,44 +1,11 @@ /* - * Copyright (C) 2010, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.junit.http; @@ -48,38 +15,56 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +/** + * Mock ServletConfig + */ public class MockServletConfig implements ServletConfig { - private final Map<String, String> parameters = new HashMap<String, String>(); + private final Map<String, String> parameters = new HashMap<>(); + /** + * Set init parameter. + * + * @param name + * parameter name + * @param value + * parameter value + */ public void setInitParameter(String name, String value) { parameters.put(name, value); } + @Override public String getInitParameter(String name) { return parameters.get(name); } - public Enumeration getInitParameterNames() { + @Override + public Enumeration<String> getInitParameterNames() { final Iterator<String> i = parameters.keySet().iterator(); - return new Enumeration<String>() { + return new Enumeration<>() { + + @Override public boolean hasMoreElements() { return i.hasNext(); } + @Override public String nextElement() { return i.next(); } }; } + @Override public String getServletName() { return "MOCK_SERVLET"; } + @Override public ServletContext getServletContext() { return null; } -}
\ No newline at end of file +} diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/RecordingLogger.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/RecordingLogger.java index 7600843d23..f56e1fa5c4 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/RecordingLogger.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/RecordingLogger.java @@ -1,46 +1,12 @@ /* - * Copyright (C) 2010, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, 2021 Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ - package org.eclipse.jgit.junit.http; import java.text.MessageFormat; @@ -48,23 +14,32 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.eclipse.jetty.util.log.Logger; +import org.slf4j.helpers.MarkerIgnoringBase; -/** Logs warnings into an array for later inspection. */ -public class RecordingLogger implements Logger { - private static List<Warning> warnings = new ArrayList<Warning>(); +public class RecordingLogger extends MarkerIgnoringBase { - /** Clear the warnings, automatically done by {@link AppServer#setUp()} */ + private static final long serialVersionUID = 1L; + + private static List<Warning> warnings = new ArrayList<>(); + + /** + * Clear the warnings, automatically done by + * {@link org.eclipse.jgit.junit.http.AppServer#setUp()} + */ public static void clear() { synchronized (warnings) { warnings.clear(); } } - /** @return the warnings (if any) from the last execution */ + /** + * Get the <code>warnings</code>. + * + * @return the warnings (if any) from the last execution + */ public static List<Warning> getWarnings() { synchronized (warnings) { - ArrayList<Warning> copy = new ArrayList<Warning>(warnings); + ArrayList<Warning> copy = new ArrayList<>(warnings); return Collections.unmodifiableList(copy); } } @@ -84,112 +59,187 @@ public class RecordingLogger implements Logger { } } - private final String name; - + /** + * Constructor for <code>RecordingLogger</code>. + */ public RecordingLogger() { this(""); } - public RecordingLogger(final String name) { + /** + * Constructor for <code>RecordingLogger</code>. + * + * @param name + * logger name + */ + public RecordingLogger(String name) { this.name = name; } - public Logger getLogger(@SuppressWarnings("hiding") String name) { - return new RecordingLogger(name); + @Override + public boolean isTraceEnabled() { + // Ignore (not relevant to test failures) + return false; } - public String getName() { - return name; + @Override + public void trace(String msg) { + // Ignore (not relevant to test failures) } - public void warn(String msg, Object arg0, Object arg1) { - synchronized (warnings) { - warnings.add(new Warning(MessageFormat.format(msg, arg0, arg1))); - } + @Override + public void trace(String format, Object arg) { + // Ignore (not relevant to test failures) } - public void warn(String msg, Throwable th) { - synchronized (warnings) { - warnings.add(new Warning(msg, th)); - } + @Override + public void trace(String format, Object arg1, Object arg2) { + // Ignore (not relevant to test failures) } - public void warn(String msg) { - synchronized (warnings) { - warnings.add(new Warning(msg)); - } + @Override + public void trace(String format, Object... arguments) { + // Ignore (not relevant to test failures) + } + + @Override + public void trace(String msg, Throwable t) { + // Ignore (not relevant to test failures) + } + + @Override + public boolean isDebugEnabled() { + return false; } - public void debug(@SuppressWarnings("unused") String msg, - @SuppressWarnings("unused") Object arg0, - @SuppressWarnings("unused") Object arg1) { + @Override + public void debug(String msg) { // Ignore (not relevant to test failures) } - public void debug(String msg, Throwable th) { + @Override + public void debug(String format, Object arg) { // Ignore (not relevant to test failures) } - public void debug(@SuppressWarnings("unused") String msg) { + @Override + public void debug(String format, Object arg1, Object arg2) { // Ignore (not relevant to test failures) } - public void info(@SuppressWarnings("unused") String msg, - @SuppressWarnings("unused") Object arg0, - @SuppressWarnings("unused") Object arg1) { + @Override + public void debug(String format, Object... arguments) { // Ignore (not relevant to test failures) } - public void info(@SuppressWarnings("unused") String msg) { + @Override + public void debug(String msg, Throwable t) { // Ignore (not relevant to test failures) } - public boolean isDebugEnabled() { + @Override + public boolean isInfoEnabled() { return false; } - public void setDebugEnabled(boolean enabled) { + @Override + public void info(String msg) { + // Ignore (not relevant to test failures) + } + + @Override + public void info(String format, Object arg) { + // Ignore (not relevant to test failures) + } + + @Override + public void info(String format, Object arg1, Object arg2) { + // Ignore (not relevant to test failures) + } + + @Override + public void info(String format, Object... arguments) { + // Ignore (not relevant to test failures) + } + + @Override + public void info(String msg, Throwable t) { // Ignore (not relevant to test failures) } - public void warn(String msg, Object... args) { + @Override + public boolean isWarnEnabled() { + return true; + } + + @Override + public void warn(String msg) { synchronized (warnings) { - warnings.add(new Warning(MessageFormat.format(msg, args))); + warnings.add(new Warning(msg)); } } - public void warn(Throwable thrown) { + @Override + public void warn(String format, Object arg) { + addWarnings(format, Collections.singleton(arg)); + } + + @Override + public void warn(String format, Object... arguments) { + addWarnings(format, arguments); + } + + private void addWarnings(String format, Object... arguments) { synchronized (warnings) { - warnings.add(new Warning(thrown)); + int i = 0; + int index = format.indexOf("{}"); + while (index >= 0) { + format = format.replaceFirst("\\{\\}", "{" + i++ + "}"); + index = format.indexOf("{}"); + } + warnings.add(new Warning(MessageFormat.format(format, arguments))); } } - public void info(String msg, Object... args) { - // Ignore (not relevant to test failures) + @Override + public void warn(String format, Object arg1, Object arg2) { + warn(format, new Object[] { arg1, arg2 }); } - public void info(Throwable thrown) { - // Ignore (not relevant to test failures) + @Override + public void warn(String msg, Throwable t) { + synchronized (warnings) { + warnings.add(new Warning(msg, t)); + } + } + + @Override + public boolean isErrorEnabled() { + return false; } - public void info(String msg, Throwable thrown) { + @Override + public void error(String msg) { // Ignore (not relevant to test failures) } - public void debug(String msg, Object... args) { + @Override + public void error(String format, Object arg) { // Ignore (not relevant to test failures) } - public void debug(Throwable thrown) { + @Override + public void error(String format, Object arg1, Object arg2) { // Ignore (not relevant to test failures) } - public void ignore(Throwable arg0) { + @Override + public void error(String format, Object... arguments) { // Ignore (not relevant to test failures) } @Override - public void debug(String msg, long value) { + public void error(String msg, Throwable t) { // Ignore (not relevant to test failures) } } diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java index e550e6c567..bce41383d1 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/SimpleHttpServer.java @@ -1,61 +1,26 @@ /* * Copyright (C) 2009-2010, Google Inc. - * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, Jens Baumgart <jens.baumgart@sap.com> and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.junit.http; import java.net.URI; import java.net.URISyntaxException; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.ee10.servlet.ServletContextHandler; +import org.eclipse.jetty.ee10.servlet.ServletHolder; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.http.server.GitServlet; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.URIish; -import org.eclipse.jgit.transport.resolver.RepositoryResolver; -import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; /** * Simple http server for testing http access to Git repositories. @@ -69,38 +34,84 @@ public class SimpleHttpServer { private URIish uri; + private URIish secureUri; + + /** + * Constructor for <code>SimpleHttpServer</code>. + * + * @param repository + * the repository + */ public SimpleHttpServer(Repository repository) { + this(repository, false); + } + + /** + * Constructor for <code>SimpleHttpServer</code>. + * + * @param repository + * the repository + * @param withSsl + * whether to encrypt the communication + */ + public SimpleHttpServer(Repository repository, boolean withSsl) { this.db = repository; - server = new AppServer(); + server = new AppServer(0, withSsl ? 0 : -1); } + /** + * Start the server + * + * @throws Exception + * if an error occurred + */ public void start() throws Exception { ServletContextHandler sBasic = server.authBasic(smart("/sbasic")); server.setUp(); final String srcName = db.getDirectory().getName(); uri = toURIish(sBasic, srcName); + int sslPort = server.getSecurePort(); + if (sslPort > 0) { + secureUri = uri.setPort(sslPort).setScheme("https"); + } } + /** + * Stop the server. + * + * @throws Exception + * if an error occurred + */ public void stop() throws Exception { server.tearDown(); } + /** + * Get the <code>uri</code>. + * + * @return the uri + */ public URIish getUri() { return uri; } - private ServletContextHandler smart(final String path) { + /** + * Get the <code>secureUri</code>. + * + * @return the secure uri + */ + public URIish getSecureUri() { + return secureUri; + } + + private ServletContextHandler smart(String path) { GitServlet gs = new GitServlet(); - gs.setRepositoryResolver(new RepositoryResolver<HttpServletRequest>() { - public Repository open(HttpServletRequest req, String name) - throws RepositoryNotFoundException, - ServiceNotEnabledException { - if (!name.equals(nameOf(db))) - throw new RepositoryNotFoundException(name); - - db.incrementOpen(); - return db; + gs.setRepositoryResolver((HttpServletRequest req, String name) -> { + if (!name.equals(nameOf(db))) { + throw new RepositoryNotFoundException(name); } + db.incrementOpen(); + return db; }); ServletContextHandler ctx = server.addContext(path); @@ -108,7 +119,7 @@ public class SimpleHttpServer { return ctx; } - private static String nameOf(final Repository db) { + private static String nameOf(Repository db) { return db.getDirectory().getName(); } diff --git a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java index 14ea03a921..7a71951dbd 100644 --- a/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java +++ b/org.eclipse.jgit.junit.http/src/org/eclipse/jgit/junit/http/TestRequestLog.java @@ -1,136 +1,90 @@ /* - * Copyright (C) 2010, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, Google Inc. and others * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://www.eclipse.org/org/documents/edl-v10.php. * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.junit.http; -import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.Semaphore; -import javax.servlet.DispatcherType; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import org.eclipse.jetty.server.Handler.Wrapper; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; -import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.eclipse.jetty.util.Callback; /** Logs request made through {@link AppServer}. */ -class TestRequestLog extends HandlerWrapper { - private static final int MAX = 16; - - private final List<AccessEvent> events = new ArrayList<AccessEvent>(); - - private final Semaphore active = new Semaphore(MAX); - - /** Reset the log back to its original empty state. */ - void clear() { - try { - for (;;) { - try { - active.acquire(MAX); - break; - } catch (InterruptedException e) { - continue; - } - } - - synchronized (events) { - events.clear(); - } - } finally { - active.release(MAX); - } - } - - /** @return all of the events made since the last clear. */ - List<AccessEvent> getEvents() { - try { - for (;;) { - try { - active.acquire(MAX); - break; - } catch (InterruptedException e) { - continue; - } - } - - synchronized (events) { - return events; - } - } finally { - active.release(MAX); - } - } - - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { - try { - for (;;) { - try { - active.acquire(); - break; - } catch (InterruptedException e) { - continue; - } - } - - super.handle(target, baseRequest, request, response); - - if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType())) - log((Request) request, (Response) response); - - } finally { - active.release(); - } - } - - private void log(Request request, Response response) { - synchronized (events) { - events.add(new AccessEvent(request, response)); - } - } +class TestRequestLog extends Wrapper { + private static final int MAX = 16; + + private final List<AccessEvent> events = Collections + .synchronizedList(new ArrayList<>()); + + private final Semaphore active = new Semaphore(MAX, true); + + /** Reset the log back to its original empty state. */ + void clear() { + try { + for (;;) { + try { + active.acquire(MAX); + break; + } catch (InterruptedException e) { + continue; + } + } + events.clear(); + } finally { + active.release(MAX); + } + } + + /** @return all of the events made since the last clear. */ + List<AccessEvent> getEvents() { + try { + for (;;) { + try { + active.acquire(MAX); + break; + } catch (InterruptedException e) { + continue; + } + } + return Collections.unmodifiableList(new ArrayList<>(events)); + } finally { + active.release(MAX); + } + } + + @Override + public boolean handle(Request request, Response response, Callback callback) + throws Exception { + try { + for (;;) { + try { + active.acquire(); + break; + } catch (InterruptedException e) { + continue; + } + } + + AccessEvent event = new AccessEvent(request); + events.add(event); + + boolean result = super.handle(request, response, callback); + + event.setResponse(response); + return result; + } finally { + active.release(); + } + } } |