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.synccontext.named; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.util.ArrayList; 026import java.util.Map; 027import java.util.concurrent.TimeUnit; 028 029import org.eclipse.aether.Keys; 030import org.eclipse.aether.RepositorySystemSession; 031import org.eclipse.aether.impl.NamedLockFactorySelector; 032import org.eclipse.aether.named.NamedLockFactory; 033import org.eclipse.aether.spi.locking.LockingInhibitor; 034import org.eclipse.aether.spi.locking.LockingInhibitorFactory; 035import org.eclipse.aether.util.ConfigUtils; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039import static java.util.Objects.requireNonNull; 040 041/** 042 * Default implementation of {@link NamedLockFactoryAdapterFactory}. This implementation creates new instances of the 043 * adapter on every call. In turn, on shutdown, it will shut down all existing named lock factories. This is merely for 044 * simplicity, to not have to track "used" named lock factories, while it exposes all available named lock factories to 045 * callers. 046 * <p> 047 * Most members and methods of this class are protected. It is meant to be extended in case of need to customize its 048 * behavior. An exception from this are private static methods, mostly meant to provide out of the box 049 * defaults and to be used when no Eclipse Sisu component container is used. 050 * 051 * @since 1.9.1 052 */ 053@Singleton 054@Named 055public class NamedLockFactoryAdapterFactoryImpl implements NamedLockFactoryAdapterFactory { 056 public static final String DEFAULT_NAME_MAPPER_NAME = NameMappers.FILE_GAECV_NAME; 057 058 /** 059 * Name of the lock factory to use in session. Out of the box supported ones are "file-lock", "rwlock-local", 060 * "semaphore-local", "noop". By adding extensions one can extend available lock factories (for example IPC locking). 061 * <strong>Deprecated: use {@code aether.system.named...} configuration instead.</strong> 062 * 063 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 064 * @configurationType {@link java.lang.String} 065 * @deprecated 066 */ 067 @Deprecated 068 public static final String CONFIG_PROP_FACTORY_KEY = NamedLockFactoryAdapter.CONFIG_PROPS_PREFIX + "factory"; 069 070 /** 071 * Name of the name mapper to use in session. Out of the box supported ones are "static", "gav", "gaecv", "file-gav", 072 * "file-gaecv", "file-hgav", "file-hgaecv", "file-static" and "discriminating". 073 * 074 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 075 * @configurationType {@link java.lang.String} 076 * @configurationDefaultValue {@link #DEFAULT_NAME_MAPPER_NAME} 077 */ 078 public static final String CONFIG_PROP_NAME_MAPPER_KEY = NamedLockFactoryAdapter.CONFIG_PROPS_PREFIX + "nameMapper"; 079 080 protected final Logger logger = LoggerFactory.getLogger(getClass()); 081 082 protected final NamedLockFactorySelector namedLockFactorySelector; 083 084 protected final Map<String, NameMapper> nameMappers; 085 086 protected final String defaultNameMapperName; 087 088 protected final Map<String, LockingInhibitorFactory> lockingInhibitorFactories; 089 090 @Inject 091 public NamedLockFactoryAdapterFactoryImpl( 092 final NamedLockFactorySelector namedLockFactorySelector, 093 final Map<String, NameMapper> nameMappers, 094 final Map<String, LockingInhibitorFactory> lockingInhibitorFactories) { 095 this(namedLockFactorySelector, nameMappers, DEFAULT_NAME_MAPPER_NAME, lockingInhibitorFactories); 096 } 097 098 public NamedLockFactoryAdapterFactoryImpl( 099 final NamedLockFactorySelector namedLockFactorySelector, 100 final Map<String, NameMapper> nameMappers, 101 final String defaultNameMapperName, 102 final Map<String, LockingInhibitorFactory> lockingInhibitorFactories) { 103 this.namedLockFactorySelector = requireNonNull(namedLockFactorySelector); 104 this.nameMappers = requireNonNull(nameMappers); 105 this.defaultNameMapperName = requireNonNull(defaultNameMapperName); 106 this.lockingInhibitorFactories = requireNonNull(lockingInhibitorFactories); 107 108 logger.debug( 109 "Created adapter factory; available lock factories {}; available name mappers {}", 110 namedLockFactorySelector.getAvailableLockFactories(), 111 nameMappers.keySet()); 112 } 113 114 private static final Object ADAPTER_KEY = Keys.of(NamedLockFactoryAdapterFactoryImpl.class, "adapter"); 115 116 /** 117 * Current implementation memoize instance in session or delegates to {@link #createAdapter(RepositorySystemSession)}. 118 */ 119 @Override 120 public NamedLockFactoryAdapter getAdapter(RepositorySystemSession session) { 121 requireNonNull(session, "session cannot be null"); 122 return (NamedLockFactoryAdapter) session.getData().computeIfAbsent(ADAPTER_KEY, () -> createAdapter(session)); 123 } 124 125 /** 126 * Creates a new adapter instance, never returns {@code null}. 127 */ 128 protected NamedLockFactoryAdapter createAdapter(RepositorySystemSession session) { 129 final NameMapper nameMapper = selectNameMapper(session, requireNonNull(getNameMapperName(session))); 130 final NamedLockFactory factory = namedLockFactorySelector.getNamedLockFactory(session.getConfigProperties()); 131 final long lockWait = namedLockFactorySelector.getLockWaitTime(session.getConfigProperties()); 132 final TimeUnit lockWaitUnit = namedLockFactorySelector.getLockWaitTimeUnit(session.getConfigProperties()); 133 logger.debug("Creating adapter using nameMapper '{}' and factory '{}'", nameMapper, factory); 134 return new NamedLockFactoryAdapter(nameMapper, factory, lockWait, lockWaitUnit); 135 } 136 137 /** 138 * Returns the selected (user configured or default) name mapper name, never {@code null}. 139 */ 140 protected String getNameMapperName(RepositorySystemSession session) { 141 return ConfigUtils.getString(session, getDefaultNameMapperName(), CONFIG_PROP_NAME_MAPPER_KEY); 142 } 143 144 /** 145 * Returns the default name mapper name, never {@code null}. 146 */ 147 protected String getDefaultNameMapperName() { 148 return defaultNameMapperName; 149 } 150 151 /** 152 * Selects a name mapper, never returns {@code null}. Applies inhibitors. 153 */ 154 protected NameMapper selectNameMapper(final RepositorySystemSession session, final String nameMapperName) { 155 NameMapper nameMapper = nameMappers.get(nameMapperName); 156 if (nameMapper == null) { 157 throw new IllegalArgumentException( 158 "Unknown NameMapper name: '" + nameMapperName + "', known ones: " + nameMappers.keySet()); 159 } 160 if (!lockingInhibitorFactories.isEmpty()) { 161 ArrayList<LockingInhibitor> inhibitors = new ArrayList<>(); 162 for (LockingInhibitorFactory factory : lockingInhibitorFactories.values()) { 163 factory.newInstance(session).ifPresent(inhibitors::add); 164 } 165 if (!inhibitors.isEmpty()) { 166 return new InhibitingNameMapper(nameMapper, inhibitors); 167 } 168 } 169 return nameMapper; 170 } 171}