001package co.codewizards.cloudstore.ls.core.invoke.filter; 002 003import static java.util.Objects.*; 004 005import java.util.ArrayList; 006import java.util.Collections; 007import java.util.Comparator; 008import java.util.Iterator; 009import java.util.List; 010import java.util.ServiceLoader; 011 012public class InvocationFilterRegistry { 013 014 private List<Class<? extends InvocationFilter>> invocationFilterClasses; 015 016 private static final class Holder { 017 public static final InvocationFilterRegistry instance = new InvocationFilterRegistry(); 018 } 019 020 private InvocationFilterRegistry() { 021 } 022 023 public static InvocationFilterRegistry getInstance() { 024 return Holder.instance; 025 } 026 027 private List<InvocationFilter> loadInvocationFilters() { 028 final List<InvocationFilter> result = new ArrayList<>(); 029 030 final Iterator<InvocationFilter> iterator = ServiceLoader.load(InvocationFilter.class).iterator(); 031 while (iterator.hasNext()) 032 result.add(iterator.next()); 033 034 Collections.sort(result, new Comparator<InvocationFilter>() { 035 @Override 036 public int compare(InvocationFilter o1, InvocationFilter o2) { 037 int result = -1 * Integer.compare(o1.getPriority(), o2.getPriority()); 038 if (result != 0) 039 return result; 040 041 result = o1.getClass().getName().compareTo(o2.getClass().getName()); 042 return result; 043 } 044 }); 045 return result; 046 } 047 048 protected List<Class<? extends InvocationFilter>> getInvocationFilterClasses() { 049 if (invocationFilterClasses == null) { 050 final List<InvocationFilter> invocationFilters = loadInvocationFilters(); 051 final List<Class<? extends InvocationFilter>> l = new ArrayList<>(invocationFilters.size()); 052 for (final InvocationFilter invocationFilter : invocationFilters) 053 l.add(invocationFilter.getClass()); 054 055 invocationFilterClasses = Collections.unmodifiableList(l); 056 } 057 return invocationFilterClasses; 058 } 059 060 protected List<InvocationFilter> getInvocationFilters() { 061 final List<Class<? extends InvocationFilter>> invocationFilterClasses = getInvocationFilterClasses(); 062 063 final List<InvocationFilter> result = new ArrayList<InvocationFilter>(invocationFilterClasses.size()); 064 for (Class<? extends InvocationFilter> invocationFilterClass : invocationFilterClasses) 065 result.add(newInstance(invocationFilterClass)); 066 067 return Collections.unmodifiableList(result); 068 } 069 070 private <T> T newInstance(Class<T> clazz) { 071 try { 072 return clazz.newInstance(); 073 } catch (InstantiationException | IllegalAccessException e) { 074 throw new RuntimeException(e); 075 } 076 } 077 078 public boolean canInvoke(final ExtMethodInvocationRequest extMethodInvocationRequest) { 079 requireNonNull(extMethodInvocationRequest, "extMethodInvocationRequest"); 080 for (final InvocationFilter invocationFilter : getInvocationFilters()) { 081 final Boolean result = invocationFilter.canInvoke(extMethodInvocationRequest); 082 if (result != null) 083 return result; 084 } 085 return false; 086 } 087 088 public void assertCanInvoke(final ExtMethodInvocationRequest extMethodInvocationRequest) { 089 if (! canInvoke(extMethodInvocationRequest)) 090 throw new SecurityException("Invocation denied: " + extMethodInvocationRequest.getMethodInvocationRequest()); 091 } 092}