/** * This file is part of git-as-svn. It is subject to the license terms * in the LICENSE file found in the top-level directory of this distribution * and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn, * including this file, may be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file. */ package svnserver.ext.socket.config; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import ru.bozaro.protobuf.ProtobufRpcSocket; import ru.bozaro.protobuf.internal.ServiceInfo; import svnserver.context.Shared; import svnserver.context.SharedContext; import svnserver.ext.api.ServiceRegistry; import svnserver.repository.RepositoryInfo; import svnserver.repository.VcsRepositoryMapping; import java.io.IOException; import java.net.ServerSocket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Unix socket transport for API. * * @author Artem V. Navrotskiy <bozaro@users.noreply.github.com> */ public class SocketRpc implements Shared { @NotNull private static final Logger log = LoggerFactory.getLogger(SocketRpc.class); private static final long TIMEOUT = 10000; @NotNull private final ExecutorService poolExecutor; @NotNull private final ProtobufRpcSocket server; @NotNull private final SharedContext context; public SocketRpc(@NotNull SharedContext context, @NotNull ServerSocket serverSocket) throws IOException { this.poolExecutor = Executors.newCachedThreadPool(); this.context = context; log.info("Server API on socket: {}", serverSocket); this.server = new ProtobufRpcSocket(SocketRpc.this::getService, serverSocket, poolExecutor); } @Nullable public ServiceInfo getService(@NotNull String name) { int separator = name.lastIndexOf('/'); ServiceRegistry registry; if (separator < 0) { registry = ServiceRegistry.get(context); } else { try { VcsRepositoryMapping mapping = context.sure(VcsRepositoryMapping.class); SVNURL url = SVNURL.create("svn", null, "localhost", 0, name.substring(0, separator), false); RepositoryInfo repository = mapping.getRepository(url); if (repository == null || !repository.getBaseUrl().getPath().equals(url.getPath())) return null; registry = ServiceRegistry.get(repository.getRepository().getContext()); } catch (SVNException e) { log.warn("Can't find repository", e); return null; } } return registry.getService(name.substring(separator + 1)); } @Override public void close() throws Exception { poolExecutor.shutdown(); server.close(); poolExecutor.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS); } }