com.day.cq.mailer.commons.AuthorizableGroupMailingList Maven / Gradle / Ivy
/*
* ADOBE CONFIDENTIAL
* ___________________
*
* Copyright 2012 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*/
package com.day.cq.mailer.commons;
import com.day.cq.mailer.AuthorizableMailingList;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.collections.Predicate;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import javax.jcr.RepositoryException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Stack;
/**
* MailingList that takes a {@link org.apache.jackrabbit.api.security.user.Group Group's} members as
* its members. The List unfolds the transitive dependencies of
* {@link org.apache.jackrabbit.api.security.user.Group#getMembers()} Group membership}
*
* @see com.day.cq.mailer.AuthorizableMailingList
*
*/
public class AuthorizableGroupMailingList implements AuthorizableMailingList {
private final Group group;
private Predicate filterPredicate;
/**
* @param group Group
*/
public AuthorizableGroupMailingList(Group group) {
this(group, null);
}
/**
* Constructor to set an optional filter predicate.
*
* @param group
* group this list represents
* @param filterPredicate
* an optional filter predicate to filter the group members when
* accessing the {@link #members()} method.
*/
public AuthorizableGroupMailingList(Group group, Predicate filterPredicate) {
this.group = group;
this.filterPredicate = filterPredicate;
}
/**
* @return all members of the Group including transitive members
* @throws javax.jcr.RepositoryException if an error occurs.
*/
public Iterator members() throws RepositoryException {
if (filterPredicate == null) {
return new GroupUnfoldingIterator(group.getDeclaredMembers());
} else {
return (Iterator) IteratorUtils.filteredIterator(new GroupUnfoldingIterator(group.getDeclaredMembers()),
filterPredicate);
}
}
/**
* This Iterator iterates includes all
* {@link org.apache.jackrabbit.api.security.user.Authorizable Authorizables} of the backing
* Iterator. It "unfolds" any transitive membership. This means, if the
* backing iterator contains a Group A that has a Group B as member, this
* iterator will have contain the members of Group B
*/
private static final class GroupUnfoldingIterator implements Iterator {
private final Stack> iterators = new Stack>();
private final HashSet served = new HashSet();
private Authorizable next;
GroupUnfoldingIterator(Iterator base) throws RepositoryException {
iterators.push(base);
next = seek();
}
public boolean hasNext() {
return next != null;
}
public Authorizable next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Authorizable serve = next;
try {
next = seek();
} catch (RepositoryException e) {
throw new RuntimeException(e);
}
return serve;
}
public void remove() {
throw new UnsupportedOperationException();
}
private Authorizable seek() throws RepositoryException {
while (!iterators.isEmpty()) {
Iterator current = iterators.pop();
while (current != null && current.hasNext()) {
Authorizable test = current.next();
if (!served.contains(test.getID())) {
served.add(test.getID());
if (current.hasNext()) {
iterators.push(current);
}
if (test.isGroup()) {
iterators.push(((Group) test).getDeclaredMembers());
}
return test;
}
}
}
return null;
}
}
}