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; 027 028import org.eclipse.aether.MultiRuntimeException; 029import org.eclipse.aether.RepositorySystemSession; 030import org.eclipse.aether.impl.RepositorySystemLifecycle; 031import org.eclipse.aether.named.NamedLockFactory; 032import org.eclipse.aether.named.providers.FileLockNamedLockFactory; 033import org.eclipse.aether.util.ConfigUtils; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037import static java.util.Objects.requireNonNull; 038 039/** 040 * Default implementation of {@link NamedLockFactoryAdapterFactory}. This implementation creates new instances of the 041 * adapter on every call. In turn, on shutdown, it will shut down all existing named lock factories. This is merely for 042 * simplicity, to not have to track "used" named lock factories, while it exposes all available named lock factories to 043 * callers. 044 * <p> 045 * Most members and methods of this class are protected. It is meant to be extended in case of need to customize its 046 * behavior. An exception from this are private static methods, mostly meant to provide out of the box 047 * defaults and to be used when no Eclipse Sisu component container is used. 048 * 049 * @since 1.9.1 050 */ 051@Singleton 052@Named 053public class NamedLockFactoryAdapterFactoryImpl implements NamedLockFactoryAdapterFactory { 054 public static final String DEFAULT_FACTORY_NAME = FileLockNamedLockFactory.NAME; 055 056 public static final String DEFAULT_NAME_MAPPER_NAME = NameMappers.FILE_GAV_NAME; 057 058 /** 059 * Name of the lock factory to use in session. 060 * 061 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 062 * @configurationType {@link java.lang.String} 063 * @configurationDefaultValue {@link #DEFAULT_FACTORY_NAME} 064 */ 065 public static final String CONFIG_PROP_FACTORY_KEY = NamedLockFactoryAdapter.CONFIG_PROPS_PREFIX + "factory"; 066 067 /** 068 * Name of the name mapper to use in session. Out of the box supported ones are "static", "gav", "file-gav", 069 * "file-hgav", "file-static" and "discriminating". 070 * 071 * @configurationSource {@link RepositorySystemSession#getConfigProperties()} 072 * @configurationType {@link java.lang.String} 073 * @configurationDefaultValue {@link #DEFAULT_NAME_MAPPER_NAME} 074 */ 075 public static final String CONFIG_PROP_NAME_MAPPER_KEY = NamedLockFactoryAdapter.CONFIG_PROPS_PREFIX + "nameMapper"; 076 077 protected final Logger logger = LoggerFactory.getLogger(getClass()); 078 079 protected final Map<String, NamedLockFactory> factories; 080 081 protected final String defaultFactoryName; 082 083 protected final Map<String, NameMapper> nameMappers; 084 085 protected final String defaultNameMapperName; 086 087 @Inject 088 public NamedLockFactoryAdapterFactoryImpl( 089 final Map<String, NamedLockFactory> factories, 090 final Map<String, NameMapper> nameMappers, 091 final RepositorySystemLifecycle lifecycle) { 092 this(factories, DEFAULT_FACTORY_NAME, nameMappers, DEFAULT_NAME_MAPPER_NAME, lifecycle); 093 } 094 095 public NamedLockFactoryAdapterFactoryImpl( 096 final Map<String, NamedLockFactory> factories, 097 final String defaultFactoryName, 098 final Map<String, NameMapper> nameMappers, 099 final String defaultNameMapperName, 100 final RepositorySystemLifecycle lifecycle) { 101 this.factories = requireNonNull(factories); 102 this.defaultFactoryName = requireNonNull(defaultFactoryName); 103 this.nameMappers = requireNonNull(nameMappers); 104 this.defaultNameMapperName = requireNonNull(defaultNameMapperName); 105 lifecycle.addOnSystemEndedHandler(this::shutdown); 106 107 logger.debug( 108 "Created adapter factory; available factories {}; available name mappers {}", 109 factories.keySet(), 110 nameMappers.keySet()); 111 } 112 113 /** 114 * Current implementation simply delegates to {@link #createAdapter(RepositorySystemSession)}. 115 */ 116 @Override 117 public NamedLockFactoryAdapter getAdapter(RepositorySystemSession session) { 118 return createAdapter(session); 119 } 120 121 /** 122 * Creates a new adapter instance, never returns {@code null}. 123 */ 124 protected NamedLockFactoryAdapter createAdapter(RepositorySystemSession session) { 125 final String nameMapperName = requireNonNull(getNameMapperName(session)); 126 final String factoryName = requireNonNull(getFactoryName(session)); 127 final NameMapper nameMapper = selectNameMapper(nameMapperName); 128 final NamedLockFactory factory = selectFactory(factoryName); 129 logger.debug("Creating adapter using nameMapper '{}' and factory '{}'", nameMapperName, factoryName); 130 return new NamedLockFactoryAdapter(nameMapper, factory); 131 } 132 133 /** 134 * Returns the selected (user configured or default) named lock factory name, never {@code null}. 135 */ 136 protected String getFactoryName(RepositorySystemSession session) { 137 return ConfigUtils.getString(session, getDefaultFactoryName(), CONFIG_PROP_FACTORY_KEY); 138 } 139 140 /** 141 * Returns the default named lock factory name, never {@code null}. 142 */ 143 protected String getDefaultFactoryName() { 144 return defaultFactoryName; 145 } 146 147 /** 148 * Returns the selected (user configured or default) name mapper name, never {@code null}. 149 */ 150 protected String getNameMapperName(RepositorySystemSession session) { 151 return ConfigUtils.getString(session, getDefaultNameMapperName(), CONFIG_PROP_NAME_MAPPER_KEY); 152 } 153 154 /** 155 * Returns the default name mapper name, never {@code null}. 156 */ 157 protected String getDefaultNameMapperName() { 158 return defaultNameMapperName; 159 } 160 161 /** 162 * Selects a named lock factory, never returns {@code null}. 163 */ 164 protected NamedLockFactory selectFactory(final String factoryName) { 165 NamedLockFactory factory = factories.get(factoryName); 166 if (factory == null) { 167 throw new IllegalArgumentException( 168 "Unknown NamedLockFactory name: '" + factoryName + "', known ones: " + factories.keySet()); 169 } 170 return factory; 171 } 172 173 /** 174 * Selects a name mapper, never returns {@code null}. 175 */ 176 protected NameMapper selectNameMapper(final String nameMapperName) { 177 NameMapper nameMapper = nameMappers.get(nameMapperName); 178 if (nameMapper == null) { 179 throw new IllegalArgumentException( 180 "Unknown NameMapper name: '" + nameMapperName + "', known ones: " + nameMappers.keySet()); 181 } 182 return nameMapper; 183 } 184 185 /** 186 * To be invoked on repository system shut down. This method will shut down each {@link NamedLockFactory}. 187 */ 188 protected void shutdown() { 189 logger.debug( 190 "Shutting down adapter factory; available factories {}; available name mappers {}", 191 factories.keySet(), 192 nameMappers.keySet()); 193 ArrayList<Exception> exceptions = new ArrayList<>(); 194 for (Map.Entry<String, NamedLockFactory> entry : factories.entrySet()) { 195 try { 196 logger.debug("Shutting down '{}' factory", entry.getKey()); 197 entry.getValue().shutdown(); 198 } catch (Exception e) { 199 exceptions.add(e); 200 } 201 } 202 MultiRuntimeException.mayThrow("Problem shutting down factories", exceptions); 203 } 204}