001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl; 020 021import javax.inject.Named; 022import javax.inject.Singleton; 023 024import java.util.Locale; 025import java.util.concurrent.ConcurrentHashMap; 026import java.util.concurrent.ConcurrentMap; 027 028import org.eclipse.aether.ConfigurationProperties; 029import org.eclipse.aether.Keys; 030import org.eclipse.aether.RepositorySystemSession; 031import org.eclipse.aether.repository.RemoteRepository; 032import org.eclipse.aether.repository.RepositoryKeyFunction; 033import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory; 034import org.eclipse.aether.util.ConfigUtils; 035import org.eclipse.aether.util.repository.RepositoryIdHelper; 036 037import static java.util.Objects.requireNonNull; 038 039@Singleton 040@Named 041public class DefaultRepositoryKeyFunctionFactory implements RepositoryKeyFunctionFactory { 042 043 @Override 044 public RepositoryKeyFunction trackingRepositoryKeyFunction(RepositorySystemSession session) { 045 return doRepositoryKeyFunction( 046 RepositoryKeyFunctionFactory.class, 047 session, 048 ConfigurationProperties.DEFAULT_REPOSITORY_TRACKING_REPOSITORY_KEY_FUNCTION, 049 ConfigurationProperties.REPOSITORY_TRACKING_REPOSITORY_KEY_FUNCTION, 050 ConfigurationProperties.REPOSITORY_SYSTEM_REPOSITORY_KEY_FUNCTION); 051 } 052 053 @Override 054 public RepositoryKeyFunction repositoryKeyFunction( 055 Class<?> owner, RepositorySystemSession session, String defaultValue, String configurationKey) { 056 return doRepositoryKeyFunction(owner, session, defaultValue, configurationKey); 057 } 058 059 /** 060 * Method that based on configuration returns the "repository key function". The returned function will be session 061 * cached if session is equipped with cache, otherwise it will be non cached. Method never returns {@code null}. 062 * Only the {@code configurationKey} parameter may be {@code null} in which case no configuration lookup happens 063 * but the {@code defaultValue} is directly used instead. 064 */ 065 @SuppressWarnings("unchecked") 066 private RepositoryKeyFunction doRepositoryKeyFunction( 067 Class<?> owner, RepositorySystemSession session, String defaultValue, String... configurationKeys) { 068 requireNonNull(session); 069 requireNonNull(defaultValue); 070 RepositoryIdHelper.RepositoryKeyType type = 071 RepositoryIdHelper.RepositoryKeyType.valueOf((configurationKeys != null 072 ? ConfigUtils.getString(session, defaultValue, configurationKeys) 073 : defaultValue) 074 .toUpperCase(Locale.ENGLISH)); 075 final RepositoryKeyFunction repositoryKeyFunction = RepositoryIdHelper.getRepositoryKeyFunction(type.name()); 076 if (session.getCache() != null) { 077 // both are expensive methods; cache it in session (repo -> context -> ID) 078 return (repository, context) -> ((ConcurrentMap<RemoteRepository, ConcurrentMap<String, String>>) 079 session.getCache().computeIfAbsent(session, Keys.of(owner, type), ConcurrentHashMap::new)) 080 .computeIfAbsent(repository, k1 -> new ConcurrentHashMap<>()) 081 .computeIfAbsent( 082 context == null ? "" : context, k2 -> repositoryKeyFunction.apply(repository, context)); 083 } else { 084 return repositoryKeyFunction; 085 } 086 } 087}