package org.apache.jackrabbit.core.security.authorization.acl;
import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.id.ItemId;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.RepositoryException;
import java.util.Collection;
import java.util.List;
/**
* Copy-and-paste of {@code org.apache.jackrabbit.core.security.authorization.acl} in Jackrabbit 2.10.0.
* This class is in {@code org.apache.jackrabbit.core.security.authorization.acl} package due to the scope of
* collaborating classes.
*
* <p/>
* <p/>
* <p> Changes to original: </p> <ul> <li>{@code Entry} has a single private constructor, we changed the
* scope to public {@code null} {@code nextId}.</li>
* <p/>
* </ul>
*/
public class PentahoEntryFilterImpl extends EntryFilterImpl implements PentahoEntryFilter {
/**
* logger instance
*/
private static final Logger log = LoggerFactory.getLogger(PentahoEntryFilterImpl.class);
private final Collection<String> principalNames;
private final PathProvider pathProvider;
private String itemPath;
PentahoEntryFilterImpl(Collection<String> principalNames, final ItemId id, final SessionImpl sessionImpl) {
super( principalNames , id , sessionImpl );
this.principalNames = principalNames;
this.pathProvider = new PathProvider() {
public String getPath() throws RepositoryException {
Path p = sessionImpl.getHierarchyManager().getPath(id);
return sessionImpl.getJCRPath(p);
}
};
}
PentahoEntryFilterImpl(Collection<String> principalNames, final Path absPath, final PathResolver pathResolver) {
super( principalNames, absPath, pathResolver );
this.principalNames = principalNames;
this.pathProvider = new PathProvider() {
public String getPath() throws RepositoryException {
return pathResolver.getJCRPath(absPath);
}
};
}
/**
* Separately collect the entries defined for the user and group
* principals.
*
* @param entries
* @param resultLists
* @see EntryFilter#filterEntries(java.util.List, java.util.List[])
*/
@Override
public void filterEntries( List entries, List... resultLists ) {
if ( resultLists.length == 2 ) {
List<PentahoEntry> userAces = resultLists[0];
List<PentahoEntry> groupAces = resultLists[1];
int uInsertIndex = userAces.size();
int gInsertIndex = groupAces.size();
// first collect aces present on the given aclNode.
for ( PentahoEntry ace : ( List<PentahoEntry> ) entries ) {
// only process ace if 'principalName' is contained in the given set
if ( matches( ace ) ) {
// add it to the proper list (e.g. separated by principals)
/**
* NOTE: access control entries must be collected in reverse
* order in order to assert proper evaluation.
*/
if ( ace.isGroupEntry() ) {
groupAces.add( gInsertIndex, ace );
} else {
userAces.add( uInsertIndex, ace );
}
}
}
} else {
log.warn( "Filtering aborted. Expected 2 result lists." );
}
}
private boolean matches( PentahoEntry entry ) {
if ( principalNames == null || principalNames.contains( entry.getPrincipalName() ) ) {
if ( !entry.hasRestrictions() ) {
// short cut: there is no glob-restriction -> the entry matches
// because it is either defined on the node or inherited.
return true;
} else {
// there is a glob-restriction: check if the target path matches
// this entry.
try {
return entry.matches(getPath());
} catch (RepositoryException e) {
log.error("Cannot determine ACE match.", e);
}
}
}
// doesn't match this filter -> ignore
return false;
}
String getPath() throws RepositoryException {
if (itemPath == null) {
itemPath = pathProvider.getPath();
}
return itemPath;
}
//--------------------------------------------------------------------------
/**
* Interface for lazy calculation of the JCR path used for evaluation of ACE
* matching in case of entries defining restriction(s).
*/
private interface PathProvider {
String getPath() throws RepositoryException;
}
}