io.polaris.core.service.StatefulServiceLoader Maven / Gradle / Ivy
package io.polaris.core.service;
import lombok.AccessLevel;
import lombok.Getter;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Qt
* @version Jan 13, 2022
* @since 1.8
*/
public class StatefulServiceLoader implements Iterable {
private final static Map, State>> store = new ConcurrentHashMap<>();
private final ServiceLoader serviceLoader;
private StatefulServiceLoader(ServiceLoader serviceLoader) {
this.serviceLoader = serviceLoader;
}
private StatefulServiceLoader(Class service, ClassLoader loader) {
this(ServiceLoader.of(service, loader));
}
public static StatefulServiceLoader load(Class service) {
return load(service, Thread.currentThread().getContextClassLoader());
}
public static StatefulServiceLoader load(Class service, ClassLoader classLoader) {
StatefulServiceLoader loader = null;
State ref = (State) store.get(service);
if (ref == null) {
synchronized (store) {
ref = (State) store.get(service);
if (ref == null) {
loader = new StatefulServiceLoader<>(service, classLoader);
ref = new State<>(classLoader, loader);
store.put(service, ref);
}
}
}
if (loader == null) {
loader = ref.getByClassLoader(classLoader);
if (loader == null) {
synchronized (ref) {
loader = ref.getByClassLoader(classLoader);
if (loader == null) {
loader = new StatefulServiceLoader<>(service, classLoader);
ref.update(classLoader, loader);
}
}
}
}
return loader;
}
public static void clear(Class service) {
store.computeIfPresent(service, (k, v) -> {
v.map.clear();
return null;
});
}
@Override
public Iterator iterator() {
return new Iterator() {
final Iterator> iter = serviceLoader.iterator();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public S next() {
return iter.next().getSingleton();
}
};
}
public ServiceLoader serviceLoader() {
return serviceLoader;
}
public Optional optionalService() {
return Optional.ofNullable(serviceLoader.get()).map(Service::getSingleton);
}
@Nullable
public S service() {
return serviceLoader.getSingleton();
}
@Nullable
public S service(String propertyName, String propertyValue) {
return serviceLoader.getSingleton(propertyName, propertyValue);
}
public List serviceList() {
List list = new ArrayList<>();
for (Service service : serviceLoader) {
list.add(service.getSingleton());
}
return list;
}
public Map serviceMap() {
Map map = new HashMap<>();
serviceLoader.getNamings().forEach((k, v) -> map.put(k, v.getSingleton()));
return map;
}
/**
* @author Qt
* @version Jan 13, 2022
* @since 1.8
*/
static class State {
private Map> map = new ConcurrentHashMap<>();
@Getter(AccessLevel.PACKAGE)
private ClassLoader lastClassLoader;
@Getter(AccessLevel.PACKAGE)
private StatefulServiceLoader lastServiceLoader;
State(ClassLoader lastClassLoader, StatefulServiceLoader lastServiceLoader) {
update(lastClassLoader, lastServiceLoader);
}
void update(ClassLoader lastClassLoader, StatefulServiceLoader lastServiceLoader) {
this.lastClassLoader = lastClassLoader;
this.lastServiceLoader = lastServiceLoader;
this.map.put(lastClassLoader, lastServiceLoader);
}
StatefulServiceLoader getByClassLoader(ClassLoader loader) {
if (lastClassLoader == loader) {
return lastServiceLoader;
}
return map.get(loader);
}
}
}