package co.codewizards.cloudstore.ls.core.invoke.filter; import static co.codewizards.cloudstore.core.util.AssertUtil.*; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; public class InvocationFilterRegistry { private List<Class<? extends InvocationFilter>> invocationFilterClasses; private static final class Holder { public static final InvocationFilterRegistry instance = new InvocationFilterRegistry(); } private InvocationFilterRegistry() { } public static InvocationFilterRegistry getInstance() { return Holder.instance; } private List<InvocationFilter> loadInvocationFilters() { final List<InvocationFilter> result = new ArrayList<>(); final Iterator<InvocationFilter> iterator = ServiceLoader.load(InvocationFilter.class).iterator(); while (iterator.hasNext()) result.add(iterator.next()); Collections.sort(result, new Comparator<InvocationFilter>() { @Override public int compare(InvocationFilter o1, InvocationFilter o2) { int result = -1 * Integer.compare(o1.getPriority(), o2.getPriority()); if (result != 0) return result; result = o1.getClass().getName().compareTo(o2.getClass().getName()); return result; } }); return result; } protected List<Class<? extends InvocationFilter>> getInvocationFilterClasses() { if (invocationFilterClasses == null) { final List<InvocationFilter> invocationFilters = loadInvocationFilters(); final List<Class<? extends InvocationFilter>> l = new ArrayList<>(invocationFilters.size()); for (final InvocationFilter invocationFilter : invocationFilters) l.add(invocationFilter.getClass()); invocationFilterClasses = Collections.unmodifiableList(l); } return invocationFilterClasses; } protected List<InvocationFilter> getInvocationFilters() { final List<Class<? extends InvocationFilter>> invocationFilterClasses = getInvocationFilterClasses(); final List<InvocationFilter> result = new ArrayList<InvocationFilter>(invocationFilterClasses.size()); for (Class<? extends InvocationFilter> invocationFilterClass : invocationFilterClasses) result.add(newInstance(invocationFilterClass)); return Collections.unmodifiableList(result); } private <T> T newInstance(Class<T> clazz) { try { return clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } } public boolean canInvoke(final ExtMethodInvocationRequest extMethodInvocationRequest) { assertNotNull(extMethodInvocationRequest, "extMethodInvocationRequest"); for (final InvocationFilter invocationFilter : getInvocationFilters()) { final Boolean result = invocationFilter.canInvoke(extMethodInvocationRequest); if (result != null) return result; } return false; } public void assertCanInvoke(final ExtMethodInvocationRequest extMethodInvocationRequest) { if (! canInvoke(extMethodInvocationRequest)) throw new SecurityException("Invocation denied: " + extMethodInvocationRequest.getMethodInvocationRequest()); } }