|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package jdk.internal.module; |
|
|
|
import java.lang.module.ModuleDescriptor; |
|
import java.lang.module.ModuleDescriptor.Provides; |
|
import java.util.Arrays; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Objects; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.concurrent.CopyOnWriteArrayList; |
|
|
|
import jdk.internal.loader.ClassLoaderValue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class ServicesCatalog { |
|
|
|
|
|
|
|
*/ |
|
public static final class ServiceProvider { |
|
private final Module module; |
|
private final String providerName; |
|
|
|
public ServiceProvider(Module module, String providerName) { |
|
this.module = module; |
|
this.providerName = providerName; |
|
} |
|
|
|
public Module module() { |
|
return module; |
|
} |
|
|
|
public String providerName() { |
|
return providerName; |
|
} |
|
|
|
@Override |
|
public int hashCode() { |
|
return Objects.hash(module, providerName); |
|
} |
|
|
|
@Override |
|
public boolean equals(Object ob) { |
|
if (!(ob instanceof ServiceProvider)) |
|
return false; |
|
ServiceProvider that = (ServiceProvider)ob; |
|
return Objects.equals(this.module, that.module) |
|
&& Objects.equals(this.providerName, that.providerName); |
|
} |
|
} |
|
|
|
|
|
private final Map<String, List<ServiceProvider>> map = new ConcurrentHashMap<>(32); |
|
|
|
private ServicesCatalog() { } |
|
|
|
|
|
|
|
|
|
*/ |
|
public static ServicesCatalog create() { |
|
return new ServicesCatalog(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void addProviders(String service, ServiceProvider ... providers) { |
|
List<ServiceProvider> list = map.get(service); |
|
if (list == null) { |
|
list = new CopyOnWriteArrayList<>(providers); |
|
List<ServiceProvider> prev = map.putIfAbsent(service, list); |
|
if (prev != null) { |
|
|
|
prev.addAll(list); |
|
} |
|
} else { |
|
if (providers.length == 1) { |
|
list.add(providers[0]); |
|
} else { |
|
list.addAll(Arrays.asList(providers)); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void register(Module module) { |
|
ModuleDescriptor descriptor = module.getDescriptor(); |
|
for (Provides provides : descriptor.provides()) { |
|
String service = provides.service(); |
|
List<String> providerNames = provides.providers(); |
|
int count = providerNames.size(); |
|
ServiceProvider[] providers = new ServiceProvider[count]; |
|
for (int i = 0; i < count; i++) { |
|
providers[i] = new ServiceProvider(module, providerNames.get(i)); |
|
} |
|
addProviders(service, providers); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void addProvider(Module module, Class<?> service, Class<?> impl) { |
|
addProviders(service.getName(), new ServiceProvider(module, impl.getName())); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public List<ServiceProvider> findServices(String service) { |
|
return map.getOrDefault(service, List.of()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static ServicesCatalog getServicesCatalogOrNull(ClassLoader loader) { |
|
return CLV.get(loader); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static ServicesCatalog getServicesCatalog(ClassLoader loader) { |
|
|
|
ServicesCatalog catalog = CLV.get(loader); |
|
if (catalog == null) { |
|
catalog = create(); |
|
ServicesCatalog previous = CLV.putIfAbsent(loader, catalog); |
|
if (previous != null) catalog = previous; |
|
} |
|
return catalog; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void putServicesCatalog(ClassLoader loader, ServicesCatalog catalog) { |
|
ServicesCatalog previous = CLV.putIfAbsent(loader, catalog); |
|
if (previous != null) { |
|
throw new InternalError(); |
|
} |
|
} |
|
|
|
|
|
private static final ClassLoaderValue<ServicesCatalog> CLV = new ClassLoaderValue<>(); |
|
} |