001package co.codewizards.cloudstore.core.repo.transport; 002 003import static co.codewizards.cloudstore.core.util.Util.*; 004 005import java.net.URL; 006import java.util.ArrayList; 007import java.util.Collections; 008import java.util.Comparator; 009import java.util.Iterator; 010import java.util.List; 011import java.util.ServiceLoader; 012 013import co.codewizards.cloudstore.core.util.AssertUtil; 014 015public class RepoTransportFactoryRegistry { 016 017 private static class RepoTransportFactoryRegistryHolder { 018 public static final RepoTransportFactoryRegistry instance = new RepoTransportFactoryRegistry(); 019 } 020 021 public static RepoTransportFactoryRegistry getInstance() { 022 return RepoTransportFactoryRegistryHolder.instance; 023 } 024 025 protected RepoTransportFactoryRegistry() { } 026 027 private List<RepoTransportFactory> repoTransportFactories; 028 029 public RepoTransportFactory getRepoTransportFactoryOrFail(URL remoteRoot) { 030 RepoTransportFactory repoTransportFactory = getRepoTransportFactory(remoteRoot); 031 if (repoTransportFactory == null) 032 throw new IllegalStateException("There is no RepoTransportFactory supporting this URL: " + remoteRoot); 033 034 return repoTransportFactory; 035 } 036 037 public RepoTransportFactory getRepoTransportFactory(URL remoteRoot) { 038 for (RepoTransportFactory factory : getRepoTransportFactories()) { 039 if (factory.isSupported(remoteRoot)) 040 return factory; 041 } 042 return null; 043 } 044 045 public List<RepoTransportFactory> getRepoTransportFactories(URL remoteRoot) { 046 List<RepoTransportFactory> result = new ArrayList<RepoTransportFactory>(); 047 for (RepoTransportFactory factory : getRepoTransportFactories()) { 048 if (factory.isSupported(remoteRoot)) 049 result.add(factory); 050 } 051 return Collections.unmodifiableList(result); 052 } 053 054 public synchronized List<RepoTransportFactory> getRepoTransportFactories() { 055 List<RepoTransportFactory> repoTransportFactories = this.repoTransportFactories; 056 if (repoTransportFactories == null) { 057 repoTransportFactories = loadRepoTransportFactoriesViaServiceLoader(); 058 sortRepoTransportFactories(repoTransportFactories); 059 this.repoTransportFactories = repoTransportFactories = Collections.unmodifiableList(repoTransportFactories); 060 } 061 return repoTransportFactories; 062 } 063 064 private static List<RepoTransportFactory> loadRepoTransportFactoriesViaServiceLoader() { 065 ArrayList<RepoTransportFactory> repoTransportFactories = new ArrayList<RepoTransportFactory>(); 066 ServiceLoader<RepoTransportFactory> sl = ServiceLoader.load(RepoTransportFactory.class); 067 for (Iterator<RepoTransportFactory> it = sl.iterator(); it.hasNext(); ) { 068 repoTransportFactories.add(it.next()); 069 } 070 repoTransportFactories.trimToSize(); 071 return repoTransportFactories; 072 } 073 074 protected static int _compare(int x, int y) { 075 return (x < y) ? -1 : ((x == y) ? 0 : 1); 076 } 077 078 private static void sortRepoTransportFactories(List<RepoTransportFactory> repoTransportFactories) { 079 Collections.sort(repoTransportFactories, new Comparator<RepoTransportFactory>() { 080 @Override 081 public int compare(RepoTransportFactory o1, RepoTransportFactory o2) { 082 int result = -1 * _compare(o1.getPriority(), o2.getPriority()); 083 if (result != 0) 084 return result; 085 086 String name1 = o1.getName() == null ? "" : o1.getName(); 087 String name2 = o2.getName() == null ? "" : o2.getName(); 088 result = name1.compareTo(name2); 089 if (result != 0) 090 return result; 091 092 return o1.getClass().getName().compareTo(o2.getClass().getName()); 093 } 094 }); 095 } 096 097 public <F extends RepoTransportFactory> F getRepoTransportFactoryOrFail(Class<F> factoryClass) { 098 F repoTransportFactory = getRepoTransportFactory(factoryClass); 099 if (repoTransportFactory == null) 100 throw new IllegalArgumentException("There is no factory registered implementing this interface or extending this class: " + factoryClass.getName()); 101 102 return repoTransportFactory; 103 } 104 105 public <F extends RepoTransportFactory> F getRepoTransportFactory(Class<F> factoryClass) { 106 AssertUtil.assertNotNull(factoryClass, "factoryClass"); 107 List<RepoTransportFactory> repoTransportFactories = getRepoTransportFactories(); 108 for (RepoTransportFactory repoTransportFactory : repoTransportFactories) { 109 if (factoryClass.isInstance(repoTransportFactory)) { 110 return factoryClass.cast(repoTransportFactory); 111 } 112 } 113 return null; 114 } 115}