001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.client.mcp.auth;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.net.*;
022import java.util.*;
023import java.util.concurrent.*;
024
025/**
026 * Thread-safe, process-scoped default {@link McpClientRegistrationStore} keying registrations by
027 * {@code issuer.toString()} (SEP-2352 "separate registration state per authorization server").
028 *
029 * <p>
030 * Holds credential material in memory only; nothing is persisted across process restarts and nothing is logged
031 * ({@link #toString()} discloses only the set of stored issuers, never credential material).
032 *
033 * @since 10.0.0
034 */
035@SuppressWarnings({
036   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
037})
038public class InMemoryMcpClientRegistrationStore implements McpClientRegistrationStore {
039
040   private final ConcurrentMap<String,McpClientRegistration> byIssuer = new ConcurrentHashMap<>();
041
042   @Override /* McpClientRegistrationStore */
043   public Optional<McpClientRegistration> find(URI issuer) {
044      reqnn("issuer", issuer);
045      return o(byIssuer.get(issuer.toString()));
046   }
047
048   @Override /* McpClientRegistrationStore */
049   public void put(URI issuer, McpClientRegistration registration) {
050      reqnn("issuer", issuer);
051      reqnn("registration", registration);
052      byIssuer.put(issuer.toString(), registration);
053   }
054
055   @Override /* McpClientRegistrationStore */
056   public void remove(URI issuer) {
057      reqnn("issuer", issuer);
058      byIssuer.remove(issuer.toString());
059   }
060
061   /**
062    * Returns the number of stored registrations.
063    *
064    * @return The entry count.
065    */
066   public int size() {
067      return byIssuer.size();
068   }
069
070   @Override /* Object */
071   public String toString() {
072      return "InMemoryMcpClientRegistrationStore[issuers=" + byIssuer.keySet() + "]";
073   }
074}