/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.capability;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.search.SimpleResultSetMetaData;
import org.alfresco.repo.search.impl.lucene.PagingLuceneResultSet;
import org.alfresco.repo.search.impl.querymodel.QueryEngineResults;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.PermissionCheckCollection;
import org.alfresco.repo.security.permissions.PermissionCheckValue;
import org.alfresco.repo.security.permissions.PermissionCheckedCollection.PermissionCheckedCollectionMixin;
import org.alfresco.repo.security.permissions.PermissionCheckedValue;
import org.alfresco.repo.security.permissions.impl.acegi.ACLEntryVoterException;
import org.alfresco.repo.security.permissions.impl.acegi.FilteringResultSet;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.PermissionEvaluationMode;
import org.alfresco.service.cmr.search.ResultSet;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import net.sf.acegisecurity.AccessDeniedException;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.ConfigAttribute;
import net.sf.acegisecurity.ConfigAttributeDefinition;
import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
/**
* RM After Invocation Provider
*/
@SuppressWarnings("unused")
public class RMAfterInvocationProvider extends RMSecurityCommon
implements AfterInvocationProvider, InitializingBean
{
private static Log logger = LogFactory.getLog(RMAfterInvocationProvider.class);
private static final String AFTER_RM = "AFTER_RM";
private int maxPermissionChecks;
private long maxPermissionCheckTimeMillis;
public boolean supports(ConfigAttribute configAttribute)
{
String attribute = configAttribute.getAttribute();
return (StringUtils.isNotBlank(attribute) && attribute.startsWith(AFTER_RM));
}
@SuppressWarnings("rawtypes")
public boolean supports(Class clazz)
{
return (MethodInvocation.class.isAssignableFrom(clazz));
}
public void afterPropertiesSet()
{
}
/**
* Default constructor
*/
public RMAfterInvocationProvider()
{
super();
maxPermissionChecks = Integer.MAX_VALUE;
maxPermissionCheckTimeMillis = Long.MAX_VALUE;
}
/**
* Set the max number of permission checks
*
* @param maxPermissionChecks
*/
public void setMaxPermissionChecks(int maxPermissionChecks)
{
this.maxPermissionChecks = maxPermissionChecks;
}
/**
* Set the max time for permission checks
*
* @param maxPermissionCheckTimeMillis
*/
public void setMaxPermissionCheckTimeMillis(long maxPermissionCheckTimeMillis)
{
this.maxPermissionCheckTimeMillis = maxPermissionCheckTimeMillis;
}
@SuppressWarnings("rawtypes")
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object returnedObject)
{
if (logger.isDebugEnabled())
{
MethodInvocation mi = (MethodInvocation) object;
if (mi == null)
{
logger.debug("Method is null.");
}
else
{
logger.debug("Method: " + mi.getMethod().toString());
}
}
try
{
if (AuthenticationUtil.isRunAsUserTheSystemUser())
{
if (logger.isDebugEnabled())
{
logger.debug("Allowing system user access");
}
return returnedObject;
}
else if (returnedObject == null)
{
if (logger.isDebugEnabled())
{
logger.debug("Allowing null object access");
}
return null;
}
else if (PermissionCheckedValue.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (PermissionCheckedValue) returnedObject);
}
else if (PermissionCheckValue.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (PermissionCheckValue) returnedObject);
}
else if (StoreRef.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, nodeService.getRootNode((StoreRef) returnedObject)).getStoreRef();
}
else if (NodeRef.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (NodeRef) returnedObject);
}
else if (ChildAssociationRef.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (ChildAssociationRef) returnedObject);
}
else if (AssociationRef.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (AssociationRef) returnedObject);
}
else if (ResultSet.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (ResultSet) returnedObject);
}
else if (PagingLuceneResultSet.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (PagingLuceneResultSet) returnedObject);
}
else if (QueryEngineResults.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (QueryEngineResults) returnedObject);
}
else if (Collection.class.isAssignableFrom(returnedObject.getClass()))
{
return decide(authentication, object, config, (Collection) returnedObject);
}
else if (returnedObject.getClass().isArray())
{
return decide(authentication, object, config, (Object[]) returnedObject);
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("Uncontrolled object - access allowed for " + object.getClass().getName());
}
return returnedObject;
}
}
catch (AccessDeniedException ade)
{
if (logger.isDebugEnabled())
{
logger.debug("Access denied: " + ade.getMessage());
}
throw ade;
}
catch (RuntimeException re)
{
if (logger.isDebugEnabled())
{
logger.debug("Access denied by runtime exception: " + re.getMessage());
}
throw re;
}
}
private PermissionCheckedValue decide(Authentication authentication, Object object, ConfigAttributeDefinition config, PermissionCheckedValue returnedObject)
{
// This passes as it has already been filtered
// TODO: Get the filter that was applied and double-check
return returnedObject;
}
private PermissionCheckValue decide(Authentication authentication, Object object, ConfigAttributeDefinition config, PermissionCheckValue returnedObject)
{
// Get the wrapped value
NodeRef nodeRef = returnedObject.getNodeRef();
decide(authentication, object, config, nodeRef);
// This passes
return returnedObject;
}
private NodeRef decide(Authentication authentication, Object object, ConfigAttributeDefinition config, NodeRef returnedObject)
{
if (returnedObject == null)
{
return null;
}
if (isUnfiltered(returnedObject))
{
return returnedObject;
}
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
if (supportedDefinitions.size() == 0)
{
return returnedObject;
}
int parentResult = checkRead(nodeService.getPrimaryParent(returnedObject).getParentRef());
int childResult = checkRead(returnedObject);
checkSupportedDefinitions(supportedDefinitions, parentResult, childResult);
return returnedObject;
}
private void checkSupportedDefinitions(List<ConfigAttributeDefintion> supportedDefinitions, int parentResult, int childResult)
{
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
if (cad.parent && parentResult == AccessDecisionVoter.ACCESS_DENIED)
{
throw new AccessDeniedException("Access Denied");
}
else if (!cad.parent && childResult == AccessDecisionVoter.ACCESS_DENIED)
{
throw new AccessDeniedException("Access Denied");
}
}
}
private boolean isUnfiltered(NodeRef nodeRef)
{
return !nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT);
}
@SuppressWarnings("rawtypes")
private List<ConfigAttributeDefintion> extractSupportedDefinitions(ConfigAttributeDefinition config)
{
List<ConfigAttributeDefintion> definitions = new ArrayList<>();
Iterator iter = config.getConfigAttributes();
while (iter.hasNext())
{
ConfigAttribute attr = (ConfigAttribute) iter.next();
if (this.supports(attr))
{
definitions.add(new ConfigAttributeDefintion(attr));
}
}
return definitions;
}
private ChildAssociationRef decide(Authentication authentication, Object object, ConfigAttributeDefinition config, ChildAssociationRef returnedObject)
{
if (returnedObject == null)
{
return null;
}
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
if (supportedDefinitions.size() == 0)
{
return returnedObject;
}
int parentReadCheck = checkRead(returnedObject.getParentRef());
int childReadCheck = checkRead(returnedObject.getChildRef());
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
NodeRef testNodeRef = null;
if (cad.parent)
{
testNodeRef = returnedObject.getParentRef();
}
else
{
testNodeRef = returnedObject.getChildRef();
}
// Enforce Read Policy
if (isUnfiltered(testNodeRef))
{
continue;
}
if (cad.parent && parentReadCheck != AccessDecisionVoter.ACCESS_GRANTED)
{
throw new AccessDeniedException("Access Denied");
}
else if (childReadCheck != AccessDecisionVoter.ACCESS_GRANTED)
{
throw new AccessDeniedException("Access Denied");
}
}
return returnedObject;
}
private AssociationRef decide(Authentication authentication, Object object, ConfigAttributeDefinition config, AssociationRef returnedObject)
{
if (returnedObject == null)
{
return null;
}
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
if (supportedDefinitions.size() == 0)
{
return returnedObject;
}
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
NodeRef testNodeRef = null;
if (cad.parent)
{
testNodeRef = returnedObject.getSourceRef();
}
else
{
testNodeRef = returnedObject.getTargetRef();
}
if (isUnfiltered(testNodeRef))
{
continue;
}
if (checkRead(testNodeRef) != AccessDecisionVoter.ACCESS_GRANTED)
{
throw new AccessDeniedException("Access Denied");
}
}
return returnedObject;
}
private ResultSet decide(Authentication authentication, Object object, ConfigAttributeDefinition config, PagingLuceneResultSet returnedObject)
{
ResultSet raw = returnedObject.getWrapped();
ResultSet filteredForPermissions = decide(authentication, object, config, raw);
return new PagingLuceneResultSet(filteredForPermissions, returnedObject.getResultSetMetaData().getSearchParameters(), nodeService);
}
private ResultSet decide(Authentication authentication, Object object, ConfigAttributeDefinition config, ResultSet returnedObject)
{
if (returnedObject == null)
{
return null;
}
class RMFilteringResultSet extends FilteringResultSet
{
private long numberFound;
public RMFilteringResultSet(ResultSet unfiltered, BitSet inclusionMask)
{
super(unfiltered, inclusionMask);
}
@Override
public long getNumberFound()
{
return numberFound;
}
private void setNumberFound(long numberFound)
{
this.numberFound = numberFound;
}
}
BitSet inclusionMask = new BitSet(returnedObject.length());
RMFilteringResultSet filteringResultSet = new RMFilteringResultSet(returnedObject, inclusionMask);
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
Integer maxSize = null;
if (returnedObject.getResultSetMetaData().getSearchParameters().getMaxItems() >= 0)
{
maxSize = Integer.valueOf(returnedObject.getResultSetMetaData().getSearchParameters().getMaxItems());
}
if ((maxSize == null) && (returnedObject.getResultSetMetaData().getSearchParameters().getLimitBy() == LimitBy.FINAL_SIZE))
{
maxSize = Integer.valueOf(returnedObject.getResultSetMetaData().getSearchParameters().getLimit());
}
// Allow for skip
if ((maxSize != null) && (returnedObject.getResultSetMetaData().getSearchParameters().getSkipCount() >= 0))
{
maxSize = Integer.valueOf(maxSize + returnedObject.getResultSetMetaData().getSearchParameters().getSkipCount());
}
if (supportedDefinitions.size() == 0)
{
if (maxSize == null)
{
return returnedObject;
}
else if (returnedObject.length() > maxSize.intValue())
{
for (int i = 0; i < maxSize.intValue(); i++)
{
inclusionMask.set(i, true);
}
filteringResultSet.setResultSetMetaData(
new SimpleResultSetMetaData(
returnedObject.getResultSetMetaData().getLimitedBy(),
PermissionEvaluationMode.EAGER,
returnedObject.getResultSetMetaData().getSearchParameters()));
return filteringResultSet;
}
else
{
for (int i = 0; i < returnedObject.length(); i++)
{
inclusionMask.set(i, true);
}
filteringResultSet.setResultSetMetaData(
new SimpleResultSetMetaData(
returnedObject.getResultSetMetaData().getLimitedBy(),
PermissionEvaluationMode.EAGER,
returnedObject.getResultSetMetaData().getSearchParameters()));
return filteringResultSet;
}
}
// record the start time
long startTimeMillis = System.currentTimeMillis();
// set the default, unlimited resultset type
filteringResultSet.setResultSetMetaData(
new SimpleResultSetMetaData(
returnedObject.getResultSetMetaData().getLimitedBy(),
PermissionEvaluationMode.EAGER,
returnedObject.getResultSetMetaData().getSearchParameters()));
for (int i = 0; i < returnedObject.length(); i++)
{
long currentTimeMillis = System.currentTimeMillis();
// All permission checks must pass
inclusionMask.set(i, true);
if (!nodeService.exists(returnedObject.getNodeRef(i)))
{
inclusionMask.set(i, false);
}
else
{
int parentCheckRead = checkRead(returnedObject.getChildAssocRef(i).getParentRef());
int childCheckRead = checkRead(returnedObject.getNodeRef(i));
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
NodeRef testNodeRef = returnedObject.getNodeRef(i);
int checkRead = childCheckRead;
if (cad.parent)
{
testNodeRef = returnedObject.getChildAssocRef(i).getParentRef();
checkRead = parentCheckRead;
}
if (isUnfiltered(testNodeRef))
{
continue;
}
if (inclusionMask.get(i) && (testNodeRef != null) && (checkRead != AccessDecisionVoter.ACCESS_GRANTED))
{
inclusionMask.set(i, false);
}
}
}
// Bug out if we are limiting by size
if ((maxSize != null) && (filteringResultSet.length() > maxSize.intValue()))
{
// Remove the last match to fix the correct size
inclusionMask.set(i, false);
filteringResultSet.setResultSetMetaData(new SimpleResultSetMetaData(LimitBy.FINAL_SIZE, PermissionEvaluationMode.EAGER, returnedObject.getResultSetMetaData()
.getSearchParameters()));
break;
}
}
filteringResultSet.setNumberFound(returnedObject.getNumberFound());
return filteringResultSet;
}
private QueryEngineResults decide(Authentication authentication, Object object, ConfigAttributeDefinition config, QueryEngineResults returnedObject)
{
Map<Set<String>, ResultSet> map = returnedObject.getResults();
Map<Set<String>, ResultSet> answer = new HashMap<Set<String>, ResultSet>(map.size(), 1.0f);
for (Map.Entry<Set<String>, ResultSet> entry : map.entrySet())
{
ResultSet raw = entry.getValue();
ResultSet permed;
if (PagingLuceneResultSet.class.isAssignableFrom(raw.getClass()))
{
permed = decide(authentication, object, config, (PagingLuceneResultSet) raw);
}
else
{
permed = decide(authentication, object, config, raw);
}
answer.put(entry.getKey(), permed);
}
return new QueryEngineResults(answer);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Collection decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Collection returnedObject)
{
if (returnedObject == null)
{
return null;
}
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
if (logger.isDebugEnabled())
{
logger.debug("Entries are " + supportedDefinitions);
}
if (supportedDefinitions.size() == 0)
{
return returnedObject;
}
// Default to the system-wide values and we'll see if they need to be reduced
long targetResultCount = returnedObject.size();
int maxPermissionChecks = Integer.MAX_VALUE;
long maxPermissionCheckTimeMillis = this.maxPermissionCheckTimeMillis;
if (returnedObject instanceof PermissionCheckCollection<?>)
{
PermissionCheckCollection permissionCheckCollection = (PermissionCheckCollection) returnedObject;
// Get values
targetResultCount = permissionCheckCollection.getTargetResultCount();
if (permissionCheckCollection.getCutOffAfterCount() > 0)
{
maxPermissionChecks = permissionCheckCollection.getCutOffAfterCount();
}
if (permissionCheckCollection.getCutOffAfterTimeMs() > 0)
{
maxPermissionCheckTimeMillis = permissionCheckCollection.getCutOffAfterTimeMs();
}
}
// Start timer and counter for cut-off
boolean cutoff = false;
long startTimeMillis = System.currentTimeMillis();
int count = 0;
// Keep values explicitly
List<Object> keepValues = new ArrayList<Object>(returnedObject.size());
for (Object nextObject : returnedObject)
{
// if the maximum result size or time has been exceeded, then we have to remove only
long currentTimeMillis = System.currentTimeMillis();
// NOTE: for reference - the "maxPermissionChecks" has never been honoured by this loop (since previously the count was not being incremented)
if (count >= targetResultCount)
{
// We have enough results. We stop without cutoff.
break;
}
else if (count >= maxPermissionChecks)
{
// We have been cut off by count
cutoff = true;
if (logger.isDebugEnabled())
{
logger.debug("decide (collection) cut-off: " + count + " checks exceeded " + maxPermissionChecks + " checks");
}
break;
}
else if ((currentTimeMillis - startTimeMillis) > maxPermissionCheckTimeMillis)
{
// We have been cut off by time
cutoff = true;
if (logger.isDebugEnabled())
{
logger.debug("decide (collection) cut-off: " + (currentTimeMillis - startTimeMillis) + "ms exceeded " + maxPermissionCheckTimeMillis + "ms");
}
break;
}
boolean allowed = true;
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
if (cad.mode.equalsIgnoreCase("FilterNode"))
{
NodeRef testNodeRef = null;
if (cad.parent)
{
if (StoreRef.class.isAssignableFrom(nextObject.getClass()))
{
// Will be allowed
testNodeRef = null;
}
else if (NodeRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = nodeService.getPrimaryParent((NodeRef) nextObject).getParentRef();
}
else if (ChildAssociationRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = ((ChildAssociationRef) nextObject).getParentRef();
}
else if (AssociationRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = ((AssociationRef) nextObject).getSourceRef();
}
else if (PermissionCheckValue.class.isAssignableFrom(nextObject.getClass()))
{
NodeRef nodeRef = ((PermissionCheckValue) nextObject).getNodeRef();
testNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
}
else
{
throw new ACLEntryVoterException("The specified parameter is recognized: " + nextObject.getClass());
}
}
else
{
if (StoreRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = nodeService.getRootNode((StoreRef) nextObject);
}
else if (NodeRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = (NodeRef) nextObject;
}
else if (ChildAssociationRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = ((ChildAssociationRef) nextObject).getChildRef();
}
else if (AssociationRef.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = ((AssociationRef) nextObject).getTargetRef();
}
else if (PermissionCheckValue.class.isAssignableFrom(nextObject.getClass()))
{
testNodeRef = ((PermissionCheckValue) nextObject).getNodeRef();
}
else
{
throw new ACLEntryVoterException("The specified parameter is recognized: " + nextObject.getClass());
}
}
if (logger.isDebugEnabled())
{
logger.debug("\t" + cad.typeString + " test on " + testNodeRef + " from " + nextObject.getClass().getName());
}
// Null allows
if (isUnfiltered(testNodeRef))
{
// Continue to next ConfigAttributeDefintion
continue;
}
if (allowed &&
testNodeRef != null &&
checkRead(testNodeRef) != AccessDecisionVoter.ACCESS_GRANTED)
{
allowed = false;
// No point evaluating more ConfigAttributeDefintions
break;
}
}
}
// Failure or success, increase the count
count++;
if (allowed)
{
keepValues.add(nextObject);
}
}
// Work out how many were left unchecked (for whatever reason)
int sizeOriginal = returnedObject.size();
int checksRemaining = sizeOriginal - count;
// Note: There are use-cases where unmodifiable collections are passing through.
// So make sure that the collection needs modification at all
if (keepValues.size() < sizeOriginal)
{
// There are values that need to be removed. We have to modify the collection.
try
{
returnedObject.clear();
returnedObject.addAll(keepValues);
}
catch (UnsupportedOperationException e)
{
throw new AccessDeniedException("Permission-checked list must be modifiable", e);
}
}
// Attach the extra permission-check data to the collection
return PermissionCheckedCollectionMixin.create(returnedObject, cutoff, checksRemaining, sizeOriginal);
}
private Object[] decide(Authentication authentication, Object object, ConfigAttributeDefinition config, Object[] returnedObject)
{
// Assumption: value is not null
BitSet incudedSet = new BitSet(returnedObject.length);
List<ConfigAttributeDefintion> supportedDefinitions = extractSupportedDefinitions(config);
if (supportedDefinitions.size() == 0)
{
return returnedObject;
}
for (int i = 0, l = returnedObject.length; i < l; i++)
{
Object current = returnedObject[i];
int parentReadCheck = checkRead(getParentReadCheckNode(current));
int childReadChek = checkRead(getChildReadCheckNode(current));
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
incudedSet.set(i, true);
NodeRef testNodeRef = null;
if (cad.parent)
{
if (StoreRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = null;
}
else if (NodeRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = nodeService.getPrimaryParent((NodeRef) current).getParentRef();
}
else if (ChildAssociationRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = ((ChildAssociationRef) current).getParentRef();
}
else if (PermissionCheckValue.class.isAssignableFrom(current.getClass()))
{
NodeRef nodeRef = ((PermissionCheckValue) current).getNodeRef();
testNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
}
else
{
throw new ACLEntryVoterException("The specified parameter is recognized: " + current.getClass());
}
}
else
{
if (StoreRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = nodeService.getRootNode((StoreRef) current);
}
else if (NodeRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = (NodeRef) current;
}
else if (ChildAssociationRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = ((ChildAssociationRef) current).getChildRef();
}
else if (PermissionCheckValue.class.isAssignableFrom(current.getClass()))
{
testNodeRef = ((PermissionCheckValue) current).getNodeRef();
}
else
{
throw new ACLEntryVoterException("The specified parameter is recognized: " + current.getClass());
}
}
if (logger.isDebugEnabled())
{
logger.debug("\t" + cad.typeString + " test on " + testNodeRef + " from " + current.getClass().getName());
}
if (isUnfiltered(testNodeRef))
{
continue;
}
int readCheck = childReadChek;
if (cad.parent)
{
readCheck = parentReadCheck;
}
if (incudedSet.get(i) && (testNodeRef != null) && (readCheck != AccessDecisionVoter.ACCESS_GRANTED))
{
incudedSet.set(i, false);
}
}
}
if (incudedSet.cardinality() == returnedObject.length)
{
return returnedObject;
}
else
{
Object[] answer = new Object[incudedSet.cardinality()];
for (int i = incudedSet.nextSetBit(0), p = 0; i >= 0; i = incudedSet.nextSetBit(++i), p++)
{
answer[p] = returnedObject[i];
}
return answer;
}
}
private NodeRef getParentReadCheckNode(Object current)
{
NodeRef testNodeRef = null;
if (StoreRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = null;
}
else if (NodeRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = nodeService.getPrimaryParent((NodeRef) current).getParentRef();
}
else if (ChildAssociationRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = ((ChildAssociationRef) current).getParentRef();
}
else if (PermissionCheckValue.class.isAssignableFrom(current.getClass()))
{
NodeRef nodeRef = ((PermissionCheckValue) current).getNodeRef();
testNodeRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
}
else
{
throw new ACLEntryVoterException("The specified array is not of NodeRef or ChildAssociationRef");
}
return testNodeRef;
}
private NodeRef getChildReadCheckNode(Object current)
{
NodeRef testNodeRef = null;
if (StoreRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = nodeService.getRootNode((StoreRef) current);
}
else if (NodeRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = (NodeRef) current;
}
else if (ChildAssociationRef.class.isAssignableFrom(current.getClass()))
{
testNodeRef = ((ChildAssociationRef) current).getChildRef();
}
else if (PermissionCheckValue.class.isAssignableFrom(current.getClass()))
{
testNodeRef = ((PermissionCheckValue) current).getNodeRef();
}
else
{
throw new ACLEntryVoterException("The specified array is not of NodeRef or ChildAssociationRef");
}
return testNodeRef;
}
private class ConfigAttributeDefintion
{
String typeString;
String mode;
boolean parent = false;
ConfigAttributeDefintion(ConfigAttribute attr)
{
StringTokenizer st = new StringTokenizer(attr.getAttribute(), ".", false);
typeString = st.nextToken();
if (!(typeString.equals(AFTER_RM)))
{
throw new ACLEntryVoterException("Invalid type: must be AFTER_RM");
}
mode = st.nextToken();
if (st.hasMoreElements())
{
parent = true;
}
}
}
}