package co.codewizards.cloudstore.core.repo.transport;
import static co.codewizards.cloudstore.core.util.Util.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import co.codewizards.cloudstore.core.util.AssertUtil;
public class RepoTransportFactoryRegistry {
private static class RepoTransportFactoryRegistryHolder {
public static final RepoTransportFactoryRegistry instance = new RepoTransportFactoryRegistry();
}
public static RepoTransportFactoryRegistry getInstance() {
return RepoTransportFactoryRegistryHolder.instance;
}
protected RepoTransportFactoryRegistry() { }
private List<RepoTransportFactory> repoTransportFactories;
public RepoTransportFactory getRepoTransportFactoryOrFail(URL remoteRoot) {
RepoTransportFactory repoTransportFactory = getRepoTransportFactory(remoteRoot);
if (repoTransportFactory == null)
throw new IllegalStateException("There is no RepoTransportFactory supporting this URL: " + remoteRoot);
return repoTransportFactory;
}
public RepoTransportFactory getRepoTransportFactory(URL remoteRoot) {
for (RepoTransportFactory factory : getRepoTransportFactories()) {
if (factory.isSupported(remoteRoot))
return factory;
}
return null;
}
public List<RepoTransportFactory> getRepoTransportFactories(URL remoteRoot) {
List<RepoTransportFactory> result = new ArrayList<RepoTransportFactory>();
for (RepoTransportFactory factory : getRepoTransportFactories()) {
if (factory.isSupported(remoteRoot))
result.add(factory);
}
return Collections.unmodifiableList(result);
}
public synchronized List<RepoTransportFactory> getRepoTransportFactories() {
List<RepoTransportFactory> repoTransportFactories = this.repoTransportFactories;
if (repoTransportFactories == null) {
repoTransportFactories = loadRepoTransportFactoriesViaServiceLoader();
sortRepoTransportFactories(repoTransportFactories);
this.repoTransportFactories = repoTransportFactories = Collections.unmodifiableList(repoTransportFactories);
}
return repoTransportFactories;
}
private static List<RepoTransportFactory> loadRepoTransportFactoriesViaServiceLoader() {
ArrayList<RepoTransportFactory> repoTransportFactories = new ArrayList<RepoTransportFactory>();
ServiceLoader<RepoTransportFactory> sl = ServiceLoader.load(RepoTransportFactory.class);
for (Iterator<RepoTransportFactory> it = sl.iterator(); it.hasNext(); ) {
repoTransportFactories.add(it.next());
}
repoTransportFactories.trimToSize();
return repoTransportFactories;
}
protected static int _compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
private static void sortRepoTransportFactories(List<RepoTransportFactory> repoTransportFactories) {
Collections.sort(repoTransportFactories, new Comparator<RepoTransportFactory>() {
@Override
public int compare(RepoTransportFactory o1, RepoTransportFactory o2) {
int result = -1 * _compare(o1.getPriority(), o2.getPriority());
if (result != 0)
return result;
String name1 = o1.getName() == null ? "" : o1.getName();
String name2 = o2.getName() == null ? "" : o2.getName();
result = name1.compareTo(name2);
if (result != 0)
return result;
return o1.getClass().getName().compareTo(o2.getClass().getName());
}
});
}
public <F extends RepoTransportFactory> F getRepoTransportFactoryOrFail(Class<F> factoryClass) {
F repoTransportFactory = getRepoTransportFactory(factoryClass);
if (repoTransportFactory == null)
throw new IllegalArgumentException("There is no factory registered implementing this interface or extending this class: " + factoryClass.getName());
return repoTransportFactory;
}
public <F extends RepoTransportFactory> F getRepoTransportFactory(Class<F> factoryClass) {
AssertUtil.assertNotNull(factoryClass, "factoryClass");
List<RepoTransportFactory> repoTransportFactories = getRepoTransportFactories();
for (RepoTransportFactory repoTransportFactory : repoTransportFactories) {
if (factoryClass.isInstance(repoTransportFactory)) {
return factoryClass.cast(repoTransportFactory);
}
}
return null;
}
}