in oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java [679:766]
public boolean hasCapability(String methodName, Object target, Object[] arguments) throws RepositoryException {
requireNonNull(methodName, "parameter 'methodName' must not be null");
requireNonNull(target, "parameter 'target' must not be null");
checkAlive();
AccessManager accessMgr = sessionContext.getAccessManager();
if (target instanceof ItemImpl) {
ItemDelegate dlg = ((ItemImpl<?>) target).dlg;
if (dlg.isProtected()) {
return false;
}
boolean isNode = ((ItemImpl<?>) target).isNode();
NodeImpl parent = (NodeImpl) ((isNode) ? target : ((ItemImpl<?>) target).getParent());
if (!parent.internalIsCheckedOut()) {
return false;
}
boolean hasLocking = sessionContext.getRepository().getDescriptorValue(Repository.OPTION_LOCKING_SUPPORTED)
.getBoolean();
if (hasLocking && parent.isLocked()) {
return false;
}
long permission = Permissions.NO_PERMISSION;
if (isNode) {
Tree tree = ((NodeDelegate) dlg).getTree();
if ("addNode".equals(methodName)) {
String relPath = getFirstArgument(arguments);
if (relPath != null) {
// add-node needs to be checked on the (path of) the
// new node that has/will be added
String path = PathUtils.concat(tree.getPath(), sessionContext.getOakPathOrThrow(relPath));
return accessMgr.hasPermissions(path, Session.ACTION_ADD_NODE) && !isMountedReadOnly(path);
} else {
// invalid arguments -> cannot verify
log.warn("Cannot verify capability to '{}' due to missing or invalid arguments, required a valid relative path.", methodName);
return false;
}
} else if ("setPrimaryType".equals(methodName) || "addMixin".equals(methodName)
|| "removeMixin".equals(methodName)) {
permission = Permissions.NODE_TYPE_MANAGEMENT;
} else if ("orderBefore".equals(methodName)) {
if (tree.isRoot()) {
return false;
} else {
permission = Permissions.MODIFY_CHILD_NODE_COLLECTION;
tree = tree.getParent();
}
} else if ("setProperty".equals(methodName)) {
permission = Permissions.ADD_PROPERTY;
} else if ("remove".equals(methodName)) {
permission = Permissions.REMOVE_NODE;
}
return accessMgr.hasPermissions(tree, null, permission) && !isMountedReadOnly(tree.getPath());
} else {
if ("setValue".equals(methodName)) {
permission = Permissions.MODIFY_PROPERTY;
} else if ("remove".equals(methodName)) {
permission = Permissions.REMOVE_PROPERTY;
}
NodeDelegate parentDelegate = dlg.getParent();
if (parentDelegate != null) {
return accessMgr.hasPermissions(parentDelegate.getTree(),
((PropertyDelegate) dlg).getPropertyState(), permission)
&& !isMountedReadOnly(parentDelegate.getPath());
} else {
return accessMgr.hasPermissions(dlg.getPath(),
(permission == Permissions.MODIFY_PROPERTY) ? Session.ACTION_SET_PROPERTY
: Session.ACTION_REMOVE)
&& !isMountedReadOnly(dlg.getPath());
}
}
} else if (target instanceof AccessControlManager && isPolicyWriteMethod(methodName)) {
if (!hasArguments(arguments)) {
log.warn("Cannot verify capability to '{}' due to missing arguments.", methodName);
return false;
}
String path = getFirstArgument(arguments);
if (path == null) {
return getAccessControlManager().hasPrivileges(null, AccessControlUtils.privilegesFromNames(this, PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL));
} else {
String oakPath = getOakPathOrThrow(path);
return !isMountedReadOnly(oakPath) && accessMgr.hasPermissions(oakPath, JackrabbitSession.ACTION_MODIFY_ACCESS_CONTROL);
}
}
// TODO: add more best-effort checks
return true;
}