package org.carlspring.strongbox.authentication.registry; import org.carlspring.strongbox.authentication.api.Authenticator; import org.carlspring.strongbox.authentication.registry.support.xml.AuthenticatorsAdapter; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; /** * @author Przemyslaw Fusik */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class AuthenticatorsRegistry implements Iterable<Authenticator> { @XmlElement(name = "authenticators") @XmlJavaTypeAdapter(AuthenticatorsAdapter.class) private volatile Authenticator[] array; /** * Creates an empty registry. */ public AuthenticatorsRegistry() { setArray(new Authenticator[0]); } /** * Creates a registry containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. */ public AuthenticatorsRegistry(Collection<? extends Authenticator> c) { reloadInternally(c); } private Authenticator[] getArray() { return array; } private void setArray(Authenticator[] elements) { array = Arrays.copyOf(elements, elements.length); } /** * Reloads the registry by replacing all authenticators using * given collection. * * @param c new collection of authenticators */ public synchronized void reload(Collection<? extends Authenticator> c) { reloadInternally(c); } /** * Reorders elements in the registry. */ public synchronized void reorder(int first, int second) { Authenticator[] elements = getArray(); elements = Arrays.copyOf(elements, elements.length); final Authenticator firstA = elements[first]; final Authenticator secondA = elements[second]; elements[first] = secondA; elements[second] = firstA; setArray(elements); } public int size() { return getArray().length; } public boolean isEmpty() { return size() == 0; } private void reloadInternally(Collection<? extends Authenticator> c) { final Authenticator[] elements = c.toArray(new Authenticator[0]); setArray(elements); } @Override public String toString() { final StringBuilder builder = new StringBuilder(); final Authenticator[] view = getArray(); for (int index = 0; index < view.length; index++) { final Authenticator authenticator = view[index]; builder.append(Arrays.toString(new Object[]{ index, authenticator.getName() })); } return builder.toString(); } @Override public Iterator<Authenticator> iterator() { return new COWIterator(getArray(), 0); } static final class COWIterator implements Iterator<Authenticator> { private final Authenticator[] snapshot; private int cursor; private COWIterator(Authenticator[] elements, int initialCursor) { cursor = initialCursor; snapshot = Arrays.copyOf(elements, elements.length); } @Override public boolean hasNext() { return cursor < snapshot.length; } @Override public Authenticator next() { if (!hasNext()) { throw new NoSuchElementException(); } return snapshot[cursor++]; } } }