Fix review findings

This commit is contained in:
Sebastian Sdorra
2020-11-19 10:21:17 +01:00
parent b6c5a253cb
commit 29faa5ec6c
5 changed files with 199 additions and 93 deletions

View File

@@ -32,6 +32,7 @@ import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.ExceptionWithContext;
import sonia.scm.NotFoundException;
import sonia.scm.repository.RepositoryHookType;
import sonia.scm.repository.api.HgHookMessage;
@@ -110,6 +111,9 @@ class DefaultHookHandler implements HookHandler {
} catch (NotFoundException ex) {
LOG.warn("could not find repository with id {}", request.getRepositoryId(), ex);
return error("repository not found");
} catch (ExceptionWithContext ex) {
LOG.debug("scm exception on hook occurred", ex);
return error(context, ex);
} catch (Exception ex) {
LOG.warn("unknown error on hook occurred", ex);
return error(context, ex);

View File

@@ -52,12 +52,63 @@ public class HookServer implements AutoCloseable {
private ExecutorService acceptor;
private ExecutorService workerPool;
private ServerSocket serverSocket;
private SecurityManager securityManager;
@Inject
public HookServer(HookHandlerFactory handlerFactory) {
this.handlerFactory = handlerFactory;
}
public int start() throws IOException {
securityManager = SecurityUtils.getSecurityManager();
acceptor = createAcceptor();
workerPool = createWorkerPool();
serverSocket = createServerSocket();
// set timeout to 2 min, to avoid blocking clients
serverSocket.setSoTimeout(2 * 60 * 1000);
accept();
int port = serverSocket.getLocalPort();
LOG.info("open hg hook server on port {}", port);
return port;
}
private void accept() {
acceptor.submit(() -> {
while (!serverSocket.isClosed()) {
try {
LOG.trace("wait for next hook connection");
Socket clientSocket = serverSocket.accept();
LOG.trace("accept incoming hook client from {}", clientSocket.getInetAddress());
HookHandler hookHandler = handlerFactory.create(clientSocket);
workerPool.submit(associateSecurityManager(hookHandler));
} catch (IOException ex) {
LOG.debug("failed to accept socket, possible closed", ex);
}
}
LOG.warn("ServerSocket is closed");
});
}
private Runnable associateSecurityManager(HookHandler hookHandler) {
return () -> {
ThreadContext.bind(securityManager);
try {
hookHandler.run();
} finally {
ThreadContext.unbindSubject();
ThreadContext.unbindSecurityManager();
}
};
}
@Nonnull
private ServerSocket createServerSocket() throws IOException {
return new ServerSocket(0, 0, InetAddress.getLoopbackAddress());
}
private ExecutorService createAcceptor() {
return Executors.newSingleThreadExecutor(
createThreadFactory("HgHookAcceptor")
@@ -77,64 +128,23 @@ public class HookServer implements AutoCloseable {
.build();
}
public int start() throws IOException {
acceptor = createAcceptor();
workerPool = createWorkerPool();
serverSocket = createServerSocket();
// set timeout to 2 min, to avoid blocking clients
serverSocket.setSoTimeout(2 * 60 * 1000);
accept();
int port = serverSocket.getLocalPort();
LOG.info("open hg hook server on port {}", port);
return port;
}
private void accept() {
SecurityManager securityManager = SecurityUtils.getSecurityManager();
acceptor.submit(() -> {
while (!serverSocket.isClosed()) {
try {
LOG.trace("wait for next hook connection");
Socket clientSocket = serverSocket.accept();
LOG.trace("accept incoming hook client from {}", clientSocket.getInetAddress());
HookHandler hookHandler = handlerFactory.create(clientSocket);
workerPool.submit(associateSecurityManager(securityManager, hookHandler));
} catch (IOException ex) {
LOG.debug("failed to accept socket, possible closed", ex);
}
}
LOG.warn("ServerSocket is closed");
});
}
private Runnable associateSecurityManager(SecurityManager securityManager, HookHandler hookHandler) {
return () -> {
ThreadContext.bind(securityManager);
try {
hookHandler.run();
} finally {
ThreadContext.unbindSubject();
ThreadContext.unbindSecurityManager();
}
};
}
@Nonnull
private ServerSocket createServerSocket() throws IOException {
return new ServerSocket(0, 0, InetAddress.getLoopbackAddress());
}
@Override
public void close() throws IOException {
if (serverSocket != null) {
serverSocket.close();
}
public void close() {
closeSocket();
shutdown(acceptor);
shutdown(workerPool);
}
private void closeSocket() {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException ex) {
LOG.warn("failed to close server socket", ex);
}
}
}
private void shutdown(ExecutorService acceptor) {
if (acceptor != null) {
acceptor.shutdown();