/* * Copyright (C) 2024 Thomas Wolf and others * * 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. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.lib; import java.text.MessageFormat; import java.util.EnumMap; import java.util.Map; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.internal.JGitText; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Manages the available signers. * * @since 7.0 */ public final class Signers { private static final Logger LOG = LoggerFactory.getLogger(Signers.class); private static final Map SIGNER_FACTORIES = loadSigners(); private static final Map SIGNERS = new ConcurrentHashMap<>(); private static Map loadSigners() { Map result = new EnumMap<>( GpgConfig.GpgFormat.class); try { for (SignerFactory factory : ServiceLoader .load(SignerFactory.class)) { GpgConfig.GpgFormat format = factory.getType(); SignerFactory existing = result.get(format); if (existing != null) { LOG.warn("{}", //$NON-NLS-1$ MessageFormat.format( JGitText.get().signatureServiceConflict, "SignerFactory", format, //$NON-NLS-1$ existing.getClass().getCanonicalName(), factory.getClass().getCanonicalName())); } else { result.put(format, factory); } } } catch (ServiceConfigurationError e) { LOG.error(e.getMessage(), e); } return result; } private Signers() { // No instantiation } /** * Retrieves a {@link Signer} that can produce signatures of the given type * {@code format}. * * @param format * {@link GpgConfig.GpgFormat} the signer must support * @return a {@link Signer}, or {@code null} if none is available */ public static Signer get(@NonNull GpgConfig.GpgFormat format) { return SIGNERS.computeIfAbsent(format, f -> { SignerFactory factory = SIGNER_FACTORIES.get(format); if (factory == null) { return null; } return factory.create(); }); } /** * Sets a specific signer to use for a specific signature type. * * @param format * signature type to set the {@code signer} for * @param signer * the {@link Signer} to use for signatures of type * {@code format}; if {@code null}, a default implementation, if * available, may be used. */ public static void set(@NonNull GpgConfig.GpgFormat format, Signer signer) { if (signer == null) { SIGNERS.remove(format); } else { SIGNERS.put(format, signer); } } }